frostfs-node/pkg/local_object_storage/metabase/graveyard.go

79 lines
1.6 KiB
Go

package meta
import (
"bytes"
"errors"
"fmt"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
"go.etcd.io/bbolt"
)
// Grave represents descriptor of DB's graveyard item.
type Grave struct {
gcMark bool
addr *addressSDK.Address
}
// WithGCMark returns true if grave marked for GC to be removed.
func (g *Grave) WithGCMark() bool {
return g.gcMark
}
// Address returns buried object address.
func (g *Grave) Address() *addressSDK.Address {
return g.addr
}
// GraveHandler is a Grave handling function.
type GraveHandler func(*Grave) error
// IterateOverGraveyard iterates over all graves in DB.
//
// If h returns ErrInterruptIterator, nil returns immediately.
// Returns other errors of h directly.
func (db *DB) IterateOverGraveyard(h GraveHandler) error {
return db.boltDB.View(func(tx *bbolt.Tx) error {
return db.iterateOverGraveyard(tx, h)
})
}
func (db *DB) iterateOverGraveyard(tx *bbolt.Tx, h GraveHandler) error {
// get graveyard bucket
bktGraveyard := tx.Bucket(graveyardBucketName)
if bktGraveyard == nil {
return nil
}
// iterate over all graves
err := bktGraveyard.ForEach(func(k, v []byte) error {
// parse Grave
g, err := graveFromKV(k, v)
if err != nil {
return fmt.Errorf("could not parse Grave: %w", err)
}
// handler Grave
return h(g)
})
if errors.Is(err, ErrInterruptIterator) {
err = nil
}
return err
}
func graveFromKV(k, v []byte) (*Grave, error) {
addr, err := addressFromKey(k)
if err != nil {
return nil, fmt.Errorf("could not parse address: %w", err)
}
return &Grave{
gcMark: bytes.Equal(v, []byte(inhumeGCMarkValue)),
addr: addr,
}, nil
}