Merge pull request #5516 from bhandras/etcd_kvdb_fixes

etcd: kvdb fixes
This commit is contained in:
Oliver Gugger 2021-07-20 17:50:36 +02:00 committed by GitHub
commit bc98bb3f88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 20 deletions

8
kvdb/debug.go Normal file

@ -0,0 +1,8 @@
// +build dev
package kvdb
const (
// Switch on extra debug code.
etcdDebug = true
)

8
kvdb/etcd/debug.go Normal file

@ -0,0 +1,8 @@
// +build dev
package etcd
const (
// Switch on extra debug code.
etcdDebug = true
)

8
kvdb/etcd/nodebug.go Normal file

@ -0,0 +1,8 @@
// +build !dev
package etcd
const (
// Switch off extra debug code.
etcdDebug = false
)

@ -118,6 +118,10 @@ func (b *readWriteBucket) NestedReadWriteBucket(key []byte) walletdb.ReadWriteBu
// assertNoValue checks if the value for the passed key exists. // assertNoValue checks if the value for the passed key exists.
func (b *readWriteBucket) assertNoValue(key []byte) error { func (b *readWriteBucket) assertNoValue(key []byte) error {
if !etcdDebug {
return nil
}
val, err := b.tx.stm.Get(string(makeValueKey(b.id, key))) val, err := b.tx.stm.Get(string(makeValueKey(b.id, key)))
if err != nil { if err != nil {
return err return err
@ -130,6 +134,24 @@ func (b *readWriteBucket) assertNoValue(key []byte) error {
return nil return nil
} }
// assertNoBucket checks if the bucket for the passed key exists.
func (b *readWriteBucket) assertNoBucket(key []byte) error {
if !etcdDebug {
return nil
}
val, err := b.tx.stm.Get(string(makeBucketKey(b.id, key)))
if err != nil {
return err
}
if val != nil {
return walletdb.ErrIncompatibleValue
}
return nil
}
// CreateBucket creates and returns a new nested bucket with the given // CreateBucket creates and returns a new nested bucket with the given
// key. Returns ErrBucketExists if the bucket already exists, // key. Returns ErrBucketExists if the bucket already exists,
// ErrBucketNameRequired if the key is empty, or ErrIncompatibleValue // ErrBucketNameRequired if the key is empty, or ErrIncompatibleValue
@ -272,15 +294,10 @@ func (b *readWriteBucket) Put(key, value []byte) error {
return walletdb.ErrKeyRequired return walletdb.ErrKeyRequired
} }
val, err := b.tx.stm.Get(string(makeBucketKey(b.id, key))) if err := b.assertNoBucket(key); err != nil {
if err != nil {
return err return err
} }
if val != nil {
return walletdb.ErrIncompatibleValue
}
// Update the transaction with the new value. // Update the transaction with the new value.
b.tx.stm.Put(string(makeValueKey(b.id, key)), string(value)) b.tx.stm.Put(string(makeValueKey(b.id, key)), string(value))

@ -116,23 +116,11 @@ func (c *readWriteCursor) Seek(seek []byte) (key, value []byte) {
// invalidating the cursor. Returns ErrIncompatibleValue if attempted // invalidating the cursor. Returns ErrIncompatibleValue if attempted
// when the cursor points to a nested bucket. // when the cursor points to a nested bucket.
func (c *readWriteCursor) Delete() error { func (c *readWriteCursor) Delete() error {
// Get the next key after the current one. We could do this
// after deletion too but it's one step more efficient here.
nextKey, err := c.bucket.tx.stm.Next(c.prefix, c.currKey)
if err != nil {
return err
}
if isBucketKey(c.currKey) { if isBucketKey(c.currKey) {
c.bucket.DeleteNestedBucket(getKey(c.currKey)) c.bucket.DeleteNestedBucket(getKey(c.currKey))
} else { } else {
c.bucket.Delete(getKey(c.currKey)) c.bucket.Delete(getKey(c.currKey))
} }
if nextKey != nil {
// Set current key to the next one.
c.currKey = nextKey.key
}
return nil return nil
} }

@ -19,6 +19,7 @@ var (
func TestEtcd(t *testing.T) { func TestEtcd(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
debugOnly bool
test func(*testing.T, walletdb.DB) test func(*testing.T, walletdb.DB)
expectedDb map[string]string expectedDb map[string]string
}{ }{
@ -103,8 +104,9 @@ func TestEtcd(t *testing.T) {
test: testBucketSequence, test: testBucketSequence,
}, },
{ {
name: "key clash", name: "key clash",
test: testKeyClash, debugOnly: true,
test: testKeyClash,
expectedDb: map[string]string{ expectedDb: map[string]string{
bkey("apple"): bval("apple"), bkey("apple"): bval("apple"),
bkey("apple", "banana"): bval("apple", "banana"), bkey("apple", "banana"): bval("apple", "banana"),
@ -137,6 +139,10 @@ func TestEtcd(t *testing.T) {
for _, test := range tests { for _, test := range tests {
test := test test := test
if test.debugOnly && !etcdDebug {
continue
}
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
t.Parallel() t.Parallel()

8
kvdb/nodebug.go Normal file

@ -0,0 +1,8 @@
// +build !dev
package kvdb
const (
// Switch off extra debug code.
etcdDebug = false
)