etcd: remove assertion when creating bucket and value with the same key

This commit removes an assertion which is not needed because with etcd
we can safely create keys and values with the same key since they are
stored under different keys in the DB. This saves us one unnecessary Get
on every Put.
This commit is contained in:
Andras Banki-Horvath 2021-06-16 16:56:38 +02:00
parent 11a44a94b1
commit 96caa6f242
No known key found for this signature in database
GPG Key ID: 80E5375C094198D8
6 changed files with 63 additions and 8 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))

@ -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
}{ }{
@ -104,6 +105,7 @@ func TestEtcd(t *testing.T) {
}, },
{ {
name: "key clash", name: "key clash",
debugOnly: true,
test: testKeyClash, test: testKeyClash,
expectedDb: map[string]string{ expectedDb: map[string]string{
bkey("apple"): bval("apple"), bkey("apple"): bval("apple"),
@ -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
)