mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
swarm/shed: remove MockIndex
This commit is contained in:
parent
3685c959e0
commit
181cb23968
5 changed files with 23 additions and 286 deletions
|
|
@ -24,14 +24,10 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/swarm/shed"
|
||||
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||
"github.com/ethereum/go-ethereum/swarm/storage/mock"
|
||||
"github.com/ethereum/go-ethereum/swarm/storage/mock/mem"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
|
|
@ -47,7 +43,7 @@ type Store struct {
|
|||
schemaName shed.StringField
|
||||
sizeCounter shed.Uint64Field
|
||||
accessCounter shed.Uint64Field
|
||||
retrievalIndex shed.IndexInterface // example of swapable Index/MockIndex
|
||||
retrievalIndex shed.Index
|
||||
accessIndex shed.Index
|
||||
gcIndex shed.Index
|
||||
}
|
||||
|
|
@ -55,7 +51,7 @@ type Store struct {
|
|||
// New returns new Store. All fields and indexes are initialized
|
||||
// and possible conflicts with schema from existing database is checked
|
||||
// automatically.
|
||||
func New(path string, mockStore *mock.NodeStore) (s *Store, err error) {
|
||||
func New(path string) (s *Store, err error) {
|
||||
db, err := shed.NewDB(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -74,7 +70,7 @@ func New(path string, mockStore *mock.NodeStore) (s *Store, err error) {
|
|||
return nil, err
|
||||
}
|
||||
// Index storing actual chunk address, data and store timestamp.
|
||||
retrievalIndex, err := db.NewIndex("Address->StoreTimestamp|Data", shed.IndexFuncs{
|
||||
s.retrievalIndex, err = db.NewIndex("Address->StoreTimestamp|Data", shed.IndexFuncs{
|
||||
EncodeKey: func(fields shed.IndexItem) (key []byte, err error) {
|
||||
return fields.Address, nil
|
||||
},
|
||||
|
|
@ -97,11 +93,6 @@ func New(path string, mockStore *mock.NodeStore) (s *Store, err error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.retrievalIndex = retrievalIndex
|
||||
if mockStore != nil {
|
||||
// If mock store is provided, use it for retrieval index.
|
||||
s.retrievalIndex = retrievalIndex.NewMockIndex(mockStore)
|
||||
}
|
||||
// Index storing access timestamp for a particular address.
|
||||
// It is needed in order to update gc index keys for iteration order.
|
||||
s.accessIndex, err = db.NewIndex("Address->AccessTimestamp", shed.IndexFuncs{
|
||||
|
|
@ -318,20 +309,7 @@ func Example_store() {
|
|||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
var mockStore *mock.NodeStore
|
||||
// Configuring mock store using environment variable is
|
||||
// just an example, it can be accomplished in more elegant ways.
|
||||
if strings.EqualFold(os.Getenv("SWARM_USE_MOCKSTORE"), "true") {
|
||||
// Global store is constructed here for example purposes.
|
||||
// It should be available globally so that all nodes can access it.
|
||||
globalStore := mem.NewGlobalStore()
|
||||
// An arbitrary address is used for this example.
|
||||
// In real situations this address should be the same as the Swarm
|
||||
// node address.
|
||||
mockStore = globalStore.NewNodeStore(common.HexToAddress("12345678"))
|
||||
}
|
||||
|
||||
s, err := New(dir, mockStore)
|
||||
s, err := New(dir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package shed
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/swarm/storage/mock"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
|
|
@ -96,8 +95,23 @@ func (db *DB) NewIndex(name string, funcs IndexFuncs) (f Index, err error) {
|
|||
return Index{
|
||||
db: db,
|
||||
prefix: prefix,
|
||||
encodeKeyFunc: newIndexEncodeKeyFunc(funcs.EncodeKey, id),
|
||||
decodeKeyFunc: newDecodeKeyFunc(funcs.DecodeKey),
|
||||
// This function adjusts Index LevelDB key
|
||||
// by appending the provided index id byte.
|
||||
// This is needed to avoid collisions between keys of different
|
||||
// indexes as all index ids are unique.
|
||||
encodeKeyFunc: func(e IndexItem) (key []byte, err error) {
|
||||
key, err = funcs.EncodeKey(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(append(make([]byte, 0, len(key)+1), prefix...), key...), nil
|
||||
},
|
||||
// This function reverses the encodeKeyFunc constructed key
|
||||
// to transparently work with index keys without their index ids.
|
||||
// It assumes that index keys are prefixed with only one byte.
|
||||
decodeKeyFunc: func(key []byte) (e IndexItem, err error) {
|
||||
return funcs.DecodeKey(key[1:])
|
||||
},
|
||||
encodeValueFunc: funcs.EncodeValue,
|
||||
decodeValueFunc: funcs.DecodeValue,
|
||||
}, nil
|
||||
|
|
@ -242,68 +256,3 @@ func (f Index) IterateFrom(start IndexItem, fn IndexIterFunc) (err error) {
|
|||
}
|
||||
return it.Error()
|
||||
}
|
||||
|
||||
// NewMockIndex is a helper function to easily construct MockIndex
|
||||
// when from the same definition of Index.
|
||||
func (f Index) NewMockIndex(store *mock.NodeStore) (m MockIndex) {
|
||||
return MockIndex{
|
||||
store: store,
|
||||
prefix: f.prefix,
|
||||
encodeKeyFunc: f.encodeKeyFunc,
|
||||
decodeKeyFunc: f.decodeKeyFunc,
|
||||
encodeValueFunc: f.encodeValueFunc,
|
||||
decodeValueFunc: f.decodeValueFunc,
|
||||
}
|
||||
}
|
||||
|
||||
// IndexInterface defines methods that are required for a simple index
|
||||
// that does not use iterations.
|
||||
// It can be used when Index should be swapped with MockIndex or any other
|
||||
// IndexInterface implementation.
|
||||
// In most cases, interface is not needed and it is recommended to use the
|
||||
// Index implementation whenever possible.
|
||||
type IndexInterface interface {
|
||||
Get(keyFields IndexItem) (out IndexItem, err error)
|
||||
Put(i IndexItem) (err error)
|
||||
PutInBatch(batch *leveldb.Batch, i IndexItem) (err error)
|
||||
Delete(keyFields IndexItem) (err error)
|
||||
DeleteInBatch(batch *leveldb.Batch, keyFields IndexItem) (err error)
|
||||
}
|
||||
|
||||
// IndexIteratorInterface defines metods for a full index implementation with
|
||||
// iterators. Index type implements this type.
|
||||
// In most cases, interface is not needed and it is recommended to use the
|
||||
// Index implementation whenever possible.
|
||||
type IndexIteratorInterface interface {
|
||||
IndexInterface
|
||||
IterateAll(fn IndexIterFunc) (err error)
|
||||
IterateFrom(start IndexItem, fn IndexIterFunc) (err error)
|
||||
}
|
||||
|
||||
// newIndexEncodeKeyFunc adjusts Index and MockIndex LevelDB key
|
||||
// by appending the provided index id byte.
|
||||
// This is needed to avoid collisions between keys of different
|
||||
// indexes as all index ids are unique.
|
||||
func newIndexEncodeKeyFunc(
|
||||
encodeKeyFunc func(fields IndexItem) (key []byte, err error),
|
||||
id byte,
|
||||
) (f func(e IndexItem) (key []byte, err error)) {
|
||||
prefix := []byte{id}
|
||||
return func(e IndexItem) (key []byte, err error) {
|
||||
key, err = encodeKeyFunc(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(append(make([]byte, 0, len(key)+1), prefix...), key...), nil
|
||||
}
|
||||
}
|
||||
|
||||
// newDecodeKeyFunc reverses the newIndexEncodeKeyFunc constructd key
|
||||
// to transparently work with index keys without their index ids.
|
||||
// This function is used in NewIndex and NewMockIndex constructors.
|
||||
// It assumes that index keys are prefixed with only one byte.
|
||||
func newDecodeKeyFunc(decodeKeyFunc func(key []byte) (e IndexItem, err error)) (f func(key []byte) (e IndexItem, err error)) {
|
||||
return func(key []byte) (e IndexItem, err error) {
|
||||
return decodeKeyFunc(key[1:])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,113 +0,0 @@
|
|||
// Copyright 2018 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package shed
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/swarm/storage/mock"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
// MockIndex provides a way to inject a mock.NodeStore to store
|
||||
// data centrally instead on provided DB. DB is used just for schema
|
||||
// validation and identifying byte prefix for the particular index
|
||||
// that is mocked.
|
||||
// Iterator functions are not implemented and MockIndex can not replace
|
||||
// indexes that rely on them.
|
||||
// It implements IndexField interface.
|
||||
type MockIndex struct {
|
||||
store *mock.NodeStore
|
||||
prefix []byte
|
||||
encodeKeyFunc func(fields IndexItem) (key []byte, err error)
|
||||
decodeKeyFunc func(key []byte) (e IndexItem, err error)
|
||||
encodeValueFunc func(fields IndexItem) (value []byte, err error)
|
||||
decodeValueFunc func(value []byte) (e IndexItem, err error)
|
||||
}
|
||||
|
||||
// NewMockIndex returns a new MockIndex instance with defined name and
|
||||
// encoding functions. The name must be unique and will be validated
|
||||
// on database schema for a key prefix byte.
|
||||
// The data will not be saved on the DB itself, but using a provided
|
||||
// mock.NodeStore.
|
||||
func (db *DB) NewMockIndex(store *mock.NodeStore, name string, funcs IndexFuncs) (f MockIndex, err error) {
|
||||
id, err := db.schemaIndexPrefix(name)
|
||||
if err != nil {
|
||||
return f, err
|
||||
}
|
||||
return MockIndex{
|
||||
store: store,
|
||||
prefix: []byte{id},
|
||||
encodeKeyFunc: newIndexEncodeKeyFunc(funcs.EncodeKey, id),
|
||||
decodeKeyFunc: newDecodeKeyFunc(funcs.DecodeKey),
|
||||
encodeValueFunc: funcs.EncodeValue,
|
||||
decodeValueFunc: funcs.DecodeValue,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Get accepts key fields represented as IndexItem to retrieve a
|
||||
// value from the index and return maximum available information
|
||||
// from the index represented as another IndexItem.
|
||||
func (f MockIndex) Get(keyFields IndexItem) (out IndexItem, err error) {
|
||||
key, err := f.encodeKeyFunc(keyFields)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
value, err := f.store.Get(key)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
out, err = f.decodeValueFunc(value)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
return out.Join(keyFields), nil
|
||||
}
|
||||
|
||||
// Put accepts IndexItem to encode information from it
|
||||
// and save it to the database.
|
||||
func (f MockIndex) Put(i IndexItem) (err error) {
|
||||
key, err := f.encodeKeyFunc(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
value, err := f.encodeValueFunc(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.store.Put(key, value)
|
||||
}
|
||||
|
||||
// PutInBatch is the same as Put method.
|
||||
// Batch is ignored and the data is saved to the mock store instantly.
|
||||
func (f MockIndex) PutInBatch(_ *leveldb.Batch, i IndexItem) (err error) {
|
||||
return f.Put(i)
|
||||
}
|
||||
|
||||
// Delete accepts IndexItem to remove a key/value pair
|
||||
// form the database based on its fields.
|
||||
func (f MockIndex) Delete(keyFields IndexItem) (err error) {
|
||||
key, err := f.encodeKeyFunc(keyFields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.store.Delete(key)
|
||||
}
|
||||
|
||||
// DeleteInBatch is the same as Delete just the operation.
|
||||
// Batch is ignored and the data is deleted on the mock store instantly.
|
||||
func (f MockIndex) DeleteInBatch(_ *leveldb.Batch, keyFields IndexItem) (err error) {
|
||||
return f.Delete(keyFields)
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright 2018 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package shed
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/ethereum/go-ethereum/swarm/storage/mock/mem"
|
||||
)
|
||||
|
||||
// TestMockIndex validates put, get and delete functions of
|
||||
// the MockIndex implementation.
|
||||
func TestMockIndex(t *testing.T) {
|
||||
db, cleanupFunc := newTestDB(t)
|
||||
defer cleanupFunc()
|
||||
|
||||
globalStore := mem.NewGlobalStore()
|
||||
|
||||
index, err := db.NewMockIndex(
|
||||
globalStore.NewNodeStore(common.HexToAddress("12345678")),
|
||||
"retrieval",
|
||||
retrievalIndexFuncs,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testIndex(t, db, index)
|
||||
}
|
||||
|
|
@ -24,9 +24,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/swarm/storage/mock"
|
||||
"github.com/ethereum/go-ethereum/swarm/storage/mock/mem"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
|
|
@ -62,29 +59,6 @@ func TestIndex(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testIndex(t, db, index)
|
||||
}
|
||||
|
||||
// TestIndex_NewMockIndex validates put, get and delete functions of
|
||||
// the MockIndex implementation, when constructed with Index.NewMockIndex function.
|
||||
func TestIndex_NewMockIndex(t *testing.T) {
|
||||
db, cleanupFunc := newTestDB(t)
|
||||
defer cleanupFunc()
|
||||
|
||||
index, err := db.NewIndex("retrieval", retrievalIndexFuncs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
globalStore := mem.NewGlobalStore()
|
||||
|
||||
mockIndex := index.NewMockIndex(globalStore.NewNodeStore(common.HexToAddress("12345678")))
|
||||
|
||||
testIndex(t, db, mockIndex)
|
||||
}
|
||||
|
||||
// testIndex validates put, get and delete functions of a index interface.
|
||||
func testIndex(t *testing.T, db *DB, index IndexInterface) {
|
||||
t.Run("put", func(t *testing.T) {
|
||||
want := IndexItem{
|
||||
Address: []byte("put-hash"),
|
||||
|
|
@ -196,9 +170,6 @@ func testIndex(t *testing.T, db *DB, index IndexInterface) {
|
|||
}
|
||||
|
||||
wantErr := leveldb.ErrNotFound
|
||||
if _, ok := index.(MockIndex); ok {
|
||||
wantErr = mock.ErrNotFound
|
||||
}
|
||||
got, err = index.Get(IndexItem{
|
||||
Address: want.Address,
|
||||
})
|
||||
|
|
@ -236,9 +207,6 @@ func testIndex(t *testing.T, db *DB, index IndexInterface) {
|
|||
}
|
||||
|
||||
wantErr := leveldb.ErrNotFound
|
||||
if _, ok := index.(MockIndex); ok {
|
||||
wantErr = mock.ErrNotFound
|
||||
}
|
||||
got, err = index.Get(IndexItem{
|
||||
Address: want.Address,
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue