diff --git a/swarm/storage/localstore/accessor_test.go b/swarm/storage/localstore/accessor_test.go index 1c847b7529..f09eb82ee1 100644 --- a/swarm/storage/localstore/accessor_test.go +++ b/swarm/storage/localstore/accessor_test.go @@ -52,7 +52,6 @@ func testAccessors(t *testing.T, db *DB) { ModeSyncing, ModeUpload, ModeRequest, - ModeSynced, modeAccess, } { t.Run(ModeName(m), func(t *testing.T) { @@ -75,6 +74,25 @@ func testAccessors(t *testing.T, db *DB) { }) } + // Synced mode does not put the item to retrieval index. + t.Run(ModeName(ModeSynced), func(t *testing.T) { + a := db.Accessor(ModeSynced) + + chunk := generateRandomChunk() + + // first put a random chunk to the database + err := a.Put(context.Background(), chunk) + if err != nil { + t.Fatal(err) + } + + wantError := storage.ErrChunkNotFound + _, err = a.Get(context.Background(), chunk.Address()) + if err != wantError { + t.Errorf("got error %v, want %v", err, wantError) + } + }) + // Removal mode is a special case as it removes the chunk // from the database. t.Run(ModeName(modeRemoval), func(t *testing.T) { diff --git a/swarm/storage/localstore/mode.go b/swarm/storage/localstore/mode.go index 32b622762a..d914a8c4ed 100644 --- a/swarm/storage/localstore/mode.go +++ b/swarm/storage/localstore/mode.go @@ -181,9 +181,25 @@ func (db *DB) updateBatch(b *batch, mode Mode, item shed.IndexItem) (err error) // delete from push, insert to gc item.StoreTimestamp = now() if db.useRetrievalCompositeIndex { - db.retrievalCompositeIndex.PutInBatch(b.Batch, item) + i, err := db.retrievalCompositeIndex.Get(item) + switch err { + case nil: + item.AccessTimestamp = i.AccessTimestamp + case leveldb.ErrNotFound: + item.AccessTimestamp = now() + default: + return err + } } else { - db.retrievalDataIndex.PutInBatch(b.Batch, item) + i, err := db.retrievalAccessIndex.Get(item) + switch err { + case nil: + item.AccessTimestamp = i.AccessTimestamp + case leveldb.ErrNotFound: + item.AccessTimestamp = now() + default: + return err + } } db.pushIndex.DeleteInBatch(b.Batch, item) db.gcIndex.PutInBatch(b.Batch, item) diff --git a/swarm/storage/localstore/mode_test.go b/swarm/storage/localstore/mode_test.go index 75a48397e0..8d72f829a6 100644 --- a/swarm/storage/localstore/mode_test.go +++ b/swarm/storage/localstore/mode_test.go @@ -158,19 +158,61 @@ func testModeRequestValues(t *testing.T, db *DB) { return wantTimestamp } - wantSize, err := db.sizeCounter.Get() + err := a.Put(context.Background(), chunk) if err != nil { t.Fatal(err) } + t.Run("retrieve indexes", testRetrieveIndexesValuesWithAccess(db, chunk, wantTimestamp, wantTimestamp)) + + t.Run("gc index", testGCIndexValues(db, chunk, wantTimestamp, wantTimestamp)) +} + +// TestModeSynced validates internal data operations and state +// for ModeSynced on DB with default configuration. +func TestModeSynced(t *testing.T) { + db, cleanupFunc := newTestDB(t) + defer cleanupFunc() + + testModeSyncedValues(t, db) +} + +// TestModeSynced_withRetrievalCompositeIndex validates internal +// data operations and state for ModeSynced on DB with +// retrieval composite index enabled. +func TestModeSynced_withRetrievalCompositeIndex(t *testing.T) { + db, cleanupFunc := newTestDB(t, WithRetrievalCompositeIndex(true)) + defer cleanupFunc() + + testModeSyncedValues(t, db) +} + +// testModeSyncedValues validates ModeSynced on the provided DB. +func testModeSyncedValues(t *testing.T, db *DB) { + a := db.Accessor(ModeSyncing) + + chunk := generateRandomChunk() + + wantTimestamp := time.Now().UTC().UnixNano() + now = func() (t int64) { + return wantTimestamp + } + + err := a.Put(context.Background(), chunk) + if err != nil { + t.Fatal(err) + } + + a = db.Accessor(ModeSynced) + err = a.Put(context.Background(), chunk) if err != nil { t.Fatal(err) } - wantSize++ + t.Run("retrieve indexes", testRetrieveIndexesValues(db, chunk, wantTimestamp, wantTimestamp)) - t.Run("retrieve indexes", testRetrieveIndexesValuesWithAccess(db, chunk, wantTimestamp, wantTimestamp)) + t.Run("push index", testPushIndexValues(db, chunk, wantTimestamp, leveldb.ErrNotFound)) t.Run("gc index", testGCIndexValues(db, chunk, wantTimestamp, wantTimestamp)) } @@ -246,16 +288,18 @@ func testPullIndexValues(db *DB, chunk storage.Chunk, storeTimestamp int64) func // testPushIndexValues returns a test function that validates if the right // chunk values are in the push index. -func testPushIndexValues(db *DB, chunk storage.Chunk, storeTimestamp int64) func(t *testing.T) { +func testPushIndexValues(db *DB, chunk storage.Chunk, storeTimestamp int64, wantError error) func(t *testing.T) { return func(t *testing.T) { item, err := db.pushIndex.Get(shed.IndexItem{ Address: chunk.Address(), StoreTimestamp: storeTimestamp, }) - if err != nil { - t.Fatal(err) + if err != wantError { + t.Errorf("got error %v, want %v", err, wantError) + } + if err == nil { + validateItem(t, item, chunk.Address(), nil, storeTimestamp, 0) } - validateItem(t, item, chunk.Address(), nil, storeTimestamp, 0) } }