-
Notifications
You must be signed in to change notification settings - Fork 324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[facotry] add factoryWithHeight for archive mode #4474
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,8 +90,7 @@ type ( | |
ReadContractStorage(context.Context, address.Address, []byte) ([]byte, error) | ||
PutBlock(context.Context, *block.Block) error | ||
DeleteTipBlock(context.Context, *block.Block) error | ||
StateAtHeight(uint64, interface{}, ...protocol.StateOption) error | ||
StatesAtHeight(uint64, ...protocol.StateOption) (state.Iterator, error) | ||
AtHeight(uint64) (protocol.ArchiveStateSimulator, error) // returns a factory at the given height | ||
} | ||
|
||
// factory implements StateFactory interface, tracks changes to account/contract and batch-commits to DB | ||
|
@@ -346,6 +345,21 @@ func (sf *factory) Validate(ctx context.Context, blk *block.Block) error { | |
return nil | ||
} | ||
|
||
func (sf *factory) AtHeight(h uint64) (protocol.ArchiveStateSimulator, error) { | ||
sf.mutex.RLock() | ||
defer sf.mutex.RUnlock() | ||
if h == sf.currentChainHeight { | ||
return sf, nil | ||
} | ||
if !sf.saveHistory { | ||
return nil, errors.Wrap(ErrNoArchiveData, "archive mode not enabled") | ||
} | ||
return &factoryWithHeight{ | ||
factory: sf, | ||
height: h, | ||
}, nil | ||
} | ||
|
||
// NewBlockBuilder returns block builder which hasn't been signed yet | ||
func (sf *factory) NewBlockBuilder( | ||
ctx context.Context, | ||
|
@@ -485,52 +499,6 @@ func (sf *factory) DeleteTipBlock(_ context.Context, _ *block.Block) error { | |
return errors.Wrap(ErrNotSupported, "cannot delete tip block from factory") | ||
} | ||
|
||
// StateAtHeight returns a confirmed state at height -- archive mode | ||
func (sf *factory) StateAtHeight(height uint64, s interface{}, opts ...protocol.StateOption) error { | ||
sf.mutex.RLock() | ||
defer sf.mutex.RUnlock() | ||
cfg, err := processOptions(opts...) | ||
if err != nil { | ||
return err | ||
} | ||
if cfg.Keys != nil { | ||
return errors.Wrap(ErrNotSupported, "Read state with keys option has not been implemented yet") | ||
} | ||
if height > sf.currentChainHeight { | ||
return errors.Errorf("query height %d is higher than tip height %d", height, sf.currentChainHeight) | ||
} | ||
return sf.stateAtHeight(height, cfg.Namespace, cfg.Key, s) | ||
} | ||
|
||
// StatesAtHeight returns a set states in the state factory at height -- archive mode | ||
func (sf *factory) StatesAtHeight(height uint64, opts ...protocol.StateOption) (state.Iterator, error) { | ||
sf.mutex.RLock() | ||
defer sf.mutex.RUnlock() | ||
if height > sf.currentChainHeight { | ||
return nil, errors.Errorf("query height %d is higher than tip height %d", height, sf.currentChainHeight) | ||
} | ||
cfg, err := processOptions(opts...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if cfg.Keys != nil { | ||
return nil, errors.Wrap(ErrNotSupported, "Read states with keys option has not been implemented yet") | ||
} | ||
tlt, err := newTwoLayerTrie(ArchiveTrieNamespace, sf.dao, fmt.Sprintf("%s-%d", ArchiveTrieRootKey, height), false) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "failed to generate trie for %d", height) | ||
} | ||
if err := tlt.Start(context.Background()); err != nil { | ||
return nil, err | ||
} | ||
defer tlt.Stop(context.Background()) | ||
keys, values, err := readStatesFromTLT(tlt, cfg.Namespace, cfg.Keys) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return state.NewIterator(keys, values) | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. move to |
||
// State returns a confirmed state in the state factory | ||
func (sf *factory) State(s interface{}, opts ...protocol.StateOption) (uint64, error) { | ||
sf.mutex.RLock() | ||
|
@@ -602,26 +570,6 @@ func legacyKeyLen() int { | |
return 20 | ||
} | ||
|
||
func (sf *factory) stateAtHeight(height uint64, ns string, key []byte, s interface{}) error { | ||
if !sf.saveHistory { | ||
return ErrNoArchiveData | ||
} | ||
tlt, err := newTwoLayerTrie(ArchiveTrieNamespace, sf.dao, fmt.Sprintf("%s-%d", ArchiveTrieRootKey, height), false) | ||
if err != nil { | ||
return errors.Wrapf(err, "failed to generate trie for %d", height) | ||
} | ||
if err := tlt.Start(context.Background()); err != nil { | ||
return err | ||
} | ||
defer tlt.Stop(context.Background()) | ||
|
||
value, err := readStateFromTLT(tlt, ns, key) | ||
if err != nil { | ||
return err | ||
} | ||
return state.Deserialize(s, value) | ||
} | ||
|
||
func (sf *factory) createGenesisStates(ctx context.Context) error { | ||
ws, err := sf.newWorkingSet(ctx, 0) | ||
if err != nil { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok just added, was thinking to add it later in API PR |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// Copyright (c) 2020 IoTeX Foundation | ||
// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability | ||
// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. | ||
// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. | ||
|
||
package factory | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"github.com/iotexproject/iotex-core/v2/action/protocol" | ||
"github.com/iotexproject/iotex-core/v2/state" | ||
) | ||
|
||
type factoryWithHeight struct { | ||
*factory | ||
height uint64 | ||
} | ||
|
||
func (sf *factoryWithHeight) State(s interface{}, opts ...protocol.StateOption) (uint64, error) { | ||
sf.mutex.RLock() | ||
defer sf.mutex.RUnlock() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why does it share the same mutex with factory? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I think reading on archive state can be lock-free There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated in latest commit |
||
cfg, err := processOptions(opts...) | ||
if err != nil { | ||
return 0, err | ||
} | ||
if cfg.Keys != nil { | ||
return 0, errors.Wrap(ErrNotSupported, "Read state with keys option has not been implemented yet") | ||
} | ||
if sf.height > sf.currentChainHeight { | ||
return 0, errors.Errorf("query height %d is higher than tip height %d", sf.height, sf.currentChainHeight) | ||
} | ||
return sf.height, sf.stateAtHeight(sf.height, cfg.Namespace, cfg.Key, s) | ||
} | ||
|
||
func (sf *factoryWithHeight) stateAtHeight(height uint64, ns string, key []byte, s interface{}) error { | ||
if !sf.saveHistory { | ||
return ErrNoArchiveData | ||
} | ||
tlt, err := newTwoLayerTrie(ArchiveTrieNamespace, sf.dao, fmt.Sprintf("%s-%d", ArchiveTrieRootKey, height), false) | ||
if err != nil { | ||
return errors.Wrapf(err, "failed to generate trie for %d", height) | ||
} | ||
if err := tlt.Start(context.Background()); err != nil { | ||
return err | ||
} | ||
defer tlt.Stop(context.Background()) | ||
|
||
value, err := readStateFromTLT(tlt, ns, key) | ||
if err != nil { | ||
return err | ||
} | ||
return state.Deserialize(s, value) | ||
} | ||
|
||
func (sf *factoryWithHeight) States(opts ...protocol.StateOption) (uint64, state.Iterator, error) { | ||
sf.mutex.RLock() | ||
defer sf.mutex.RUnlock() | ||
if sf.height > sf.currentChainHeight { | ||
return 0, nil, errors.Errorf("query height %d is higher than tip height %d", sf.height, sf.currentChainHeight) | ||
} | ||
cfg, err := processOptions(opts...) | ||
if err != nil { | ||
return 0, nil, err | ||
} | ||
if cfg.Keys != nil { | ||
return 0, nil, errors.Wrap(ErrNotSupported, "Read states with keys option has not been implemented yet") | ||
} | ||
tlt, err := newTwoLayerTrie(ArchiveTrieNamespace, sf.dao, fmt.Sprintf("%s-%d", ArchiveTrieRootKey, sf.height), false) | ||
if err != nil { | ||
return 0, nil, errors.Wrapf(err, "failed to generate trie for %d", sf.height) | ||
} | ||
if err := tlt.Start(context.Background()); err != nil { | ||
return 0, nil, err | ||
} | ||
defer tlt.Stop(context.Background()) | ||
keys, values, err := readStatesFromTLT(tlt, cfg.Namespace, cfg.Keys) | ||
if err != nil { | ||
return 0, nil, err | ||
} | ||
iter, err := state.NewIterator(keys, values) | ||
if err != nil { | ||
return 0, nil, err | ||
} | ||
return sf.height, iter, err | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these 2 are needed for archive-node API