Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DAOS-10418 ddb: More program options #9210

Merged
merged 3 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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;
ryon-jensen marked this conversation as resolved.
Show resolved Hide resolved
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) {
ryon-jensen marked this conversation as resolved.
Show resolved Hide resolved
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);
ryon-jensen marked this conversation as resolved.
Show resolved Hide resolved
ryon-jensen marked this conversation as resolved.
Show resolved Hide resolved
ryon-jensen marked this conversation as resolved.
Show resolved Hide resolved
ryon-jensen marked this conversation as resolved.
Show resolved Hide resolved
/* 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