[#1008] metabase: Do not update storageID on put

There may be a race condition between put an object and
flushing the writecache:
1. Put object to the writecache
2. Writecache flushes object to the blobstore and sets blobstore's
storageID
3. Put object to the metabase, set writecache's storageID

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2024-02-26 16:30:03 +03:00
parent 2ad433dbcb
commit 918613546f
3 changed files with 36 additions and 23 deletions

View file

@ -137,7 +137,7 @@ func (db *DB) updateObj(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *obje
// When storage engine moves objects between different sub-storages,
// it calls metabase.Put method with new storage ID, thus triggering this code.
if !isParent && id != nil {
return updateStorageID(tx, objectCore.AddressOf(obj), id)
return setStorageID(tx, objectCore.AddressOf(obj), id, true)
}
// when storage already has last object in split hierarchy and there is
@ -236,12 +236,7 @@ func putUniqueIndexes(
// index storageID if it is present
if id != nil {
err = putUniqueIndexItem(tx, namedBucketItem{
name: smallBucketName(cnr, bucketName),
key: objKey,
val: id,
})
if err != nil {
if err = setStorageID(tx, objectCore.AddressOf(obj), id, false); err != nil {
return err
}
}
@ -483,16 +478,19 @@ func getVarUint(data []byte) (uint64, int, error) {
}
}
// updateStorageID for existing objects if they were moved from one
// setStorageID for existing objects if they were moved from one
// storage location to another.
func updateStorageID(tx *bbolt.Tx, addr oid.Address, id []byte) error {
func setStorageID(tx *bbolt.Tx, addr oid.Address, id []byte, override bool) error {
key := make([]byte, bucketKeySize)
bkt, err := createBucketLikelyExists(tx, smallBucketName(addr.Container(), key))
if err != nil {
return err
}
return bkt.Put(objectKey(addr.Object(), key), id)
key = objectKey(addr.Object(), key)
if override || bkt.Get(key) == nil {
return bkt.Put(key, id)
}
return nil
}
// updateSpliInfo for existing objects if storage filled with extra information