From 6ad2b5d5b87519a532b0dfa9f90c50c3214d288c Mon Sep 17 00:00:00 2001
From: Evgenii Stratonikov <evgeniy@morphbits.ru>
Date: Thu, 17 Nov 2022 09:06:59 +0300
Subject: [PATCH] [#2068] blobovnicza: Add `Exists` method

Signed-off-by: Evgenii Stratonikov <evgeniy@morphbits.ru>
---
 .../blobovnicza/exists.go                     | 29 +++++++++++++++++++
 .../blobovnicza/get_test.go                   | 10 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 pkg/local_object_storage/blobovnicza/exists.go

diff --git a/pkg/local_object_storage/blobovnicza/exists.go b/pkg/local_object_storage/blobovnicza/exists.go
new file mode 100644
index 000000000..47d57d6fb
--- /dev/null
+++ b/pkg/local_object_storage/blobovnicza/exists.go
@@ -0,0 +1,29 @@
+package blobovnicza
+
+import (
+	oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
+	"go.etcd.io/bbolt"
+)
+
+// Exists check if object with the specified address is stored in b.
+func (b *Blobovnicza) Exists(addr oid.Address) (bool, error) {
+	var (
+		exists  bool
+		addrKey = addressKey(addr)
+	)
+
+	err := b.boltDB.View(func(tx *bbolt.Tx) error {
+		return tx.ForEach(func(_ []byte, buck *bbolt.Bucket) error {
+			exists = buck.Get(addrKey) != nil
+			if exists {
+				return errInterruptForEach
+			}
+			return nil
+		})
+	})
+
+	if err == errInterruptForEach {
+		err = nil
+	}
+	return exists, err
+}
diff --git a/pkg/local_object_storage/blobovnicza/get_test.go b/pkg/local_object_storage/blobovnicza/get_test.go
index 91b56fc52..147f00662 100644
--- a/pkg/local_object_storage/blobovnicza/get_test.go
+++ b/pkg/local_object_storage/blobovnicza/get_test.go
@@ -40,12 +40,16 @@ func TestBlobovnicza_Get(t *testing.T) {
 		addr := oidtest.Address()
 		obj := make([]byte, firstBucketBound+1)
 
+		exists, err := blz.Exists(addr)
+		require.NoError(t, err)
+		require.False(t, exists)
+
 		var prmPut PutPrm
 		prmPut.SetAddress(addr)
 		prmPut.SetMarshaledObject(obj)
 
 		// place object to [32K:64K] bucket
-		_, err := blz.Put(prmPut)
+		_, err = blz.Put(prmPut)
 		require.NoError(t, err)
 
 		var prmGet GetPrm
@@ -55,6 +59,10 @@ func TestBlobovnicza_Get(t *testing.T) {
 			res, err := blz.Get(prmGet)
 			require.NoError(t, err)
 			require.Equal(t, obj, res.Object())
+
+			exists, err := blz.Exists(addr)
+			require.NoError(t, err)
+			require.True(t, exists)
 		}
 
 		// object should be available