summaryrefslogtreecommitdiffstats
path: root/lib/db/namespaced.go
diff options
context:
space:
mode:
authorSimon Frei <freisim93@gmail.com>2019-02-01 09:54:21 +0100
committerJakob Borg <jakob@kastelo.net>2019-02-01 09:54:21 +0100
commit583172dc8db6c3d1764a7f2beea97f400f27ae45 (patch)
tree3b07c24aa3497fd5b9256653dc9b2ee2b546db86 /lib/db/namespaced.go
parent15295633320ee0357ba5e6ceb6fc5a1181d8af47 (diff)
lib/db: Fix race in NamespacedKV (#5496)
Diffstat (limited to 'lib/db/namespaced.go')
-rw-r--r--lib/db/namespaced.go46
1 files changed, 22 insertions, 24 deletions
diff --git a/lib/db/namespaced.go b/lib/db/namespaced.go
index 7a26bdff52..fd6432726e 100644
--- a/lib/db/namespaced.go
+++ b/lib/db/namespaced.go
@@ -24,9 +24,14 @@ type NamespacedKV struct {
// NewNamespacedKV returns a new NamespacedKV that lives in the namespace
// specified by the prefix.
func NewNamespacedKV(db *Lowlevel, prefix string) *NamespacedKV {
+ prefixBs := []byte(prefix)
+ // After the conversion from string the cap will be larger than the len (in Go 1.11.5,
+ // 32 bytes cap for small strings). We need to cut it down to ensure append() calls
+ // on the prefix make a new allocation.
+ prefixBs = prefixBs[:len(prefixBs):len(prefixBs)]
return &NamespacedKV{
db: db,
- prefix: []byte(prefix),
+ prefix: prefixBs,
}
}
@@ -54,17 +59,15 @@ func (n *NamespacedKV) Reset() {
// 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)
+ n.db.Put(n.prefixedKey(key), 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)
+ valBs, err := n.db.Get(n.prefixedKey(key), nil)
if err != nil {
return 0, false
}
@@ -75,17 +78,15 @@ func (n *NamespacedKV) Int64(key string) (int64, bool) {
// 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)
+ n.db.Put(n.prefixedKey(key), 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)
+ valBs, err := n.db.Get(n.prefixedKey(key), nil)
if err != nil {
return t, false
}
@@ -96,15 +97,13 @@ func (n NamespacedKV) Time(key string) (time.Time, bool) {
// 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)
+ n.db.Put(n.prefixedKey(key), []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)
+ valBs, err := n.db.Get(n.prefixedKey(key), nil)
if err != nil {
return "", false
}
@@ -114,15 +113,13 @@ func (n NamespacedKV) String(key string) (string, bool) {
// 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)
+ n.db.Put(n.prefixedKey(key), 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)
+ valBs, err := n.db.Get(n.prefixedKey(key), nil)
if err != nil {
return nil, false
}
@@ -132,19 +129,17 @@ func (n NamespacedKV) Bytes(key string) ([]byte, bool) {
// 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)
+ n.db.Put(n.prefixedKey(key), []byte{0x0}, nil)
} else {
- n.db.Put(keyBs, []byte{0x1}, nil)
+ n.db.Put(n.prefixedKey(key), []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)
+ valBs, err := n.db.Get(n.prefixedKey(key), nil)
if err != nil {
return false, false
}
@@ -154,8 +149,11 @@ func (n NamespacedKV) Bool(key string) (bool, bool) {
// 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)
+ n.db.Delete(n.prefixedKey(key), nil)
+}
+
+func (n NamespacedKV) prefixedKey(key string) []byte {
+ return append(n.prefix, []byte(key)...)
}
// Well known namespaces that can be instantiated without knowing the key