forked from TrueCloudLab/frostfs-node
Dmitrii Stepanov
918613546f
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>
119 lines
3.5 KiB
Go
119 lines
3.5 KiB
Go
package meta_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
|
|
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDB_StorageID(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db := newDB(t)
|
|
defer func() { require.NoError(t, db.Close()) }()
|
|
|
|
raw1 := testutil.GenerateObject()
|
|
raw2 := testutil.GenerateObject()
|
|
deleted := testutil.GenerateObject()
|
|
|
|
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)
|
|
|
|
// put object with storageID and delete it
|
|
err = metaPut(db, deleted, storageID)
|
|
require.NoError(t, err)
|
|
|
|
cnrID, ok := deleted.ContainerID()
|
|
require.True(t, ok)
|
|
ts := testutil.GenerateObjectWithCID(cnrID)
|
|
require.NoError(t, metaInhume(db, object.AddressOf(deleted), object.AddressOf(ts)))
|
|
|
|
// 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)
|
|
|
|
// check StorageID for deleted object with storageID
|
|
fetchedStorageID, err = metaStorageID(db, object.AddressOf(deleted))
|
|
require.NoError(t, err)
|
|
require.Equal(t, storageID, fetchedStorageID)
|
|
|
|
t.Run("update", func(t *testing.T) {
|
|
storageID := []byte{1, 2, 3, 4, 5}
|
|
require.NoError(t, metaUpdateStorageID(db, object.AddressOf(raw2), storageID))
|
|
require.NoError(t, metaUpdateStorageID(db, object.AddressOf(deleted), storageID))
|
|
|
|
fetchedStorageID, err = metaStorageID(db, object.AddressOf(raw2))
|
|
require.NoError(t, err)
|
|
require.Equal(t, storageID, fetchedStorageID)
|
|
|
|
fetchedStorageID, err = metaStorageID(db, object.AddressOf(deleted))
|
|
require.NoError(t, err)
|
|
require.Equal(t, storageID, fetchedStorageID)
|
|
})
|
|
}
|
|
|
|
func TestPutWritecacheDataRace(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db := newDB(t)
|
|
defer func() { require.NoError(t, db.Close()) }()
|
|
|
|
putStorageID := []byte{1, 2, 3}
|
|
wcStorageID := []byte{1, 2, 3, 4, 5}
|
|
o := testutil.GenerateObject()
|
|
|
|
fetchedStorageID, err := metaStorageID(db, object.AddressOf(o))
|
|
require.NoError(t, err)
|
|
require.Nil(t, fetchedStorageID)
|
|
|
|
// writecache flushes object and updates storageID before object actually saved to the metabase
|
|
metaUpdateStorageID(db, object.AddressOf(o), wcStorageID)
|
|
|
|
// put object completes with writecache's storageID
|
|
err = metaPut(db, o, putStorageID)
|
|
require.NoError(t, err)
|
|
|
|
fetchedStorageID, err = metaStorageID(db, object.AddressOf(o))
|
|
require.NoError(t, err)
|
|
require.Equal(t, wcStorageID, fetchedStorageID)
|
|
}
|
|
|
|
func metaUpdateStorageID(db *meta.DB, addr oid.Address, id []byte) error {
|
|
var sidPrm meta.UpdateStorageIDPrm
|
|
sidPrm.SetAddress(addr)
|
|
sidPrm.SetStorageID(id)
|
|
|
|
_, err := db.UpdateStorageID(context.Background(), sidPrm)
|
|
return err
|
|
}
|
|
|
|
func metaStorageID(db *meta.DB, addr oid.Address) ([]byte, error) {
|
|
var sidPrm meta.StorageIDPrm
|
|
sidPrm.SetAddress(addr)
|
|
|
|
r, err := db.StorageID(context.Background(), sidPrm)
|
|
return r.StorageID(), err
|
|
}
|