mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
libs/db: boltdb: use slice instead of sync.Map (#3633)
for storing batch keys and values in boltDBBatch. NOTE: batch does not have to be safe for concurrent access. Delete may be slow, but given it should not be used often, it's ok. Fixes #3631
This commit is contained in:
parent
a7358bc69f
commit
a076b48202
@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/etcd-io/bbolt"
|
||||
)
|
||||
@ -150,36 +149,58 @@ func (bdb *BoltDB) Stats() map[string]string {
|
||||
// boltDBBatch stores key values in sync.Map and dumps them to the underlying
|
||||
// DB upon Write call.
|
||||
type boltDBBatch struct {
|
||||
buffer *sync.Map
|
||||
db *BoltDB
|
||||
buffer []struct {
|
||||
k []byte
|
||||
v []byte
|
||||
}
|
||||
db *BoltDB
|
||||
}
|
||||
|
||||
// NewBatch returns a new batch.
|
||||
func (bdb *BoltDB) NewBatch() Batch {
|
||||
return &boltDBBatch{
|
||||
buffer: &sync.Map{},
|
||||
db: bdb,
|
||||
buffer: make([]struct {
|
||||
k []byte
|
||||
v []byte
|
||||
}, 0),
|
||||
db: bdb,
|
||||
}
|
||||
}
|
||||
|
||||
// It is safe to modify the contents of the argument after Set returns but not
|
||||
// before.
|
||||
func (bdb *boltDBBatch) Set(key, value []byte) {
|
||||
bdb.buffer.Store(string(key), value)
|
||||
bdb.buffer = append(bdb.buffer, struct {
|
||||
k []byte
|
||||
v []byte
|
||||
}{
|
||||
key, value,
|
||||
})
|
||||
}
|
||||
|
||||
// It is safe to modify the contents of the argument after Delete returns but
|
||||
// not before.
|
||||
func (bdb *boltDBBatch) Delete(key []byte) {
|
||||
bdb.buffer.Delete(string(key))
|
||||
for i, elem := range bdb.buffer {
|
||||
if bytes.Equal(elem.k, key) {
|
||||
// delete without preserving order
|
||||
bdb.buffer[i] = bdb.buffer[len(bdb.buffer)-1]
|
||||
bdb.buffer = bdb.buffer[:len(bdb.buffer)-1]
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: the operation is synchronous (see BoltDB for reasons)
|
||||
func (bdb *boltDBBatch) Write() {
|
||||
err := bdb.db.db.Batch(func(tx *bbolt.Tx) error {
|
||||
b := tx.Bucket(bucket)
|
||||
var putErr error
|
||||
bdb.buffer.Range(func(key, value interface{}) bool {
|
||||
putErr = b.Put([]byte(key.(string)), value.([]byte))
|
||||
return putErr == nil // stop if putErr is not nil
|
||||
})
|
||||
return putErr
|
||||
for _, elem := range bdb.buffer {
|
||||
if putErr := b.Put(elem.k, elem.v); putErr != nil {
|
||||
return putErr
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
Loading…
x
Reference in New Issue
Block a user