diff --git a/swarm/shed/example_store_test.go b/swarm/shed/example_store_test.go index d1e6aa463b..563a98c899 100644 --- a/swarm/shed/example_store_test.go +++ b/swarm/shed/example_store_test.go @@ -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) } diff --git a/swarm/shed/index.go b/swarm/shed/index.go index 04ed0f19c9..aa23dc9ecc 100644 --- a/swarm/shed/index.go +++ b/swarm/shed/index.go @@ -17,7 +17,6 @@ package shed import ( - "github.com/ethereum/go-ethereum/swarm/storage/mock" "github.com/syndtr/goleveldb/leveldb" ) @@ -94,10 +93,25 @@ func (db *DB) NewIndex(name string, funcs IndexFuncs) (f Index, err error) { } prefix := []byte{id} return Index{ - db: db, - prefix: prefix, - encodeKeyFunc: newIndexEncodeKeyFunc(funcs.EncodeKey, id), - decodeKeyFunc: newDecodeKeyFunc(funcs.DecodeKey), + db: db, + prefix: prefix, + // 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:]) - } -} diff --git a/swarm/shed/index_mock.go b/swarm/shed/index_mock.go deleted file mode 100644 index d9b7187a3d..0000000000 --- a/swarm/shed/index_mock.go +++ /dev/null @@ -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 . - -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) -} diff --git a/swarm/shed/index_mock_test.go b/swarm/shed/index_mock_test.go deleted file mode 100644 index adc9dd068f..0000000000 --- a/swarm/shed/index_mock_test.go +++ /dev/null @@ -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 . - -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) -} diff --git a/swarm/shed/index_test.go b/swarm/shed/index_test.go index a5c81091cc..f36ab7a383 100644 --- a/swarm/shed/index_test.go +++ b/swarm/shed/index_test.go @@ -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, })