diff --git a/examples/basecoin/main.go b/examples/basecoin/main.go index e7bd230021..3b6d86cd8d 100644 --- a/examples/basecoin/main.go +++ b/examples/basecoin/main.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "fmt" "os" @@ -36,13 +35,13 @@ func main() { ibcLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory) // The key to access the main KVStore. - var mainStoreKey = new(KVStoreKey) - var ibcStoreKey = new(KVStoreKey) + var mainStoreKey = sdk.NewKVStoreKey("main") + var ibcStoreKey = sdk.NewKVStoreKey("ibc") // Create MultiStore multiStore := store.NewCommitMultiStore(db) - multiStore.SetSubstoreLoader("main", mainStoreKey, mainLoader) - multiStore.SetSubstoreLoader("ibc", ibcStoreKey, ibcLoader) + multiStore.SetSubstoreLoader(mainStoreKey, mainLoader) + multiStore.SetSubstoreLoader(ibcStoreKey, ibcLoader) app.SetCommitMultiStore(multiStore) // Set Tx decoder diff --git a/store/cachemultistore.go b/store/cachemultistore.go index cb1cbd9c07..3396a68f6e 100644 --- a/store/cachemultistore.go +++ b/store/cachemultistore.go @@ -9,7 +9,7 @@ type cacheMultiStore struct { db CacheKVStore nextVersion int64 lastCommitID CommitID - substores map[string]CacheWrap + substores map[SubstoreKey]CacheWrap } func newCacheMultiStoreFromRMS(rms *rootMultiStore) cacheMultiStore { @@ -17,10 +17,10 @@ func newCacheMultiStoreFromRMS(rms *rootMultiStore) cacheMultiStore { db: NewCacheKVStore(rms.db), nextVersion: rms.nextVersion, lastCommitID: rms.lastCommitID, - substores: make(map[string]CacheWrap, len(rms.substores)), + substores: make(map[SubstoreKey]CacheWrap, len(rms.substores)), } - for name, substore := range rms.substores { - cms.substores[name] = substore.CacheWrap() + for key, substore := range rms.substores { + cms.substores[key] = substore.CacheWrap() } return cms } @@ -30,10 +30,10 @@ func newCacheMultiStoreFromCMS(cms cacheMultiStore) cacheMultiStore { db: NewCacheKVStore(cms.db), nextVersion: cms.nextVersion, lastCommitID: cms.lastCommitID, - substores: make(map[string]CacheWrap, len(cms.substores)), + substores: make(map[SubstoreKey]CacheWrap, len(cms.substores)), } - for name, substore := range cms.substores { - cms2.substores[name] = substore.CacheWrap() + for key, substore := range cms.substores { + cms2.substores[key] = substore.CacheWrap() } return cms2 } @@ -67,11 +67,11 @@ func (cms cacheMultiStore) CacheMultiStore() CacheMultiStore { } // Implements CacheMultiStore -func (cms cacheMultiStore) GetStore(name string) interface{} { - return cms.substores[name] +func (cms cacheMultiStore) GetStore(key SubstoreKey) interface{} { + return cms.substores[key] } // Implements CacheMultiStore -func (cms cacheMultiStore) GetKVStore(name string) KVStore { - return cms.substores[name].(KVStore) +func (cms cacheMultiStore) GetKVStore(key SubstoreKey) KVStore { + return cms.substores[key].(KVStore) } diff --git a/store/rootmultistore.go b/store/rootmultistore.go index 495df1839f..5913468692 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -22,8 +22,8 @@ type rootMultiStore struct { db dbm.DB nextVersion int64 lastCommitID CommitID - storeLoaders map[string]CommitStoreLoader - substores map[string]CommitStore + storeLoaders map[SubstoreKey]CommitStoreLoader + substores map[SubstoreKey]CommitStore } var _ CommitMultiStore = (*rootMultiStore)(nil) @@ -32,22 +32,22 @@ func NewCommitMultiStore(db dbm.DB) *rootMultiStore { return &rootMultiStore{ db: db, nextVersion: 0, - storeLoaders: make(map[string]CommitStoreLoader), - substores: make(map[string]CommitStore), + storeLoaders: make(map[SubstoreKey]CommitStoreLoader), + substores: make(map[SubstoreKey]CommitStore), } } // Implements CommitMultiStore. -func (rs *rootMultiStore) SetSubstoreLoader(name string, loader CommitStoreLoader) { - if _, ok := rs.storeLoaders[name]; ok { - panic(fmt.Sprintf("rootMultiStore duplicate substore name " + name)) +func (rs *rootMultiStore) SetSubstoreLoader(key SubstoreKey, loader CommitStoreLoader) { + if _, ok := rs.storeLoaders[key]; ok { + panic(fmt.Sprintf("rootMultiStore duplicate substore key", key)) } - rs.storeLoaders[name] = loader + rs.storeLoaders[key] = loader } // Implements CommitMultiStore. -func (rs *rootMultiStore) GetSubstore(name string) CommitStore { - return rs.substores[name] +func (rs *rootMultiStore) GetSubstore(key SubstoreKey) CommitStore { + return rs.substores[key] } // Implements CommitMultiStore. @@ -61,12 +61,12 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error { // Special logic for version 0 if ver == 0 { - for name, storeLoader := range rs.storeLoaders { + for key, storeLoader := range rs.storeLoaders { store, err := storeLoader(CommitID{}) if err != nil { return fmt.Errorf("Failed to load rootMultiStore: %v", err) } - rs.substores[name] = store + rs.substores[key] = store } rs.nextVersion = 1 @@ -82,24 +82,24 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error { } // Load each Substore - var newSubstores = make(map[string]CommitStore) + var newSubstores = make(map[SubstoreKey]CommitStore) for _, store := range state.Substores { - name, commitID := store.Name, store.CommitID - storeLoader := rs.storeLoaders[name] + key, commitID := rs.nameToKey(store.Name), store.CommitID + storeLoader := rs.storeLoaders[key] if storeLoader == nil { - return fmt.Errorf("Failed to load rootMultiStore substore %v for commitID %v: %v", name, commitID, err) + return fmt.Errorf("Failed to load rootMultiStore substore %v for commitID %v: %v", key, commitID, err) } store, err := storeLoader(commitID) if err != nil { return fmt.Errorf("Failed to load rootMultiStore: %v", err) } - newSubstores[name] = store + newSubstores[key] = store } // If any CommitStoreLoaders were not used, return error. - for name := range rs.storeLoaders { - if _, ok := newSubstores[name]; !ok { - return fmt.Errorf("Unused CommitStoreLoader: %v", name) + for key := range rs.storeLoaders { + if _, ok := newSubstores[key]; !ok { + return fmt.Errorf("Unused CommitStoreLoader: %v", key) } } @@ -110,6 +110,15 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error { return nil } +func (rs *rootMultiStore) nameToKey(name string) SubstoreKey { + for key, _ := range rs.substores { + if key.Name() == name { + return key + } + } + panic("Unknown name " + name) +} + //---------------------------------------- // +CommitStore @@ -161,13 +170,13 @@ func (rs *rootMultiStore) CacheMultiStore() CacheMultiStore { } // Implements MultiStore. -func (rs *rootMultiStore) GetStore(name string) interface{} { - return rs.substores[name] +func (rs *rootMultiStore) GetStore(key SubstoreKey) interface{} { + return rs.substores[key] } // Implements MultiStore. -func (rs *rootMultiStore) GetKVStore(name string) KVStore { - return rs.substores[name].(KVStore) +func (rs *rootMultiStore) GetKVStore(key SubstoreKey) KVStore { + return rs.substores[key].(KVStore) } //---------------------------------------- @@ -246,16 +255,16 @@ func setLatestVersion(batch dbm.Batch, version int64) { } // Commits each substore and returns a new commitState. -func commitSubstores(version int64, substoresMap map[string]CommitStore) commitState { +func commitSubstores(version int64, substoresMap map[SubstoreKey]CommitStore) commitState { substores := make([]substore, 0, len(substoresMap)) - for name, store := range substoresMap { + for key, store := range substoresMap { // Commit commitID := store.Commit() // Record CommitID substore := substore{} - substore.Name = name + substore.Name = key.Name() substore.CommitID = commitID substores = append(substores, substore) } diff --git a/store/types.go b/store/types.go index ec572e7663..db946f2e2b 100644 --- a/store/types.go +++ b/store/types.go @@ -17,3 +17,4 @@ type CacheKVStore = types.CacheKVStore type CacheWrapper = types.CacheWrapper type CacheWrap = types.CacheWrap type CommitID = types.CommitID +type SubstoreKey = types.SubstoreKey diff --git a/types/context.go b/types/context.go index 4a0879a866..ba3263d465 100644 --- a/types/context.go +++ b/types/context.go @@ -2,6 +2,8 @@ package types import ( "context" + "sync" + "github.com/golang/protobuf/proto" abci "github.com/tendermint/abci/types" @@ -83,7 +85,7 @@ func (c Context) WithProtoMsg(key interface{}, value proto.Message) Context { return c.withValue(key, value) } -func (c Context) WithMultiStore(key *MultiStoreKey, ms MultiStore) Context { +func (c Context) WithMultiStore(key *KVStoreKey, ms MultiStore) Context { return c.withValue(key, ms) } @@ -218,7 +220,7 @@ type thePast struct { func newThePast() *thePast { return &thePast{ - val: 0, + ver: 0, ops: nil, } } @@ -238,10 +240,11 @@ func (pst *thePast) version() int { // Returns false if ver > 0. // The first operation is version 1. -func (pst *thePast) getOp(ver int) (Op, bool) { +func (pst *thePast) getOp(ver int64) (Op, bool) { pst.mtx.RLock() defer pst.mtx.RUnlock() - if len(pst.ops) < ver { + l := int64(len(pst.ops)) + if l < ver { return Op{}, false } else { return pst.ops[ver-1], true diff --git a/types/store.go b/types/store.go index 2d7d77f70a..8e6d9bf466 100644 --- a/types/store.go +++ b/types/store.go @@ -27,8 +27,8 @@ type MultiStore interface { CacheMultiStore() CacheMultiStore // Convenience for fetching substores. - GetStore(name string) interface{} - GetKVStore(name string) KVStore + GetStore(SubstoreKey) interface{} + GetKVStore(SubstoreKey) KVStore } // From MultiStore.CacheMultiStore().... @@ -54,10 +54,10 @@ type CommitMultiStore interface { MultiStore // Add a substore loader. - SetSubstoreLoader(name string, loader CommitStoreLoader) + SetSubstoreLoader(key SubstoreKey, loader CommitStoreLoader) // Gets the substore, which is a CommitSubstore. - GetSubstore(name string) CommitStore + GetSubstore(key SubstoreKey) CommitStore // Load the latest persisted version. // Called once after all calls to SetSubstoreLoader are complete. @@ -148,7 +148,7 @@ type CacheWrap interface { } //---------------------------------------- -// etc +// CommitID // CommitID contains the tree version number and its merkle root. type CommitID struct { @@ -164,5 +164,34 @@ func (cid CommitID) String() string { return fmt.Sprintf("CommitID{%v:%X}", cid.Hash, cid.Version) } -// new(KVStoreKey) is a capabilities key. -type KVStoreKey struct{} +//---------------------------------------- +// Keys for accessing substores + +// SubstoreKey is a key used to index substores. +type SubstoreKey interface { + Name() string + + String() string +} + +// KVStoreKey is used for accessing substores. +// Only the pointer value should ever be used - it functions as a capabilities key. +type KVStoreKey struct { + name string +} + +// NewKVStoreKey returns a new pointer to a KVStoreKey. +// Use a pointer so keys don't collide. +func NewKVStoreKey(name string) *KVStoreKey { + return &KVStoreKey{ + name: name, + } +} + +func (key *KVStoreKey) Name() string { + return key.name +} + +func (key *KVStoreKey) String() string { + return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name) +}