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"
|
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
|
2023-03-07 13:38:26 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
|
|
|
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
|
2022-06-28 13:42:50 +00:00
|
|
|
require.NoError(t, blobStor.Open(false))
|
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) {
|
2022-07-05 13:47:39 +00:00
|
|
|
t.Skip()
|
2023-03-07 13:38:26 +00:00
|
|
|
// dir := t.TempDir()
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// const (
|
2022-07-05 13:47:39 +00:00
|
|
|
// smallSize = 512
|
|
|
|
// objCount = 5
|
2023-03-07 13:38:26 +00:00
|
|
|
// )
|
|
|
|
// bsOpts := []Option{
|
2022-07-05 13:47:39 +00:00
|
|
|
// WithCompressObjects(true),
|
|
|
|
// WithRootPath(dir),
|
|
|
|
// WithSmallSizeLimit(smallSize * 2), // + header
|
|
|
|
// WithBlobovniczaOpenedCacheSize(1),
|
|
|
|
// WithBlobovniczaShallowWidth(1),
|
|
|
|
// WithBlobovniczaShallowDepth(1)}
|
2023-03-07 13:38:26 +00:00
|
|
|
// bs := New(bsOpts...)
|
|
|
|
// require.NoError(t, bs.Open(false))
|
|
|
|
// require.NoError(t, bs.Init())
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// addrs := make([]oid.Address, objCount)
|
|
|
|
// for i := range addrs {
|
2022-07-05 13:47:39 +00:00
|
|
|
// addrs[i] = oidtest.Address()
|
|
|
|
//
|
|
|
|
// obj := object.New()
|
|
|
|
// obj.SetContainerID(addrs[i].Container())
|
|
|
|
// obj.SetID(addrs[i].Object())
|
|
|
|
// obj.SetPayload(make([]byte, smallSize<<(i%2)))
|
|
|
|
//
|
|
|
|
// objData, err := obj.Marshal()
|
|
|
|
// require.NoError(t, err)
|
|
|
|
//
|
|
|
|
// _, err = bs.PutRaw(addrs[i], objData, true)
|
|
|
|
// require.NoError(t, err)
|
2023-03-07 13:38:26 +00:00
|
|
|
// }
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// // Construct corrupted compressed object.
|
|
|
|
// buf := bytes.NewBuffer(nil)
|
|
|
|
// badObject := make([]byte, smallSize/2+1)
|
|
|
|
// enc, err := zstd.NewWriter(buf)
|
|
|
|
// require.NoError(t, err)
|
|
|
|
// rawData := enc.EncodeAll(badObject, nil)
|
|
|
|
// for i := 4; /* magic size */ i < len(rawData); i += 2 {
|
2022-07-05 13:47:39 +00:00
|
|
|
// rawData[i] ^= 0xFF
|
2023-03-07 13:38:26 +00:00
|
|
|
// }
|
|
|
|
// // Will be put uncompressed but fetched as compressed because of magic.
|
|
|
|
// _, err = bs.PutRaw(oidtest.Address(), rawData, false)
|
|
|
|
// require.NoError(t, err)
|
|
|
|
// require.NoError(t, bs.fsTree.Put(oidtest.Address(), rawData))
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// require.NoError(t, bs.Close())
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// // Increase width to have blobovnicza which is definitely empty.
|
|
|
|
// b := New(append(bsOpts, WithBlobovniczaShallowWidth(2))...)
|
|
|
|
// require.NoError(t, b.Open(false))
|
|
|
|
// require.NoError(t, b.Init())
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// var p string
|
|
|
|
// for i := 0; i < 2; i++ {
|
2022-07-05 13:47:39 +00:00
|
|
|
// bp := filepath.Join(bs.rootPath, "1", strconv.FormatUint(uint64(i), 10))
|
|
|
|
// if _, ok := bs.blobovniczas.opened.Get(bp); !ok {
|
|
|
|
// p = bp
|
|
|
|
// break
|
|
|
|
// }
|
2023-03-07 13:38:26 +00:00
|
|
|
// }
|
|
|
|
// require.NotEqual(t, "", p, "expected to not have at least 1 blobovnicza in cache")
|
|
|
|
// require.NoError(t, os.Chmod(p, 0))
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// require.NoError(t, b.Close())
|
|
|
|
// require.NoError(t, bs.Open(false))
|
|
|
|
// require.NoError(t, bs.Init())
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// var prm IteratePrm
|
|
|
|
// prm.SetIterationHandler(func(e IterationElement) error {
|
2022-07-05 13:47:39 +00:00
|
|
|
// return nil
|
2023-03-07 13:38:26 +00:00
|
|
|
// })
|
|
|
|
// _, err = bs.Iterate(prm)
|
|
|
|
// require.Error(t, err)
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// prm.IgnoreErrors()
|
2022-07-05 13:47:39 +00:00
|
|
|
//
|
2023-03-07 13:38:26 +00:00
|
|
|
// t.Run("skip invalid objects", func(t *testing.T) {
|
2022-07-05 13:47:39 +00:00
|
|
|
// actual := make([]oid.Address, 0, len(addrs))
|
|
|
|
// prm.SetIterationHandler(func(e IterationElement) error {
|
|
|
|
// obj := object.New()
|
|
|
|
// err := obj.Unmarshal(e.data)
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// var addr oid.Address
|
|
|
|
// cnr, _ := obj.ContainerID()
|
|
|
|
// addr.SetContainer(cnr)
|
|
|
|
// id, _ := obj.ID()
|
|
|
|
// addr.SetObject(id)
|
|
|
|
// actual = append(actual, addr)
|
|
|
|
// return nil
|
|
|
|
// })
|
|
|
|
//
|
|
|
|
// _, err := bs.Iterate(prm)
|
|
|
|
// require.NoError(t, err)
|
|
|
|
// require.ElementsMatch(t, addrs, actual)
|
2023-03-07 13:38:26 +00:00
|
|
|
// })
|
|
|
|
// t.Run("return errors from handler", func(t *testing.T) {
|
2022-07-05 13:47:39 +00:00
|
|
|
// n := 0
|
|
|
|
// expectedErr := errors.New("expected error")
|
|
|
|
// prm.SetIterationHandler(func(e IterationElement) error {
|
|
|
|
// if n++; n == objCount/2 {
|
|
|
|
// return expectedErr
|
|
|
|
// }
|
|
|
|
// return nil
|
|
|
|
// })
|
|
|
|
// _, err := bs.Iterate(prm)
|
|
|
|
// require.ErrorIs(t, err, expectedErr)
|
2023-03-07 13:38:26 +00:00
|
|
|
// })
|
2022-01-20 16:32:49 +00:00
|
|
|
}
|