2015-04-30 16:22:37 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2015-05-02 03:17:31 +00:00
|
|
|
"fmt"
|
2015-05-14 15:17:43 +00:00
|
|
|
"github.com/br0xen/bolt"
|
2015-05-08 15:14:02 +00:00
|
|
|
"os"
|
2015-04-30 16:22:37 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// A Database, basically a collection of buckets
|
|
|
|
type BoltDB struct {
|
|
|
|
buckets []BoltBucket
|
|
|
|
}
|
|
|
|
|
2015-05-03 23:57:37 +00:00
|
|
|
type BoltBucket struct {
|
2015-05-08 15:14:02 +00:00
|
|
|
name string
|
|
|
|
path []string
|
|
|
|
pairs []BoltPair
|
|
|
|
buckets []BoltBucket
|
|
|
|
parent *BoltBucket
|
|
|
|
expanded bool
|
|
|
|
error_flag bool
|
2015-05-03 23:57:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type BoltPair struct {
|
|
|
|
path []string
|
|
|
|
parent *BoltBucket
|
|
|
|
key string
|
|
|
|
val string
|
|
|
|
}
|
|
|
|
|
2015-04-30 16:22:37 +00:00
|
|
|
func (bd *BoltDB) getGenericFromPath(path []string) (*BoltBucket, *BoltPair, error) {
|
|
|
|
// Check if 'path' leads to a pair
|
|
|
|
p, err := bd.getPairFromPath(path)
|
|
|
|
if err == nil {
|
|
|
|
return nil, p, nil
|
|
|
|
}
|
|
|
|
// Nope, check if it leads to a bucket
|
|
|
|
b, err := bd.getBucketFromPath(path)
|
|
|
|
if err == nil {
|
|
|
|
return b, nil, nil
|
|
|
|
}
|
|
|
|
// Nope, error
|
|
|
|
return nil, nil, errors.New("Invalid Path")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bd *BoltDB) getBucketFromPath(path []string) (*BoltBucket, error) {
|
|
|
|
if len(path) > 0 {
|
|
|
|
// Find the BoltBucket with a path == path
|
|
|
|
var b *BoltBucket
|
|
|
|
var err error
|
|
|
|
// Find the root bucket
|
|
|
|
b, err = memBolt.getBucket(path[0])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if len(path) > 1 {
|
|
|
|
for p := 1; p < len(path); p++ {
|
2015-05-08 15:14:02 +00:00
|
|
|
b, err = b.getBucket(path[p])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-04-30 16:22:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
return nil, errors.New("Invalid Path")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bd *BoltDB) getPairFromPath(path []string) (*BoltPair, error) {
|
2015-05-08 15:14:02 +00:00
|
|
|
if len(path) <= 0 {
|
|
|
|
return nil, errors.New("No Path")
|
|
|
|
}
|
|
|
|
b, err := bd.getBucketFromPath(path[:len(path)-1])
|
2015-04-30 16:22:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// Found the bucket, pull out the pair
|
|
|
|
p, err := b.getPair(path[len(path)-1])
|
|
|
|
return p, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bd *BoltDB) getVisibleItemCount(path []string) (int, error) {
|
|
|
|
vis := 0
|
|
|
|
var ret_err error
|
|
|
|
if len(path) == 0 {
|
|
|
|
for i := range bd.buckets {
|
|
|
|
n, err := bd.getVisibleItemCount(bd.buckets[i].path)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
vis += n
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
b, err := bd.getBucketFromPath(path)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
// 1 for the bucket
|
|
|
|
vis += 1
|
|
|
|
if b.expanded {
|
|
|
|
// This bucket is expanded, add up it's children
|
|
|
|
// * 1 for each pair
|
|
|
|
vis += len(b.pairs)
|
|
|
|
// * recurse for buckets
|
|
|
|
for i := range b.buckets {
|
|
|
|
n, err := bd.getVisibleItemCount(b.buckets[i].path)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
vis += n
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return vis, ret_err
|
|
|
|
}
|
|
|
|
|
2015-05-08 15:14:02 +00:00
|
|
|
func (bd *BoltDB) buildVisiblePathSlice() ([]string, error) {
|
|
|
|
var ret_slice []string
|
|
|
|
var ret_err error
|
|
|
|
// The root path, recurse for root buckets
|
|
|
|
for i := range bd.buckets {
|
|
|
|
bkt_s, bkt_err := bd.buckets[i].buildVisiblePathSlice([]string{})
|
|
|
|
if bkt_err == nil {
|
|
|
|
ret_slice = append(ret_slice, bkt_s...)
|
|
|
|
} else {
|
|
|
|
// Something went wrong, set the error flag
|
|
|
|
bd.buckets[i].error_flag = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret_slice, ret_err
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (bd *BoltDB) buildVisiblePathSlice_old(path []string) ([]string, error) {
|
2015-04-30 16:22:37 +00:00
|
|
|
var ret_slice []string
|
|
|
|
var ret_err error
|
|
|
|
if len(path) == 0 {
|
|
|
|
for i := range bd.buckets {
|
|
|
|
n, err := bd.buildVisiblePathSlice(bd.buckets[i].path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
ret_slice = append(ret_slice, n...)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
b, err := bd.getBucketFromPath(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// Add the bucket's path
|
|
|
|
ret_slice = append(ret_slice, strings.Join(b.path, "/"))
|
|
|
|
if b.expanded {
|
2015-05-08 15:14:02 +00:00
|
|
|
// This bucket is expanded, include it's children
|
2015-04-30 16:22:37 +00:00
|
|
|
// * recurse for buckets
|
|
|
|
for i := range b.buckets {
|
|
|
|
n, err := bd.buildVisiblePathSlice(b.buckets[i].path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
ret_slice = append(ret_slice, n...)
|
|
|
|
}
|
|
|
|
// * one path for each pair
|
|
|
|
for i := range b.pairs {
|
|
|
|
ret_slice = append(ret_slice, strings.Join(b.pairs[i].path, "/"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret_slice, ret_err
|
|
|
|
}
|
2015-05-08 15:14:02 +00:00
|
|
|
*/
|
2015-04-30 16:22:37 +00:00
|
|
|
|
|
|
|
func (bd *BoltDB) getPrevVisiblePath(path []string) []string {
|
2015-05-08 15:14:02 +00:00
|
|
|
vis_paths, err := bd.buildVisiblePathSlice()
|
2015-04-30 16:22:37 +00:00
|
|
|
if path == nil {
|
2015-05-08 15:14:02 +00:00
|
|
|
if len(vis_paths) > 0 {
|
|
|
|
return strings.Split(vis_paths[len(vis_paths)-1], "/")
|
|
|
|
} else {
|
|
|
|
return nil
|
|
|
|
}
|
2015-04-30 16:22:37 +00:00
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
find_path := strings.Join(path, "/")
|
|
|
|
for i := range vis_paths {
|
|
|
|
if vis_paths[i] == find_path && i > 0 {
|
|
|
|
return strings.Split(vis_paths[i-1], "/")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func (bd *BoltDB) getNextVisiblePath(path []string) []string {
|
2015-05-08 15:14:02 +00:00
|
|
|
vis_paths, err := bd.buildVisiblePathSlice()
|
2015-04-30 16:22:37 +00:00
|
|
|
if path == nil {
|
2015-05-08 15:14:02 +00:00
|
|
|
if len(vis_paths) > 0 {
|
|
|
|
return strings.Split(vis_paths[0], "/")
|
|
|
|
} else {
|
|
|
|
return nil
|
|
|
|
}
|
2015-04-30 16:22:37 +00:00
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
find_path := strings.Join(path, "/")
|
|
|
|
for i := range vis_paths {
|
|
|
|
if vis_paths[i] == find_path && i < len(vis_paths)-1 {
|
|
|
|
return strings.Split(vis_paths[i+1], "/")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-05-04 18:50:41 +00:00
|
|
|
func (bd *BoltDB) toggleOpenBucket(path []string) error {
|
|
|
|
// Find the BoltBucket with a path == path
|
|
|
|
b, err := bd.getBucketFromPath(path)
|
|
|
|
if err == nil {
|
|
|
|
b.expanded = !b.expanded
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bd *BoltDB) closeBucket(path []string) error {
|
|
|
|
// Find the BoltBucket with a path == path
|
|
|
|
b, err := bd.getBucketFromPath(path)
|
|
|
|
if err == nil {
|
|
|
|
b.expanded = false
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bd *BoltDB) openBucket(path []string) error {
|
|
|
|
// Find the BoltBucket with a path == path
|
|
|
|
b, err := bd.getBucketFromPath(path)
|
|
|
|
if err == nil {
|
|
|
|
b.expanded = true
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-04-30 16:22:37 +00:00
|
|
|
func (bd *BoltDB) getBucket(k string) (*BoltBucket, error) {
|
|
|
|
for i := range bd.buckets {
|
|
|
|
if bd.buckets[i].name == k {
|
|
|
|
return &bd.buckets[i], nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, errors.New("Bucket Not Found")
|
|
|
|
}
|
|
|
|
|
2015-05-04 18:50:41 +00:00
|
|
|
func (bd *BoltDB) syncOpenBuckets(shadow *BoltDB) {
|
|
|
|
// First test this bucket
|
|
|
|
for i := range bd.buckets {
|
|
|
|
for j := range shadow.buckets {
|
|
|
|
if bd.buckets[i].name == shadow.buckets[j].name {
|
|
|
|
bd.buckets[i].syncOpenBuckets(&shadow.buckets[j])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-08 15:14:02 +00:00
|
|
|
func (bd *BoltDB) refreshDatabase() *BoltDB {
|
|
|
|
// Reload the database into memBolt
|
|
|
|
memBolt = new(BoltDB)
|
|
|
|
db.View(func(tx *bolt.Tx) error {
|
|
|
|
return tx.ForEach(func(nm []byte, b *bolt.Bucket) error {
|
|
|
|
bb, err := readBucket(b)
|
|
|
|
if err == nil {
|
|
|
|
bb.name = string(nm)
|
|
|
|
bb.setPath([]string{bb.name})
|
|
|
|
bb.expanded = false
|
|
|
|
memBolt.buckets = append(memBolt.buckets, *bb)
|
|
|
|
//updatePaths(bb)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
})
|
|
|
|
})
|
|
|
|
return memBolt
|
|
|
|
}
|
|
|
|
|
2015-05-12 21:04:49 +00:00
|
|
|
func (b *BoltBucket) GetPath() []string {
|
|
|
|
b.path[len(b.path)-1] = b.name
|
|
|
|
return b.path
|
|
|
|
}
|
|
|
|
|
2015-05-08 15:14:02 +00:00
|
|
|
func (b *BoltBucket) buildVisiblePathSlice(prefix []string) ([]string, error) {
|
|
|
|
var ret_slice []string
|
|
|
|
var ret_err error
|
|
|
|
// Add this bucket to the slice
|
|
|
|
prefix = append(prefix, b.name)
|
|
|
|
ret_slice = append(ret_slice, strings.Join(prefix, "/"))
|
|
|
|
if b.expanded {
|
|
|
|
// Add subbuckets
|
|
|
|
for i := range b.buckets {
|
|
|
|
bkt_s, bkt_err := b.buckets[i].buildVisiblePathSlice(prefix)
|
|
|
|
if bkt_err == nil {
|
|
|
|
ret_slice = append(ret_slice, bkt_s...)
|
|
|
|
} else {
|
|
|
|
// Something went wrong, set the error flag
|
|
|
|
b.buckets[i].error_flag = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Add Pairs
|
|
|
|
for i := range b.pairs {
|
2015-05-12 21:04:49 +00:00
|
|
|
ret_slice = append(ret_slice, strings.Join(prefix, "/")+"/"+b.pairs[i].key)
|
2015-05-08 15:14:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret_slice, ret_err
|
|
|
|
}
|
|
|
|
|
2015-05-04 18:50:41 +00:00
|
|
|
func (b *BoltBucket) syncOpenBuckets(shadow *BoltBucket) {
|
|
|
|
// First test this bucket
|
|
|
|
b.expanded = shadow.expanded
|
|
|
|
for i := range b.buckets {
|
|
|
|
for j := range shadow.buckets {
|
|
|
|
if b.buckets[i].name == shadow.buckets[j].name {
|
|
|
|
b.buckets[i].syncOpenBuckets(&shadow.buckets[j])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-30 16:22:37 +00:00
|
|
|
func (b *BoltBucket) getBucket(k string) (*BoltBucket, error) {
|
|
|
|
for i := range b.buckets {
|
|
|
|
if b.buckets[i].name == k {
|
|
|
|
return &b.buckets[i], nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, errors.New("Bucket Not Found")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BoltBucket) getPair(k string) (*BoltPair, error) {
|
|
|
|
for i := range b.pairs {
|
|
|
|
if b.pairs[i].key == k {
|
|
|
|
return &b.pairs[i], nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, errors.New("Pair Not Found")
|
|
|
|
}
|
|
|
|
|
2015-05-08 15:14:02 +00:00
|
|
|
func (b *BoltBucket) setPath(p []string) {
|
|
|
|
b.path = p
|
|
|
|
for i := range b.buckets {
|
|
|
|
b.buckets[i].setPath(append(p, b.buckets[i].name))
|
|
|
|
}
|
|
|
|
for i := range b.pairs {
|
|
|
|
b.pairs[i].path = append(p, b.pairs[i].key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-30 16:22:37 +00:00
|
|
|
func deleteKey(path []string) error {
|
|
|
|
err := db.Update(func(tx *bolt.Tx) error {
|
|
|
|
// len(b.path)-1 is the key we need to delete, the rest are buckets leading to that key
|
2015-05-04 18:50:41 +00:00
|
|
|
if len(path) == 1 {
|
|
|
|
// Deleting a root bucket
|
|
|
|
return tx.DeleteBucket([]byte(path[0]))
|
|
|
|
} else {
|
|
|
|
b := tx.Bucket([]byte(path[0]))
|
|
|
|
if b != nil {
|
|
|
|
if len(path) > 1 {
|
|
|
|
for i := range path[1 : len(path)-1] {
|
|
|
|
b = b.Bucket([]byte(path[i+1]))
|
|
|
|
if b == nil {
|
|
|
|
return errors.New("deleteKey: Invalid Path")
|
|
|
|
}
|
2015-04-30 16:22:37 +00:00
|
|
|
}
|
|
|
|
}
|
2015-05-04 18:50:41 +00:00
|
|
|
// Now delete the last key in the path
|
|
|
|
var err error
|
|
|
|
if delete_bkt := b.Bucket([]byte(path[len(path)-1])); delete_bkt == nil {
|
|
|
|
// Must be a pair
|
|
|
|
err = b.Delete([]byte(path[len(path)-1]))
|
|
|
|
} else {
|
|
|
|
err = b.DeleteBucket([]byte(path[len(path)-1]))
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
} else {
|
|
|
|
return errors.New("deleteKey: Invalid Path")
|
2015-04-30 16:22:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func readBucket(b *bolt.Bucket) (*BoltBucket, error) {
|
|
|
|
bb := new(BoltBucket)
|
|
|
|
b.ForEach(func(k, v []byte) error {
|
|
|
|
if v == nil {
|
|
|
|
tb, err := readBucket(b.Bucket(k))
|
|
|
|
tb.parent = bb
|
|
|
|
if err == nil {
|
|
|
|
tb.name = string(k)
|
|
|
|
bb.buckets = append(bb.buckets, *tb)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tp := BoltPair{key: string(k), val: string(v)}
|
|
|
|
tp.parent = bb
|
|
|
|
bb.pairs = append(bb.pairs, tp)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return bb, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func updatePaths(b *BoltBucket) {
|
|
|
|
for i := range b.buckets {
|
2015-05-08 15:14:02 +00:00
|
|
|
|
2015-04-30 16:22:37 +00:00
|
|
|
b.buckets[i].path = append(b.path, b.buckets[i].name)
|
|
|
|
updatePaths(&b.buckets[i])
|
|
|
|
}
|
|
|
|
for i := range b.pairs {
|
|
|
|
b.pairs[i].path = append(b.path, b.pairs[i].key)
|
|
|
|
}
|
|
|
|
}
|
2015-05-02 03:17:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
func renameBucket(path []string, name string) error {
|
|
|
|
err := db.Update(func(tx *bolt.Tx) error {
|
|
|
|
// len(b.path)-1 is the key we need to delete, the rest are buckets leading to that key
|
|
|
|
b := tx.Bucket([]byte(path[0]))
|
|
|
|
if b != nil {
|
|
|
|
if len(path) > 1 {
|
|
|
|
for i := range path[1 : len(path)-1] {
|
|
|
|
b = b.Bucket([]byte(path[i+1]))
|
|
|
|
if b == nil {
|
|
|
|
return errors.New("updatePairValue: Invalid Path")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Now update the last key in the path
|
|
|
|
err := b.Put([]byte(path[len(path)-1]), []byte(v))
|
|
|
|
return err
|
|
|
|
} else {
|
|
|
|
return errors.New("renameBucket: Invalid Path")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
refreshDatabase()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
func updatePairValue(path []string, v string) error {
|
|
|
|
err := db.Update(func(tx *bolt.Tx) error {
|
|
|
|
// len(b.path)-1 is the key we need to delete, the rest are buckets leading to that key
|
|
|
|
b := tx.Bucket([]byte(path[0]))
|
|
|
|
if b != nil {
|
2015-05-12 21:04:49 +00:00
|
|
|
if len(path) > 0 {
|
2015-05-02 03:17:31 +00:00
|
|
|
for i := range path[1 : len(path)-1] {
|
|
|
|
b = b.Bucket([]byte(path[i+1]))
|
|
|
|
if b == nil {
|
|
|
|
return errors.New("updatePairValue: Invalid Path")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Now update the last key in the path
|
|
|
|
err := b.Put([]byte(path[len(path)-1]), []byte(v))
|
|
|
|
return err
|
|
|
|
} else {
|
|
|
|
return errors.New("updatePairValue: Invalid Path")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func insertBucket(path []string, n string) error {
|
2015-05-04 22:41:47 +00:00
|
|
|
// Inserts a new bucket named 'n' at 'path'
|
2015-05-02 03:17:31 +00:00
|
|
|
err := db.Update(func(tx *bolt.Tx) error {
|
2015-05-08 15:14:02 +00:00
|
|
|
if len(path) == 0 {
|
2015-05-02 03:17:31 +00:00
|
|
|
// insert at root
|
|
|
|
_, err := tx.CreateBucket([]byte(n))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("insertBucket: %s", err)
|
|
|
|
}
|
2015-05-08 15:14:02 +00:00
|
|
|
} else {
|
|
|
|
root_bucket, path := path[0], path[1:]
|
|
|
|
b := tx.Bucket([]byte(root_bucket))
|
2015-05-02 03:17:31 +00:00
|
|
|
if b != nil {
|
2015-05-08 15:14:02 +00:00
|
|
|
for len(path) > 0 {
|
|
|
|
tst_bucket := ""
|
|
|
|
tst_bucket, path = path[0], path[1:]
|
|
|
|
n_b := b.Bucket([]byte(tst_bucket))
|
|
|
|
if n_b == nil {
|
|
|
|
// Not a bucket, if we're out of path, just move on
|
|
|
|
if len(path) != 0 {
|
|
|
|
// Out of path, error
|
|
|
|
return errors.New("insertBucket: Invalid Path 1")
|
2015-05-02 03:17:31 +00:00
|
|
|
}
|
2015-05-08 15:14:02 +00:00
|
|
|
} else {
|
|
|
|
b = n_b
|
2015-05-02 03:17:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_, err := b.CreateBucket([]byte(n))
|
2015-05-08 15:14:02 +00:00
|
|
|
return err
|
2015-05-02 03:17:31 +00:00
|
|
|
}
|
2015-05-08 15:14:02 +00:00
|
|
|
return fmt.Errorf("insertBucket: Invalid Path %s", root_bucket)
|
2015-05-02 03:17:31 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
2015-05-04 22:41:47 +00:00
|
|
|
|
|
|
|
func insertPair(path []string, k string, v string) error {
|
|
|
|
// Insert a new pair k => v at path
|
|
|
|
err := db.Update(func(tx *bolt.Tx) error {
|
2015-05-12 21:04:49 +00:00
|
|
|
if len(path) == 0 {
|
2015-05-04 22:41:47 +00:00
|
|
|
// We cannot insert a pair at root
|
|
|
|
return errors.New("insertPair: Cannot insert pair at root.")
|
2015-05-12 21:04:49 +00:00
|
|
|
} else {
|
2015-05-04 22:41:47 +00:00
|
|
|
var err error
|
|
|
|
b := tx.Bucket([]byte(path[0]))
|
|
|
|
if b != nil {
|
2015-05-12 21:04:49 +00:00
|
|
|
if len(path) > 0 {
|
2015-05-14 15:17:43 +00:00
|
|
|
for i := 1; i < len(path); i++ {
|
2015-05-12 21:04:49 +00:00
|
|
|
b = b.Bucket([]byte(path[i]))
|
2015-05-04 22:41:47 +00:00
|
|
|
if b == nil {
|
|
|
|
return fmt.Errorf("insertPair: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err := b.Put([]byte(k), []byte(v))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("insertPair: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
2015-05-08 15:14:02 +00:00
|
|
|
|
|
|
|
var f *os.File
|
|
|
|
|
|
|
|
func logToFile(s string) {
|
|
|
|
if f == nil {
|
2015-05-14 15:17:43 +00:00
|
|
|
f, _ = os.OpenFile("bolt-log", os.O_RDWR|os.O_APPEND, 0660)
|
2015-05-08 15:14:02 +00:00
|
|
|
}
|
|
|
|
f.WriteString(s + "\n")
|
|
|
|
f.Sync()
|
|
|
|
}
|