swarm/storage: replace DbStore mock store data functions

This commit is contained in:
Janos Guljas 2018-01-16 16:41:54 +01:00
parent 44e942ece5
commit 4e6ffd64f5

View file

@ -77,13 +77,14 @@ type DbStore struct {
lock sync.Mutex lock sync.Mutex
// Functions putDataFunc and getFunc are used for // Functions encodeDataFunc is used to bypass
// saving and retreiving chunk data from the store. // the default functionality of DbStore with
// They must be set on DbStore initialization and must not be nil.
// They are used to bypass the default functionality of DbStore with
// mock.NodeStore for testing purposes. // mock.NodeStore for testing purposes.
putDataFunc func(batch *leveldb.Batch, _ Key, data []byte) encodeDataFunc func(chunk *Chunk) []byte
getFunc func(key Key) (chunk *Chunk, err error) // If getDataFunc is defined, it will be used for
// retrieving the chunk data instead from the local
// LevelDB database.
getDataFunc func(key Key) (data []byte, err error)
} }
func NewDbStore(path string, hash SwarmHasher, capacity uint64, radius int) (s *DbStore, err error) { func NewDbStore(path string, hash SwarmHasher, capacity uint64, radius int) (s *DbStore, err error) {
@ -91,9 +92,8 @@ func NewDbStore(path string, hash SwarmHasher, capacity uint64, radius int) (s *
s.hashfunc = hash s.hashfunc = hash
// associate put and get with default functionality // associate encodeData with default functionality
s.putDataFunc = s.dbPutDataFunc s.encodeDataFunc = encodeData
s.getFunc = s.dbGetFunc
s.db, err = NewLDBDatabase(path) s.db, err = NewLDBDatabase(path)
if err != nil { if err != nil {
@ -129,8 +129,8 @@ func NewMockDbStore(path string, hash SwarmHasher, capacity uint64, radius int,
} }
// replace put and get with mock store functionality // replace put and get with mock store functionality
if mockStore != nil { if mockStore != nil {
s.putDataFunc = newMockPutDataFunc(mockStore) s.encodeDataFunc = newMockEncodeDataFunc(mockStore)
s.getFunc = newMockGetFunc(mockStore) s.getDataFunc = newMockGetDataFunc(mockStore)
} }
return return
} }
@ -438,7 +438,7 @@ func (s *DbStore) Put(chunk *Chunk) {
return // already exists, only update access return // already exists, only update access
} }
data := encodeData(chunk) data := s.encodeDataFunc(chunk)
//data := ethutil.Encode([]interface{}{entry}) //data := ethutil.Encode([]interface{}{entry})
if s.entryCnt >= s.capacity { if s.entryCnt >= s.capacity {
@ -447,7 +447,7 @@ func (s *DbStore) Put(chunk *Chunk) {
batch := new(leveldb.Batch) batch := new(leveldb.Batch)
s.putDataFunc(batch, chunk.Key, data) batch.Put(getDataKey(s.dataIdx), data)
index.Idx = s.dataIdx index.Idx = s.dataIdx
s.updateIndexAccess(&index) s.updateIndexAccess(&index)
@ -469,17 +469,16 @@ func (s *DbStore) Put(chunk *Chunk) {
log.Trace(fmt.Sprintf("DbStore.Put: %v. db storage counter: %v ", chunk.Key.Log(), s.dataIdx)) log.Trace(fmt.Sprintf("DbStore.Put: %v. db storage counter: %v ", chunk.Key.Log(), s.dataIdx))
} }
func (s *DbStore) dbPutDataFunc(batch *leveldb.Batch, _ Key, data []byte) { // newMockEncodeDataFunc returns a function that stores the chunk data
batch.Put(getDataKey(s.dataIdx), data) // to a mock store to bypass the default functionality encodeData.
} // The constructed function always returns the nil data, as DbStore does
// not need to store the data, but still need to create the index.
// newMockPutDataFunc returns a function that stores the chunk data func newMockEncodeDataFunc(mockStore *mock.NodeStore) func(chunk *Chunk) []byte {
// to a mock store to bypass the default functionality of DbStore. return func(chunk *Chunk) []byte {
func newMockPutDataFunc(mockStore *mock.NodeStore) func(_ *leveldb.Batch, key Key, data []byte) { if err := mockStore.Put(chunk.Key, chunk.SData); err != nil {
return func(_ *leveldb.Batch, key Key, data []byte) { log.Error(fmt.Sprintf("%T: Chunk %v put: %v", mockStore, chunk.Key.Log(), err))
if err := mockStore.Put(key, data); err != nil {
log.Error(fmt.Sprintf("%T: Chunk %v put: %v", mockStore, key.Log(), err))
} }
return nil
} }
} }
@ -505,12 +504,6 @@ func (s *DbStore) tryAccessIdx(ikey []byte, index *dpaDBIndex) bool {
} }
func (s *DbStore) Get(key Key) (chunk *Chunk, err error) { func (s *DbStore) Get(key Key) (chunk *Chunk, err error) {
return s.getFunc(key)
}
// dbGetFunc provides the default functionality for accessing
// the chunk data from LevelDB.
func (s *DbStore) dbGetFunc(key Key) (chunk *Chunk, err error) {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
@ -518,11 +511,20 @@ func (s *DbStore) dbGetFunc(key Key) (chunk *Chunk, err error) {
if s.tryAccessIdx(getIndexKey(key), &index) { if s.tryAccessIdx(getIndexKey(key), &index) {
var data []byte var data []byte
data, err = s.db.Get(getDataKey(index.Idx)) if s.getDataFunc != nil {
if err != nil { // if getDataFunc is defined, use it to retrieve the chunk data
log.Trace(fmt.Sprintf("DBStore: Chunk %v found but could not be accessed: %v", key.Log(), err)) data, err = s.getDataFunc(key)
s.delete(index.Idx, getIndexKey(key)) if err != nil {
return return
}
} else {
// default DbStore functionality to retrieve chunk data
data, err = s.db.Get(getDataKey(index.Idx))
if err != nil {
log.Trace(fmt.Sprintf("DBStore: Chunk %v found but could not be accessed: %v", key.Log(), err))
s.delete(index.Idx, getIndexKey(key))
return
}
} }
if s.hashfunc != nil { if s.hashfunc != nil {
@ -539,32 +541,25 @@ func (s *DbStore) dbGetFunc(key Key) (chunk *Chunk, err error) {
Key: key, Key: key,
} }
decodeData(data, chunk) decodeData(data, chunk)
} else { } else {
err = notFound err = notFound
} }
return return
} }
// newMockGetFunc returns a function that reads chunk data from // newMockGetFunc returns a function that reads chunk data from
// the mock database, which is used as the value for DbStore.getFunc // the mock database, which is used as the value for DbStore.getFunc
// to bypass the default functionality of DbStore with a mock store. // to bypass the default functionality of DbStore with a mock store.
func newMockGetFunc(mockStore *mock.NodeStore) func(key Key) (chunk *Chunk, err error) { func newMockGetDataFunc(mockStore *mock.NodeStore) func(key Key) (data []byte, err error) {
return func(key Key) (chunk *Chunk, err error) { return func(key Key) (data []byte, err error) {
data, err := mockStore.Get(key) data, err = mockStore.Get(key)
if err != nil { if err == mock.ErrNotFound {
if err == mock.ErrNotFound { // preserve notFound error
// preserve notFound error err = notFound
err = notFound
}
return nil, err
} }
chunk = &Chunk{ return data, err
Key: key,
}
decodeData(data, chunk)
return chunk, nil
} }
} }