mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 03:18:59 +00:00
lib/db: Fix race in NamespacedKV (#5496)
This commit is contained in:
parent
1529563332
commit
583172dc8d
@ -24,9 +24,14 @@ type NamespacedKV struct {
|
|||||||
// NewNamespacedKV returns a new NamespacedKV that lives in the namespace
|
// NewNamespacedKV returns a new NamespacedKV that lives in the namespace
|
||||||
// specified by the prefix.
|
// specified by the prefix.
|
||||||
func NewNamespacedKV(db *Lowlevel, prefix string) *NamespacedKV {
|
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{
|
return &NamespacedKV{
|
||||||
db: db,
|
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)
|
// PutInt64 stores a new int64. Any existing value (even if of another type)
|
||||||
// is overwritten.
|
// is overwritten.
|
||||||
func (n *NamespacedKV) PutInt64(key string, val int64) {
|
func (n *NamespacedKV) PutInt64(key string, val int64) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
|
||||||
var valBs [8]byte
|
var valBs [8]byte
|
||||||
binary.BigEndian.PutUint64(valBs[:], uint64(val))
|
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
|
// Int64 returns the stored value interpreted as an int64 and a boolean that
|
||||||
// is false if no value was stored at the key.
|
// is false if no value was stored at the key.
|
||||||
func (n *NamespacedKV) Int64(key string) (int64, bool) {
|
func (n *NamespacedKV) Int64(key string) (int64, bool) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
valBs, err := n.db.Get(n.prefixedKey(key), nil)
|
||||||
valBs, err := n.db.Get(keyBs, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, false
|
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
|
// PutTime stores a new time.Time. Any existing value (even if of another
|
||||||
// type) is overwritten.
|
// type) is overwritten.
|
||||||
func (n *NamespacedKV) PutTime(key string, val time.Time) {
|
func (n *NamespacedKV) PutTime(key string, val time.Time) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
|
||||||
valBs, _ := val.MarshalBinary() // never returns an error
|
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
|
// Time returns the stored value interpreted as a time.Time and a boolean
|
||||||
// that is false if no value was stored at the key.
|
// that is false if no value was stored at the key.
|
||||||
func (n NamespacedKV) Time(key string) (time.Time, bool) {
|
func (n NamespacedKV) Time(key string) (time.Time, bool) {
|
||||||
var t time.Time
|
var t time.Time
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
valBs, err := n.db.Get(n.prefixedKey(key), nil)
|
||||||
valBs, err := n.db.Get(keyBs, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return t, false
|
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)
|
// PutString stores a new string. Any existing value (even if of another type)
|
||||||
// is overwritten.
|
// is overwritten.
|
||||||
func (n *NamespacedKV) PutString(key, val string) {
|
func (n *NamespacedKV) PutString(key, val string) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
n.db.Put(n.prefixedKey(key), []byte(val), nil)
|
||||||
n.db.Put(keyBs, []byte(val), nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the stored value interpreted as a string and a boolean that
|
// String returns the stored value interpreted as a string and a boolean that
|
||||||
// is false if no value was stored at the key.
|
// is false if no value was stored at the key.
|
||||||
func (n NamespacedKV) String(key string) (string, bool) {
|
func (n NamespacedKV) String(key string) (string, bool) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
valBs, err := n.db.Get(n.prefixedKey(key), nil)
|
||||||
valBs, err := n.db.Get(keyBs, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false
|
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)
|
// PutBytes stores a new byte slice. Any existing value (even if of another type)
|
||||||
// is overwritten.
|
// is overwritten.
|
||||||
func (n *NamespacedKV) PutBytes(key string, val []byte) {
|
func (n *NamespacedKV) PutBytes(key string, val []byte) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
n.db.Put(n.prefixedKey(key), val, nil)
|
||||||
n.db.Put(keyBs, val, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns the stored value as a raw byte slice and a boolean that
|
// Bytes returns the stored value as a raw byte slice and a boolean that
|
||||||
// is false if no value was stored at the key.
|
// is false if no value was stored at the key.
|
||||||
func (n NamespacedKV) Bytes(key string) ([]byte, bool) {
|
func (n NamespacedKV) Bytes(key string) ([]byte, bool) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
valBs, err := n.db.Get(n.prefixedKey(key), nil)
|
||||||
valBs, err := n.db.Get(keyBs, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false
|
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)
|
// PutBool stores a new boolean. Any existing value (even if of another type)
|
||||||
// is overwritten.
|
// is overwritten.
|
||||||
func (n *NamespacedKV) PutBool(key string, val bool) {
|
func (n *NamespacedKV) PutBool(key string, val bool) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
|
||||||
if val {
|
if val {
|
||||||
n.db.Put(keyBs, []byte{0x0}, nil)
|
n.db.Put(n.prefixedKey(key), []byte{0x0}, nil)
|
||||||
} else {
|
} 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
|
// Bool returns the stored value as a boolean and a boolean that
|
||||||
// is false if no value was stored at the key.
|
// is false if no value was stored at the key.
|
||||||
func (n NamespacedKV) Bool(key string) (bool, bool) {
|
func (n NamespacedKV) Bool(key string) (bool, bool) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
valBs, err := n.db.Get(n.prefixedKey(key), nil)
|
||||||
valBs, err := n.db.Get(keyBs, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, false
|
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
|
// Delete deletes the specified key. It is allowed to delete a nonexistent
|
||||||
// key.
|
// key.
|
||||||
func (n NamespacedKV) Delete(key string) {
|
func (n NamespacedKV) Delete(key string) {
|
||||||
keyBs := append(n.prefix, []byte(key)...)
|
n.db.Delete(n.prefixedKey(key), nil)
|
||||||
n.db.Delete(keyBs, 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
|
// Well known namespaces that can be instantiated without knowing the key
|
||||||
|
Loading…
Reference in New Issue
Block a user