Skip to content
Snippets Groups Projects
Commit 5f252121 authored by Sean Young's avatar Sean Young
Browse files

Remove iteration from cache


The IterateStorage and IterateAccounts methods are broken. They return
entries accounts which have been removed, and entries which are in
the cache are returned twice (from cache and backend).

So remove iterability from the cache and solve these problems.

Signed-off-by: default avatarSean Young <sean.young@monax.io>
parent bf1675eb
No related branches found
No related tags found
No related merge requests found
......@@ -24,16 +24,15 @@ import (
)
type Cache interface {
IterableWriter
Writer
Sync(state Writer) error
Reset(backend Iterable)
Flush(state IterableWriter) error
Backend() Iterable
}
type stateCache struct {
sync.RWMutex
backend Iterable
backend Reader
accounts map[acm.Address]*accountInfo
}
......@@ -47,7 +46,7 @@ type accountInfo struct {
// Returns a Cache that wraps an underlying Reader to use on a cache miss, can write to an output Writer
// via Sync. Goroutine safe for concurrent access.
func NewCache(backend Iterable) Cache {
func NewCache(backend Reader) Cache {
return &stateCache{
backend: backend,
accounts: make(map[acm.Address]*accountInfo),
......@@ -97,8 +96,8 @@ func (cache *stateCache) RemoveAccount(address acm.Address) error {
return nil
}
// Iterates over all accounts first in cache and then in backend until consumer returns true for 'stop'
func (cache *stateCache) IterateAccounts(consumer func(acm.Account) (stop bool)) (stopped bool, err error) {
// Iterates over all cached accounts first in cache and then in backend until consumer returns true for 'stop'
func (cache *stateCache) IterateCachedAccount(consumer func(acm.Account) (stop bool)) (stopped bool, err error) {
// Try cache first for early exit
cache.RLock()
for _, info := range cache.accounts {
......@@ -108,7 +107,7 @@ func (cache *stateCache) IterateAccounts(consumer func(acm.Account) (stop bool))
}
}
cache.RUnlock()
return cache.backend.IterateAccounts(consumer)
return false, nil
}
func (cache *stateCache) GetStorage(address acm.Address, key binary.Word256) (binary.Word256, error) {
......@@ -152,8 +151,8 @@ func (cache *stateCache) SetStorage(address acm.Address, key binary.Word256, val
return nil
}
// Iterates over all storage items first in cache and then in backend until consumer returns true for 'stop'
func (cache *stateCache) IterateStorage(address acm.Address,
// Iterates over all cached storage items first in cache and then in backend until consumer returns true for 'stop'
func (cache *stateCache) IterateCachedStorage(address acm.Address,
consumer func(key, value binary.Word256) (stop bool)) (stopped bool, err error) {
accInfo, err := cache.get(address)
if err != nil {
......@@ -168,7 +167,7 @@ func (cache *stateCache) IterateStorage(address acm.Address,
}
}
accInfo.RUnlock()
return cache.backend.IterateStorage(address, consumer)
return false, nil
}
// Syncs changes to the backend in deterministic order. Sends storage updates before updating
......@@ -234,10 +233,6 @@ func (cache *stateCache) Flush(state IterableWriter) error {
return nil
}
func (cache *stateCache) Backend() Iterable {
return cache.backend
}
// Get the cache accountInfo item creating it if necessary
func (cache *stateCache) get(address acm.Address) (*accountInfo, error) {
cache.RLock()
......
......@@ -131,8 +131,6 @@ type testState struct {
Storage map[acm.Address]map[binary.Word256]binary.Word256
}
var _ Iterable = &testState{}
func newTestState() *testState {
return &testState{
Accounts: make(map[acm.Address]acm.Account),
......@@ -165,24 +163,6 @@ func word(str string) binary.Word256 {
return binary.LeftPadWord256([]byte(str))
}
func (tsr *testState) IterateAccounts(consumer func(acm.Account) (stop bool)) (stopped bool, err error) {
for _, acc := range tsr.Accounts {
if consumer(acc) {
return true, nil
}
}
return false, nil
}
func (tsr *testState) IterateStorage(address acm.Address, consumer func(key, value binary.Word256) (stop bool)) (stopped bool, err error) {
for key, value := range tsr.Storage[address] {
if consumer(key, value) {
return true, nil
}
}
return false, nil
}
func (tsr *testState) GetAccount(address acm.Address) (acm.Account, error) {
return tsr.Accounts[address], nil
}
......
......@@ -37,9 +37,7 @@ import (
const GasLimit = uint64(1000000)
type BatchExecutor interface {
state.Iterable
state.AccountUpdater
state.StorageSetter
state.Reader
// Execute transaction against block cache (i.e. block buffer)
Execute(tx txs.Tx) error
// Reset executor to underlying State
......@@ -120,31 +118,11 @@ func (exe *executor) GetAccount(address acm.Address) (acm.Account, error) {
return exe.stateCache.GetAccount(address)
}
func (exe *executor) UpdateAccount(account acm.Account) error {
return exe.stateCache.UpdateAccount(account)
}
func (exe *executor) RemoveAccount(address acm.Address) error {
return exe.stateCache.RemoveAccount(address)
}
func (exe *executor) IterateAccounts(consumer func(acm.Account) bool) (bool, error) {
return exe.stateCache.IterateAccounts(consumer)
}
// Storage
func (exe *executor) GetStorage(address acm.Address, key binary.Word256) (binary.Word256, error) {
return exe.stateCache.GetStorage(address, key)
}
func (exe *executor) SetStorage(address acm.Address, key binary.Word256, value binary.Word256) error {
return exe.stateCache.SetStorage(address, key, value)
}
func (exe *executor) IterateStorage(address acm.Address, consumer func(key, value binary.Word256) bool) (bool, error) {
return exe.stateCache.IterateStorage(address, consumer)
}
func (exe *executor) Commit() (hash []byte, err error) {
exe.Lock()
defer exe.Unlock()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment