mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
swarm/storage/localstore: add mock store option for chunk data
This commit is contained in:
parent
96409ff600
commit
b782bfe464
7 changed files with 197 additions and 100 deletions
|
|
@ -84,7 +84,7 @@ func New(path string) (s *Store, err error) {
|
||||||
value = append(b, fields.Data...)
|
value = append(b, fields.Data...)
|
||||||
return value, nil
|
return value, nil
|
||||||
},
|
},
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
DecodeValue: func(keyItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
||||||
e.Data = value[8:]
|
e.Data = value[8:]
|
||||||
return e, nil
|
return e, nil
|
||||||
|
|
@ -108,7 +108,7 @@ func New(path string) (s *Store, err error) {
|
||||||
binary.BigEndian.PutUint64(b, uint64(fields.AccessTimestamp))
|
binary.BigEndian.PutUint64(b, uint64(fields.AccessTimestamp))
|
||||||
return b, nil
|
return b, nil
|
||||||
},
|
},
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
DecodeValue: func(keyItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
e.AccessTimestamp = int64(binary.BigEndian.Uint64(value))
|
e.AccessTimestamp = int64(binary.BigEndian.Uint64(value))
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
|
|
@ -134,7 +134,7 @@ func New(path string) (s *Store, err error) {
|
||||||
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
DecodeValue: func(keyItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ type Index struct {
|
||||||
encodeKeyFunc func(fields IndexItem) (key []byte, err error)
|
encodeKeyFunc func(fields IndexItem) (key []byte, err error)
|
||||||
decodeKeyFunc func(key []byte) (e IndexItem, err error)
|
decodeKeyFunc func(key []byte) (e IndexItem, err error)
|
||||||
encodeValueFunc func(fields IndexItem) (value []byte, err error)
|
encodeValueFunc func(fields IndexItem) (value []byte, err error)
|
||||||
decodeValueFunc func(value []byte) (e IndexItem, err error)
|
decodeValueFunc func(keyFields IndexItem, value []byte) (e IndexItem, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndexFuncs structure defines functions for encoding and decoding
|
// IndexFuncs structure defines functions for encoding and decoding
|
||||||
|
|
@ -86,7 +86,7 @@ type IndexFuncs struct {
|
||||||
EncodeKey func(fields IndexItem) (key []byte, err error)
|
EncodeKey func(fields IndexItem) (key []byte, err error)
|
||||||
DecodeKey func(key []byte) (e IndexItem, err error)
|
DecodeKey func(key []byte) (e IndexItem, err error)
|
||||||
EncodeValue func(fields IndexItem) (value []byte, err error)
|
EncodeValue func(fields IndexItem) (value []byte, err error)
|
||||||
DecodeValue func(value []byte) (e IndexItem, err error)
|
DecodeValue func(keyFields IndexItem, value []byte) (e IndexItem, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIndex returns a new Index instance with defined name and
|
// NewIndex returns a new Index instance with defined name and
|
||||||
|
|
@ -135,7 +135,7 @@ func (f Index) Get(keyFields IndexItem) (out IndexItem, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
out, err = f.decodeValueFunc(value)
|
out, err = f.decodeValueFunc(keyFields, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
@ -210,15 +210,15 @@ func (f Index) IterateAll(fn IndexIterFunc) (err error) {
|
||||||
if key[0] != f.prefix[0] {
|
if key[0] != f.prefix[0] {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
keyIndexItem, err := f.decodeKeyFunc(key)
|
keyItem, err := f.decodeKeyFunc(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
valueIndexItem, err := f.decodeValueFunc(it.Value())
|
valueItem, err := f.decodeValueFunc(keyItem, it.Value())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stop, err := fn(keyIndexItem.Merge(valueIndexItem))
|
stop, err := fn(keyItem.Merge(valueItem))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -244,15 +244,15 @@ func (f Index) IterateFrom(start IndexItem, fn IndexIterFunc) (err error) {
|
||||||
if key[0] != f.prefix[0] {
|
if key[0] != f.prefix[0] {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
keyIndexItem, err := f.decodeKeyFunc(key)
|
keyItem, err := f.decodeKeyFunc(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
valueIndexItem, err := f.decodeValueFunc(it.Value())
|
valueItem, err := f.decodeValueFunc(keyItem, it.Value())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stop, err := fn(keyIndexItem.Merge(valueIndexItem))
|
stop, err := fn(keyItem.Merge(valueItem))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ var retrievalIndexFuncs = IndexFuncs{
|
||||||
value = append(b, fields.Data...)
|
value = append(b, fields.Data...)
|
||||||
return value, nil
|
return value, nil
|
||||||
},
|
},
|
||||||
DecodeValue: func(value []byte) (e IndexItem, err error) {
|
DecodeValue: func(keyItem IndexItem, value []byte) (e IndexItem, err error) {
|
||||||
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
||||||
e.Data = value[8:]
|
e.Data = value[8:]
|
||||||
return e, nil
|
return e, nil
|
||||||
|
|
|
||||||
|
|
@ -19,30 +19,74 @@ package localstore
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/swarm/storage"
|
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/storage/mock"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/storage/mock/mem"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAccessors tests most basic Put and Get functionalities
|
// TestAccessors tests most basic Put and Get functionalities
|
||||||
// for different accessors.
|
// for different accessors.
|
||||||
func TestAccessors(t *testing.T) {
|
func TestAccessors(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t)
|
db, cleanupFunc := newTestDB(t, nil)
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testAccessors(t, db)
|
testAccessors(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestAccessors_withRetrievalCompositeIndex tests most basic
|
// TestAccessors_useRetrievalCompositeIndex tests most basic
|
||||||
// Put and Get functionalities for different accessors
|
// Put and Get functionalities for different accessors
|
||||||
// by using retrieval composite index.
|
// by using retrieval composite index.
|
||||||
func TestAccessors_withRetrievalCompositeIndex(t *testing.T) {
|
func TestAccessors_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: true})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testAccessors(t, db)
|
testAccessors(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestAccessors_mockStore tests most basic Put and Get
|
||||||
|
// functionalities for different accessors with the mock store
|
||||||
|
// as the storage for chunk data.
|
||||||
|
func TestAccessors_mockStore(t *testing.T) {
|
||||||
|
globalStore := mem.NewGlobalStore()
|
||||||
|
|
||||||
|
addr := common.BytesToAddress(make([]byte, 32))
|
||||||
|
|
||||||
|
db, cleanupFunc := newTestDB(t, &Options{
|
||||||
|
MockStore: globalStore.NewNodeStore(addr),
|
||||||
|
})
|
||||||
|
defer cleanupFunc()
|
||||||
|
|
||||||
|
testAccessors(t, db)
|
||||||
|
|
||||||
|
// testAccessors leaves 5 chunks in global store
|
||||||
|
checkGlobalStoreChunkCount(t, globalStore, 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAccessors_mockStore_useRetrievalCompositeIndex tests
|
||||||
|
// most basic Put and Get functionalities for different accessors
|
||||||
|
// with the mock store as the storage for chunk data and by using
|
||||||
|
// retrieval composite index.
|
||||||
|
func TestAccessors_mockStore_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
|
globalStore := mem.NewGlobalStore()
|
||||||
|
|
||||||
|
addr := common.BytesToAddress(make([]byte, 32))
|
||||||
|
|
||||||
|
db, cleanupFunc := newTestDB(t, &Options{
|
||||||
|
MockStore: globalStore.NewNodeStore(addr),
|
||||||
|
UseRetrievalCompositeIndex: true,
|
||||||
|
})
|
||||||
|
defer cleanupFunc()
|
||||||
|
|
||||||
|
testAccessors(t, db)
|
||||||
|
|
||||||
|
// testAccessors leaves 5 chunks in global store
|
||||||
|
checkGlobalStoreChunkCount(t, globalStore, 5)
|
||||||
|
}
|
||||||
|
|
||||||
// testAccessors tests most basic Put and Get functionalities
|
// testAccessors tests most basic Put and Get functionalities
|
||||||
// for different accessors. This test validates that the chunk
|
// for different accessors. This test validates that the chunk
|
||||||
// is retrievable from the database, not if all indexes are set
|
// is retrievable from the database, not if all indexes are set
|
||||||
|
|
@ -153,3 +197,17 @@ func testAccessors(t *testing.T, db *DB) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkGlobalStoreChunkCount counts the number of chunks
|
||||||
|
// in a global mock store to validate it against the expected value.
|
||||||
|
func checkGlobalStoreChunkCount(t *testing.T, s mock.ImportExporter, want int) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
n, err := s.Export(ioutil.Discard)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n != want {
|
||||||
|
t.Errorf("got %v chunks, want %v", n, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/swarm/shed"
|
"github.com/ethereum/go-ethereum/swarm/shed"
|
||||||
"github.com/ethereum/go-ethereum/swarm/storage"
|
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/storage/mock"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -73,36 +74,26 @@ type DB struct {
|
||||||
close chan struct{} // closed on Close, signals other goroutines to terminate
|
close chan struct{} // closed on Close, signals other goroutines to terminate
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option is a function that sets optional field values on DB.
|
// Options struct holds optional parameters for configuring DB.
|
||||||
// It is used as a variadic parameter to New constructor.
|
type Options struct {
|
||||||
type Option func(*DB)
|
UseRetrievalCompositeIndex bool
|
||||||
|
MockStore *mock.NodeStore
|
||||||
// WithRetrievalCompositeIndex is the optional variadic parameter to New constructor
|
|
||||||
// to use the single retrieval composite index instead two separate for data
|
|
||||||
// and access timestamp. This option is used for benchmarking this two types of
|
|
||||||
// retrieval schemas for performance. Composite retrieval index performes less seeks
|
|
||||||
// on retrieval as it has two times less key/value pairs then alternative approach,
|
|
||||||
// but it needs to write chunk data on every access timestamp change.
|
|
||||||
func WithRetrievalCompositeIndex(use bool) Option {
|
|
||||||
return func(db *DB) {
|
|
||||||
db.useRetrievalCompositeIndex = use
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new DB. All fields and indexes are initialized
|
// New returns a new DB. All fields and indexes are initialized
|
||||||
// and possible conflicts with schema from existing database is checked.
|
// and possible conflicts with schema from existing database is checked.
|
||||||
// One goroutine for writing batches is created.
|
// One goroutine for writing batches is created.
|
||||||
func New(path string, baseKey []byte, opts ...Option) (db *DB, err error) {
|
func New(path string, baseKey []byte, o *Options) (db *DB, err error) {
|
||||||
db = &DB{
|
if o == nil {
|
||||||
baseKey: baseKey,
|
o = new(Options)
|
||||||
batch: newBatch(),
|
|
||||||
writeTrigger: make(chan struct{}, 1),
|
|
||||||
close: make(chan struct{}),
|
|
||||||
writeDone: make(chan struct{}),
|
|
||||||
}
|
}
|
||||||
|
db = &DB{
|
||||||
for _, o := range opts {
|
baseKey: baseKey,
|
||||||
o(db)
|
useRetrievalCompositeIndex: o.UseRetrievalCompositeIndex,
|
||||||
|
batch: newBatch(),
|
||||||
|
writeTrigger: make(chan struct{}, 1),
|
||||||
|
close: make(chan struct{}),
|
||||||
|
writeDone: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
db.shed, err = shed.NewDB(path)
|
db.shed, err = shed.NewDB(path)
|
||||||
|
|
@ -119,6 +110,42 @@ func New(path string, baseKey []byte, opts ...Option) (db *DB, err error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if db.useRetrievalCompositeIndex {
|
if db.useRetrievalCompositeIndex {
|
||||||
|
var (
|
||||||
|
encodeValueFunc func(fields shed.IndexItem) (value []byte, err error)
|
||||||
|
decodeValueFunc func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error)
|
||||||
|
)
|
||||||
|
if o.MockStore != nil {
|
||||||
|
encodeValueFunc = func(fields shed.IndexItem) (value []byte, err error) {
|
||||||
|
b := make([]byte, 16)
|
||||||
|
binary.BigEndian.PutUint64(b[:8], uint64(fields.StoreTimestamp))
|
||||||
|
binary.BigEndian.PutUint64(b[8:16], uint64(fields.AccessTimestamp))
|
||||||
|
err = o.MockStore.Put(fields.Address, fields.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
decodeValueFunc = func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
|
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
||||||
|
e.AccessTimestamp = int64(binary.BigEndian.Uint64(value[8:16]))
|
||||||
|
e.Data, err = o.MockStore.Get(keyIndexItem.Address)
|
||||||
|
return e, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
encodeValueFunc = func(fields shed.IndexItem) (value []byte, err error) {
|
||||||
|
b := make([]byte, 16)
|
||||||
|
binary.BigEndian.PutUint64(b[:8], uint64(fields.StoreTimestamp))
|
||||||
|
binary.BigEndian.PutUint64(b[8:16], uint64(fields.AccessTimestamp))
|
||||||
|
value = append(b, fields.Data...)
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
decodeValueFunc = func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
|
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
||||||
|
e.AccessTimestamp = int64(binary.BigEndian.Uint64(value[8:16]))
|
||||||
|
e.Data = value[16:]
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
// Index storing chunk data with stored and access timestamps.
|
// Index storing chunk data with stored and access timestamps.
|
||||||
db.retrievalCompositeIndex, err = db.shed.NewIndex("Hash->StoredTimestamp|AccessTimestamp|Data", shed.IndexFuncs{
|
db.retrievalCompositeIndex, err = db.shed.NewIndex("Hash->StoredTimestamp|AccessTimestamp|Data", shed.IndexFuncs{
|
||||||
EncodeKey: func(fields shed.IndexItem) (key []byte, err error) {
|
EncodeKey: func(fields shed.IndexItem) (key []byte, err error) {
|
||||||
|
|
@ -128,24 +155,45 @@ func New(path string, baseKey []byte, opts ...Option) (db *DB, err error) {
|
||||||
e.Address = key
|
e.Address = key
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
EncodeValue: encodeValueFunc,
|
||||||
b := make([]byte, 16)
|
DecodeValue: decodeValueFunc,
|
||||||
binary.BigEndian.PutUint64(b[:8], uint64(fields.StoreTimestamp))
|
|
||||||
binary.BigEndian.PutUint64(b[8:16], uint64(fields.AccessTimestamp))
|
|
||||||
value = append(b, fields.Data...)
|
|
||||||
return value, nil
|
|
||||||
},
|
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
|
||||||
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
|
||||||
e.AccessTimestamp = int64(binary.BigEndian.Uint64(value[8:16]))
|
|
||||||
e.Data = value[16:]
|
|
||||||
return e, nil
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
var (
|
||||||
|
encodeValueFunc func(fields shed.IndexItem) (value []byte, err error)
|
||||||
|
decodeValueFunc func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error)
|
||||||
|
)
|
||||||
|
if o.MockStore != nil {
|
||||||
|
encodeValueFunc = func(fields shed.IndexItem) (value []byte, err error) {
|
||||||
|
b := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(b, uint64(fields.StoreTimestamp))
|
||||||
|
err = o.MockStore.Put(fields.Address, fields.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
decodeValueFunc = func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
|
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
||||||
|
e.Data, err = o.MockStore.Get(keyIndexItem.Address)
|
||||||
|
return e, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
encodeValueFunc = func(fields shed.IndexItem) (value []byte, err error) {
|
||||||
|
b := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(b, uint64(fields.StoreTimestamp))
|
||||||
|
value = append(b, fields.Data...)
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
decodeValueFunc = func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
|
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
||||||
|
e.Data = value[8:]
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
// Index storing actual chunk address, data and store timestamp.
|
// Index storing actual chunk address, data and store timestamp.
|
||||||
db.retrievalDataIndex, err = db.shed.NewIndex("Address->StoreTimestamp|Data", shed.IndexFuncs{
|
db.retrievalDataIndex, err = db.shed.NewIndex("Address->StoreTimestamp|Data", shed.IndexFuncs{
|
||||||
EncodeKey: func(fields shed.IndexItem) (key []byte, err error) {
|
EncodeKey: func(fields shed.IndexItem) (key []byte, err error) {
|
||||||
|
|
@ -155,17 +203,8 @@ func New(path string, baseKey []byte, opts ...Option) (db *DB, err error) {
|
||||||
e.Address = key
|
e.Address = key
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
EncodeValue: encodeValueFunc,
|
||||||
b := make([]byte, 8)
|
DecodeValue: decodeValueFunc,
|
||||||
binary.BigEndian.PutUint64(b, uint64(fields.StoreTimestamp))
|
|
||||||
value = append(b, fields.Data...)
|
|
||||||
return value, nil
|
|
||||||
},
|
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
|
||||||
e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8]))
|
|
||||||
e.Data = value[8:]
|
|
||||||
return e, nil
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -185,7 +224,7 @@ func New(path string, baseKey []byte, opts ...Option) (db *DB, err error) {
|
||||||
binary.BigEndian.PutUint64(b, uint64(fields.AccessTimestamp))
|
binary.BigEndian.PutUint64(b, uint64(fields.AccessTimestamp))
|
||||||
return b, nil
|
return b, nil
|
||||||
},
|
},
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
DecodeValue: func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
e.AccessTimestamp = int64(binary.BigEndian.Uint64(value))
|
e.AccessTimestamp = int64(binary.BigEndian.Uint64(value))
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
|
|
@ -211,7 +250,7 @@ func New(path string, baseKey []byte, opts ...Option) (db *DB, err error) {
|
||||||
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
DecodeValue: func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -234,7 +273,7 @@ func New(path string, baseKey []byte, opts ...Option) (db *DB, err error) {
|
||||||
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
DecodeValue: func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -259,7 +298,7 @@ func New(path string, baseKey []byte, opts ...Option) (db *DB, err error) {
|
||||||
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
EncodeValue: func(fields shed.IndexItem) (value []byte, err error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
DecodeValue: func(value []byte) (e shed.IndexItem, err error) {
|
DecodeValue: func(keyIndexItem shed.IndexItem, value []byte) (e shed.IndexItem, err error) {
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/swarm/storage"
|
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestWithRetrievalCompositeIndex checks if optional argument
|
// TestDB_useRetrievalCompositeIndex checks if optional argument
|
||||||
// WithRetrievalCompositeIndex to New constructor is setting the
|
// WithRetrievalCompositeIndex to New constructor is setting the
|
||||||
// correct state.
|
// correct state.
|
||||||
func TestWithRetrievalCompositeIndex(t *testing.T) {
|
func TestDB_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
t.Run("set true", func(t *testing.T) {
|
t.Run("set true", func(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: true})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
if !db.useRetrievalCompositeIndex {
|
if !db.useRetrievalCompositeIndex {
|
||||||
|
|
@ -39,7 +39,7 @@ func TestWithRetrievalCompositeIndex(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("set false", func(t *testing.T) {
|
t.Run("set false", func(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(false))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: false})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
if db.useRetrievalCompositeIndex {
|
if db.useRetrievalCompositeIndex {
|
||||||
|
|
@ -47,7 +47,7 @@ func TestWithRetrievalCompositeIndex(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("unset", func(t *testing.T) {
|
t.Run("unset", func(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t)
|
db, cleanupFunc := newTestDB(t, nil)
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
if db.useRetrievalCompositeIndex {
|
if db.useRetrievalCompositeIndex {
|
||||||
|
|
@ -59,7 +59,7 @@ func TestWithRetrievalCompositeIndex(t *testing.T) {
|
||||||
// newTestDB is a helper function that constructs a
|
// newTestDB is a helper function that constructs a
|
||||||
// temporary database and returns a cleanup function that must
|
// temporary database and returns a cleanup function that must
|
||||||
// be called to remove the data.
|
// be called to remove the data.
|
||||||
func newTestDB(t *testing.T, opts ...Option) (db *DB, cleanupFunc func()) {
|
func newTestDB(t *testing.T, o *Options) (db *DB, cleanupFunc func()) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
dir, err := ioutil.TempDir("", "shed-test")
|
dir, err := ioutil.TempDir("", "shed-test")
|
||||||
|
|
@ -71,7 +71,7 @@ func newTestDB(t *testing.T, opts ...Option) (db *DB, cleanupFunc func()) {
|
||||||
if _, err := rand.Read(baseKey); err != nil {
|
if _, err := rand.Read(baseKey); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
db, err = New(dir, baseKey, opts...)
|
db, err = New(dir, baseKey, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanupFunc()
|
cleanupFunc()
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -31,17 +31,17 @@ import (
|
||||||
// TestModeSyncing validates internal data operations and state
|
// TestModeSyncing validates internal data operations and state
|
||||||
// for ModeSyncing on DB with default configuration.
|
// for ModeSyncing on DB with default configuration.
|
||||||
func TestModeSyncing(t *testing.T) {
|
func TestModeSyncing(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t)
|
db, cleanupFunc := newTestDB(t, nil)
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeSyncingValues(t, db)
|
testModeSyncingValues(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestModeSyncing_withRetrievalCompositeIndex validates internal
|
// TestModeSyncing_useRetrievalCompositeIndex validates internal
|
||||||
// data operations and state for ModeSyncing on DB with
|
// data operations and state for ModeSyncing on DB with
|
||||||
// retrieval composite index enabled.
|
// retrieval composite index enabled.
|
||||||
func TestModeSyncing_withRetrievalCompositeIndex(t *testing.T) {
|
func TestModeSyncing_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: true})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeSyncingValues(t, db)
|
testModeSyncingValues(t, db)
|
||||||
|
|
@ -81,17 +81,17 @@ func testModeSyncingValues(t *testing.T, db *DB) {
|
||||||
// TestModeUpload validates internal data operations and state
|
// TestModeUpload validates internal data operations and state
|
||||||
// for ModeUpload on DB with default configuration.
|
// for ModeUpload on DB with default configuration.
|
||||||
func TestModeUpload(t *testing.T) {
|
func TestModeUpload(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t)
|
db, cleanupFunc := newTestDB(t, nil)
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeUploadValues(t, db)
|
testModeUploadValues(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestModeUpload_withRetrievalCompositeIndex validates internal
|
// TestModeUpload_useRetrievalCompositeIndex validates internal
|
||||||
// data operations and state for ModeUpload on DB with
|
// data operations and state for ModeUpload on DB with
|
||||||
// retrieval composite index enabled.
|
// retrieval composite index enabled.
|
||||||
func TestModeUpload_withRetrievalCompositeIndex(t *testing.T) {
|
func TestModeUpload_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: true})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeUploadValues(t, db)
|
testModeUploadValues(t, db)
|
||||||
|
|
@ -133,17 +133,17 @@ func testModeUploadValues(t *testing.T, db *DB) {
|
||||||
// TestModeRequest validates internal data operations and state
|
// TestModeRequest validates internal data operations and state
|
||||||
// for ModeRequest on DB with default configuration.
|
// for ModeRequest on DB with default configuration.
|
||||||
func TestModeRequest(t *testing.T) {
|
func TestModeRequest(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t)
|
db, cleanupFunc := newTestDB(t, nil)
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeRequestValues(t, db)
|
testModeRequestValues(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestModeRequest_withRetrievalCompositeIndex validates internal
|
// TestModeRequest_useRetrievalCompositeIndex validates internal
|
||||||
// data operations and state for ModeRequest on DB with
|
// data operations and state for ModeRequest on DB with
|
||||||
// retrieval composite index enabled.
|
// retrieval composite index enabled.
|
||||||
func TestModeRequest_withRetrievalCompositeIndex(t *testing.T) {
|
func TestModeRequest_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: true})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeRequestValues(t, db)
|
testModeRequestValues(t, db)
|
||||||
|
|
@ -174,17 +174,17 @@ func testModeRequestValues(t *testing.T, db *DB) {
|
||||||
// TestModeSynced validates internal data operations and state
|
// TestModeSynced validates internal data operations and state
|
||||||
// for ModeSynced on DB with default configuration.
|
// for ModeSynced on DB with default configuration.
|
||||||
func TestModeSynced(t *testing.T) {
|
func TestModeSynced(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t)
|
db, cleanupFunc := newTestDB(t, nil)
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeSyncedValues(t, db)
|
testModeSyncedValues(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestModeSynced_withRetrievalCompositeIndex validates internal
|
// TestModeSynced_useRetrievalCompositeIndex validates internal
|
||||||
// data operations and state for ModeSynced on DB with
|
// data operations and state for ModeSynced on DB with
|
||||||
// retrieval composite index enabled.
|
// retrieval composite index enabled.
|
||||||
func TestModeSynced_withRetrievalCompositeIndex(t *testing.T) {
|
func TestModeSynced_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: true})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeSyncedValues(t, db)
|
testModeSyncedValues(t, db)
|
||||||
|
|
@ -224,17 +224,17 @@ func testModeSyncedValues(t *testing.T, db *DB) {
|
||||||
// TestModeAccess validates internal data operations and state
|
// TestModeAccess validates internal data operations and state
|
||||||
// for ModeAccess on DB with default configuration.
|
// for ModeAccess on DB with default configuration.
|
||||||
func TestModeAccess(t *testing.T) {
|
func TestModeAccess(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t)
|
db, cleanupFunc := newTestDB(t, nil)
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeAccessValues(t, db)
|
testModeAccessValues(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestModeAccess_withRetrievalCompositeIndex validates internal
|
// TestModeAccess_useRetrievalCompositeIndex validates internal
|
||||||
// data operations and state for ModeAccess on DB with
|
// data operations and state for ModeAccess on DB with
|
||||||
// retrieval composite index enabled.
|
// retrieval composite index enabled.
|
||||||
func TestModeAccess_withRetrievalCompositeIndex(t *testing.T) {
|
func TestModeAccess_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: true})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeAccessValues(t, db)
|
testModeAccessValues(t, db)
|
||||||
|
|
@ -310,17 +310,17 @@ func testModeAccessValues(t *testing.T, db *DB) {
|
||||||
// TestModeRemoval validates internal data operations and state
|
// TestModeRemoval validates internal data operations and state
|
||||||
// for ModeRemoval on DB with default configuration.
|
// for ModeRemoval on DB with default configuration.
|
||||||
func TestModeRemoval(t *testing.T) {
|
func TestModeRemoval(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t)
|
db, cleanupFunc := newTestDB(t, nil)
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeRemovalValues(t, db)
|
testModeRemovalValues(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestModeRemoval_withRetrievalCompositeIndex validates internal
|
// TestModeRemoval_useRetrievalCompositeIndex validates internal
|
||||||
// data operations and state for ModeRemoval on DB with
|
// data operations and state for ModeRemoval on DB with
|
||||||
// retrieval composite index enabled.
|
// retrieval composite index enabled.
|
||||||
func TestModeRemoval_withRetrievalCompositeIndex(t *testing.T) {
|
func TestModeRemoval_useRetrievalCompositeIndex(t *testing.T) {
|
||||||
db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true))
|
db, cleanupFunc := newTestDB(t, &Options{UseRetrievalCompositeIndex: true})
|
||||||
defer cleanupFunc()
|
defer cleanupFunc()
|
||||||
|
|
||||||
testModeRemovalValues(t, db)
|
testModeRemovalValues(t, db)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue