storage: add Exists flag to KeyValue in batch

Set Exists flag if an item with the specified key was already
present in storage before persisting.
This commit is contained in:
Evgenii Stratonikov 2020-02-07 15:08:25 +03:00
parent a1fecd2e88
commit 0a894db7f8
3 changed files with 19 additions and 8 deletions

View file

@ -68,9 +68,14 @@ func batchToMap(index uint32, batch *storage.MemBatch) map[string]interface{} {
continue continue
} }
op := "Added"
if batch.Put[i].Exists {
op = "Changed"
}
key = toNeoStorageKey(key[1:]) key = toNeoStorageKey(key[1:])
ops = append(ops, storageOp{ ops = append(ops, storageOp{
State: "Added", State: op,
Key: hex.EncodeToString(key), Key: hex.EncodeToString(key),
Value: "00" + hex.EncodeToString(batch.Put[i].Value), Value: "00" + hex.EncodeToString(batch.Put[i].Value),
}) })
@ -78,7 +83,7 @@ func batchToMap(index uint32, batch *storage.MemBatch) map[string]interface{} {
for i := range batch.Deleted { for i := range batch.Deleted {
key := batch.Deleted[i].Key key := batch.Deleted[i].Key
if len(key) == 0 || key[0] != byte(storage.STStorage) { if len(key) == 0 || key[0] != byte(storage.STStorage) || !batch.Deleted[i].Exists {
continue continue
} }

View file

@ -14,6 +14,8 @@ type (
KeyValue struct { KeyValue struct {
Key []byte Key []byte
Value []byte Value []byte
Exists bool
} }
// MemBatch represents a changeset to be persisted. // MemBatch represents a changeset to be persisted.
@ -54,12 +56,16 @@ func (s *MemCachedStore) GetBatch() *MemBatch {
b.Put = make([]KeyValue, 0, len(s.mem)) b.Put = make([]KeyValue, 0, len(s.mem))
for k, v := range s.mem { for k, v := range s.mem {
b.Put = append(b.Put, KeyValue{Key: []byte(k), Value: v}) key := []byte(k)
_, err := s.ps.Get(key)
b.Put = append(b.Put, KeyValue{Key: key, Value: v, Exists: err == nil})
} }
b.Deleted = make([]KeyValue, 0, len(s.del)) b.Deleted = make([]KeyValue, 0, len(s.del))
for k := range s.del { for k := range s.del {
b.Deleted = append(b.Deleted, KeyValue{Key: []byte(k)}) key := []byte(k)
_, err := s.ps.Get(key)
b.Deleted = append(b.Deleted, KeyValue{Key: key, Exists: err == nil})
} }
return &b return &b

View file

@ -18,7 +18,7 @@ func TestMemCachedStorePersist(t *testing.T) {
assert.Equal(t, 0, c) assert.Equal(t, 0, c)
// persisting one key should result in one key in ps and nothing in ts // persisting one key should result in one key in ps and nothing in ts
assert.NoError(t, ts.Put([]byte("key"), []byte("value"))) assert.NoError(t, ts.Put([]byte("key"), []byte("value")))
checkBatch(t, ts, []KeyValue{{[]byte("key"), []byte("value")}}, nil) checkBatch(t, ts, []KeyValue{{Key: []byte("key"), Value: []byte("value")}}, nil)
c, err = ts.Persist() c, err = ts.Persist()
checkBatch(t, ts, nil, nil) checkBatch(t, ts, nil, nil)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
@ -38,8 +38,8 @@ func TestMemCachedStorePersist(t *testing.T) {
assert.Equal(t, ErrKeyNotFound, err) assert.Equal(t, ErrKeyNotFound, err)
assert.Equal(t, []byte(nil), v) assert.Equal(t, []byte(nil), v)
checkBatch(t, ts, []KeyValue{ checkBatch(t, ts, []KeyValue{
{[]byte("key"), []byte("newvalue")}, {Key: []byte("key"), Value: []byte("newvalue"), Exists: true},
{[]byte("key2"), []byte("value2")}, {Key: []byte("key2"), Value: []byte("value2")},
}, nil) }, nil)
// two keys should be persisted (one overwritten and one new) and // two keys should be persisted (one overwritten and one new) and
// available in the ps // available in the ps
@ -67,7 +67,7 @@ func TestMemCachedStorePersist(t *testing.T) {
// test persisting deletions // test persisting deletions
err = ts.Delete([]byte("key")) err = ts.Delete([]byte("key"))
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
checkBatch(t, ts, nil, []KeyValue{{Key: []byte("key")}}) checkBatch(t, ts, nil, []KeyValue{{Key: []byte("key"), Exists: true}})
c, err = ts.Persist() c, err = ts.Persist()
checkBatch(t, ts, nil, nil) checkBatch(t, ts, nil, nil)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)