forked from TrueCloudLab/frostfs-node
[#1523] shard: Store generic storage ID in metabase
Allow to extend blobstor with more storage sub-systems. Currently objects stored in the FSTree have empty byte slice descriptor and object from blobovnicza tree have the same id as earlier. Each such change in the identifier formation should be accompanied with metabase version increase. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>support/v0.34
parent
9eb018672c
commit
73f8bb3e5f
|
@ -11,3 +11,7 @@ func NewIDFromBytes(v []byte) *ID {
|
||||||
func (id ID) String() string {
|
func (id ID) String() string {
|
||||||
return string(id)
|
return string(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (id ID) Bytes() []byte {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
|
@ -204,7 +204,7 @@ func (b *Blobovniczas) Put(prm common.PutPrm) (common.PutRes, error) {
|
||||||
return common.PutRes{}, errPutFailed
|
return common.PutRes{}, errPutFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
return common.PutRes{BlobovniczaID: id}, nil
|
return common.PutRes{StorageID: id.Bytes()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get reads object from blobovnicza tree.
|
// Get reads object from blobovnicza tree.
|
||||||
|
@ -215,8 +215,9 @@ func (b *Blobovniczas) Get(prm common.GetPrm) (res common.GetRes, err error) {
|
||||||
var bPrm blobovnicza.GetPrm
|
var bPrm blobovnicza.GetPrm
|
||||||
bPrm.SetAddress(prm.Address)
|
bPrm.SetAddress(prm.Address)
|
||||||
|
|
||||||
if prm.BlobovniczaID != nil {
|
if prm.StorageID != nil {
|
||||||
blz, err := b.openBlobovnicza(prm.BlobovniczaID.String())
|
id := blobovnicza.NewIDFromBytes(prm.StorageID)
|
||||||
|
blz, err := b.openBlobovnicza(id.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
@ -265,8 +266,9 @@ func (b *Blobovniczas) Delete(prm common.DeletePrm) (res common.DeleteRes, err e
|
||||||
var bPrm blobovnicza.DeletePrm
|
var bPrm blobovnicza.DeletePrm
|
||||||
bPrm.SetAddress(prm.Address)
|
bPrm.SetAddress(prm.Address)
|
||||||
|
|
||||||
if prm.BlobovniczaID != nil {
|
if prm.StorageID != nil {
|
||||||
blz, err := b.openBlobovnicza(prm.BlobovniczaID.String())
|
id := blobovnicza.NewIDFromBytes(prm.StorageID)
|
||||||
|
blz, err := b.openBlobovnicza(id.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
@ -318,8 +320,9 @@ func (b *Blobovniczas) Delete(prm common.DeletePrm) (res common.DeleteRes, err e
|
||||||
// If blobocvnicza ID is specified, only this blobovnicza is processed.
|
// If blobocvnicza ID is specified, only this blobovnicza is processed.
|
||||||
// Otherwise, all Blobovniczas are processed descending weight.
|
// Otherwise, all Blobovniczas are processed descending weight.
|
||||||
func (b *Blobovniczas) GetRange(prm common.GetRangePrm) (res common.GetRangeRes, err error) {
|
func (b *Blobovniczas) GetRange(prm common.GetRangePrm) (res common.GetRangeRes, err error) {
|
||||||
if prm.BlobovniczaID != nil {
|
if prm.StorageID != nil {
|
||||||
blz, err := b.openBlobovnicza(prm.BlobovniczaID.String())
|
id := blobovnicza.NewIDFromBytes(prm.StorageID)
|
||||||
|
blz, err := b.openBlobovnicza(id.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.GetRangeRes{}, err
|
return common.GetRangeRes{}, err
|
||||||
}
|
}
|
||||||
|
@ -573,7 +576,7 @@ func (b *Blobovniczas) deleteObject(blz *blobovnicza.Blobovnicza, prm blobovnicz
|
||||||
storagelog.Write(b.log,
|
storagelog.Write(b.log,
|
||||||
storagelog.AddressField(dp.Address),
|
storagelog.AddressField(dp.Address),
|
||||||
storagelog.OpField("Blobovniczas DELETE"),
|
storagelog.OpField("Blobovniczas DELETE"),
|
||||||
zap.Stringer("blobovnicza ID", dp.BlobovniczaID),
|
zap.Stringer("blobovnicza ID", blobovnicza.NewIDFromBytes(dp.StorageID)),
|
||||||
)
|
)
|
||||||
|
|
||||||
return common.DeleteRes{}, nil
|
return common.DeleteRes{}, nil
|
||||||
|
|
|
@ -78,7 +78,7 @@ func TestBlobovniczas(t *testing.T) {
|
||||||
|
|
||||||
// get w/ blobovnicza ID
|
// get w/ blobovnicza ID
|
||||||
var prm common.GetPrm
|
var prm common.GetPrm
|
||||||
prm.BlobovniczaID = pRes.BlobovniczaID
|
prm.StorageID = pRes.StorageID
|
||||||
prm.Address = addr
|
prm.Address = addr
|
||||||
|
|
||||||
res, err := b.Get(prm)
|
res, err := b.Get(prm)
|
||||||
|
@ -86,7 +86,7 @@ func TestBlobovniczas(t *testing.T) {
|
||||||
require.Equal(t, obj, res.Object)
|
require.Equal(t, obj, res.Object)
|
||||||
|
|
||||||
// get w/o blobovnicza ID
|
// get w/o blobovnicza ID
|
||||||
prm.BlobovniczaID = nil
|
prm.StorageID = nil
|
||||||
|
|
||||||
res, err = b.Get(prm)
|
res, err = b.Get(prm)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -94,7 +94,7 @@ func TestBlobovniczas(t *testing.T) {
|
||||||
|
|
||||||
// get range w/ blobovnicza ID
|
// get range w/ blobovnicza ID
|
||||||
var rngPrm common.GetRangePrm
|
var rngPrm common.GetRangePrm
|
||||||
rngPrm.BlobovniczaID = pRes.BlobovniczaID
|
rngPrm.StorageID = pRes.StorageID
|
||||||
rngPrm.Address = addr
|
rngPrm.Address = addr
|
||||||
|
|
||||||
payload := obj.Payload()
|
payload := obj.Payload()
|
||||||
|
@ -109,7 +109,7 @@ func TestBlobovniczas(t *testing.T) {
|
||||||
require.Equal(t, payload[off:off+ln], rngRes.Data)
|
require.Equal(t, payload[off:off+ln], rngRes.Data)
|
||||||
|
|
||||||
// get range w/o blobovnicza ID
|
// get range w/o blobovnicza ID
|
||||||
rngPrm.BlobovniczaID = nil
|
rngPrm.StorageID = nil
|
||||||
|
|
||||||
rngRes, err = b.GetRange(rngPrm)
|
rngRes, err = b.GetRange(rngPrm)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeletePrm groups the parameters of Delete operation.
|
// DeletePrm groups the parameters of Delete operation.
|
||||||
type DeletePrm struct {
|
type DeletePrm struct {
|
||||||
Address oid.Address
|
Address oid.Address
|
||||||
BlobovniczaID *blobovnicza.ID
|
StorageID []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRes groups the resulting values of Delete operation.
|
// DeleteRes groups the resulting values of Delete operation.
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GetPrm struct {
|
type GetPrm struct {
|
||||||
Address oid.Address
|
Address oid.Address
|
||||||
BlobovniczaID *blobovnicza.ID
|
StorageID []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetRes struct {
|
type GetRes struct {
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GetRangePrm struct {
|
type GetRangePrm struct {
|
||||||
Address oid.Address
|
Address oid.Address
|
||||||
Range objectSDK.Range
|
Range objectSDK.Range
|
||||||
BlobovniczaID *blobovnicza.ID
|
StorageID []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetRangeRes struct {
|
type GetRangeRes struct {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
)
|
)
|
||||||
|
@ -15,5 +14,5 @@ type PutPrm struct {
|
||||||
|
|
||||||
// PutRes groups the resulting values of Put operation.
|
// PutRes groups the resulting values of Put operation.
|
||||||
type PutRes struct {
|
type PutRes struct {
|
||||||
BlobovniczaID *blobovnicza.ID
|
StorageID []byte
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *BlobStor) Delete(prm common.DeletePrm) (common.DeleteRes, error) {
|
func (b *BlobStor) Delete(prm common.DeletePrm) (common.DeleteRes, error) {
|
||||||
if prm.BlobovniczaID == nil {
|
if prm.StorageID == nil {
|
||||||
// Nothing specified, try everything.
|
// Nothing specified, try everything.
|
||||||
res, err := b.deleteBig(prm)
|
res, err := b.deleteBig(prm)
|
||||||
if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) {
|
if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) {
|
||||||
|
@ -18,7 +18,7 @@ func (b *BlobStor) Delete(prm common.DeletePrm) (common.DeleteRes, error) {
|
||||||
}
|
}
|
||||||
return b.deleteSmall(prm)
|
return b.deleteSmall(prm)
|
||||||
}
|
}
|
||||||
if *prm.BlobovniczaID == nil {
|
if len(prm.StorageID) == 0 {
|
||||||
return b.deleteBig(prm)
|
return b.deleteBig(prm)
|
||||||
}
|
}
|
||||||
return b.deleteSmall(prm)
|
return b.deleteSmall(prm)
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
// If the descriptor is present, only one sub-storage is tried,
|
// If the descriptor is present, only one sub-storage is tried,
|
||||||
// Otherwise, each sub-storage is tried in order.
|
// Otherwise, each sub-storage is tried in order.
|
||||||
func (b *BlobStor) Get(prm common.GetPrm) (common.GetRes, error) {
|
func (b *BlobStor) Get(prm common.GetPrm) (common.GetRes, error) {
|
||||||
if prm.BlobovniczaID == nil {
|
if prm.StorageID == nil {
|
||||||
// Nothing specified, try everything.
|
// Nothing specified, try everything.
|
||||||
res, err := b.getBig(prm)
|
res, err := b.getBig(prm)
|
||||||
if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) {
|
if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) {
|
||||||
|
@ -22,7 +22,7 @@ func (b *BlobStor) Get(prm common.GetPrm) (common.GetRes, error) {
|
||||||
}
|
}
|
||||||
return b.getSmall(prm)
|
return b.getSmall(prm)
|
||||||
}
|
}
|
||||||
if *prm.BlobovniczaID == nil {
|
if len(prm.StorageID) == 0 {
|
||||||
return b.getBig(prm)
|
return b.getBig(prm)
|
||||||
}
|
}
|
||||||
return b.getSmall(prm)
|
return b.getSmall(prm)
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
// If the descriptor is present, only one sub-storage is tried,
|
// If the descriptor is present, only one sub-storage is tried,
|
||||||
// Otherwise, each sub-storage is tried in order.
|
// Otherwise, each sub-storage is tried in order.
|
||||||
func (b *BlobStor) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error) {
|
func (b *BlobStor) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error) {
|
||||||
if prm.BlobovniczaID == nil {
|
if prm.StorageID == nil {
|
||||||
// Nothing specified, try everything.
|
// Nothing specified, try everything.
|
||||||
res, err := b.getRangeBig(prm)
|
res, err := b.getRangeBig(prm)
|
||||||
if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) {
|
if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) {
|
||||||
|
@ -22,7 +22,7 @@ func (b *BlobStor) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error)
|
||||||
}
|
}
|
||||||
return b.getRangeSmall(prm)
|
return b.getRangeSmall(prm)
|
||||||
}
|
}
|
||||||
if *prm.BlobovniczaID == nil {
|
if len(prm.StorageID) == 0 {
|
||||||
return b.getRangeBig(prm)
|
return b.getRangeBig(prm)
|
||||||
}
|
}
|
||||||
return b.getRangeSmall(prm)
|
return b.getRangeSmall(prm)
|
||||||
|
|
|
@ -15,7 +15,7 @@ type IterationElement struct {
|
||||||
|
|
||||||
addr oid.Address
|
addr oid.Address
|
||||||
|
|
||||||
blzID *blobovnicza.ID
|
descriptor []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectData returns the stored object in a binary representation.
|
// ObjectData returns the stored object in a binary representation.
|
||||||
|
@ -23,10 +23,9 @@ func (x IterationElement) ObjectData() []byte {
|
||||||
return x.data
|
return x.data
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlobovniczaID returns the identifier of Blobovnicza in which object is stored.
|
// Descriptor returns the identifier of storage part where x is stored.
|
||||||
// Returns nil if the object isn't in Blobovnicza.
|
func (x IterationElement) Descriptor() []byte {
|
||||||
func (x IterationElement) BlobovniczaID() *blobovnicza.ID {
|
return x.descriptor
|
||||||
return x.blzID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address returns the object address.
|
// Address returns the object address.
|
||||||
|
@ -89,7 +88,7 @@ func (b *BlobStor) Iterate(prm IteratePrm) (IterateRes, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.addr = addr
|
elem.addr = addr
|
||||||
elem.blzID = blobovnicza.NewIDFromBytes([]byte(p))
|
elem.descriptor = []byte(p)
|
||||||
|
|
||||||
return prm.handler(elem)
|
return prm.handler(elem)
|
||||||
})
|
})
|
||||||
|
@ -103,7 +102,7 @@ func (b *BlobStor) Iterate(prm IteratePrm) (IterateRes, error) {
|
||||||
return IterateRes{}, fmt.Errorf("blobovniczas iterator failure: %w", err)
|
return IterateRes{}, fmt.Errorf("blobovniczas iterator failure: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.blzID = nil
|
elem.descriptor = []byte{}
|
||||||
|
|
||||||
var fsPrm fstree.IterationPrm
|
var fsPrm fstree.IterationPrm
|
||||||
fsPrm.WithIgnoreErrors(prm.ignoreErrors)
|
fsPrm.WithIgnoreErrors(prm.ignoreErrors)
|
||||||
|
@ -136,11 +135,11 @@ func (b *BlobStor) Iterate(prm IteratePrm) (IterateRes, error) {
|
||||||
|
|
||||||
// IterateBinaryObjects is a helper function which iterates over BlobStor and passes binary objects to f.
|
// IterateBinaryObjects is a helper function which iterates over BlobStor and passes binary objects to f.
|
||||||
// Errors related to object reading and unmarshaling are logged and skipped.
|
// Errors related to object reading and unmarshaling are logged and skipped.
|
||||||
func IterateBinaryObjects(blz *BlobStor, f func(addr oid.Address, data []byte, blzID *blobovnicza.ID) error) error {
|
func IterateBinaryObjects(blz *BlobStor, f func(addr oid.Address, data []byte, descriptor []byte) error) error {
|
||||||
var prm IteratePrm
|
var prm IteratePrm
|
||||||
|
|
||||||
prm.SetIterationHandler(func(elem IterationElement) error {
|
prm.SetIterationHandler(func(elem IterationElement) error {
|
||||||
return f(elem.Address(), elem.ObjectData(), elem.BlobovniczaID())
|
return f(elem.Address(), elem.ObjectData(), elem.Descriptor())
|
||||||
})
|
})
|
||||||
prm.IgnoreErrors()
|
prm.IgnoreErrors()
|
||||||
prm.SetErrorHandler(func(addr oid.Address, err error) error {
|
prm.SetErrorHandler(func(addr oid.Address, err error) error {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
|
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
|
||||||
|
@ -71,16 +70,16 @@ func TestIterateObjects(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := IterateBinaryObjects(blobStor, func(_ oid.Address, data []byte, blzID *blobovnicza.ID) error {
|
err := IterateBinaryObjects(blobStor, func(_ oid.Address, data []byte, descriptor []byte) error {
|
||||||
v, ok := mObjs[string(data)]
|
v, ok := mObjs[string(data)]
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
require.Equal(t, v.data, data)
|
require.Equal(t, v.data, data)
|
||||||
|
|
||||||
if v.big {
|
if v.big {
|
||||||
require.Nil(t, blzID)
|
require.True(t, descriptor != nil && len(descriptor) == 0)
|
||||||
} else {
|
} else {
|
||||||
require.NotNil(t, blzID)
|
require.NotEmpty(t, descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(mObjs, string(data))
|
delete(mObjs, string(data))
|
||||||
|
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
This file describes changes between the metabase versions.
|
This file describes changes between the metabase versions.
|
||||||
|
|
||||||
## Version 0
|
## Current
|
||||||
|
|
||||||
- Container ID is encoded as base58 string
|
|
||||||
- Object ID is encoded as base58 string
|
|
||||||
- Address is encoded as container ID + "/" + object ID
|
|
||||||
|
|
||||||
### Primary buckets
|
### Primary buckets
|
||||||
- Graveyard bucket
|
- Graveyard bucket
|
||||||
|
@ -53,10 +49,10 @@ This file describes changes between the metabase versions.
|
||||||
- Name: container ID + `_TS`
|
- Name: container ID + `_TS`
|
||||||
- Key: object ID
|
- Key: object ID
|
||||||
- Value: marshaled object
|
- Value: marshaled object
|
||||||
- Buckets mapping objects to the blobovniczas they are stored in
|
- Buckets mapping objects to the storage ID they are stored in
|
||||||
- Name: container ID + `_small`
|
- Name: container ID + `_small`
|
||||||
- Key: object ID
|
- Key: object ID
|
||||||
- Value: blobovnicza ID
|
- Value: storage ID
|
||||||
- Buckets for mapping parent object to the split info
|
- Buckets for mapping parent object to the split info
|
||||||
- Name: container ID + `_root`
|
- Name: container ID + `_root`
|
||||||
- Key: object ID
|
- Key: object ID
|
||||||
|
@ -85,3 +81,16 @@ This file describes changes between the metabase versions.
|
||||||
- Name: container ID + `_splitid`
|
- Name: container ID + `_splitid`
|
||||||
- Key: split ID
|
- Key: split ID
|
||||||
- Value: list of object IDs
|
- Value: list of object IDs
|
||||||
|
|
||||||
|
|
||||||
|
# History
|
||||||
|
|
||||||
|
## Version 1
|
||||||
|
|
||||||
|
- Metabase now stores generic storage id instead of blobovnicza ID.
|
||||||
|
|
||||||
|
## Version 0
|
||||||
|
|
||||||
|
- Container ID is encoded as base58 string
|
||||||
|
- Object ID is encoded as base58 string
|
||||||
|
- Address is encoded as container ID + "/" + object ID
|
|
@ -254,7 +254,7 @@ func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
delUniqueIndexItem(tx, namedBucketItem{ // remove from small blobovnicza id index
|
delUniqueIndexItem(tx, namedBucketItem{ // remove from storage id index
|
||||||
name: smallBucketName(cnr),
|
name: smallBucketName(cnr),
|
||||||
key: objKey,
|
key: objKey,
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||||
objectCore "github.com/nspcc-dev/neofs-node/pkg/core/object"
|
objectCore "github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log"
|
storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
|
||||||
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
|
@ -27,7 +26,7 @@ type (
|
||||||
type PutPrm struct {
|
type PutPrm struct {
|
||||||
obj *objectSDK.Object
|
obj *objectSDK.Object
|
||||||
|
|
||||||
id *blobovnicza.ID
|
id []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutRes groups the resulting values of Put operation.
|
// PutRes groups the resulting values of Put operation.
|
||||||
|
@ -38,8 +37,8 @@ func (p *PutPrm) SetObject(obj *objectSDK.Object) {
|
||||||
p.obj = obj
|
p.obj = obj
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBlobovniczaID is a Put option to set blobovnicza ID to save.
|
// SetStorageID is a Put option to set storage ID to save.
|
||||||
func (p *PutPrm) SetBlobovniczaID(id *blobovnicza.ID) {
|
func (p *PutPrm) SetStorageID(id []byte) {
|
||||||
p.id = id
|
p.id = id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +49,6 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Put saves object header in metabase. Object payload expected to be cut.
|
// Put saves object header in metabase. Object payload expected to be cut.
|
||||||
// Big objects have nil blobovniczaID.
|
|
||||||
//
|
//
|
||||||
// Returns an error of type apistatus.ObjectAlreadyRemoved if object has been placed in graveyard.
|
// Returns an error of type apistatus.ObjectAlreadyRemoved if object has been placed in graveyard.
|
||||||
// Returns the object.ErrObjectIsExpired if the object is presented but already expired.
|
// Returns the object.ErrObjectIsExpired if the object is presented but already expired.
|
||||||
|
@ -73,7 +71,7 @@ func (db *DB) Put(prm PutPrm) (res PutRes, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) put(
|
func (db *DB) put(
|
||||||
tx *bbolt.Tx, obj *objectSDK.Object, id *blobovnicza.ID,
|
tx *bbolt.Tx, obj *objectSDK.Object, id []byte,
|
||||||
si *objectSDK.SplitInfo, currEpoch uint64) error {
|
si *objectSDK.SplitInfo, currEpoch uint64) error {
|
||||||
cnr, ok := obj.ContainerID()
|
cnr, ok := obj.ContainerID()
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -93,11 +91,10 @@ func (db *DB) put(
|
||||||
// most right child and split header overlap parent so we have to
|
// most right child and split header overlap parent so we have to
|
||||||
// check if object exists to not overwrite it twice
|
// check if object exists to not overwrite it twice
|
||||||
if exists {
|
if exists {
|
||||||
// when storage engine moves small objects from one blobovniczaID
|
// When storage engine moves objects between different sub-storages,
|
||||||
// to another, then it calls metabase.Put method with new blobovniczaID
|
// it calls metabase.Put method with new storage ID, thus triggering this code.
|
||||||
// and this code should be triggered
|
|
||||||
if !isParent && id != nil {
|
if !isParent && id != nil {
|
||||||
return updateBlobovniczaID(tx, object.AddressOf(obj), id)
|
return updateStorageID(tx, object.AddressOf(obj), id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// when storage already has last object in split hierarchy and there is
|
// when storage already has last object in split hierarchy and there is
|
||||||
|
@ -152,7 +149,7 @@ func putUniqueIndexes(
|
||||||
tx *bbolt.Tx,
|
tx *bbolt.Tx,
|
||||||
obj *objectSDK.Object,
|
obj *objectSDK.Object,
|
||||||
si *objectSDK.SplitInfo,
|
si *objectSDK.SplitInfo,
|
||||||
id *blobovnicza.ID,
|
id []byte,
|
||||||
) error {
|
) error {
|
||||||
isParent := si != nil
|
isParent := si != nil
|
||||||
addr := object.AddressOf(obj)
|
addr := object.AddressOf(obj)
|
||||||
|
@ -190,12 +187,12 @@ func putUniqueIndexes(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// index blobovniczaID if it is present
|
// index storageID if it is present
|
||||||
if id != nil {
|
if id != nil {
|
||||||
err = putUniqueIndexItem(tx, namedBucketItem{
|
err = putUniqueIndexItem(tx, namedBucketItem{
|
||||||
name: smallBucketName(cnr),
|
name: smallBucketName(cnr),
|
||||||
key: objKey,
|
key: objKey,
|
||||||
val: *id,
|
val: id,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -423,15 +420,15 @@ func getVarUint(data []byte) (uint64, int, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateBlobovniczaID for existing objects if they were moved from from
|
// updateStorageID for existing objects if they were moved from one
|
||||||
// one blobovnicza to another.
|
// storage location to another.
|
||||||
func updateBlobovniczaID(tx *bbolt.Tx, addr oid.Address, id *blobovnicza.ID) error {
|
func updateStorageID(tx *bbolt.Tx, addr oid.Address, id []byte) error {
|
||||||
bkt, err := tx.CreateBucketIfNotExists(smallBucketName(addr.Container()))
|
bkt, err := tx.CreateBucketIfNotExists(smallBucketName(addr.Container()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return bkt.Put(objectKey(addr.Object()), *id)
|
return bkt.Put(objectKey(addr.Object()), id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateSpliInfo for existing objects if storage filled with extra information
|
// updateSpliInfo for existing objects if storage filled with extra information
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/util/rand"
|
"github.com/nspcc-dev/neofs-node/pkg/util/rand"
|
||||||
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
||||||
|
@ -80,42 +79,42 @@ func TestDB_PutBlobovnicaUpdate(t *testing.T) {
|
||||||
db := newDB(t)
|
db := newDB(t)
|
||||||
|
|
||||||
raw1 := generateObject(t)
|
raw1 := generateObject(t)
|
||||||
blobovniczaID := blobovnicza.ID{1, 2, 3, 4}
|
storageID := []byte{1, 2, 3, 4}
|
||||||
|
|
||||||
// put one object with blobovniczaID
|
// put one object with storageID
|
||||||
err := metaPut(db, raw1, &blobovniczaID)
|
err := metaPut(db, raw1, storageID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
fetchedBlobovniczaID, err := metaIsSmall(db, object.AddressOf(raw1))
|
fetchedStorageID, err := metaStorageID(db, object.AddressOf(raw1))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &blobovniczaID, fetchedBlobovniczaID)
|
require.Equal(t, storageID, fetchedStorageID)
|
||||||
|
|
||||||
t.Run("update blobovniczaID", func(t *testing.T) {
|
t.Run("update storageID", func(t *testing.T) {
|
||||||
newID := blobovnicza.ID{5, 6, 7, 8}
|
newID := []byte{5, 6, 7, 8}
|
||||||
|
|
||||||
err := metaPut(db, raw1, &newID)
|
err := metaPut(db, raw1, newID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
fetchedBlobovniczaID, err := metaIsSmall(db, object.AddressOf(raw1))
|
fetchedBlobovniczaID, err := metaStorageID(db, object.AddressOf(raw1))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &newID, fetchedBlobovniczaID)
|
require.Equal(t, newID, fetchedBlobovniczaID)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("update blobovniczaID on bad object", func(t *testing.T) {
|
t.Run("update storageID on bad object", func(t *testing.T) {
|
||||||
raw2 := generateObject(t)
|
raw2 := generateObject(t)
|
||||||
err := putBig(db, raw2)
|
err := putBig(db, raw2)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
fetchedBlobovniczaID, err := metaIsSmall(db, object.AddressOf(raw2))
|
fetchedBlobovniczaID, err := metaStorageID(db, object.AddressOf(raw2))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Nil(t, fetchedBlobovniczaID)
|
require.Nil(t, fetchedBlobovniczaID)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func metaPut(db *meta.DB, obj *objectSDK.Object, id *blobovnicza.ID) error {
|
func metaPut(db *meta.DB, obj *objectSDK.Object, id []byte) error {
|
||||||
var putPrm meta.PutPrm
|
var putPrm meta.PutPrm
|
||||||
putPrm.SetObject(obj)
|
putPrm.SetObject(obj)
|
||||||
putPrm.SetBlobovniczaID(id)
|
putPrm.SetStorageID(id)
|
||||||
|
|
||||||
_, err := db.Put(putPrm)
|
_, err := db.Put(putPrm)
|
||||||
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
package meta
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util/slice"
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
|
||||||
"go.etcd.io/bbolt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsSmallPrm groups the parameters of IsSmall operation.
|
|
||||||
type IsSmallPrm struct {
|
|
||||||
addr oid.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSmallRes groups the resulting values of IsSmall operation.
|
|
||||||
type IsSmallRes struct {
|
|
||||||
id *blobovnicza.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAddress is a IsSmall option to set the object address to check.
|
|
||||||
func (p *IsSmallPrm) WithAddress(addr oid.Address) {
|
|
||||||
if p != nil {
|
|
||||||
p.addr = addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlobovniczaID returns blobovnicza identifier.
|
|
||||||
func (r IsSmallRes) BlobovniczaID() *blobovnicza.ID {
|
|
||||||
return r.id
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSmall returns blobovniczaID for small objects and nil for big objects.
|
|
||||||
// Small objects stored in blobovnicza instances. Big objects stored in FS by
|
|
||||||
// shallow path which is calculated from address and therefore it is not
|
|
||||||
// indexed in metabase.
|
|
||||||
func (db *DB) IsSmall(prm IsSmallPrm) (res IsSmallRes, err error) {
|
|
||||||
db.modeMtx.RLock()
|
|
||||||
defer db.modeMtx.RUnlock()
|
|
||||||
|
|
||||||
err = db.boltDB.View(func(tx *bbolt.Tx) error {
|
|
||||||
res.id, err = db.isSmall(tx, prm.addr)
|
|
||||||
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *DB) isSmall(tx *bbolt.Tx, addr oid.Address) (*blobovnicza.ID, error) {
|
|
||||||
smallBucket := tx.Bucket(smallBucketName(addr.Container()))
|
|
||||||
if smallBucket == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
blobovniczaID := smallBucket.Get(objectKey(addr.Object()))
|
|
||||||
if len(blobovniczaID) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return blobovnicza.NewIDFromBytes(slice.Copy(blobovniczaID)), nil
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package meta_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDB_IsSmall(t *testing.T) {
|
|
||||||
db := newDB(t)
|
|
||||||
|
|
||||||
raw1 := generateObject(t)
|
|
||||||
raw2 := generateObject(t)
|
|
||||||
|
|
||||||
blobovniczaID := blobovnicza.ID{1, 2, 3, 4}
|
|
||||||
|
|
||||||
// check IsSmall from empty database
|
|
||||||
fetchedBlobovniczaID, err := metaIsSmall(db, object.AddressOf(raw1))
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Nil(t, fetchedBlobovniczaID)
|
|
||||||
|
|
||||||
// put one object with blobovniczaID
|
|
||||||
err = metaPut(db, raw1, &blobovniczaID)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// put one object without blobovniczaID
|
|
||||||
err = putBig(db, raw2)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// check IsSmall for object without blobovniczaID
|
|
||||||
fetchedBlobovniczaID, err = metaIsSmall(db, object.AddressOf(raw2))
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Nil(t, fetchedBlobovniczaID)
|
|
||||||
|
|
||||||
// check IsSmall for object with blobovniczaID
|
|
||||||
fetchedBlobovniczaID, err = metaIsSmall(db, object.AddressOf(raw1))
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, &blobovniczaID, fetchedBlobovniczaID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func metaIsSmall(db *meta.DB, addr oid.Address) (*blobovnicza.ID, error) {
|
|
||||||
var isSmallPrm meta.IsSmallPrm
|
|
||||||
isSmallPrm.WithAddress(addr)
|
|
||||||
|
|
||||||
r, err := db.IsSmall(isSmallPrm)
|
|
||||||
return r.BlobovniczaID(), err
|
|
||||||
}
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package meta
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util/slice"
|
||||||
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
|
"go.etcd.io/bbolt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StorageIDPrm groups the parameters of StorageID operation.
|
||||||
|
type StorageIDPrm struct {
|
||||||
|
addr oid.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageIDRes groups the resulting values of StorageID operation.
|
||||||
|
type StorageIDRes struct {
|
||||||
|
id []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAddress is a StorageID option to set the object address to check.
|
||||||
|
func (p *StorageIDPrm) SetAddress(addr oid.Address) {
|
||||||
|
p.addr = addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageID returns storage ID.
|
||||||
|
func (r StorageIDRes) StorageID() []byte {
|
||||||
|
return r.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageID returns storage descriptor for objects from the blobstor.
|
||||||
|
// It is put together with the object can makes get/delete operation faster.
|
||||||
|
func (db *DB) StorageID(prm StorageIDPrm) (res StorageIDRes, err error) {
|
||||||
|
err = db.boltDB.View(func(tx *bbolt.Tx) error {
|
||||||
|
res.id, err = db.storageID(tx, prm.addr)
|
||||||
|
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) storageID(tx *bbolt.Tx, addr oid.Address) ([]byte, error) {
|
||||||
|
smallBucket := tx.Bucket(smallBucketName(addr.Container()))
|
||||||
|
if smallBucket == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
storageID := smallBucket.Get(objectKey(addr.Object()))
|
||||||
|
if storageID == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return slice.Copy(storageID), nil
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package meta_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||||
|
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
||||||
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDB_IsSmall(t *testing.T) {
|
||||||
|
db := newDB(t)
|
||||||
|
|
||||||
|
raw1 := generateObject(t)
|
||||||
|
raw2 := generateObject(t)
|
||||||
|
|
||||||
|
storageID := []byte{1, 2, 3, 4}
|
||||||
|
|
||||||
|
// check StorageID from empty database
|
||||||
|
fetchedStorageID, err := metaStorageID(db, object.AddressOf(raw1))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Nil(t, fetchedStorageID)
|
||||||
|
|
||||||
|
// put one object with storageID
|
||||||
|
err = metaPut(db, raw1, storageID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// put one object without storageID
|
||||||
|
err = putBig(db, raw2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// check StorageID for object without storageID
|
||||||
|
fetchedStorageID, err = metaStorageID(db, object.AddressOf(raw2))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Nil(t, fetchedStorageID)
|
||||||
|
|
||||||
|
// check StorageID for object with storageID
|
||||||
|
fetchedStorageID, err = metaStorageID(db, object.AddressOf(raw1))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, storageID, fetchedStorageID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func metaStorageID(db *meta.DB, addr oid.Address) ([]byte, error) {
|
||||||
|
var sidPrm meta.StorageIDPrm
|
||||||
|
sidPrm.SetAddress(addr)
|
||||||
|
|
||||||
|
r, err := db.StorageID(sidPrm)
|
||||||
|
return r.StorageID(), err
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// version contains current metabase version.
|
// version contains current metabase version.
|
||||||
const version = 0
|
const version = 1
|
||||||
|
|
||||||
var versionKey = []byte("version")
|
var versionKey = []byte("version")
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
||||||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode"
|
||||||
|
@ -150,7 +149,7 @@ func (s *Shard) refillMetabase() error {
|
||||||
|
|
||||||
obj := objectSDK.New()
|
obj := objectSDK.New()
|
||||||
|
|
||||||
return blobstor.IterateBinaryObjects(s.blobStor, func(addr oid.Address, data []byte, blzID *blobovnicza.ID) error {
|
return blobstor.IterateBinaryObjects(s.blobStor, func(addr oid.Address, data []byte, descriptor []byte) error {
|
||||||
if err := obj.Unmarshal(data); err != nil {
|
if err := obj.Unmarshal(data); err != nil {
|
||||||
s.log.Warn("could not unmarshal object",
|
s.log.Warn("could not unmarshal object",
|
||||||
zap.Stringer("address", addr),
|
zap.Stringer("address", addr),
|
||||||
|
@ -206,7 +205,7 @@ func (s *Shard) refillMetabase() error {
|
||||||
|
|
||||||
var mPrm meta.PutPrm
|
var mPrm meta.PutPrm
|
||||||
mPrm.SetObject(obj)
|
mPrm.SetObject(obj)
|
||||||
mPrm.SetBlobovniczaID(blzID)
|
mPrm.SetStorageID(descriptor)
|
||||||
|
|
||||||
_, err := s.metaBase.Put(mPrm)
|
_, err := s.metaBase.Put(mPrm)
|
||||||
if err != nil && !meta.IsErrRemoved(err) && !errors.Is(err, object.ErrObjectIsExpired) {
|
if err != nil && !meta.IsErrRemoved(err) && !errors.Is(err, object.ErrObjectIsExpired) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package shard
|
package shard
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
||||||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache"
|
||||||
|
@ -36,7 +35,7 @@ func (s *Shard) Delete(prm DeletePrm) (DeleteRes, error) {
|
||||||
|
|
||||||
ln := len(prm.addr)
|
ln := len(prm.addr)
|
||||||
|
|
||||||
smalls := make(map[oid.Address]*blobovnicza.ID, ln)
|
smalls := make(map[oid.Address][]byte, ln)
|
||||||
|
|
||||||
for i := range prm.addr {
|
for i := range prm.addr {
|
||||||
if s.hasWriteCache() {
|
if s.hasWriteCache() {
|
||||||
|
@ -46,10 +45,10 @@ func (s *Shard) Delete(prm DeletePrm) (DeleteRes, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var sPrm meta.IsSmallPrm
|
var sPrm meta.StorageIDPrm
|
||||||
sPrm.WithAddress(prm.addr[i])
|
sPrm.SetAddress(prm.addr[i])
|
||||||
|
|
||||||
res, err := s.metaBase.IsSmall(sPrm)
|
res, err := s.metaBase.StorageID(sPrm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Debug("can't get blobovniczaID from metabase",
|
s.log.Debug("can't get blobovniczaID from metabase",
|
||||||
zap.Stringer("object", prm.addr[i]),
|
zap.Stringer("object", prm.addr[i]),
|
||||||
|
@ -58,8 +57,8 @@ func (s *Shard) Delete(prm DeletePrm) (DeleteRes, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if res.BlobovniczaID() != nil {
|
if res.StorageID() != nil {
|
||||||
smalls[prm.addr[i]] = res.BlobovniczaID()
|
smalls[prm.addr[i]] = res.StorageID()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,31 +71,14 @@ func (s *Shard) Delete(prm DeletePrm) (DeleteRes, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range prm.addr { // delete small object
|
for i := range prm.addr { // delete small object
|
||||||
if id, ok := smalls[prm.addr[i]]; ok {
|
var delPrm common.DeletePrm
|
||||||
var delSmallPrm common.DeletePrm
|
delPrm.Address = prm.addr[i]
|
||||||
delSmallPrm.Address = prm.addr[i]
|
id := smalls[prm.addr[i]]
|
||||||
delSmallPrm.BlobovniczaID = id
|
delPrm.StorageID = id
|
||||||
|
|
||||||
_, err = s.blobStor.Delete(delSmallPrm)
|
_, err = s.blobStor.Delete(delPrm)
|
||||||
if err != nil {
|
|
||||||
s.log.Debug("can't remove small object from blobStor",
|
|
||||||
zap.Stringer("object_address", prm.addr[i]),
|
|
||||||
zap.String("error", err.Error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var id blobovnicza.ID
|
|
||||||
|
|
||||||
// delete big object
|
|
||||||
var delBigPrm common.DeletePrm
|
|
||||||
delBigPrm.Address = prm.addr[i]
|
|
||||||
delBigPrm.BlobovniczaID = &id
|
|
||||||
|
|
||||||
_, err = s.blobStor.Delete(delBigPrm)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Debug("can't remove big object from blobStor",
|
s.log.Debug("can't remove small object from blobStor",
|
||||||
zap.Stringer("object_address", prm.addr[i]),
|
zap.Stringer("object_address", prm.addr[i]),
|
||||||
zap.String("error", err.Error()))
|
zap.String("error", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package shard
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
||||||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
||||||
|
@ -16,7 +15,7 @@ import (
|
||||||
|
|
||||||
// storFetcher is a type to unify object fetching mechanism in `fetchObjectData`
|
// storFetcher is a type to unify object fetching mechanism in `fetchObjectData`
|
||||||
// method. It represents generalization of `getSmall` and `getBig` methods.
|
// method. It represents generalization of `getSmall` and `getBig` methods.
|
||||||
type storFetcher = func(stor *blobstor.BlobStor, id *blobovnicza.ID) (*objectSDK.Object, error)
|
type storFetcher = func(stor *blobstor.BlobStor, id []byte) (*objectSDK.Object, error)
|
||||||
|
|
||||||
// GetPrm groups the parameters of Get operation.
|
// GetPrm groups the parameters of Get operation.
|
||||||
type GetPrm struct {
|
type GetPrm struct {
|
||||||
|
@ -62,10 +61,10 @@ func (r GetRes) HasMeta() bool {
|
||||||
// Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
|
// Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
|
||||||
// Returns the object.ErrObjectIsExpired if the object is presented but already expired.
|
// Returns the object.ErrObjectIsExpired if the object is presented but already expired.
|
||||||
func (s *Shard) Get(prm GetPrm) (GetRes, error) {
|
func (s *Shard) Get(prm GetPrm) (GetRes, error) {
|
||||||
cb := func(stor *blobstor.BlobStor, id *blobovnicza.ID) (*objectSDK.Object, error) {
|
cb := func(stor *blobstor.BlobStor, id []byte) (*objectSDK.Object, error) {
|
||||||
var getPrm common.GetPrm
|
var getPrm common.GetPrm
|
||||||
getPrm.Address = prm.addr
|
getPrm.Address = prm.addr
|
||||||
getPrm.BlobovniczaID = id
|
getPrm.StorageID = id
|
||||||
|
|
||||||
res, err := stor.Get(getPrm)
|
res, err := stor.Get(getPrm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -131,21 +130,15 @@ func (s *Shard) fetchObjectData(addr oid.Address, skipMeta bool, cb storFetcher,
|
||||||
return nil, false, errNotFound
|
return nil, false, errNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
var mPrm meta.IsSmallPrm
|
var mPrm meta.StorageIDPrm
|
||||||
mPrm.WithAddress(addr)
|
mPrm.SetAddress(addr)
|
||||||
|
|
||||||
mRes, err := s.metaBase.IsSmall(mPrm)
|
mRes, err := s.metaBase.StorageID(mPrm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, true, fmt.Errorf("can't fetch blobovnicza id from metabase: %w", err)
|
return nil, true, fmt.Errorf("can't fetch blobovnicza id from metabase: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
blobovniczaID := mRes.BlobovniczaID()
|
res, err = cb(s.blobStor, mRes.StorageID())
|
||||||
if blobovniczaID == nil {
|
|
||||||
var id blobovnicza.ID
|
|
||||||
blobovniczaID = &id
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err = cb(s.blobStor, blobovniczaID)
|
|
||||||
|
|
||||||
return res, true, err
|
return res, true, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ func (s *Shard) Put(prm PutPrm) (PutRes, error) {
|
||||||
if !m.NoMetabase() {
|
if !m.NoMetabase() {
|
||||||
var pPrm meta.PutPrm
|
var pPrm meta.PutPrm
|
||||||
pPrm.SetObject(prm.obj)
|
pPrm.SetObject(prm.obj)
|
||||||
pPrm.SetBlobovniczaID(res.BlobovniczaID)
|
pPrm.SetStorageID(res.StorageID)
|
||||||
if _, err := s.metaBase.Put(pPrm); err != nil {
|
if _, err := s.metaBase.Put(pPrm); err != nil {
|
||||||
// may we need to handle this case in a special way
|
// may we need to handle this case in a special way
|
||||||
// since the object has been successfully written to BlobStor
|
// since the object has been successfully written to BlobStor
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package shard
|
package shard
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache"
|
||||||
|
@ -67,12 +66,12 @@ func (r RngRes) HasMeta() bool {
|
||||||
// Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
|
// Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
|
||||||
// Returns the object.ErrObjectIsExpired if the object is presented but already expired.
|
// Returns the object.ErrObjectIsExpired if the object is presented but already expired.
|
||||||
func (s *Shard) GetRange(prm RngPrm) (RngRes, error) {
|
func (s *Shard) GetRange(prm RngPrm) (RngRes, error) {
|
||||||
cb := func(stor *blobstor.BlobStor, id *blobovnicza.ID) (*object.Object, error) {
|
cb := func(stor *blobstor.BlobStor, id []byte) (*object.Object, error) {
|
||||||
var getRngPrm common.GetRangePrm
|
var getRngPrm common.GetRangePrm
|
||||||
getRngPrm.Address = prm.addr
|
getRngPrm.Address = prm.addr
|
||||||
getRngPrm.Range.SetOffset(prm.off)
|
getRngPrm.Range.SetOffset(prm.off)
|
||||||
getRngPrm.Range.SetLength(prm.ln)
|
getRngPrm.Range.SetLength(prm.ln)
|
||||||
getRngPrm.BlobovniczaID = id
|
getRngPrm.StorageID = id
|
||||||
|
|
||||||
res, err := stor.GetRange(getRngPrm)
|
res, err := stor.GetRange(getRngPrm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
|
||||||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
||||||
|
@ -228,7 +227,7 @@ func (c *cache) flushWorker(num int) {
|
||||||
|
|
||||||
// writeObject is used to write object directly to the main storage.
|
// writeObject is used to write object directly to the main storage.
|
||||||
func (c *cache) writeObject(obj *object.Object, metaOnly bool) error {
|
func (c *cache) writeObject(obj *object.Object, metaOnly bool) error {
|
||||||
var id *blobovnicza.ID
|
var descriptor []byte
|
||||||
|
|
||||||
if !metaOnly {
|
if !metaOnly {
|
||||||
var prm common.PutPrm
|
var prm common.PutPrm
|
||||||
|
@ -239,12 +238,12 @@ func (c *cache) writeObject(obj *object.Object, metaOnly bool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id = res.BlobovniczaID
|
descriptor = res.StorageID
|
||||||
}
|
}
|
||||||
|
|
||||||
var pPrm meta.PutPrm
|
var pPrm meta.PutPrm
|
||||||
pPrm.SetObject(obj)
|
pPrm.SetObject(obj)
|
||||||
pPrm.SetBlobovniczaID(id)
|
pPrm.SetStorageID(descriptor)
|
||||||
|
|
||||||
_, err := c.metabase.Put(pPrm)
|
_, err := c.metabase.Put(pPrm)
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in New Issue