Skip to content

Commit

Permalink
DAOS-10418 ddb: More program options (#9210)
Browse files Browse the repository at this point in the history
- Add -w option so commands that modify the tree can
  only be run in "write mode".
- Add testing for -R option
- Fix a bug where the pool wasn't being closed on program exit.
- Add -f command to pass in a file with a list of commands
- Restructure some of the ddb_main code for better reuse
- Don't actually need to add "program_name" back in when
  running commands

Signed-off-by: Ryon Jensen <[email protected]>
  • Loading branch information
ryon-jensen authored Jun 7, 2022
1 parent 7e8f61b commit 5cc4d48
Show file tree
Hide file tree
Showing 13 changed files with 392 additions and 248 deletions.
201 changes: 61 additions & 140 deletions src/ddb/ddb_cmd_options.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/ddb/ddb_cmd_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ struct ddb_cmd_info {
} dci_cmd_option;
};

int ddb_parse_cmd_args(struct ddb_ctx *ctx, struct argv_parsed *parsed, struct ddb_cmd_info *info);
int ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_cmd_info *info);

/* Run commands ... */
int ddb_run_help(struct ddb_ctx *ctx);
Expand Down
4 changes: 3 additions & 1 deletion src/ddb/ddb_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,10 @@ ddb_run_load(struct ddb_ctx *ctx, struct load_options *opt)
if (rc < 0) {
ddb_errorf(ctx, "System error: "DF_RC"\n", DP_RC(rc));
D_GOTO(done, rc);
} else if (!(rc == iov.iov_buf_len && rc == iov.iov_len)) {
D_ERROR("Bytes read from file does not match results from get file size\n");
D_GOTO(done, rc = -DER_UNKNOWN);
}
D_ASSERT(rc == iov.iov_buf_len && rc == iov.iov_len);

rc = dv_update(ctx->dc_poh, &pb.vtp_path, &iov, epoch);
if (!SUCCESS(rc)) {
Expand Down
18 changes: 15 additions & 3 deletions src/ddb/ddb_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#define SUCCESS(rc) ((rc) == DER_SUCCESS)

#define ddb_print(ctx, str) \
do { if (ctx->dc_io_ft.ddb_print_message) \
ctx->dc_io_ft.ddb_print_message(str); \
do { if ((ctx)->dc_io_ft.ddb_print_message) \
(ctx)->dc_io_ft.ddb_print_message(str); \
else \
printf(str); } while (0)

Expand All @@ -43,6 +43,8 @@
} while (0)


typedef int (*ddb_io_line_cb)(void *cb_args, char *line, uint32_t str_len);

struct ddb_io_ft {
/**
* Print a message.
Expand Down Expand Up @@ -102,13 +104,23 @@ struct ddb_io_ft {
* @return number of bytes read from the src_path
*/
size_t (*ddb_read_file)(const char *src_path, d_iov_t *contents);

/**
* Read contents of a file line by line. For each line, the line_cb will be called.
* @param path Path of the file to read
* @param line_cb Callback function used for each line
* @param cb_args Caller arguments passed to the callback function
* @return 0 on success, else an error code
*/
int (*ddb_get_lines)(const char *path, ddb_io_line_cb line_cb, void *cb_args);

};

struct ddb_ctx {
struct ddb_io_ft dc_io_ft;
daos_handle_t dc_poh;
daos_handle_t dc_coh;
bool dc_should_quit;
bool dc_write_mode;
};

struct dv_tree_path {
Expand Down
38 changes: 37 additions & 1 deletion src/ddb/ddb_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,41 @@ file_exists(const char *path)
return access(path, F_OK) == 0;
}

static int
get_lines(const char *path, ddb_io_line_cb line_cb, void *cb_args)
{
FILE *f;
char *line = NULL;
uint64_t len = 0;
uint64_t read;
int rc = 0;

f = fopen(path, "r");
if (f == NULL) {
rc = daos_errno2der(errno);
print_error("Unable to open path '%s': "DF_RC"\n", path, DP_RC(rc));
return rc;
}

while ((read = getline(&line, &len, f)) != -1) {
rc = line_cb(cb_args, line, read);
if (!SUCCESS(rc)) {
print_error("Issue with line '%s': "DF_RC"\n", line, DP_RC(rc));
break;
}
}

rc = daos_errno2der(errno);
if (!SUCCESS(rc))
print_error("Error reading line from file '%s': "DF_RC"\n", path, DP_RC(rc));

fclose(f);
if (line)
D_FREE(line);

return rc;
}

int main(int argc, char *argv[])
{
int rc;
Expand All @@ -99,7 +134,8 @@ int main(int argc, char *argv[])
.ddb_write_file = write_file,
.ddb_read_file = read_file,
.ddb_get_file_size = get_file_size,
.ddb_get_file_exists = file_exists
.ddb_get_file_exists = file_exists,
.ddb_get_lines = get_lines,
};

rc = ddb_init();
Expand Down
140 changes: 99 additions & 41 deletions src/ddb/ddb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "ddb_vos.h"
#include "ddb_cmd_options.h"

#define error_msg_write_mode_only "Can only modify the VOS tree in 'write mode'\n"

int
ddb_init()
{
Expand All @@ -27,12 +29,29 @@ ddb_fini()
}

static int
run_cmd(struct ddb_ctx *ctx, struct argv_parsed *parse_args)
run_cmd(struct ddb_ctx *ctx, const char *cmd_str, bool write_mode)
{
struct ddb_cmd_info info = {0};
int rc = 0;
struct argv_parsed parse_args = {0};
struct ddb_cmd_info info = {0};
int rc;
char *cmd_copy = strdup(cmd_str);

/* Remove newline if needed */
if (cmd_copy[strlen(cmd_copy) - 1] == '\n')
cmd_copy[strlen(cmd_copy) - 1] = '\0';

rc = ddb_str2argv_create(cmd_copy, &parse_args);
if (!SUCCESS(rc))
D_GOTO(done, rc);

ddb_parse_cmd_args(ctx, parse_args, &info);
if (parse_args.ap_argc == 0) {
D_ERROR("Nothing parsed\n");
return -DER_INVAL;
}

rc = ddb_parse_cmd_args(ctx, parse_args.ap_argc, parse_args.ap_argv, &info);
if (!SUCCESS(rc))
D_GOTO(done, rc);

switch (info.dci_cmd) {
case DDB_CMD_UNKNOWN:
Expand Down Expand Up @@ -65,12 +84,27 @@ run_cmd(struct ddb_ctx *ctx, struct argv_parsed *parse_args)
rc = ddb_run_dump_value(ctx, &info.dci_cmd_option.dci_dump_value);
break;
case DDB_CMD_RM:
/* The 'rm' command deletes branches of the tree */
if (!write_mode) {
ddb_print(ctx, error_msg_write_mode_only);
rc = -DER_INVAL;
break;
}
rc = ddb_run_rm(ctx, &info.dci_cmd_option.dci_rm);
break;
case DDB_CMD_DUMP_DTX:
rc = ddb_run_dump_dtx(ctx, &info.dci_cmd_option.dci_dump_dtx);
break;
case DDB_CMD_LOAD:
/*
* The load command loads alters the tree by modifying an existing value or
* creating a new one.
*/
if (!write_mode) {
ddb_print(ctx, error_msg_write_mode_only);
rc = -DER_INVAL;
break;
}
rc = ddb_run_load(ctx, &info.dci_cmd_option.dci_load);
break;
case DDB_CMD_COMMIT_ILOG:
Expand All @@ -80,96 +114,120 @@ run_cmd(struct ddb_ctx *ctx, struct argv_parsed *parse_args)
rc = ddb_run_rm_ilog(ctx, &info.dci_cmd_option.dci_rm_ilog);
break;
case DDB_CMD_CLEAR_CMT_DTX:
/*
* The clear_cmt_dtx command removes dtx entries.
*/
if (!write_mode) {
ddb_print(ctx, error_msg_write_mode_only);
rc = -DER_INVAL;
break;
}
rc = ddb_run_clear_cmt_dtx(ctx, &info.dci_cmd_option.dci_clear_cmt_dtx);
break;
case DDB_CMD_SMD_SYNC:
rc = ddb_run_smd_sync(ctx);
break;
}

ddb_str2argv_free(parse_args);
done:
ddb_str2argv_free(&parse_args);
D_FREE(cmd_copy);

return rc;
}

static bool
all_whitespace(const char *str, uint32_t str_len)
{
int i;

for (i = 0; i < str_len; i++) {
if (!isspace(str[i]))
return false;
}
return true;
}

static int
process_line_cb(void *cb_args, char *line, uint32_t line_len)
{
struct ddb_ctx *ctx = cb_args;

ddb_printf(ctx, "Command: %s", line);
/* ignore empty lines */
if (all_whitespace(line, line_len))
return 0;
return run_cmd(ctx, line, ctx->dc_write_mode);
}

#define str_has_value(str) ((str) != NULL && strlen(str) > 0)

int
ddb_main(struct ddb_io_ft *io_ft, int argc, char *argv[])
{
struct program_args pa = {0};
uint32_t input_buf_len = 1024;
uint32_t buf_len = input_buf_len * 2;
char *buf;
char *input_buf;
struct argv_parsed parse_args = {0};
int rc = 0;
struct ddb_ctx ctx = {0};

D_ASSERT(io_ft);
ctx.dc_io_ft = *io_ft;

D_ALLOC(buf, buf_len + 1024);
if (buf == NULL)
return -DER_NOMEM;
D_ALLOC(input_buf, input_buf_len);
if (input_buf == NULL) {
D_FREE(buf);
if (input_buf == NULL)
return -DER_NOMEM;
}

rc = ddb_parse_program_args(&ctx, argc, argv, &pa);
if (!SUCCESS(rc))
D_GOTO(done, rc);

ctx.dc_write_mode = pa.pa_write_mode;

if (str_has_value(pa.pa_r_cmd_run) && str_has_value(pa.pa_cmd_file)) {
ddb_print(&ctx, "Cannot use both '-R' and '-f'.\n");
D_GOTO(done, rc = -DER_INVAL);
}

if (str_has_value(pa.pa_pool_path)) {
rc = dv_pool_open(pa.pa_pool_path, &ctx.dc_poh);
if (!SUCCESS(rc))
D_GOTO(done, rc);
}

if (str_has_value(pa.pa_r_cmd_run)) {
/* Add program name back */
snprintf(buf, buf_len, "%s %s", argv[0], pa.pa_r_cmd_run);
rc = ddb_str2argv_create(buf, &parse_args);
if (!SUCCESS(rc)) {
dv_pool_close(ctx.dc_poh);
D_GOTO(done, rc);
}

rc = run_cmd(&ctx, &parse_args);

ddb_str2argv_free(&parse_args);
rc = run_cmd(&ctx, pa.pa_r_cmd_run, pa.pa_write_mode);
if (!SUCCESS(rc))
D_ERROR("Command '%s' failed: "DF_RC"\n", input_buf, DP_RC(rc));
D_GOTO(done, rc);
}

if (str_has_value(pa.pa_cmd_file)) {
/* Still to be implemented */
D_GOTO(done, rc = -DER_NOSYS);
if (!io_ft->ddb_get_file_exists(pa.pa_cmd_file)) {
ddb_errorf(&ctx, "Unable to access file: '%s'\n", pa.pa_cmd_file);
D_GOTO(done, rc = -DER_INVAL);
}

rc = io_ft->ddb_get_lines(pa.pa_cmd_file, process_line_cb, &ctx);
D_GOTO(done, rc);
}

while (!ctx.dc_should_quit) {
io_ft->ddb_print_message("$ ");
io_ft->ddb_get_input(input_buf, input_buf_len);
input_buf[strlen(input_buf) - 1] = '\0'; /* Remove newline */

/* add program name to beginning of string that will be parsed into argv. That way
* is the same as argv from command line into main()
*/
snprintf(buf, buf_len, "%s %s", argv[0], input_buf);
rc = ddb_str2argv_create(buf, &parse_args);
rc = run_cmd(&ctx, input_buf, pa.pa_write_mode);
if (!SUCCESS(rc)) {
ddb_errorf(&ctx, "Error with input: "DF_RC"\n", DP_RC(rc));
ddb_str2argv_free(&parse_args);
continue;
D_ERROR("Command '%s' failed: "DF_RC"\n", input_buf, DP_RC(rc));
}

rc = run_cmd(&ctx, &parse_args);
ddb_str2argv_free(&parse_args);
}

done:
D_FREE(buf);
if (daos_handle_is_valid(ctx.dc_poh)) {
int tmp_rc = dv_pool_close(ctx.dc_poh);

if (rc == 0)
rc = tmp_rc;
}
D_FREE(input_buf);

return rc;
Expand Down
13 changes: 4 additions & 9 deletions src/ddb/ddb_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,30 +100,25 @@ ddb_parse_program_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct p
{ "write_mode", no_argument, NULL, 'w' },
{ "run_cmd", required_argument, NULL, 'R' },
{ "cmd_file", required_argument, NULL, 'f' },
{ "pool", required_argument, NULL, 'p' },
{ NULL }
};
int index = 0, opt;

optind = 1;
optind = 0; /* Reinitialize getopt */
opterr = 0;
while ((opt = getopt_long(argc, argv,
"wR:f:p:", program_options, &index)) != -1) {
while ((opt = getopt_long(argc, argv, "wR:f:", program_options, &index)) != -1) {
switch (opt) {
case 'w':
pa->pa_write_mode = true;
break;
case 'R':
pa->pa_r_cmd_run = optarg;
break;
case 'f':
pa->pa_cmd_file = optarg;
break;
case 'p':
pa->pa_pool_uuid = optarg;
break;
case '?':
ddb_errorf(ctx, "'%c' is unknown\n", optopt);
return -DER_INVAL;
ddb_errorf(ctx, "'%c'(0x%x) is unknown\n", optopt, optopt);
default:
return -DER_INVAL;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ddb/ddb_parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct program_args {
char *pa_cmd_file;
char *pa_r_cmd_run;
char *pa_pool_path;
char *pa_pool_uuid;
bool pa_write_mode;
};

struct vos_file_parts {
Expand Down
Loading

0 comments on commit 5cc4d48

Please sign in to comment.