ironsmith/datastore/ds.go

111 lines
2.4 KiB
Go

// Copyright 2016 Tim Shannon. All rights reserved.
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
// Package datastore manages the bolt data files and the reading and writing data to them
package datastore
import (
"bytes"
"encoding/json"
"errors"
"io"
"time"
"github.com/boltdb/bolt"
)
// ErrNotFound is the error returned when a value cannot be found in the store for the given key
var ErrNotFound = errors.New("Value not found")
// Store is a datastore for getting and setting data for a given ironsmith project
// run on top of a Bolt DB file
type Store struct {
bolt *bolt.DB
}
// Open opens an existing datastore file, or creates a new one
// caller is responsible for closing the datastore
func Open(filename string) (*Store, error) {
db, err := bolt.Open(filename, 0666, &bolt.Options{Timeout: 1 * time.Minute})
if err != nil {
return nil, err
}
store := &Store{
bolt: db,
}
err = store.bolt.Update(func(tx *bolt.Tx) error {
_, err := tx.CreateBucketIfNotExists([]byte(bucketLog))
if err != nil {
return err
}
_, err = tx.CreateBucketIfNotExists([]byte(bucketReleases))
if err != nil {
return err
}
_, err = tx.CreateBucketIfNotExists([]byte(bucketFiles))
if err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return store, nil
}
// Close closes the bolt datastore
func (ds *Store) Close() error {
return ds.bolt.Close()
}
func (ds *Store) get(bucket string, key TimeKey, result interface{}) error {
return ds.bolt.View(func(tx *bolt.Tx) error {
dsValue := tx.Bucket([]byte(bucket)).Get(key.Bytes())
if dsValue == nil {
return ErrNotFound
}
if value, ok := result.([]byte); ok {
buff := bytes.NewBuffer(value)
_, err := io.Copy(buff, bytes.NewReader(dsValue))
if err != nil {
return err
}
return nil
}
return json.Unmarshal(dsValue, result)
})
}
func (ds *Store) put(bucket string, key TimeKey, value interface{}) error {
var err error
dsValue, ok := value.([]byte)
if !ok {
dsValue, err = json.Marshal(value)
if err != nil {
return err
}
}
return ds.bolt.Update(func(tx *bolt.Tx) error {
return tx.Bucket([]byte(bucket)).Put(key.Bytes(), dsValue)
})
}
func (ds *Store) delete(bucket string, key TimeKey) error {
return ds.bolt.Update(func(tx *bolt.Tx) error {
return tx.Bucket([]byte(bucket)).Delete(key.Bytes())
})
}