2020-11-25 09:53:17 +00:00
|
|
|
package blobstor
|
|
|
|
|
|
|
|
import (
|
2021-09-13 11:51:17 +00:00
|
|
|
"fmt"
|
|
|
|
|
2020-11-25 09:53:17 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
2022-01-20 15:53:29 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
|
2022-05-31 17:00:41 +00:00
|
|
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
2022-06-21 07:52:03 +00:00
|
|
|
"go.uber.org/zap"
|
2020-11-25 09:53:17 +00:00
|
|
|
)
|
|
|
|
|
2021-09-13 11:51:17 +00:00
|
|
|
// IterationElement represents a unit of elements through which Iterate operation passes.
|
|
|
|
type IterationElement struct {
|
|
|
|
data []byte
|
|
|
|
|
2022-06-21 07:52:03 +00:00
|
|
|
addr oid.Address
|
|
|
|
|
2022-07-06 14:09:50 +00:00
|
|
|
descriptor []byte
|
2021-09-13 11:51:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-21 11:28:05 +00:00
|
|
|
// ObjectData returns the stored object in a binary representation.
|
2021-09-13 11:51:17 +00:00
|
|
|
func (x IterationElement) ObjectData() []byte {
|
|
|
|
return x.data
|
|
|
|
}
|
|
|
|
|
2022-07-06 14:09:50 +00:00
|
|
|
// Descriptor returns the identifier of storage part where x is stored.
|
|
|
|
func (x IterationElement) Descriptor() []byte {
|
|
|
|
return x.descriptor
|
2021-09-13 11:51:17 +00:00
|
|
|
}
|
|
|
|
|
2022-06-21 07:52:03 +00:00
|
|
|
// Address returns the object address.
|
|
|
|
func (x IterationElement) Address() oid.Address {
|
|
|
|
return x.addr
|
|
|
|
}
|
|
|
|
|
2021-09-13 11:51:17 +00:00
|
|
|
// IterationHandler is a generic processor of IterationElement.
|
|
|
|
type IterationHandler func(IterationElement) error
|
2020-11-25 09:53:17 +00:00
|
|
|
|
|
|
|
// IteratePrm groups the parameters of Iterate operation.
|
|
|
|
type IteratePrm struct {
|
2022-01-20 16:32:49 +00:00
|
|
|
handler IterationHandler
|
|
|
|
ignoreErrors bool
|
2022-06-21 07:52:03 +00:00
|
|
|
errorHandler func(oid.Address, error) error
|
2020-11-25 09:53:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-21 11:28:05 +00:00
|
|
|
// IterateRes groups the resulting values of Iterate operation.
|
2020-11-25 09:53:17 +00:00
|
|
|
type IterateRes struct{}
|
|
|
|
|
|
|
|
// SetIterationHandler sets the action to be performed on each iteration.
|
|
|
|
func (i *IteratePrm) SetIterationHandler(h IterationHandler) {
|
|
|
|
i.handler = h
|
|
|
|
}
|
|
|
|
|
2022-01-20 16:32:49 +00:00
|
|
|
// IgnoreErrors sets the flag signifying whether errors should be ignored.
|
|
|
|
func (i *IteratePrm) IgnoreErrors() {
|
|
|
|
i.ignoreErrors = true
|
|
|
|
}
|
|
|
|
|
2022-06-21 07:52:03 +00:00
|
|
|
// SetErrorHandler sets error handler for objects that cannot be read or unmarshaled.
|
|
|
|
func (i *IteratePrm) SetErrorHandler(f func(oid.Address, error) error) {
|
|
|
|
i.errorHandler = f
|
|
|
|
}
|
|
|
|
|
2020-11-25 09:53:17 +00:00
|
|
|
// Iterate traverses the storage over the stored objects and calls the handler
|
|
|
|
// on each element.
|
|
|
|
//
|
|
|
|
// Returns any error encountered that
|
|
|
|
// did not allow to completely iterate over the storage.
|
|
|
|
//
|
2021-09-13 11:51:17 +00:00
|
|
|
// If handler returns an error, method wraps and returns it immediately.
|
2022-05-31 12:18:32 +00:00
|
|
|
func (b *BlobStor) Iterate(prm IteratePrm) (IterateRes, error) {
|
2021-09-13 11:51:17 +00:00
|
|
|
var elem IterationElement
|
|
|
|
|
2022-07-05 13:47:39 +00:00
|
|
|
err := b.blobovniczas.Iterate(prm.ignoreErrors, func(p string, blz *blobovnicza.Blobovnicza) error {
|
2022-06-21 07:52:03 +00:00
|
|
|
err := blobovnicza.IterateObjects(blz, func(addr oid.Address, data []byte) error {
|
2021-09-13 11:51:17 +00:00
|
|
|
var err error
|
|
|
|
|
|
|
|
// decompress the data
|
2022-07-05 13:47:39 +00:00
|
|
|
elem.data, err = b.Decompress(data)
|
2021-09-13 11:51:17 +00:00
|
|
|
if err != nil {
|
2022-01-20 16:32:49 +00:00
|
|
|
if prm.ignoreErrors {
|
2022-06-21 07:52:03 +00:00
|
|
|
if prm.errorHandler != nil {
|
|
|
|
return prm.errorHandler(addr, err)
|
|
|
|
}
|
2022-01-20 16:32:49 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-09-13 11:51:17 +00:00
|
|
|
return fmt.Errorf("could not decompress object data: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-06-21 07:52:03 +00:00
|
|
|
elem.addr = addr
|
2022-07-06 14:09:50 +00:00
|
|
|
elem.descriptor = []byte(p)
|
2021-09-13 11:51:17 +00:00
|
|
|
|
|
|
|
return prm.handler(elem)
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("blobovnicza iterator failure %s: %w", p, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
2022-05-31 12:18:32 +00:00
|
|
|
return IterateRes{}, fmt.Errorf("blobovniczas iterator failure: %w", err)
|
2021-09-13 11:51:17 +00:00
|
|
|
}
|
|
|
|
|
2022-07-06 14:09:50 +00:00
|
|
|
elem.descriptor = []byte{}
|
2021-09-13 11:51:17 +00:00
|
|
|
|
2022-05-23 14:15:16 +00:00
|
|
|
var fsPrm fstree.IterationPrm
|
|
|
|
fsPrm.WithIgnoreErrors(prm.ignoreErrors)
|
2022-06-21 07:52:03 +00:00
|
|
|
fsPrm.WithHandler(func(addr oid.Address, data []byte) error {
|
2021-09-13 11:51:17 +00:00
|
|
|
// decompress the data
|
2022-07-05 13:47:39 +00:00
|
|
|
elem.data, err = b.Decompress(data)
|
2021-09-13 11:51:17 +00:00
|
|
|
if err != nil {
|
2022-01-20 16:32:49 +00:00
|
|
|
if prm.ignoreErrors {
|
2022-06-21 07:52:03 +00:00
|
|
|
if prm.errorHandler != nil {
|
|
|
|
return prm.errorHandler(addr, err)
|
|
|
|
}
|
2022-01-20 16:32:49 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-09-13 11:51:17 +00:00
|
|
|
return fmt.Errorf("could not decompress object data: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-06-21 07:52:03 +00:00
|
|
|
elem.addr = addr
|
|
|
|
|
2021-09-13 11:51:17 +00:00
|
|
|
return prm.handler(elem)
|
2022-05-23 14:15:16 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
err = b.fsTree.Iterate(fsPrm)
|
2022-01-20 16:32:49 +00:00
|
|
|
|
2021-09-13 11:51:17 +00:00
|
|
|
if err != nil {
|
2022-05-31 12:18:32 +00:00
|
|
|
return IterateRes{}, fmt.Errorf("fs tree iterator failure: %w", err)
|
2021-09-13 11:51:17 +00:00
|
|
|
}
|
|
|
|
|
2022-05-31 12:18:32 +00:00
|
|
|
return IterateRes{}, nil
|
2021-09-13 11:51:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// IterateBinaryObjects is a helper function which iterates over BlobStor and passes binary objects to f.
|
2022-06-21 07:52:03 +00:00
|
|
|
// Errors related to object reading and unmarshaling are logged and skipped.
|
2022-07-06 14:09:50 +00:00
|
|
|
func IterateBinaryObjects(blz *BlobStor, f func(addr oid.Address, data []byte, descriptor []byte) error) error {
|
2021-09-13 11:51:17 +00:00
|
|
|
var prm IteratePrm
|
|
|
|
|
|
|
|
prm.SetIterationHandler(func(elem IterationElement) error {
|
2022-07-06 14:09:50 +00:00
|
|
|
return f(elem.Address(), elem.ObjectData(), elem.Descriptor())
|
2022-06-21 07:52:03 +00:00
|
|
|
})
|
|
|
|
prm.IgnoreErrors()
|
|
|
|
prm.SetErrorHandler(func(addr oid.Address, err error) error {
|
|
|
|
blz.log.Warn("error occurred during the iteration",
|
|
|
|
zap.Stringer("address", addr),
|
|
|
|
zap.String("err", err.Error()))
|
|
|
|
return nil
|
2021-09-13 11:51:17 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
_, err := blz.Iterate(prm)
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|