2015-05-01 04:08:42 +00:00
|
|
|
package builtin
|
2015-04-07 08:20:55 +00:00
|
|
|
|
2015-04-10 19:52:33 +00:00
|
|
|
import (
|
2015-04-13 22:51:15 +00:00
|
|
|
"bytes"
|
|
|
|
|
2015-04-10 19:52:33 +00:00
|
|
|
"github.com/boltdb/bolt"
|
2015-05-06 03:22:02 +00:00
|
|
|
//"github.com/youtube/vitess/go/bson"
|
|
|
|
"encoding/gob"
|
2015-04-10 19:52:33 +00:00
|
|
|
)
|
2015-04-07 08:20:55 +00:00
|
|
|
|
|
|
|
func encode(v interface{}) ([]byte, error) {
|
2015-05-06 03:22:02 +00:00
|
|
|
var buf bytes.Buffer
|
|
|
|
var err = gob.NewEncoder(&buf).Encode(v)
|
|
|
|
return buf.Bytes(), err
|
|
|
|
//return bson.Marshal(v)
|
2015-04-07 08:20:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func decode(raw []byte, v interface{}) error {
|
2015-05-06 03:22:02 +00:00
|
|
|
var buf bytes.Buffer
|
|
|
|
buf.Write(raw)
|
|
|
|
var err = gob.NewDecoder(&buf).Decode(v)
|
|
|
|
return err
|
|
|
|
//return bson.Unmarshal(raw, v)
|
2015-04-07 08:20:55 +00:00
|
|
|
}
|
|
|
|
|
2015-04-10 19:52:33 +00:00
|
|
|
func get(t *bolt.Tx, bucket, key []byte, v interface{}) error {
|
2015-04-07 08:20:55 +00:00
|
|
|
raw := t.Bucket(bucket).Get(key)
|
|
|
|
if raw == nil {
|
|
|
|
return ErrKeyNotFound
|
|
|
|
}
|
2015-05-06 03:22:02 +00:00
|
|
|
return decode(raw, v)
|
2015-04-07 08:20:55 +00:00
|
|
|
}
|
|
|
|
|
2015-04-10 19:52:33 +00:00
|
|
|
func raw(t *bolt.Tx, bucket, key []byte) ([]byte, error) {
|
2015-04-07 08:20:55 +00:00
|
|
|
raw := t.Bucket(bucket).Get(key)
|
|
|
|
if raw == nil {
|
|
|
|
return nil, ErrKeyNotFound
|
|
|
|
}
|
|
|
|
return raw, nil
|
|
|
|
}
|
|
|
|
|
2015-04-10 19:52:33 +00:00
|
|
|
func update(t *bolt.Tx, bucket, key []byte, v interface{}) error {
|
2015-04-07 08:20:55 +00:00
|
|
|
raw, err := encode(v)
|
|
|
|
if err != nil {
|
|
|
|
t.Rollback()
|
|
|
|
return err
|
|
|
|
}
|
2015-04-11 05:22:55 +00:00
|
|
|
return t.Bucket(bucket).Put(key, raw)
|
2015-04-07 08:20:55 +00:00
|
|
|
}
|
|
|
|
|
2015-04-10 19:52:33 +00:00
|
|
|
func insert(t *bolt.Tx, bucket, key []byte, v interface{}) error {
|
2015-04-07 08:20:55 +00:00
|
|
|
raw, err := encode(v)
|
|
|
|
if err != nil {
|
|
|
|
t.Rollback()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// verify the key does not already exists
|
|
|
|
// in the bucket. If exists, fail
|
|
|
|
if t.Bucket(bucket).Get(key) != nil {
|
|
|
|
return ErrKeyExists
|
|
|
|
}
|
2015-04-11 05:22:55 +00:00
|
|
|
return t.Bucket(bucket).Put(key, raw)
|
2015-04-07 08:20:55 +00:00
|
|
|
}
|
|
|
|
|
2015-04-10 19:52:33 +00:00
|
|
|
func delete(t *bolt.Tx, bucket, key []byte) error {
|
2015-04-11 05:22:55 +00:00
|
|
|
return t.Bucket(bucket).Delete(key)
|
2015-04-07 08:20:55 +00:00
|
|
|
}
|
2015-04-13 22:51:15 +00:00
|
|
|
|
|
|
|
func push(t *bolt.Tx, bucket, index, value []byte) error {
|
|
|
|
var keys [][]byte
|
|
|
|
err := get(t, bucket, index, &keys)
|
|
|
|
if err != nil && err != ErrKeyNotFound {
|
|
|
|
return err
|
|
|
|
}
|
2015-04-30 21:23:46 +00:00
|
|
|
// we shouldn't add a key that already exists
|
|
|
|
for _, key := range keys {
|
|
|
|
if bytes.Equal(key, value) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2015-04-13 22:51:15 +00:00
|
|
|
keys = append(keys, value)
|
|
|
|
return update(t, bucket, index, &keys)
|
|
|
|
}
|
|
|
|
|
|
|
|
func splice(t *bolt.Tx, bucket, index, value []byte) error {
|
|
|
|
var keys [][]byte
|
|
|
|
err := get(t, bucket, index, &keys)
|
|
|
|
if err != nil && err != ErrKeyNotFound {
|
|
|
|
return err
|
|
|
|
}
|
2015-04-14 04:39:05 +00:00
|
|
|
|
2015-04-13 22:51:15 +00:00
|
|
|
for i, key := range keys {
|
|
|
|
if bytes.Equal(key, value) {
|
|
|
|
keys = keys[:i+copy(keys[i:], keys[i+1:])]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2015-04-14 04:39:05 +00:00
|
|
|
|
2015-04-13 22:51:15 +00:00
|
|
|
return update(t, bucket, index, &keys)
|
|
|
|
}
|
2015-04-20 22:48:44 +00:00
|
|
|
|
2015-04-22 16:50:45 +00:00
|
|
|
func deleteWithPrefix(t *bolt.Tx, bucket, prefix []byte) error {
|
2015-04-20 22:48:44 +00:00
|
|
|
var err error
|
|
|
|
|
|
|
|
c := t.Bucket(bucket).Cursor()
|
|
|
|
for k, _ := c.Seek(prefix); bytes.HasPrefix(k, prefix); k, _ = c.Next() {
|
|
|
|
err = c.Delete()
|
2015-04-22 16:50:45 +00:00
|
|
|
if err != nil {
|
2015-04-20 22:48:44 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-22 16:50:45 +00:00
|
|
|
// only error here is if our Tx is read-only
|
2015-04-20 22:48:44 +00:00
|
|
|
return err
|
|
|
|
}
|