Skip to content

Commit

Permalink
fix bug: when get value from level db (ontio#62)
Browse files Browse the repository at this point in the history
* fix bug: when get value from level db should judge  return err, but not the value self.

* Update state_batch.go
  • Loading branch information
tanZiWen authored and laizy committed Apr 25, 2018
1 parent 090f05f commit 4985f31
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 37 deletions.
63 changes: 35 additions & 28 deletions core/store/statestore/state_batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func NewStateStoreBatch(memoryStore common.MemoryCacheStore, store common.Persis
}

func (self *StateBatch) Find(prefix common.DataEntryPrefix, key []byte) ([]*common.StateItem, error) {
var states []*common.StateItem
var sts []*common.StateItem
bp := []byte{byte(prefix)}
iter := self.store.NewIterator(append(bp, key...))
defer iter.Release()
Expand All @@ -56,68 +56,76 @@ func (self *StateBatch) Find(prefix common.DataEntryPrefix, key []byte) ([]*comm
if err != nil {
return nil, err
}
states = append(states, &common.StateItem{Key: string(keyV), Value: state})
sts = append(sts, &common.StateItem{Key: string(keyV), Value: state})
}
}
keyP := string(append(bp, key...))
for _, v := range self.memoryStore.Find() {
if v.State != common.Deleted && strings.HasPrefix(v.Key, keyP) {
states = append(states, v.Copy())
sts = append(sts, v.Copy())
}
}
return states, nil
return sts, nil
}

func (self *StateBatch) TryAdd(prefix common.DataEntryPrefix, key []byte, value states.StateValue) {
self.setStateObject(byte(prefix), key, value, common.Changed)
}

func (self *StateBatch) TryGetOrAdd(prefix common.DataEntryPrefix, key []byte, value states.StateValue) error {
state := self.memoryStore.Get(byte(prefix), key)
bPrefix := byte(prefix)
aPrefix := []byte{bPrefix}
state := self.memoryStore.Get(bPrefix, key)
if state != nil {
if state.State == common.Deleted {
self.setStateObject(byte(prefix), key, value, common.Changed)
self.setStateObject(bPrefix, key, value, common.Changed)
return nil
}
return nil
}
item, err := self.store.Get(append([]byte{byte(prefix)}, key...))
if err != nil && err != leveldb.ErrNotFound {
_, err := self.store.Get(append(aPrefix, key...))
if err != nil {
if err == leveldb.ErrNotFound {
return nil
}
return errors.NewDetailErr(err, errors.ErrNoCode, "[TryGetOrAdd], leveldb store get data failed.")
}
if item != nil {
return nil
}
self.setStateObject(byte(prefix), key, value, common.Changed)

self.setStateObject(bPrefix, key, value, common.Changed)
return nil
}

func (self *StateBatch) TryGet(prefix common.DataEntryPrefix, key []byte) (*common.StateItem, error) {
state := self.memoryStore.Get(byte(prefix), key)
bPrefix := byte(prefix)
aPrefix := []byte{bPrefix}
pk := append(aPrefix, key...)
state := self.memoryStore.Get(bPrefix, key)
if state != nil {
if state.State == common.Deleted {
return nil, nil
}
return state, nil
}
enc, err := self.store.Get(append([]byte{byte(prefix)}, key...))
if err != nil && err != leveldb.ErrNotFound {
enc, err := self.store.Get(pk)
if err != nil {
if err == leveldb.ErrNotFound {
return nil, nil
}
return nil, errors.NewDetailErr(err, errors.ErrNoCode, "[TryGet], leveldb store get data failed.")
}

if enc == nil {
return nil, nil
}
stateVal, err := getStateObject(prefix, enc)
if err != nil {
return nil, err
}
self.setStateObject(byte(prefix), key, stateVal, common.None)
return &common.StateItem{Key: string(append([]byte{byte(prefix)}, key...)), Value: stateVal, State: common.None}, nil
self.setStateObject(bPrefix, key, stateVal, common.None)
return &common.StateItem{Key: string(pk), Value: stateVal, State: common.None}, nil
}

func (self *StateBatch) TryGetAndChange(prefix common.DataEntryPrefix, key []byte) (states.StateValue, error) {
state := self.memoryStore.Get(byte(prefix), key)
bPrefix := byte(prefix)
aPrefix := []byte{bPrefix}
state := self.memoryStore.Get(bPrefix, key)
if state != nil {
if state.State == common.Deleted {
return nil, nil
Expand All @@ -126,21 +134,20 @@ func (self *StateBatch) TryGetAndChange(prefix common.DataEntryPrefix, key []byt
}
return state.Value, nil
}
k := append([]byte{byte(prefix)}, key...)
k := append(aPrefix, key...)
enc, err := self.store.Get(k)
if err != nil && err != leveldb.ErrNotFound {
if err != nil {
if err == leveldb.ErrNotFound {
return nil, nil
}
return nil, errors.NewDetailErr(err, errors.ErrNoCode, "[TryGetAndChange], leveldb store get data failed.")
}

if enc == nil {
return nil, nil
}

val, err := getStateObject(prefix, enc)
if err != nil {
return nil, err
}
self.setStateObject(byte(prefix), key, val, common.Changed)
self.setStateObject(bPrefix, key, val, common.Changed)
return val, nil
}

Expand Down
23 changes: 14 additions & 9 deletions smartcontract/storage/dbcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,19 @@ func NewCloneCache(store common.StateStore) *CloneCache {
// Commit current transaction cache to block cache
func (cloneCache *CloneCache) Commit() {
for _, v := range cloneCache.Memory {
vk := []byte(v.Key)
if v.State == common.Deleted {
cloneCache.Store.TryDelete(v.Prefix, []byte(v.Key))
cloneCache.Store.TryDelete(v.Prefix, vk)
} else if v.State == common.Changed {
cloneCache.Store.TryAdd(v.Prefix, []byte(v.Key), v.Value)
cloneCache.Store.TryAdd(v.Prefix, vk, v.Value)
}
}
}

// Add item to cache
func (cloneCache *CloneCache) Add(prefix common.DataEntryPrefix, key []byte, value states.StateValue) {
cloneCache.Memory[string(append([]byte{byte(prefix)}, key...))] = &StateItem{
pk := string(append([]byte{byte(prefix)}, key...))
cloneCache.Memory[pk] = &StateItem{
Prefix: prefix,
Key: string(key),
Value: value,
Expand All @@ -73,9 +75,10 @@ func (cloneCache *CloneCache) Add(prefix common.DataEntryPrefix, key []byte, val
// If item has existed, return it
// Else add it to cache
func (cloneCache *CloneCache) GetOrAdd(prefix common.DataEntryPrefix, key []byte, value states.StateValue) (states.StateValue, error) {
if v, ok := cloneCache.Memory[string(append([]byte{byte(prefix)}, key...))]; ok {
pk := string(append([]byte{byte(prefix)}, key...))
if v, ok := cloneCache.Memory[pk]; ok {
if v.State == common.Deleted {
cloneCache.Memory[string(append([]byte{byte(prefix)}, key...))] = &StateItem{Prefix: prefix, Key: string(key), Value: value, State: common.Changed}
cloneCache.Memory[pk] = &StateItem{Prefix: prefix, Key: string(key), Value: value, State: common.Changed}
return value, nil
}
return v.Value, nil
Expand All @@ -87,13 +90,14 @@ func (cloneCache *CloneCache) GetOrAdd(prefix common.DataEntryPrefix, key []byte
if item != nil && item.State != common.Deleted {
return item.Value, nil
}
cloneCache.Memory[string(append([]byte{byte(prefix)}, key...))] = &StateItem{Prefix: prefix, Key: string(key), Value: value, State: common.Changed}
cloneCache.Memory[pk] = &StateItem{Prefix: prefix, Key: string(key), Value: value, State: common.Changed}
return value, nil
}

// Get item by key
func (cloneCache *CloneCache) Get(prefix common.DataEntryPrefix, key []byte) (states.StateValue, error) {
if v, ok := cloneCache.Memory[string(append([]byte{byte(prefix)}, key...))]; ok {
pk := string(append([]byte{byte(prefix)}, key...))
if v, ok := cloneCache.Memory[pk]; ok {
if v.State == common.Deleted {
return nil, nil
}
Expand All @@ -111,10 +115,11 @@ func (cloneCache *CloneCache) Get(prefix common.DataEntryPrefix, key []byte) (st

// Delete item from cache
func (cloneCache *CloneCache) Delete(prefix common.DataEntryPrefix, key []byte) {
if v, ok := cloneCache.Memory[string(append([]byte{byte(prefix)}, key...))]; ok {
pk := string(append([]byte{byte(prefix)}, key...))
if v, ok := cloneCache.Memory[pk]; ok {
v.State = common.Deleted
} else {
cloneCache.Memory[string(append([]byte{byte(prefix)}, key...))] = &StateItem{
cloneCache.Memory[pk] = &StateItem{
Prefix: prefix,
Key: string(key),
State: common.Deleted,
Expand Down

0 comments on commit 4985f31

Please sign in to comment.