Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
00fc38b
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Apr 30, 2025
3ee405a
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Apr 30, 2025
0be6e7e
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Apr 30, 2025
f6b3aa3
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 10, 2025
983d9d4
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 8, 2025
77e3c21
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 8, 2025
2b72e15
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 8, 2025
59acca7
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 11, 2025
3ff2b3a
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 8, 2025
7c96b6a
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 8, 2025
fbf5bcd
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 15, 2025
ffb3208
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 15, 2025
adcd6df
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 15, 2025
bc2c785
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 15, 2025
cfc25bd
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 16, 2025
a2796f0
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 16, 2025
6ccb846
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 17, 2025
d30d360
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 18, 2025
49be495
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 15, 2025
7f056de
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 19, 2025
9d81546
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 15, 2025
29583d0
DAOS-17322 ddb: DTX aggregation with ddb
kanard38 Sep 15, 2025
d0947f9
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 21, 2025
2129d3f
Merge remote-tracking branch 'origin/master' into ckochhof/dev/master…
kanard38 Sep 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/control/cmd/ddb/commands_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,12 @@ func ddbDevReplace(ctx *DdbContext, db_path string, old_devid string, new_devid
/* Run the c code command */
return daosError(C.ddb_run_dev_replace(&ctx.ctx, &options))
}

func ddbDtxStat(ctx *DdbContext, path string) error {
/* Set up the options */
options := C.struct_dtx_stat_options{}
options.path = C.CString(path)
defer freeString(options.path)
/* Run the c code command */
return daosError(C.ddb_run_dtx_stat(&ctx.ctx, &options))
}
15 changes: 15 additions & 0 deletions src/control/cmd/ddb/ddb_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,4 +381,19 @@ the path must include the extent, otherwise, it must not.`,
},
Completer: nil,
})
// Command dtx_stat
app.AddCommand(&grumble.Command{
Name: "dtx_stat",
Aliases: nil,
Help: "Stat on DTX entries",
LongHelp: "Print statistic on the DTX entries",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we print the DTX statistics information like that:
if container UUID is specified in the path, then for the container; otherwise, if only pool UUID is available, then for the DTX summary of the pool or every container's DTX statistics information in the pool.

@knard38 knard38 Sep 5, 2025 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Print stat for all containers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Print stat for all containers.

Fixed with commit 2b72e15

HelpGroup: "vos",
Args: func(a *grumble.Args) {
a.String("path", "Optional, VOS tree path to query.", grumble.Default(""))
},
Run: func(c *grumble.Context) error {
return ddbDtxStat(ctx, c.Args.String("path"))
},
Completer: nil,
})
}
1 change: 1 addition & 0 deletions src/dtx/tests/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def scons():
'sched_mock.c',
'srv_mock.c',
'srv_module_mock.c',
'dts_count.c'
]
dtx_ut = tenv.d_program('dtx_ut', test_src + vos_src, LIBS=libraries)

Expand Down
140 changes: 140 additions & 0 deletions src/dtx/tests/dts_count.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/**
* (C) Copyright 2025 Hewlett Packard Enterprise Development LP.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define D_LOGFAC DD_FAC(tests)

#include <stddef.h>
#include <stdarg.h>
#include <setjmp.h>
#include <string.h>
#include <cmocka.h>

#include <daos_types.h>
#include <daos/mem.h>
#include <daos_errno.h>
#include <daos_srv/vos.h>
#include <daos/tests_lib.h>

#include "vos_internal.h"

/* mocks */

#define DTX_CMT_BLOB_MAGIC 0x2502191c
#define DBD_COUNT 0x3
#define DBD_BLOB_DF_CAP 0x8
#define CELL_SIZE \
sizeof(struct vos_dtx_blob_df) + DBD_BLOB_DF_CAP * sizeof(struct vos_dtx_cmt_ent_df)

static struct vos_pool mock_pool;
static struct vos_container mock_cont;
static struct vos_cont_df mock_cont_df;
static struct vos_dtx_blob_df *mock_dbds[DBD_COUNT];
static umem_off_t mock_dbds_off[DBD_COUNT];
static daos_handle_t mock_coh;

/* setup & teardown */

static int
test_setup(void **unused)
{
int i;

memset(&mock_pool, 0, sizeof(mock_pool));
memset(&mock_cont, 0, sizeof(mock_cont));
memset(&mock_cont_df, 0, sizeof(mock_cont_df));

for (i = 0; i < DBD_COUNT; i++) {
D_ALLOC(mock_dbds[i], CELL_SIZE);
assert_non_null(mock_dbds[i]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mock_dbds_off[i] = umem_ptr2off(&mock_pool.vp_umm, mock_dbds[i]);

Add above line in this for section. Then in subsequent for section, we can directly use them, for example:

		if (i == DBD_COUNT - 1)
			mock_dbds[i]->dbd_next = UMOFF_NULL;
		else
			mock_dbds[i]->dbd_next = mock_dbds_off[i + 1];
		if (i == 0)
			mock_dbds[i]->dbd_prev = UMOFF_NULL;
		else
			mock_dbds[i]->dbd_prev = mock_dbds_off[i - 1];

Anyway, just some code optimization, not fatal. If you have other chance to refresh the patch, you can consider.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I have no mandatory change requested, I will integrate your remarks in the following up PR introducing the ddb aggregation command.

@knard38 knard38 Sep 22, 2025 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Simplify linked list management

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Simplify linked list management

Fixed with commit 182b4ac of PR #16746

}

for (i = 0; i < DBD_COUNT; i++) {
mock_dbds[i]->dbd_magic = DTX_CMT_BLOB_MAGIC;
mock_dbds[i]->dbd_cap = DBD_BLOB_DF_CAP;
if (i == DBD_COUNT - 1)
mock_dbds[i]->dbd_next = UMOFF_NULL;
else
mock_dbds[i]->dbd_next = umem_ptr2off(&mock_pool.vp_umm, mock_dbds[i + 1]);
if (i == 0)
mock_dbds[i]->dbd_prev = UMOFF_NULL;
else
mock_dbds[i]->dbd_prev = umem_ptr2off(&mock_pool.vp_umm, mock_dbds[i - 1]);
mock_dbds[i]->dbd_count = (i + 1) * 2;
assert_true(mock_dbds[i]->dbd_count <= DBD_BLOB_DF_CAP);

mock_dbds_off[i] = umem_ptr2off(&mock_pool.vp_umm, mock_dbds[i]);
}

mock_cont.vc_pool = &mock_pool;
mock_cont.vc_cont_df = &mock_cont_df;
mock_cont_df.cd_dtx_committed_head = mock_dbds_off[0];
mock_cont_df.cd_dtx_committed_tail = mock_dbds_off[DBD_COUNT - 1];
mock_coh.cookie = (uint64_t)&mock_cont;

return 0;
}

static int
test_teardown(void **unused)
{
int i;

for (i = 0; i < DBD_COUNT; i++)
D_FREE(mock_dbds[i]);

return 0;
}

/* tests */

static void
test_asserts(void **unused)
{
daos_handle_t hdl_null = {0};
uint32_t cnt;
int rc;

/* Invalid arguments. */
rc = vos_dtx_get_cmt_cnt(hdl_null, &cnt);
assert_rc_equal(rc, -DER_INVAL);
rc = vos_dtx_get_cmt_cnt(mock_coh, NULL);
assert_rc_equal(rc, -DER_INVAL);

/* Corrupted dbd */
mock_dbds[1]->dbd_magic = 42;
rc = vos_dtx_get_cmt_cnt(mock_coh, &cnt);
assert_rc_equal(rc, -DER_INVAL);
}

static void
test_count(void **unused)
{
uint32_t cnt;
int rc;

/* Container with several DTX entries table */
rc = vos_dtx_get_cmt_cnt(mock_coh, &cnt);
assert_rc_equal(rc, 0);
assert_int_equal(cnt, DBD_COUNT * (DBD_COUNT + 1));
}

/* compilation unit's entry point */
#define TEST(name, func) \
{ \
name ": vos_dtx_get_cmt_cnt - " #func, func, test_setup, test_teardown \
}

static const struct CMUnitTest vos_dtx_count_tests_all[] = {
TEST("DTX600", test_asserts),
TEST("DTX601", test_count),
};

int
run_dtx_count_tests(void)
{
const char *test_name = "vos_dtx_get_cmt_cnt";

return cmocka_run_group_tests_name(test_name, vos_dtx_count_tests_all, NULL, NULL);
}
7 changes: 5 additions & 2 deletions src/dtx/tests/dtx_ut.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ int
run_structs_tests(void);
int
run_discard_invalid_tests(void);
int
run_dtx_count_tests(void);

static void
print_usage()
Expand All @@ -40,6 +42,7 @@ run_all_tests(int keys)

failed += run_structs_tests();
failed += run_discard_invalid_tests();
failed += run_dtx_count_tests();

return failed;
}
Expand Down Expand Up @@ -77,7 +80,7 @@ main(int argc, char **argv)
#if CMOCKA_FILTER_SUPPORTED == 1 /** requires cmocka 1.1.5 */
cmocka_set_skip_filter(optarg);
#else
D_PRINT("filter not enabled");
D_PRINT("filter not enabled\n");
#endif

break;
Expand All @@ -92,7 +95,7 @@ main(int argc, char **argv)
printf("Test filter: %s\n", filter);
}
#else
D_PRINT("filter not enabled");
D_PRINT("filter not enabled\n");
#endif
break;
default:
Expand Down
11 changes: 11 additions & 0 deletions src/include/daos_srv/vos.h
Original file line number Diff line number Diff line change
Expand Up @@ -1777,4 +1777,15 @@ vos_pin_objects(daos_handle_t coh, daos_unit_oid_t oids[], int count, struct vos
bool
vos_oi_exist(daos_handle_t coh, daos_unit_oid_t oid);

/**
* Return the number of DTX committed entries of a container.
*
* \param[in] coh container open handle.
* \param[out] cnt number of DTX committed entries.
*
* \return 0 on success, error otherwise.
*/
int
vos_dtx_get_cmt_cnt(daos_handle_t coh, uint32_t *cnt);

#endif /* __VOS_API_H */
109 changes: 83 additions & 26 deletions src/utils/ddb/ddb.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,44 @@
#include <getopt.h>
#include <gurt/debug.h>
#include <daos_srv/vos.h>
#include <stdlib.h>
#include <time.h>

#include "ddb.h"
#include "daos/common.h"
#include "daos_errno.h"
#include "ddb_common.h"
#include "ddb_parse.h"

#define MAX_COMMAND_LEN 1024

#define same(a, b) (strcmp((a), (b)) == 0)
#define COMMAND_NAME_HELP "help"
#define COMMAND_NAME_QUIT "quit"
#define COMMAND_NAME_LS "ls"
#define COMMAND_NAME_OPEN "open"
#define COMMAND_NAME_VERSION "version"
#define COMMAND_NAME_CLOSE "close"
#define COMMAND_NAME_SUPERBLOCK_DUMP "superblock_dump"
#define COMMAND_NAME_VALUE_DUMP "value_dump"
#define COMMAND_NAME_RM "rm"
#define COMMAND_NAME_VALUE_LOAD "value_load"
#define COMMAND_NAME_ILOG_DUMP "ilog_dump"
#define COMMAND_NAME_ILOG_COMMIT "ilog_commit"
#define COMMAND_NAME_ILOG_CLEAR "ilog_clear"
#define COMMAND_NAME_DTX_DUMP "dtx_dump"
#define COMMAND_NAME_DTX_CMT_CLEAR "dtx_cmt_clear"
#define COMMAND_NAME_SMD_SYNC "smd_sync"
#define COMMAND_NAME_VEA_DUMP "vea_dump"
#define COMMAND_NAME_VEA_UPDATE "vea_update"
#define COMMAND_NAME_DTX_ACT_COMMIT "dtx_act_commit"
#define COMMAND_NAME_DTX_ACT_ABORT "dtx_act_abort"
#define COMMAND_NAME_FEATURE "feature"
#define COMMAND_NAME_RM_POOL "rm_pool"
#define MAX_COMMAND_LEN 1024

#define same(a, b) (strcmp((a), (b)) == 0)
#define COMMAND_NAME_HELP "help"
#define COMMAND_NAME_QUIT "quit"
#define COMMAND_NAME_LS "ls"
#define COMMAND_NAME_OPEN "open"
#define COMMAND_NAME_VERSION "version"
#define COMMAND_NAME_CLOSE "close"
#define COMMAND_NAME_SUPERBLOCK_DUMP "superblock_dump"
#define COMMAND_NAME_VALUE_DUMP "value_dump"
#define COMMAND_NAME_RM "rm"
#define COMMAND_NAME_VALUE_LOAD "value_load"
#define COMMAND_NAME_ILOG_DUMP "ilog_dump"
#define COMMAND_NAME_ILOG_COMMIT "ilog_commit"
#define COMMAND_NAME_ILOG_CLEAR "ilog_clear"
#define COMMAND_NAME_DTX_DUMP "dtx_dump"
#define COMMAND_NAME_DTX_CMT_CLEAR "dtx_cmt_clear"
#define COMMAND_NAME_SMD_SYNC "smd_sync"
#define COMMAND_NAME_VEA_DUMP "vea_dump"
#define COMMAND_NAME_VEA_UPDATE "vea_update"
#define COMMAND_NAME_DTX_ACT_COMMIT "dtx_act_commit"
#define COMMAND_NAME_DTX_ACT_ABORT "dtx_act_abort"
#define COMMAND_NAME_FEATURE "feature"
#define COMMAND_NAME_RM_POOL "rm_pool"
#define COMMAND_NAME_DTX_ACT_DISCARD_INVALID "dtx_act_discard_invalid"
#define COMMAND_NAME_DEV_LIST "dev_list"
#define COMMAND_NAME_DEV_REPLACE "dev_replace"
#define COMMAND_NAME_DTX_STAT "dtx_stat"

/* Parse command line options for the 'ls' command */
static int
Expand Down Expand Up @@ -814,6 +819,40 @@ dev_replace_option_parse(struct ddb_ctx *ctx, struct dev_replace_options *cmd_ar
return 0;
}

/* Parse command line options for the 'dtx_stat' command */
static int
dtx_stat_option_parse(struct ddb_ctx *ctx, struct dtx_stat_options *cmd_args, uint32_t argc,
char **argv)
{
char *options_short = "";
int index = 0;
struct option options_long[] = {{NULL}};

memset(cmd_args, 0, sizeof(*cmd_args));

/* Restart getopt */
optind = 1;
opterr = 0;
if (getopt_long(argc, argv, options_short, options_long, &index) != -1) {
ddb_printf(ctx, "Unknown option: '%c'\n", optopt);
return -DER_INVAL;
}

index = optind;
cmd_args->path = NULL;
if (argc - index > 0 && *argv[index] != '\0') {
cmd_args->path = argv[index];
index++;
}

if (argc - index > 0) {
ddb_printf(ctx, "Unexpected argument: %s\n", argv[index]);
return -DER_INVAL;
}

return 0;
}

int
ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_cmd_info *info)
{
Expand Down Expand Up @@ -935,6 +974,11 @@ ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_c
argv);
}

if (same(cmd, COMMAND_NAME_DTX_STAT)) {
info->dci_cmd = DDB_CMD_DTX_STAT;
return dtx_stat_option_parse(ctx, &info->dci_cmd_option.dci_dtx_stat, argc, argv);
}

ddb_errorf(ctx,
"'%s' is not a valid command. Available commands are:"
"'help', "
Expand All @@ -960,7 +1004,8 @@ ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_c
"'feature', "
"'rm_pool', "
"'dev_list', "
"'dev_replace'\n",
"'dev_replace', "
"'dtx_stat'\n",
cmd);

return -DER_INVAL;
Expand Down Expand Up @@ -1136,6 +1181,10 @@ ddb_run_cmd(struct ddb_ctx *ctx, const char *cmd_str)
rc = ddb_run_dev_replace(ctx, &info.dci_cmd_option.dci_dev_replace);
break;

case DDB_CMD_DTX_STAT:
rc = ddb_run_dtx_stat(ctx, &info.dci_cmd_option.dci_dtx_stat);
break;

case DDB_CMD_UNKNOWN:
ddb_error(ctx, "Unknown command\n");
rc = -DER_INVAL;
Expand Down Expand Up @@ -1341,6 +1390,13 @@ ddb_commands_help(struct ddb_ctx *ctx)
ddb_print(ctx, " -n, --new_dev\n");
ddb_print(ctx, "\tSpecify the new device UUID\n");
ddb_print(ctx, "\n");

/* Command: dtx_stat */
ddb_print(ctx, "dtx_stat [path]\n");
ddb_print(ctx, "\tPrint statistic on the DTX entries.\n");
ddb_print(ctx, " [path]\n");
ddb_print(ctx, "\tOptional, VOS tree path to query.\n");
ddb_print(ctx, "\n");
}

void
Expand Down Expand Up @@ -1408,4 +1464,5 @@ ddb_program_help(struct ddb_ctx *ctx)
ddb_print(ctx, " rm_pool Remove pool shard\n");
ddb_print(ctx, " dev_list List all devices\n");
ddb_print(ctx, " dev_replace Replace an old device with a new unused device\n");
ddb_print(ctx, " dtx_stat Stat on DTX entries\n");
}
Loading
Loading