2020-04-20 21:29:18 +01:00
|
|
|
// Copyright (C) 2020 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package pieces_test
|
|
|
|
|
|
|
|
import (
|
2020-04-24 00:09:15 +01:00
|
|
|
"context"
|
2020-04-20 21:29:18 +01:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.uber.org/zap/zaptest"
|
|
|
|
|
|
|
|
"storj.io/common/memory"
|
|
|
|
"storj.io/common/pb"
|
2020-04-24 00:09:15 +01:00
|
|
|
"storj.io/common/storj"
|
2020-04-20 21:29:18 +01:00
|
|
|
"storj.io/common/testcontext"
|
|
|
|
"storj.io/common/testrand"
|
2021-04-01 15:10:08 +01:00
|
|
|
"storj.io/storj/storagenode"
|
2023-04-05 18:03:06 +01:00
|
|
|
"storj.io/storj/storagenode/blobstore/filestore"
|
2020-04-20 21:29:18 +01:00
|
|
|
"storj.io/storj/storagenode/pieces"
|
2021-04-01 15:10:08 +01:00
|
|
|
"storj.io/storj/storagenode/storagenodedb/storagenodedbtest"
|
2020-04-20 21:29:18 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestDeleter(t *testing.T) {
|
2021-04-01 15:10:08 +01:00
|
|
|
cases := []struct {
|
|
|
|
testID string
|
|
|
|
deleteToTrash bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
testID: "regular-delete",
|
|
|
|
deleteToTrash: false,
|
|
|
|
}, {
|
|
|
|
testID: "trash-delete",
|
|
|
|
deleteToTrash: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
|
|
|
testCase := c
|
|
|
|
t.Run(testCase.testID, func(t *testing.T) {
|
|
|
|
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
|
2023-03-01 03:59:53 +00:00
|
|
|
log := zaptest.NewLogger(t)
|
|
|
|
dir, err := filestore.NewDir(log, ctx.Dir("piecedeleter"))
|
2021-04-01 15:10:08 +01:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-03-01 03:59:53 +00:00
|
|
|
blobs := filestore.New(log, dir, filestore.DefaultConfig)
|
2021-04-01 15:10:08 +01:00
|
|
|
defer ctx.Check(blobs.Close)
|
|
|
|
|
|
|
|
v0PieceInfo, ok := db.V0PieceInfo().(pieces.V0PieceInfoDBForTest)
|
|
|
|
require.True(t, ok, "V0PieceInfoDB can not satisfy V0PieceInfoDBForTest")
|
|
|
|
|
|
|
|
conf := pieces.Config{
|
|
|
|
WritePreallocSize: 4 * memory.MiB,
|
|
|
|
DeleteToTrash: testCase.deleteToTrash,
|
|
|
|
}
|
2023-02-28 13:54:01 +00:00
|
|
|
store := pieces.NewStore(log, pieces.NewFileWalker(log, blobs, v0PieceInfo), nil, blobs, v0PieceInfo, db.PieceExpirationDB(), nil, conf)
|
2023-03-01 03:59:53 +00:00
|
|
|
deleter := pieces.NewDeleter(log, store, 1, 10000)
|
2021-04-01 15:10:08 +01:00
|
|
|
defer ctx.Check(deleter.Close)
|
|
|
|
deleter.SetupTest()
|
|
|
|
|
|
|
|
require.NoError(t, deleter.Run(ctx))
|
|
|
|
satelliteID := testrand.NodeID()
|
|
|
|
pieceID := testrand.PieceID()
|
|
|
|
|
|
|
|
data := testrand.Bytes(memory.KB)
|
2022-08-01 10:30:33 +01:00
|
|
|
w, err := store.Writer(ctx, satelliteID, pieceID, pb.PieceHashAlgorithm_SHA256)
|
2021-04-01 15:10:08 +01:00
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = w.Write(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, w.Commit(ctx, &pb.PieceHeader{}))
|
|
|
|
|
|
|
|
// Delete the piece we've created
|
|
|
|
unhandled := deleter.Enqueue(ctx, satelliteID, []pb.PieceID{pieceID})
|
|
|
|
require.Equal(t, 0, unhandled)
|
|
|
|
|
|
|
|
// wait for test hook to fire twice
|
|
|
|
deleter.Wait(ctx)
|
|
|
|
|
|
|
|
// check that piece is not available
|
|
|
|
r1, err := store.Reader(ctx, satelliteID, pieceID)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, r1)
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if r1 != nil {
|
|
|
|
ctx.Check(r1.Close)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// check the trash
|
|
|
|
err = store.RestoreTrash(ctx, satelliteID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
r2, err := store.Reader(ctx, satelliteID, pieceID)
|
|
|
|
defer func() {
|
|
|
|
if r2 != nil {
|
|
|
|
ctx.Check(r2.Close)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
if !testCase.deleteToTrash {
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, r2)
|
|
|
|
}
|
|
|
|
if testCase.deleteToTrash {
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, r2)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Also delete a random non-existent piece, so we know it doesn't blow up when this happens
|
|
|
|
unhandled = deleter.Enqueue(ctx, satelliteID, []pb.PieceID{testrand.PieceID()})
|
|
|
|
require.Equal(t, 0, unhandled)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2020-04-20 21:29:18 +01:00
|
|
|
}
|
2020-04-24 00:09:15 +01:00
|
|
|
|
|
|
|
func TestEnqueueUnhandled(t *testing.T) {
|
|
|
|
testcases := []struct {
|
|
|
|
queueSize int
|
|
|
|
pieces int
|
|
|
|
expUnhandled int
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
queueSize: 5,
|
|
|
|
pieces: 5,
|
|
|
|
expUnhandled: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
queueSize: 4,
|
|
|
|
pieces: 5,
|
|
|
|
expUnhandled: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
queueSize: 1,
|
|
|
|
pieces: 10,
|
|
|
|
expUnhandled: 9,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testcases {
|
|
|
|
satelliteID := testrand.NodeID()
|
|
|
|
pieceIDs := make([]storj.PieceID, 0, tc.pieces)
|
|
|
|
for i := 0; i < tc.pieces; i++ {
|
|
|
|
pieceIDs = append(pieceIDs, testrand.PieceID())
|
|
|
|
}
|
2020-05-15 18:10:26 +01:00
|
|
|
deleter := pieces.NewDeleter(zaptest.NewLogger(t), nil, 1, tc.queueSize)
|
2020-04-24 00:09:15 +01:00
|
|
|
unhandled := deleter.Enqueue(context.Background(), satelliteID, pieceIDs)
|
|
|
|
require.Equal(t, tc.expUnhandled, unhandled)
|
|
|
|
require.NoError(t, deleter.Close())
|
|
|
|
}
|
|
|
|
}
|