diff --git a/cmd/neofs-lens/internal/meta/inspect.go b/cmd/neofs-lens/internal/meta/inspect.go new file mode 100644 index 00000000..3a05e2fa --- /dev/null +++ b/cmd/neofs-lens/internal/meta/inspect.go @@ -0,0 +1,84 @@ +package meta + +import ( + "errors" + "fmt" + "time" + + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza" + meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" + "github.com/nspcc-dev/neofs-sdk-go/object" + oid "github.com/nspcc-dev/neofs-sdk-go/object/id" + "github.com/spf13/cobra" + "go.etcd.io/bbolt" +) + +var inspectCMD = &cobra.Command{ + Use: "inspect", + Short: "Object inspection", + Long: `Inspect specific object in a metabase.`, + Run: inspectFunc, +} + +func init() { + common.AddAddressFlag(inspectCMD, &vAddress) + common.AddComponentPathFlag(inspectCMD, &vPath) +} + +func inspectFunc(cmd *cobra.Command, _ []string) { + var addr oid.Address + + err := addr.DecodeString(vAddress) + common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) + + db := meta.New( + meta.WithPath(vPath), + meta.WithBoltDBOptions(&bbolt.Options{ + ReadOnly: true, + Timeout: 100 * time.Millisecond, + }), + meta.WithEpochState(epochState{}), + ) + + common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(true))) + + storageID := meta.StorageIDPrm{} + storageID.SetAddress(addr) + + resStorageID, err := db.StorageID(storageID) + common.ExitOnErr(cmd, common.Errf("could not check if the obj is small: %w", err)) + + if id := resStorageID.StorageID(); id != nil { + cmd.Printf("Object storageID: %s\n\n", blobovnicza.NewIDFromBytes(id).String()) + } else { + cmd.Printf("Object does not contain storageID\n\n") + } + + prm := meta.GetPrm{} + prm.SetAddress(addr) + prm.SetRaw(true) + + siErr := new(object.SplitInfoError) + + res, err := db.Get(prm) + if errors.As(err, &siErr) { + link, linkSet := siErr.SplitInfo().Link() + last, lastSet := siErr.SplitInfo().LastPart() + + fmt.Println("Object is split") + cmd.Println("\tSplitID:", siErr.SplitInfo().SplitID().String()) + + if linkSet { + cmd.Println("\tLink:", link) + } + if lastSet { + cmd.Println("\tLast:", last) + } + + return + } + common.ExitOnErr(cmd, common.Errf("could not get object: %w", err)) + + common.PrintObjectHeader(cmd, *res.Header()) +} diff --git a/cmd/neofs-lens/internal/meta/list-garbage.go b/cmd/neofs-lens/internal/meta/list-garbage.go new file mode 100644 index 00000000..4ca74998 --- /dev/null +++ b/cmd/neofs-lens/internal/meta/list-garbage.go @@ -0,0 +1,44 @@ +package meta + +import ( + "time" + + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" + meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" + "github.com/spf13/cobra" + "go.etcd.io/bbolt" +) + +var listGarbageCMD = &cobra.Command{ + Use: "list-garbage", + Short: "Garbage listing", + Long: `List all the objects that have received GC Mark.`, + Run: listGarbageFunc, +} + +func init() { + common.AddComponentPathFlag(listGarbageCMD, &vPath) +} + +func listGarbageFunc(cmd *cobra.Command, _ []string) { + db := meta.New( + meta.WithPath(vPath), + meta.WithBoltDBOptions(&bbolt.Options{ + ReadOnly: true, + Timeout: 100 * time.Millisecond, + }), + meta.WithEpochState(epochState{}), + ) + + common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(true))) + + var garbPrm meta.GarbageIterationPrm + garbPrm.SetHandler( + func(garbageObject meta.GarbageObject) error { + cmd.Println(garbageObject.Address().EncodeToString()) + return nil + }) + + err := db.IterateOverGarbage(garbPrm) + common.ExitOnErr(cmd, common.Errf("could not iterate over garbage bucket: %w", err)) +} diff --git a/cmd/neofs-lens/internal/meta/list-graveyard.go b/cmd/neofs-lens/internal/meta/list-graveyard.go new file mode 100644 index 00000000..0853452e --- /dev/null +++ b/cmd/neofs-lens/internal/meta/list-graveyard.go @@ -0,0 +1,49 @@ +package meta + +import ( + "time" + + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" + meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" + "github.com/spf13/cobra" + "go.etcd.io/bbolt" +) + +var listGraveyardCMD = &cobra.Command{ + Use: "list-graveyard", + Short: "Graveyard listing", + Long: `List all the objects that have been covered with a Tomb Stone.`, + Run: listGraveyardFunc, +} + +func init() { + common.AddComponentPathFlag(listGraveyardCMD, &vPath) +} + +func listGraveyardFunc(cmd *cobra.Command, _ []string) { + db := meta.New( + meta.WithPath(vPath), + meta.WithBoltDBOptions(&bbolt.Options{ + ReadOnly: true, + Timeout: 100 * time.Millisecond, + }), + meta.WithEpochState(epochState{}), + ) + + common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(true))) + + var gravePrm meta.GraveyardIterationPrm + gravePrm.SetHandler( + func(tsObj meta.TombstonedObject) error { + cmd.Printf( + "Object: %s\nTS: %s\n", + tsObj.Address().EncodeToString(), + tsObj.Tombstone().EncodeToString(), + ) + + return nil + }) + + err := db.IterateOverGraveyard(gravePrm) + common.ExitOnErr(cmd, common.Errf("could not iterate over graveyard bucket: %w", err)) +} diff --git a/cmd/neofs-lens/internal/meta/root.go b/cmd/neofs-lens/internal/meta/root.go new file mode 100644 index 00000000..9534abdb --- /dev/null +++ b/cmd/neofs-lens/internal/meta/root.go @@ -0,0 +1,30 @@ +package meta + +import ( + "github.com/spf13/cobra" +) + +var ( + vAddress string + vPath string +) + +type epochState struct{} + +func (s epochState) CurrentEpoch() uint64 { + return 0 +} + +// Root contains `meta` command definition. +var Root = &cobra.Command{ + Use: "meta", + Short: "Operations with a metabase", +} + +func init() { + Root.AddCommand( + inspectCMD, + listGraveyardCMD, + listGarbageCMD, + ) +} diff --git a/cmd/neofs-lens/root.go b/cmd/neofs-lens/root.go index 96f1193a..3e3854a7 100644 --- a/cmd/neofs-lens/root.go +++ b/cmd/neofs-lens/root.go @@ -4,6 +4,7 @@ import ( "os" "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal/blobovnicza" + "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal/meta" "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal/writecache" "github.com/nspcc-dev/neofs-node/misc" "github.com/nspcc-dev/neofs-node/pkg/util/gendoc" @@ -35,6 +36,7 @@ func init() { command.Flags().Bool("version", false, "application version") command.AddCommand( blobovnicza.Root, + meta.Root, writecache.Root, gendoc.Command(command), )