forked from TrueCloudLab/frostfs-node
[#1175] metabase: Implement LOCK operation
Implement `DB.Lock` method which marks list of the objects as locked by another object. Only regular objects can be locked. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
14d27455f3
commit
9f13674a10
4 changed files with 169 additions and 17 deletions
|
@ -1,13 +1,99 @@
|
|||
package meta
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
"go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
// suffix for container buckets with locked objects.
|
||||
const bucketNameSuffixLocked = invalidBase58String + "LOCKED"
|
||||
// bucket name for locked objects.
|
||||
var bucketNameLocked = []byte(invalidBase58String + "Locked")
|
||||
|
||||
// returns name of the bucket with locked objects for specified container.
|
||||
func bucketNameLocked(idCnr cid.ID) []byte {
|
||||
return []byte(idCnr.String() + bucketNameSuffixLocked)
|
||||
// suffix for container buckets with objects of type LOCK.
|
||||
const bucketNameSuffixLockers = invalidBase58String + "LOCKER"
|
||||
|
||||
// returns name of the bucket with objects of type LOCK for specified container.
|
||||
func bucketNameLockers(idCnr cid.ID) []byte {
|
||||
return []byte(idCnr.String() + bucketNameSuffixLockers)
|
||||
}
|
||||
|
||||
// ErrLockIrregularObject is returned when trying to lock an irregular object.
|
||||
var ErrLockIrregularObject = errors.New("locking irregular object")
|
||||
|
||||
// Lock marks objects as locked with another object. All objects are from the
|
||||
// specified container.
|
||||
//
|
||||
// Allows locking regular objects only (otherwise returns ErrLockIrregularObject).
|
||||
//
|
||||
// Locked list should be unique. Panics if it is empty.
|
||||
func (db *DB) Lock(cnr cid.ID, locker oid.ID, locked []oid.ID) error {
|
||||
if len(locked) == 0 {
|
||||
panic("empty locked list")
|
||||
}
|
||||
|
||||
return db.boltDB.Update(func(tx *bbolt.Tx) error {
|
||||
// check if all objects are regular
|
||||
bucketKeysLocked := make([][]byte, len(locked))
|
||||
|
||||
for i := range locked {
|
||||
bucketKeysLocked[i] = objectKey(&locked[i])
|
||||
}
|
||||
|
||||
if firstIrregularObjectType(tx, cnr, bucketKeysLocked...) != object.TypeRegular {
|
||||
return ErrLockIrregularObject
|
||||
}
|
||||
|
||||
bucketLocked, err := tx.CreateBucketIfNotExists(bucketNameLocked)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create global bucket for locked objects: %w", err)
|
||||
}
|
||||
|
||||
bucketLockedContainer, err := bucketLocked.CreateBucketIfNotExists([]byte(cnr.String()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("create container bucket for locked objects %v: %w", cnr, err)
|
||||
}
|
||||
|
||||
keyLocker := objectKey(&locker)
|
||||
var exLockers [][]byte
|
||||
var updLockers []byte
|
||||
|
||||
loop:
|
||||
for i := range bucketKeysLocked {
|
||||
// decode list of already existing lockers
|
||||
exLockers, err = decodeList(bucketLockedContainer.Get(bucketKeysLocked[i]))
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode list of object lockers: %w", err)
|
||||
}
|
||||
|
||||
for i := range exLockers {
|
||||
if bytes.Equal(exLockers[i], keyLocker) {
|
||||
continue loop
|
||||
}
|
||||
}
|
||||
|
||||
// update the list of lockers
|
||||
if exLockers == nil {
|
||||
updLockers = keyLocker
|
||||
} else {
|
||||
updLockers, err = encodeList(append(exLockers, keyLocker))
|
||||
if err != nil {
|
||||
// maybe continue for the best effort?
|
||||
return fmt.Errorf("encode list of object lockers: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// write updated list of lockers
|
||||
err = bucketLockedContainer.Put(bucketKeysLocked[i], updLockers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update list of object lockers: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue