summaryrefslogtreecommitdiffstats
path: root/lib/db/namespaced.go
diff options
context:
space:
mode:
authorJakob Borg <jakob@nym.se>2015-08-06 11:29:25 +0200
committerJakob Borg <jakob@nym.se>2015-08-09 09:35:26 +0200
commit7705a6c1f165a9a81856d0c493eac5042b6e18bf (patch)
tree4def8ef959ea73e655edd0189e7ee88ef57377f4 /lib/db/namespaced.go
parent0a803891a465254376ed776ee82aa4220fc2eb23 (diff)
mv internal lib
Diffstat (limited to 'lib/db/namespaced.go')
-rw-r--r--lib/db/namespaced.go159
1 files changed, 159 insertions, 0 deletions
diff --git a/lib/db/namespaced.go b/lib/db/namespaced.go
new file mode 100644
index 0000000000..d1b1bf15a0
--- /dev/null
+++ b/lib/db/namespaced.go
@@ -0,0 +1,159 @@
+// Copyright (C) 2014 The Syncthing Authors.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package db
+
+import (
+ "encoding/binary"
+ "time"
+
+ "github.com/syndtr/goleveldb/leveldb"
+ "github.com/syndtr/goleveldb/leveldb/util"
+)
+
+// NamespacedKV is a simple key-value store using a specific namespace within
+// a leveldb.
+type NamespacedKV struct {
+ db *leveldb.DB
+ prefix []byte
+}
+
+// NewNamespacedKV returns a new NamespacedKV that lives in the namespace
+// specified by the prefix.
+func NewNamespacedKV(db *leveldb.DB, prefix string) *NamespacedKV {
+ return &NamespacedKV{
+ db: db,
+ prefix: []byte(prefix),
+ }
+}
+
+// Reset removes all entries in this namespace.
+func (n *NamespacedKV) Reset() {
+ it := n.db.NewIterator(util.BytesPrefix(n.prefix), nil)
+ defer it.Release()
+ batch := new(leveldb.Batch)
+ for it.Next() {
+ batch.Delete(it.Key())
+ if batch.Len() > batchFlushSize {
+ if err := n.db.Write(batch, nil); err != nil {
+ panic(err)
+ }
+ batch.Reset()
+ }
+ }
+ if batch.Len() > 0 {
+ if err := n.db.Write(batch, nil); err != nil {
+ panic(err)
+ }
+ }
+}
+
+// PutInt64 stores a new int64. Any existing value (even if of another type)
+// is overwritten.
+func (n *NamespacedKV) PutInt64(key string, val int64) {
+ keyBs := append(n.prefix, []byte(key)...)
+ var valBs [8]byte
+ binary.BigEndian.PutUint64(valBs[:], uint64(val))
+ n.db.Put(keyBs, valBs[:], nil)
+}
+
+// Int64 returns the stored value interpreted as an int64 and a boolean that
+// is false if no value was stored at the key.
+func (n *NamespacedKV) Int64(key string) (int64, bool) {
+ keyBs := append(n.prefix, []byte(key)...)
+ valBs, err := n.db.Get(keyBs, nil)
+ if err != nil {
+ return 0, false
+ }
+ val := binary.BigEndian.Uint64(valBs)
+ return int64(val), true
+}
+
+// PutTime stores a new time.Time. Any existing value (even if of another
+// type) is overwritten.
+func (n *NamespacedKV) PutTime(key string, val time.Time) {
+ keyBs := append(n.prefix, []byte(key)...)
+ valBs, _ := val.MarshalBinary() // never returns an error
+ n.db.Put(keyBs, valBs, nil)
+}
+
+// Time returns the stored value interpreted as a time.Time and a boolean
+// that is false if no value was stored at the key.
+func (n NamespacedKV) Time(key string) (time.Time, bool) {
+ var t time.Time
+ keyBs := append(n.prefix, []byte(key)...)
+ valBs, err := n.db.Get(keyBs, nil)
+ if err != nil {
+ return t, false
+ }
+ err = t.UnmarshalBinary(valBs)
+ return t, err == nil
+}
+
+// PutString stores a new string. Any existing value (even if of another type)
+// is overwritten.
+func (n *NamespacedKV) PutString(key, val string) {
+ keyBs := append(n.prefix, []byte(key)...)
+ n.db.Put(keyBs, []byte(val), nil)
+}
+
+// String returns the stored value interpreted as a string and a boolean that
+// is false if no value was stored at the key.
+func (n NamespacedKV) String(key string) (string, bool) {
+ keyBs := append(n.prefix, []byte(key)...)
+ valBs, err := n.db.Get(keyBs, nil)
+ if err != nil {
+ return "", false
+ }
+ return string(valBs), true
+}
+
+// PutBytes stores a new byte slice. Any existing value (even if of another type)
+// is overwritten.
+func (n *NamespacedKV) PutBytes(key string, val []byte) {
+ keyBs := append(n.prefix, []byte(key)...)
+ n.db.Put(keyBs, val, nil)
+}
+
+// Bytes returns the stored value as a raw byte slice and a boolean that
+// is false if no value was stored at the key.
+func (n NamespacedKV) Bytes(key string) ([]byte, bool) {
+ keyBs := append(n.prefix, []byte(key)...)
+ valBs, err := n.db.Get(keyBs, nil)
+ if err != nil {
+ return nil, false
+ }
+ return valBs, true
+}
+
+// PutBool stores a new boolean. Any existing value (even if of another type)
+// is overwritten.
+func (n *NamespacedKV) PutBool(key string, val bool) {
+ keyBs := append(n.prefix, []byte(key)...)
+ if val {
+ n.db.Put(keyBs, []byte{0x0}, nil)
+ } else {
+ n.db.Put(keyBs, []byte{0x1}, nil)
+ }
+}
+
+// Bool returns the stored value as a boolean and a boolean that
+// is false if no value was stored at the key.
+func (n NamespacedKV) Bool(key string) (bool, bool) {
+ keyBs := append(n.prefix, []byte(key)...)
+ valBs, err := n.db.Get(keyBs, nil)
+ if err != nil {
+ return false, false
+ }
+ return valBs[0] == 0x0, true
+}
+
+// Delete deletes the specified key. It is allowed to delete a nonexistent
+// key.
+func (n NamespacedKV) Delete(key string) {
+ keyBs := append(n.prefix, []byte(key)...)
+ n.db.Delete(keyBs, nil)
+}