frostfs-node/pkg/local_object_storage/metabase/upgrade_test.go
Ekaterina Lebedeva a685fcdc96
All checks were successful
DCO action / DCO (pull_request) Successful in 2m41s
Tests and linters / Run gofumpt (pull_request) Successful in 2m32s
Vulncheck / Vulncheck (pull_request) Successful in 2m38s
Build / Build Components (1.23) (pull_request) Successful in 3m0s
Build / Build Components (1.22) (pull_request) Successful in 3m3s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m33s
Tests and linters / Tests (1.22) (pull_request) Successful in 3m34s
Tests and linters / Tests (1.23) (pull_request) Successful in 3m36s
Tests and linters / Staticcheck (pull_request) Successful in 3m35s
Tests and linters / Lint (pull_request) Successful in 4m18s
Tests and linters / Tests with -race (pull_request) Successful in 4m20s
Tests and linters / gopls check (pull_request) Successful in 4m25s
[#1317] go.mod: Use range over int
Since Go 1.22 a "for" statement with a "range" clause is able
to iterate through integer values from zero to an upper limit.

gopatch script:
@@
var i, e expression
@@
-for i := 0; i <= e - 1; i++ {
+for i := range e {
    ...
}

@@
var i, e expression
@@
-for i := 0; i <= e; i++ {
+for i := range e + 1 {
    ...
}

@@
var i, e expression
@@
-for i := 0; i < e; i++ {
+for i := range e {
    ...
}

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-09-03 13:00:54 +03:00

215 lines
7.5 KiB
Go

//go:build integration
package meta
import (
"context"
"fmt"
"io"
"os"
"strconv"
"testing"
"time"
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"
)
const upgradeFilePath = "/path/to/metabase.v2"
func TestUpgradeV2ToV3(t *testing.T) {
path := createTempCopy(t, upgradeFilePath)
defer func() {
require.NoError(t, os.Remove(path))
}()
db := New(WithPath(path), WithEpochState(epochState{e: 1000}), WithLogger(test.NewLogger(t)))
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
require.ErrorIs(t, db.Init(), ErrOutdatedVersion)
require.NoError(t, db.Close())
require.NoError(t, Upgrade(context.Background(), path, true, t.Log))
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
require.NoError(t, db.Init())
require.NoError(t, db.Close())
fmt.Println()
}
func createTempCopy(t *testing.T, path string) string {
src, err := os.Open(path)
require.NoError(t, err)
tmpPath := upgradeFilePath + time.Now().Format(time.RFC3339)
dest, err := os.Create(tmpPath)
require.NoError(t, err)
_, err = io.Copy(dest, src)
require.NoError(t, err)
require.NoError(t, src.Close())
require.NoError(t, dest.Close())
return tmpPath
}
func TestGenerateMetabaseFile(t *testing.T) {
t.Skip("for generating db")
const (
containersCount = 10_000
simpleObjectsCount = 500_000
complexObjectsCount = 500_000 // x2
deletedByGCMarksCount = 100_000
deletedByTombstoneCount = 100_000 // x2
lockedCount = 100_000 // x2
allocSize = 128 << 20
generateWorkersCount = 1_000
minEpoch = 1_000
maxFilename = 1_000
maxStorageID = 10_000
)
db := New(WithPath(upgradeFilePath), WithEpochState(epochState{e: minEpoch}), WithLogger(test.NewLogger(t)))
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
db.boltDB.AllocSize = allocSize
db.boltDB.NoSync = true
require.NoError(t, db.Init())
containers := make([]cid.ID, containersCount)
for i := range containers {
containers[i] = cidtest.ID()
}
oc, err := db.ObjectCounters()
require.NoError(t, err)
require.True(t, oc.IsZero())
eg, ctx := errgroup.WithContext(context.Background())
eg.SetLimit(generateWorkersCount)
// simple objects
for i := range simpleObjectsCount {
i := i
eg.Go(func() error {
obj := testutil.GenerateObjectWithCID(containers[i%len(containers)])
testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10))
testutil.AddAttribute(obj, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10))
_, err := db.Put(ctx, PutPrm{
obj: obj,
id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)),
})
require.NoError(t, err)
return nil
})
}
require.NoError(t, eg.Wait())
db.log.Info("simple objects generated")
eg, ctx = errgroup.WithContext(context.Background())
eg.SetLimit(generateWorkersCount)
// complex objects
for i := range complexObjectsCount {
i := i
eg.Go(func() error {
parent := testutil.GenerateObjectWithCID(containers[i%len(containers)])
child := testutil.GenerateObjectWithCID(containers[i%len(containers)])
child.SetParent(parent)
idParent, _ := parent.ID()
child.SetParentID(idParent)
testutil.AddAttribute(child, "FileName", strconv.FormatInt(int64(i%maxFilename), 10))
testutil.AddAttribute(parent, "FileName", strconv.FormatInt(int64(i%maxFilename), 10))
testutil.AddAttribute(child, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10))
testutil.AddAttribute(parent, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10))
_, err := db.Put(ctx, PutPrm{
obj: child,
})
require.NoError(t, err)
return nil
})
}
require.NoError(t, eg.Wait())
db.log.Info("complex objects generated")
eg, ctx = errgroup.WithContext(context.Background())
eg.SetLimit(generateWorkersCount)
// simple objects deleted by gc marks
for i := range deletedByGCMarksCount {
i := i
eg.Go(func() error {
obj := testutil.GenerateObjectWithCID(containers[i%len(containers)])
testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10))
_, err := db.Put(ctx, PutPrm{
obj: obj,
id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)),
})
require.NoError(t, err)
_, err = db.Inhume(ctx, InhumePrm{
target: []oid.Address{object.AddressOf(obj)},
})
require.NoError(t, err)
return nil
})
}
require.NoError(t, eg.Wait())
db.log.Info("simple objects deleted by gc marks generated")
eg, ctx = errgroup.WithContext(context.Background())
eg.SetLimit(10000)
// simple objects deleted by tombstones
for i := range deletedByTombstoneCount {
i := i
eg.Go(func() error {
obj := testutil.GenerateObjectWithCID(containers[i%len(containers)])
testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10))
_, err := db.Put(ctx, PutPrm{
obj: obj,
id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)),
})
tomb := testutil.GenerateObjectWithCID(containers[i%len(containers)])
tomb.SetType(objectSDK.TypeTombstone)
_, err = db.Put(ctx, PutPrm{
obj: tomb,
id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)),
})
require.NoError(t, err)
tombAddr := object.AddressOf(tomb)
_, err = db.Inhume(ctx, InhumePrm{
target: []oid.Address{object.AddressOf(obj)},
tomb: &tombAddr,
})
require.NoError(t, err)
return nil
})
}
require.NoError(t, eg.Wait())
db.log.Info("simple objects deleted by tombstones generated")
eg, ctx = errgroup.WithContext(context.Background())
eg.SetLimit(generateWorkersCount)
// simple objects locked by locks
for i := range lockedCount {
i := i
eg.Go(func() error {
obj := testutil.GenerateObjectWithCID(containers[i%len(containers)])
testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10))
_, err := db.Put(ctx, PutPrm{
obj: obj,
id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)),
})
lock := testutil.GenerateObjectWithCID(containers[i%len(containers)])
lock.SetType(objectSDK.TypeLock)
testutil.AddAttribute(lock, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10))
_, err = db.Put(ctx, PutPrm{
obj: lock,
id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)),
})
require.NoError(t, err)
err = db.Lock(ctx, containers[i%len(containers)], object.AddressOf(lock).Object(), []oid.ID{object.AddressOf(obj).Object()})
require.NoError(t, err)
return nil
})
}
require.NoError(t, eg.Wait())
db.log.Info("simple objects locked by locks generated")
require.NoError(t, db.boltDB.Sync())
require.NoError(t, db.Close())
}