2021-09-13 11:51:17 +00:00
|
|
|
package blobstor
|
|
|
|
|
|
|
|
import (
|
2023-04-12 14:01:29 +00:00
|
|
|
"context"
|
2021-09-13 11:51:17 +00:00
|
|
|
"encoding/binary"
|
2024-10-07 08:50:47 +00:00
|
|
|
"errors"
|
2021-09-13 11:51:17 +00:00
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
|
2023-03-07 13:38:26 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
2024-10-07 08:50:47 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/memstore"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore"
|
2024-02-09 06:17:17 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
2023-03-07 13:38:26 +00:00
|
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
|
|
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
2021-09-13 11:51:17 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestIterateObjects(t *testing.T) {
|
|
|
|
p := t.Name()
|
|
|
|
|
|
|
|
const smalSz = 50
|
|
|
|
|
|
|
|
// create BlobStor instance
|
|
|
|
blobStor := New(
|
2022-07-11 12:34:17 +00:00
|
|
|
WithStorages(defaultStorages(p, smalSz)),
|
2021-10-07 14:19:55 +00:00
|
|
|
WithCompressObjects(true),
|
2021-09-13 11:51:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
defer os.RemoveAll(p)
|
|
|
|
|
|
|
|
// open Blobstor
|
2024-02-09 06:17:17 +00:00
|
|
|
require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite))
|
2021-09-13 11:51:17 +00:00
|
|
|
|
|
|
|
// initialize Blobstor
|
|
|
|
require.NoError(t, blobStor.Init())
|
|
|
|
|
|
|
|
defer blobStor.Close()
|
|
|
|
|
|
|
|
const objNum = 5
|
|
|
|
|
|
|
|
type addrData struct {
|
|
|
|
big bool
|
2022-05-31 17:00:41 +00:00
|
|
|
addr oid.Address
|
2021-09-13 11:51:17 +00:00
|
|
|
data []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
mObjs := make(map[string]addrData)
|
|
|
|
|
|
|
|
for i := uint64(0); i < objNum; i++ {
|
|
|
|
sz := smalSz
|
|
|
|
|
|
|
|
big := i < objNum/2
|
|
|
|
if big {
|
|
|
|
sz++
|
|
|
|
}
|
|
|
|
|
|
|
|
data := make([]byte, sz)
|
|
|
|
binary.BigEndian.PutUint64(data, i)
|
|
|
|
|
2022-05-31 17:00:41 +00:00
|
|
|
addr := oidtest.Address()
|
2021-09-13 11:51:17 +00:00
|
|
|
|
|
|
|
mObjs[string(data)] = addrData{
|
|
|
|
big: big,
|
|
|
|
addr: addr,
|
|
|
|
data: data,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, v := range mObjs {
|
2023-04-12 14:01:29 +00:00
|
|
|
_, err := blobStor.Put(context.Background(), common.PutPrm{Address: v.addr, RawData: v.data})
|
2021-09-13 11:51:17 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2023-05-24 11:09:11 +00:00
|
|
|
err := IterateBinaryObjects(context.Background(), blobStor, func(addr oid.Address, data []byte, descriptor []byte) error {
|
2021-09-13 11:51:17 +00:00
|
|
|
v, ok := mObjs[string(data)]
|
|
|
|
require.True(t, ok)
|
|
|
|
|
|
|
|
require.Equal(t, v.data, data)
|
|
|
|
|
|
|
|
if v.big {
|
2022-07-06 14:09:50 +00:00
|
|
|
require.True(t, descriptor != nil && len(descriptor) == 0)
|
2021-09-13 11:51:17 +00:00
|
|
|
} else {
|
2022-07-06 14:09:50 +00:00
|
|
|
require.NotEmpty(t, descriptor)
|
2021-09-13 11:51:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
delete(mObjs, string(data))
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, mObjs)
|
|
|
|
}
|
2022-01-20 16:32:49 +00:00
|
|
|
|
|
|
|
func TestIterate_IgnoreErrors(t *testing.T) {
|
2024-10-07 08:50:47 +00:00
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
myErr := errors.New("unique error")
|
|
|
|
nopIter := func(common.IteratePrm) (common.IterateRes, error) { return common.IterateRes{}, nil }
|
|
|
|
panicIter := func(common.IteratePrm) (common.IterateRes, error) { panic("unreachable") }
|
|
|
|
errIter := func(common.IteratePrm) (common.IterateRes, error) { return common.IterateRes{}, myErr }
|
|
|
|
|
|
|
|
var s1iter, s2iter func(common.IteratePrm) (common.IterateRes, error)
|
|
|
|
st1 := teststore.New(
|
|
|
|
teststore.WithSubstorage(memstore.New()),
|
|
|
|
teststore.WithIterate(func(prm common.IteratePrm) (common.IterateRes, error) {
|
|
|
|
return s1iter(prm)
|
|
|
|
}))
|
|
|
|
st2 := teststore.New(
|
|
|
|
teststore.WithSubstorage(memstore.New()),
|
|
|
|
teststore.WithIterate(func(prm common.IteratePrm) (common.IterateRes, error) {
|
|
|
|
return s2iter(prm)
|
|
|
|
}))
|
|
|
|
|
|
|
|
bsOpts := []Option{WithStorages([]SubStorage{
|
|
|
|
{Storage: st1},
|
|
|
|
{Storage: st2},
|
|
|
|
})}
|
|
|
|
bs := New(bsOpts...)
|
|
|
|
require.NoError(t, bs.Open(ctx, mode.ReadWrite))
|
|
|
|
require.NoError(t, bs.Init())
|
|
|
|
|
|
|
|
nopHandler := func(e common.IterationElement) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("no errors", func(t *testing.T) {
|
|
|
|
s1iter = nopIter
|
|
|
|
s2iter = nopIter
|
|
|
|
_, err := bs.Iterate(ctx, common.IteratePrm{Handler: nopHandler})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("error in the first sub storage, the second one is not iterated over", func(t *testing.T) {
|
|
|
|
s1iter = errIter
|
|
|
|
s2iter = panicIter
|
|
|
|
_, err := bs.Iterate(ctx, common.IteratePrm{Handler: nopHandler})
|
|
|
|
require.ErrorIs(t, err, myErr)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("ignore errors, storage 1", func(t *testing.T) {
|
|
|
|
s1iter = errIter
|
|
|
|
s2iter = nopIter
|
|
|
|
_, err := bs.Iterate(ctx, common.IteratePrm{IgnoreErrors: true, Handler: nopHandler})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("ignore errors, storage 2", func(t *testing.T) {
|
|
|
|
s1iter = nopIter
|
|
|
|
s2iter = errIter
|
|
|
|
_, err := bs.Iterate(ctx, common.IteratePrm{IgnoreErrors: true, Handler: nopHandler})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
2022-01-20 16:32:49 +00:00
|
|
|
}
|