From 63f604e9484bafb9b09bb160c9c161302fb531df Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Nov 2022 09:29:35 +0300 Subject: [PATCH] [#2068] blobstor: Allow to provide storage ID in `Exists` Signed-off-by: Evgenii Stratonikov --- .../blobstor/blobovniczatree/exists.go | 11 ++++ .../blobstor/blobovniczatree/exists_test.go | 65 +++++++++++++++++++ .../blobstor/common/exists.go | 3 +- pkg/local_object_storage/blobstor/exists.go | 7 ++ .../blobstor/internal/blobstortest/exists.go | 19 +++++- 5 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index 586e5bc01..ec89d5680 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -10,6 +10,17 @@ import ( // Exists implements common.Storage. func (b *Blobovniczas) Exists(prm common.ExistsPrm) (common.ExistsRes, error) { + if prm.StorageID != nil { + id := blobovnicza.NewIDFromBytes(prm.StorageID) + blz, err := b.openBlobovnicza(id.String()) + if err != nil { + return common.ExistsRes{}, err + } + + exists, err := blz.Exists(prm.Address) + return common.ExistsRes{Exists: exists}, err + } + activeCache := make(map[string]struct{}) var gPrm blobovnicza.GetPrm diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go new file mode 100644 index 000000000..bba4e092b --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -0,0 +1,65 @@ +package blobovniczatree + +import ( + "os" + "path/filepath" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/util/slice" + "github.com/nspcc-dev/neofs-node/pkg/core/object" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "github.com/nspcc-dev/neofs-node/pkg/util/logger" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" +) + +func TestExistsInvalidStorageID(t *testing.T) { + dir := t.TempDir() + b := NewBlobovniczaTree( + WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), + WithObjectSizeLimit(1024), + WithBlobovniczaShallowWidth(2), + WithBlobovniczaShallowDepth(2), + WithRootPath(dir), + WithBlobovniczaSize(1<<20)) + require.NoError(t, b.Open(false)) + require.NoError(t, b.Init()) + t.Cleanup(func() { _ = b.Close() }) + + obj := blobstortest.NewObject(1024) + addr := object.AddressOf(obj) + d, err := obj.Marshal() + require.NoError(t, err) + + putRes, err := b.Put(common.PutPrm{Address: addr, RawData: d, DontCompress: true}) + require.NoError(t, err) + + t.Run("valid but wrong storage id", func(t *testing.T) { + // "0/X/Y" <-> "1/X/Y" + storageID := slice.Copy(putRes.StorageID) + if storageID[0] == '0' { + storageID[0]++ + } else { + storageID[0]-- + } + + res, err := b.Exists(common.ExistsPrm{Address: addr, StorageID: storageID}) + require.NoError(t, err) + require.False(t, res.Exists) + }) + + t.Run("invalid storage id", func(t *testing.T) { + // "0/X/Y" <-> "1/X/Y" + storageID := slice.Copy(putRes.StorageID) + storageID[0] = '9' + badDir := filepath.Join(dir, "9") + require.NoError(t, os.MkdirAll(badDir, os.ModePerm)) + require.NoError(t, os.Chmod(badDir, 0)) + t.Cleanup(func() { _ = os.Chmod(filepath.Join(dir, "9"), os.ModePerm) }) + + res, err := b.Exists(common.ExistsPrm{Address: addr, StorageID: storageID}) + require.Error(t, err) + require.False(t, res.Exists) + }) +} diff --git a/pkg/local_object_storage/blobstor/common/exists.go b/pkg/local_object_storage/blobstor/common/exists.go index accb81d50..21187f690 100644 --- a/pkg/local_object_storage/blobstor/common/exists.go +++ b/pkg/local_object_storage/blobstor/common/exists.go @@ -4,7 +4,8 @@ import oid "github.com/nspcc-dev/neofs-sdk-go/object/id" // ExistsPrm groups the parameters of Exists operation. type ExistsPrm struct { - Address oid.Address + Address oid.Address + StorageID []byte } // ExistsRes groups the resulting values of Exists operation. diff --git a/pkg/local_object_storage/blobstor/exists.go b/pkg/local_object_storage/blobstor/exists.go index 0868a9454..5c43acfae 100644 --- a/pkg/local_object_storage/blobstor/exists.go +++ b/pkg/local_object_storage/blobstor/exists.go @@ -13,6 +13,13 @@ func (b *BlobStor) Exists(prm common.ExistsPrm) (common.ExistsRes, error) { b.modeMtx.RLock() defer b.modeMtx.RUnlock() + if prm.StorageID != nil { + if len(prm.StorageID) == 0 { + return b.storage[len(b.storage)-1].Storage.Exists(prm) + } + return b.storage[0].Storage.Exists(prm) + } + // If there was an error during existence check below, // it will be returned unless object was found in blobovnicza. // Otherwise, it is logged and the latest error is returned. diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go index efab0e7b0..de20dc0da 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go @@ -25,7 +25,20 @@ func TestExists(t *testing.T, cons Constructor, min, max uint64) { var prm common.ExistsPrm prm.Address = objects[0].addr - res, err := s.Exists(prm) - require.NoError(t, err) - require.True(t, res.Exists) + + t.Run("without storage ID", func(t *testing.T) { + prm.StorageID = nil + + res, err := s.Exists(prm) + require.NoError(t, err) + require.True(t, res.Exists) + }) + + t.Run("with storage ID", func(t *testing.T) { + prm.StorageID = objects[0].storageID + + res, err := s.Exists(prm) + require.NoError(t, err) + require.True(t, res.Exists) + }) }