From 66f16f5cb57c30cffe07293702373a707fd8fa13 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Tue, 27 Jan 2026 07:56:33 +0000 Subject: [PATCH] DAOS-17321 ddb: Add checksum dump command to ddb GO code Add checksum dump command function to ddb GO code. Features: recovery Signed-off-by: Cedric Koch-Hofer --- src/control/cmd/ddb/commands_wrapper.go | 13 ++++ src/control/cmd/ddb/ddb_commands.go | 24 +++++++ src/control/cmd/ddb/ddb_commands_test.go | 85 ++++++++++++++++++++++++ src/control/cmd/ddb/test_helpers.go | 8 +++ 4 files changed, 130 insertions(+) diff --git a/src/control/cmd/ddb/commands_wrapper.go b/src/control/cmd/ddb/commands_wrapper.go index 3464ad40c6d..9335f7063c0 100644 --- a/src/control/cmd/ddb/commands_wrapper.go +++ b/src/control/cmd/ddb/commands_wrapper.go @@ -66,6 +66,7 @@ type DdbApi interface { DtxStat(path string, details bool) error ProvMem(db_path string, tmpfs_mount string, tmpfs_mount_size uint) error DtxAggr(path string, cmt_time uint64, cmt_date string) error + CsumDump(path string, dst string, epoch uint64) error } // DdbContext structure for wrapping the C code context structure @@ -381,3 +382,15 @@ func (ctx *DdbContext) DtxAggr(path string, cmt_time uint64, cmt_date string) er /* Run the c code command */ return daosError(C.ddb_run_dtx_aggr(&ctx.ctx, &options)) } + +func (ctx *DdbContext) CsumDump(path string, dst string, epoch uint64) error { + /* Set up the options */ + options := C.struct_csum_dump_options{} + options.path = C.CString(path) + defer freeString(options.path) + options.dst = C.CString(dst) + defer freeString(options.dst) + options.epoch = C.uint64_t(epoch) + /* Run the c code command */ + return daosError(C.ddb_run_csum_dump(&ctx.ctx, &options)) +} diff --git a/src/control/cmd/ddb/ddb_commands.go b/src/control/cmd/ddb/ddb_commands.go index 6b433777b37..f9d25a3ac13 100644 --- a/src/control/cmd/ddb/ddb_commands.go +++ b/src/control/cmd/ddb/ddb_commands.go @@ -445,4 +445,28 @@ the path must include the extent, otherwise, it must not.`, }, Completer: nil, }) + // Command csum_dump + app.AddCommand(&grumble.Command{ + Name: "csum_dump", + Aliases: nil, + Help: "Dump visible checksum(s)", + LongHelp: `Dump visible checksum(s) to the screen or in a file. The vos +path should be a complete path, including the akey and if the value is an array +value it should include the extent. If a path to a file was provided then the +value(s) will be written to the file, else it will be printed to the screen. +With array values it is possible to define the maximal epoch of the visible record +extent to select`, + HelpGroup: "vos", + Args: func(a *grumble.Args) { + a.String("path", "VOS tree path to dump.") + a.String("dst", "Optional, destination vos tree path to a value.", grumble.Default("")) + }, + Flags: func(f *grumble.Flags) { + f.Uint64("e", "epoch", math.MaxUint64, "Maximal epoch of the visible array value to select (default EPOCH_MAX).") + }, + Run: func(c *grumble.Context) error { + return api.CsumDump(c.Args.String("path"), c.Args.String("dst"), c.Flags.Uint64("epoch")) + }, + Completer: nil, + }) } diff --git a/src/control/cmd/ddb/ddb_commands_test.go b/src/control/cmd/ddb/ddb_commands_test.go index 45300609dcb..5ea4b8459cf 100644 --- a/src/control/cmd/ddb/ddb_commands_test.go +++ b/src/control/cmd/ddb/ddb_commands_test.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "math" "os" "path" "strings" @@ -66,6 +67,10 @@ func TestHelpCmds(t *testing.T) { cmdStr: "open", helpSubStr: "Usage:\n open [flags] path\n", }, + "help for 'csum_dump' command": { + cmdStr: "csum_dump", + helpSubStr: "Usage:\n csum_dump [flags] path [dst]\n", + }, } { t.Run(name, func(t *testing.T) { runHelpCmd(t, tc.cmdStr, tc.helpSubStr) @@ -179,6 +184,86 @@ func TestCmds(t *testing.T) { }, expStdout: []string{"ls called"}, }, + "csum_dump invalid options": { + args: []string{"csum_dump", "--bar"}, + expErr: fmt.Errorf("invalid flag: --bar"), + }, + "csum_dump default": { + args: []string{"csum_dump", "/[0]"}, + expCalls: func(ctx *DdbContextStub) { + ctx.csumDump = func(path string, dst string, epoch uint64) error { + fmt.Println("csum_dump called") + if err := isArgEqual("/[0]", path, "path"); err != nil { + return err + } + if err := isArgEqual("", dst, "dst"); err != nil { + return err + } + if err := isArgEqual(uint64(math.MaxUint64), epoch, "epoch"); err != nil { + return err + } + return nil + } + }, + expStdout: []string{"csum_dump called"}, + }, + "csum_dump epoch short": { + args: []string{"csum_dump", "-e", "999", "/[0]"}, + expCalls: func(ctx *DdbContextStub) { + ctx.csumDump = func(path string, dst string, epoch uint64) error { + fmt.Println("csum_dump called") + if err := isArgEqual("/[0]", path, "path"); err != nil { + return err + } + if err := isArgEqual("", dst, "dst"); err != nil { + return err + } + if err := isArgEqual(uint64(999), epoch, "epoch"); err != nil { + return err + } + return nil + } + }, + expStdout: []string{"csum_dump called"}, + }, + "csum_dump epoch long": { + args: []string{"csum_dump", "--epoch=666", "/[0]"}, + expCalls: func(ctx *DdbContextStub) { + ctx.csumDump = func(path string, dst string, epoch uint64) error { + fmt.Println("csum_dump called") + if err := isArgEqual("/[0]", path, "path"); err != nil { + return err + } + if err := isArgEqual("", dst, "dst"); err != nil { + return err + } + if err := isArgEqual(uint64(666), epoch, "epoch"); err != nil { + return err + } + return nil + } + }, + expStdout: []string{"csum_dump called"}, + }, + "csum_dump destination": { + args: []string{"csum_dump", "/[0]", "/tmp/csum_dump.out"}, + expCalls: func(ctx *DdbContextStub) { + ctx.csumDump = func(path string, dst string, epoch uint64) error { + fmt.Println("csum_dump called") + if err := isArgEqual("/[0]", path, "path"); err != nil { + return err + } + if err := isArgEqual("/tmp/csum_dump.out", dst, "dst"); err != nil { + return err + } + if err := isArgEqual(uint64(math.MaxUint64), epoch, "epoch"); err != nil { + return err + } + return nil + } + }, + expStdout: []string{"csum_dump called"}, + }, } { t.Run(name, func(t *testing.T) { var opts cliOptions diff --git a/src/control/cmd/ddb/test_helpers.go b/src/control/cmd/ddb/test_helpers.go index 91b2d830a2a..98600a6b4db 100644 --- a/src/control/cmd/ddb/test_helpers.go +++ b/src/control/cmd/ddb/test_helpers.go @@ -50,6 +50,7 @@ type DdbContextStub struct { dtxStat func(path string, details bool) error provMem func(db_path string, tmpfs_mount string, tmpfs_mount_size uint) error dtxAggr func(path string, cmt_time uint64, cmt_date string) error + csumDump func(path string, dst string, epoch uint64) error } func (ctx *DdbContextStub) Init(log *logging.LeveledLogger) (func(), error) { @@ -248,6 +249,13 @@ func (ctx *DdbContextStub) DtxAggr(path string, cmt_time uint64, cmt_date string return ctx.dtxAggr(path, cmt_time, cmt_date) } +func (ctx *DdbContextStub) CsumDump(path string, dst string, epoch uint64) error { + if ctx.csumDump == nil { + return nil + } + return ctx.csumDump(path, dst, epoch) +} + func runCmdToStdout(log *logging.LeveledLogger, ctx *DdbContextStub, opts *cliOptions, args []string) (string, error) { // replace os.Stdout so that we can verify the generated output var result bytes.Buffer