2024-07-15 11:07:32 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-07-22 08:17:40 +00:00
|
|
|
"errors"
|
2024-07-15 11:07:32 +00:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/scripts/populate-metabase/util"
|
|
|
|
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
|
|
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
2024-07-22 08:13:15 +00:00
|
|
|
"golang.org/x/sync/errgroup"
|
2024-07-15 11:07:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2024-07-22 13:04:34 +00:00
|
|
|
path = flag.String("path", "", "Path to metabase")
|
|
|
|
force = flag.Bool("force", false, "Rewrite existing database")
|
|
|
|
|
2024-07-15 11:07:32 +00:00
|
|
|
numContainers = flag.Uint("containers", 0, "Number of containers to be created")
|
2024-07-22 13:04:34 +00:00
|
|
|
numObjects = flag.Uint("objects", 0, "Number of objects per container")
|
|
|
|
|
|
|
|
numAttributesPerObj = flag.Uint("attributes", 0, "Number of attributes pre object")
|
|
|
|
|
|
|
|
// Need to populate indixes.
|
|
|
|
numOwners = flag.Uint("distinct-owners", 10, "Number of distinct owners to be used")
|
|
|
|
numPayloads = flag.Uint("distinct-payloads", 10, "Number of distinct payloads to be used")
|
|
|
|
numAttributes = flag.Uint("distinct-attributes", 10, "Number of distinct attributes to be used")
|
2024-07-15 11:07:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type epochState struct{}
|
|
|
|
|
|
|
|
func (s epochState) CurrentEpoch() uint64 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
|
2024-07-22 13:04:34 +00:00
|
|
|
exitOnZero("must have payloads", *numPayloads)
|
|
|
|
exitOnZero("must have attributes", *numAttributes)
|
|
|
|
exitOnZero("must have owners", *numOwners)
|
|
|
|
exitOnZero("path to metabase not specified", *path)
|
|
|
|
|
|
|
|
if *numAttributesPerObj > *numAttributes {
|
|
|
|
exit("object can't have more attributes than available")
|
2024-07-15 11:07:32 +00:00
|
|
|
}
|
|
|
|
|
2024-07-22 08:17:40 +00:00
|
|
|
info, err := os.Stat(*path)
|
|
|
|
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
|
|
exit("can't get path info")
|
|
|
|
}
|
|
|
|
|
|
|
|
// path exits
|
|
|
|
if err == nil {
|
|
|
|
if info.IsDir() {
|
|
|
|
exit("path is a directory")
|
|
|
|
}
|
|
|
|
if !(*force) {
|
|
|
|
exit("can't rewrite existing file, use '-force' flag")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = os.Remove(*path)
|
|
|
|
exitOnErr("can't remove existing file", err)
|
|
|
|
}
|
|
|
|
|
2024-07-15 11:07:32 +00:00
|
|
|
db := meta.New([]meta.Option{
|
|
|
|
meta.WithPath(*path),
|
|
|
|
meta.WithPermissions(0o600),
|
|
|
|
meta.WithEpochState(epochState{}),
|
|
|
|
}...)
|
|
|
|
|
|
|
|
exitOnErr("can't open the metabase", db.Open(context.Background(), mode.ReadWrite))
|
|
|
|
exitOnErr("can't init the metabase", db.Init())
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
exitOnErr("can't close the metabase", db.Close())
|
|
|
|
}()
|
|
|
|
|
2024-07-22 13:04:34 +00:00
|
|
|
payloads := util.GeneratePayloadPool(*numPayloads, 32)
|
|
|
|
attributes := util.GenerateAttributePool(*numAttributes)
|
|
|
|
owners := util.GenerateOwnerPool(*numOwners)
|
|
|
|
|
|
|
|
types := []objectSDK.Type{
|
|
|
|
objectSDK.TypeRegular,
|
|
|
|
objectSDK.TypeLock,
|
|
|
|
objectSDK.TypeTombstone,
|
|
|
|
}
|
|
|
|
|
2024-07-22 08:13:15 +00:00
|
|
|
g := &errgroup.Group{}
|
|
|
|
|
2024-07-15 11:07:32 +00:00
|
|
|
var i uint
|
|
|
|
for i = 0; i < *numContainers; i++ {
|
|
|
|
cid := cidtest.ID()
|
|
|
|
|
2024-07-22 13:04:34 +00:00
|
|
|
for _, objectType := range types {
|
|
|
|
typ := objectType
|
|
|
|
g.Go(func() error {
|
|
|
|
return util.PopulateWithObjects(db, *numObjects, func() *objectSDK.Object {
|
|
|
|
return util.GenerateObject(
|
|
|
|
util.WithContainerID(cid),
|
|
|
|
util.WithType(typ),
|
|
|
|
util.WithPayloadFromPool(payloads),
|
|
|
|
util.WithAttributesFromPool(attributes, *numAttributesPerObj),
|
|
|
|
util.WithOwnerIDFromPool(owners),
|
|
|
|
)
|
|
|
|
})
|
2024-07-22 08:13:15 +00:00
|
|
|
})
|
2024-07-22 13:04:34 +00:00
|
|
|
}
|
2024-07-15 11:07:32 +00:00
|
|
|
}
|
2024-07-22 08:13:15 +00:00
|
|
|
|
|
|
|
exitOnErr("failed to populate database", g.Wait())
|
2024-07-15 11:07:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func exit(msg string) {
|
|
|
|
fmt.Fprintln(os.Stderr, msg)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2024-07-22 13:04:34 +00:00
|
|
|
func exitOnZero[T comparable](msg string, value T) {
|
|
|
|
var zero T
|
|
|
|
if value == zero {
|
|
|
|
exit(msg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-15 11:07:32 +00:00
|
|
|
func exitOnErr(msg string, err error) {
|
|
|
|
if err == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
fmt.Fprintln(os.Stderr, fmt.Errorf("%s: %w", msg, err))
|
|
|
|
os.Exit(1)
|
|
|
|
}
|