From 50534d6fb4b1f0557b45919c8efad209f68b5e26 Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Julien Date: Thu, 12 Jun 2014 15:51:13 -0400 Subject: [PATCH] Mi disable-channel command: support and validation Signed-off-by: Jonathan Rajotte Julien --- src/bin/lttng/commands/disable_channels.c | 170 ++++++++++- src/bin/lttng/commands/snapshot.c | 340 ++++++++++++++++++++-- src/common/mi-lttng.c | 254 +++++++++++++++- src/common/mi-lttng.h | 133 ++++++++- src/common/mi_lttng.xsd | 41 +++ 5 files changed, 898 insertions(+), 40 deletions(-) diff --git a/src/bin/lttng/commands/disable_channels.c b/src/bin/lttng/commands/disable_channels.c index da53d25c9..7ae2ed79a 100644 --- a/src/bin/lttng/commands/disable_channels.c +++ b/src/bin/lttng/commands/disable_channels.c @@ -23,6 +23,9 @@ #include #include #include +#include + +#include #include "../command.h" @@ -43,6 +46,7 @@ enum { }; static struct lttng_handle *handle; +static struct mi_writer *writer; static struct poptOption long_options[] = { /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ @@ -76,12 +80,57 @@ static void usage(FILE *ofp) fprintf(ofp, "\n"); } +static int mi_partial_channel_print(char *channel_name, unsigned int enabled, + int success) +{ + int ret; + + assert(writer); + assert(channel_name); + + /* Open channel element */ + ret = mi_lttng_writer_open_element(writer, config_element_channel); + if (ret) { + goto end; + } + + /* Name */ + ret = mi_lttng_writer_write_element_string(writer, config_element_name, + channel_name); + if (ret) { + goto end; + } + + /* Enabled ? */ + ret = mi_lttng_writer_write_element_bool(writer, config_element_enabled, + enabled); + if (ret) { + goto end; + } + + /* Success ? */ + ret = mi_lttng_writer_write_element_bool(writer, + mi_lttng_element_command, success); + if (ret) { + goto end; + } + + /* Closing channel element */ + ret = mi_lttng_writer_close_element(writer); + +end: + return ret; +} + /* * Disabling channel using the lttng API. */ static int disable_channels(char *session_name) { - int ret = CMD_SUCCESS, warn = 0; + int ret = CMD_SUCCESS, warn = 0, success; + + /* Normal case for disable channed is enabled = 0 */ + unsigned int enabled = 0; char *channel_name; struct lttng_domain dom; @@ -104,6 +153,17 @@ static int disable_channels(char *session_name) goto error; } + /* Prepare MI */ + if (lttng_opt_mi) { + /* open a channels element */ + ret = mi_lttng_writer_open_element(writer, config_element_channels); + if (ret) { + ret = CMD_ERROR; + goto error; + } + + } + /* Strip channel list */ channel_name = strtok(opt_channels, ","); while (channel_name != NULL) { @@ -114,9 +174,30 @@ static int disable_channels(char *session_name) ERR("Channel %s: %s (session %s)", channel_name, lttng_strerror(ret), session_name); warn = 1; + + /* + * Mi: + * We assume that if an error occurred the channel is still active. + * This might not be the case but is a good assumption. + * The client should look at the stderr stream for more informations. + */ + enabled = 1; + success = 0; + } else { MSG("%s channel %s disabled for session %s", get_domain_str(dom.type), channel_name, session_name); + enabled = 0; + success = 1; + } + + /* Print the channel */ + if (lttng_opt_mi) { + ret = mi_partial_channel_print(channel_name, enabled, success); + if (ret) { + ret = CMD_ERROR; + goto error; + } } /* Next channel */ @@ -125,8 +206,19 @@ static int disable_channels(char *session_name) ret = CMD_SUCCESS; + /* Close Mi */ + if (lttng_opt_mi) { + /* Close channels element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + ret = CMD_ERROR; + goto error; + } + } + error: - if (warn) { + /* Bypass the warning if a more important error happened */ + if (!ret && warn) { ret = CMD_WARNING; } @@ -142,7 +234,7 @@ error: */ int cmd_disable_channels(int argc, const char **argv) { - int opt, ret = CMD_SUCCESS; + int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1; static poptContext pc; char *session_name = NULL; @@ -167,13 +259,6 @@ int cmd_disable_channels(int argc, const char **argv) } } - /* TODO: mi support */ - if (lttng_opt_mi) { - ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED; - ERR("mi option not supported"); - goto end; - } - opt_channels = (char*) poptGetArg(pc); if (opt_channels == NULL) { ERR("Missing channel name(s).\n"); @@ -192,12 +277,75 @@ int cmd_disable_channels(int argc, const char **argv) session_name = opt_session_name; } - ret = disable_channels(session_name); + /* Mi check */ + if (lttng_opt_mi) { + writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); + if (!writer) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + + /* Open command element */ + ret = mi_lttng_writer_command_open(writer, + mi_lttng_element_command_disable_channel); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Open output element */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_output); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } + + command_ret = disable_channels(session_name); + if (command_ret) { + success = 0; + } + + /* Mi closing */ + if (lttng_opt_mi) { + /* Close output element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Success ? */ + ret = mi_lttng_writer_write_element_bool(writer, + mi_lttng_element_success, success); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Command element close */ + ret = mi_lttng_writer_command_close(writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } end: + /* Mi clean-up */ + if (writer && mi_lttng_writer_destroy(writer)) { + /* Preserve original error code */ + ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL; + } + if (!opt_session_name && session_name) { free(session_name); } + + /* Overwrite ret if an error occurred in disable_channels */ + ret = command_ret ? command_ret : ret; + poptFreeContext(pc); return ret; } diff --git a/src/bin/lttng/commands/snapshot.c b/src/bin/lttng/commands/snapshot.c index 564651e09..ebe1d14aa 100644 --- a/src/bin/lttng/commands/snapshot.c +++ b/src/bin/lttng/commands/snapshot.c @@ -25,8 +25,10 @@ #include #include #include +#include #include +#include #include #include "../command.h" @@ -53,6 +55,8 @@ enum { OPT_LIST_COMMANDS, }; +static struct mi_writer *writer; + static struct poptOption snapshot_opts[] = { /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0}, @@ -181,6 +185,52 @@ error_create: return NULL; } +static int mi_list_output(void) +{ + int ret; + struct lttng_snapshot_output *s_iter; + struct lttng_snapshot_output_list *list; + + assert(writer); + + ret = lttng_snapshot_list_output(current_session_name, &list); + if (ret < 0) { + goto error; + } + + ret = mi_lttng_snapshot_output_session_name(writer, current_session_name); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + while ((s_iter = lttng_snapshot_output_list_get_next(list)) != NULL) { + ret = mi_lttng_snapshot_list_output(writer, s_iter); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } + + + /* Close snapshot snapshots element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Close snapshot session element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + ret = CMD_ERROR; + } +end: + lttng_snapshot_output_list_destroy(list); +error: + return ret; +} + static int list_output(void) { int ret, output_seen = 0; @@ -213,6 +263,51 @@ error: return ret; } +/* + * Delete output by ID (machine interface version). + */ +static int mi_del_output(uint32_t id, const char *name) +{ + int ret; + struct lttng_snapshot_output *output = NULL; + + assert(writer); + + output = lttng_snapshot_output_create(); + if (!output) { + ret = CMD_FATAL; + goto error; + } + + if (name) { + ret = lttng_snapshot_output_set_name(name, output); + } else if (id != UINT32_MAX) { + ret = lttng_snapshot_output_set_id(id, output); + } else { + ret = CMD_ERROR; + goto error; + } + if (ret < 0) { + ret = CMD_FATAL; + goto error; + } + + ret = lttng_snapshot_del_output(current_session_name, output); + if (ret < 0) { + ret = CMD_FATAL; + goto error; + } + + ret = mi_lttng_snapshot_del_output(writer, id, name, current_session_name); + if (ret) { + ret = CMD_ERROR; + } + +error: + lttng_snapshot_output_destroy(output); + return ret; +} + /* * Delete output by ID. */ @@ -258,6 +353,56 @@ error: return ret; } +/* + * Add output from the user URL (machine interface). + */ +static int mi_add_output(const char *url) +{ + int ret; + struct lttng_snapshot_output *output = NULL; + char name[NAME_MAX]; + const char *n_ptr; + + if (!url && (!opt_data_url || !opt_ctrl_url)) { + ret = CMD_ERROR; + goto error; + } + + output = create_output_from_args(url); + if (!output) { + ret = CMD_FATAL; + goto error; + } + + /* This call, if successful, populates the id of the output object. */ + ret = lttng_snapshot_add_output(current_session_name, output); + if (ret < 0) { + ret = CMD_ERROR; + goto error; + } + + n_ptr = lttng_snapshot_output_get_name(output); + if (*n_ptr == '\0') { + int pret; + pret = snprintf(name, sizeof(name), DEFAULT_SNAPSHOT_NAME "-%" PRIu32, + lttng_snapshot_output_get_id(output)); + if (pret < 0) { + PERROR("snprintf add output name"); + } + n_ptr = name; + } + + ret = mi_lttng_snapshot_add_output(writer, current_session_name, n_ptr, + output); + if (ret) { + ret = CMD_ERROR; + } + +error: + lttng_snapshot_output_destroy(output); + return ret; +} + /* * Add output from the user URL. */ @@ -309,7 +454,7 @@ error: static int cmd_add_output(int argc, const char **argv) { - int ret = CMD_SUCCESS; + int ret; if (argc < 2 && (!opt_data_url || !opt_ctrl_url)) { usage(stderr); @@ -317,7 +462,11 @@ static int cmd_add_output(int argc, const char **argv) goto end; } - ret = add_output(argv[1]); + if (lttng_opt_mi) { + ret = mi_add_output(argv[1]); + } else { + ret = add_output(argv[1]); + } end: return ret; @@ -325,7 +474,7 @@ end: static int cmd_del_output(int argc, const char **argv) { - int ret = CMD_SUCCESS; + int ret; char *name; long id; @@ -338,9 +487,17 @@ static int cmd_del_output(int argc, const char **argv) errno = 0; id = strtol(argv[1], &name, 10); if (id == 0 && errno == 0) { - ret = del_output(UINT32_MAX, name); + if (lttng_opt_mi) { + ret = mi_del_output(UINT32_MAX, name); + } else { + ret = del_output(UINT32_MAX, name); + } } else if (errno == 0 && *name == '\0') { - ret = del_output(id, NULL); + if (lttng_opt_mi) { + ret = mi_del_output(id, NULL); + } else { + ret = del_output(id, NULL); + } } else { ERR("Argument %s not recognized", argv[1]); ret = -1; @@ -353,7 +510,46 @@ end: static int cmd_list_output(int argc, const char **argv) { - return list_output(); + int ret; + + if (lttng_opt_mi) { + ret = mi_list_output(); + } else { + ret = list_output(); + } + + return ret; +} + +/* + * Do a snapshot record with the URL if one is given (machine interface). + */ +static int mi_record(const char *url) +{ + int ret; + struct lttng_snapshot_output *output = NULL; + + output = create_output_from_args(url); + if (!output) { + ret = CMD_FATAL; + goto error; + } + + ret = lttng_snapshot_record(current_session_name, output, 0); + if (ret < 0) { + ret = CMD_ERROR; + goto error; + } + + ret = mi_lttng_snapshot_record(writer, current_session_name, url, + opt_ctrl_url, opt_data_url); + if (ret) { + ret = CMD_ERROR; + } + +error: + lttng_snapshot_output_destroy(output); + return ret; } /* @@ -400,9 +596,17 @@ static int cmd_record(int argc, const char **argv) if (argc == 2) { /* With a given URL */ - ret = record(argv[1]); + if (lttng_opt_mi) { + ret = mi_record(argv[1]); + } else { + ret = record(argv[1]); + } } else { - ret = record(NULL); + if (lttng_opt_mi) { + ret = mi_record(NULL); + } else { + ret = record(NULL); + } } return ret; @@ -410,13 +614,13 @@ static int cmd_record(int argc, const char **argv) static int handle_command(const char **argv) { - int ret, i = 0, argc; + int ret = CMD_SUCCESS, i = 0, argc, command_ret = CMD_SUCCESS; struct cmd_struct *cmd; if (argv == NULL || (!opt_ctrl_url && opt_data_url) || (opt_ctrl_url && !opt_data_url)) { usage(stderr); - ret = CMD_ERROR; + command_ret = CMD_ERROR; goto end; } @@ -426,37 +630,90 @@ static int handle_command(const char **argv) while (cmd->func != NULL) { /* Find command */ if (strcmp(argv[0], cmd->name) == 0) { - ret = cmd->func(argc, argv); + if (lttng_opt_mi) { + /* Action element */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_action); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Name of the action */ + ret = mi_lttng_writer_write_element_string(writer, + config_element_name, argv[0]); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Open output element */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_output); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } + + command_ret = cmd->func(argc, argv); + + if (lttng_opt_mi) { + /* Close output and action element */ + ret = mi_lttng_close_multi_element(writer, 2); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } goto end; } i++; cmd = &actions[i]; } - /* Command not found */ - ret = CMD_UNDEFINED; + ret = -CMD_UNDEFINED; end: + /* Overwrite ret if an error occured in cmd->func() */ + ret = command_ret ? command_ret : ret; return ret; } - /* * The 'snapshot ' first level command */ int cmd_snapshot(int argc, const char **argv) { - int opt, ret = CMD_SUCCESS; + int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1; char *session_name = NULL; static poptContext pc; pc = poptGetContext(NULL, argc, argv, snapshot_opts, 0); poptReadDefaultConfig(pc, 0); - /* TODO: mi support */ + /* Mi check */ if (lttng_opt_mi) { - ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED; - ERR("mi option not supported"); - goto end; + writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); + if (!writer) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + + /* Open command element */ + ret = mi_lttng_writer_command_open(writer, + mi_lttng_element_command_snapshot); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Open output element */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_output); + if (ret) { + ret = CMD_ERROR; + goto end; + } } while ((opt = poptGetNextOpt(pc)) != -1) { @@ -503,26 +760,59 @@ int cmd_snapshot(int argc, const char **argv) current_session_name = opt_session_name; } - ret = handle_command(poptGetArgs(pc)); - if (ret < 0) { - switch (-ret) { + command_ret = handle_command(poptGetArgs(pc)); + if (command_ret < 0) { + switch (-command_ret) { case LTTNG_ERR_EPERM: ERR("The session needs to be set in no output mode (--no-output)"); break; case LTTNG_ERR_SNAPSHOT_NODATA: - WARN("%s", lttng_strerror(ret)); + WARN("%s", lttng_strerror(command_ret)); break; default: - ERR("%s", lttng_strerror(ret)); + ERR("%s", lttng_strerror(command_ret)); break; } - goto end; + success = 0; + } + + if (lttng_opt_mi) { + /* Close output element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Success ? */ + ret = mi_lttng_writer_write_element_bool(writer, + mi_lttng_element_command_success, success); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Command element close */ + ret = mi_lttng_writer_command_close(writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } } end: + /* Mi clean-up */ + if (writer && mi_lttng_writer_destroy(writer)) { + /* Preserve original error code */ + ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL; + } + if (!opt_session_name) { free(session_name); } + + /* Overwrite ret if an error occured during handle_command */ + ret = command_ret ? command_ret : ret; poptFreeContext(pc); return ret; } diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index 7d5e9c6f9..1b65ddd4c 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -19,6 +19,7 @@ #include #include +#include #include "mi-lttng.h" #include @@ -40,6 +41,8 @@ const char * const mi_lttng_element_command_add_context = "add-context"; const char * const mi_lttng_element_command_enable_channels = "enable-channel"; const char * const mi_lttng_element_command_set_session = "set-session"; const char * const mi_lttng_element_command_disable_event = "disable-event"; +const char * const mi_lttng_element_command_disable_channel = "disable-channel"; +const char * const mi_lttng_element_command_action = "snapshot_action"; const char * const mi_lttng_element_command_output = "output"; const char * const mi_lttng_element_command_success = "success"; @@ -53,11 +56,15 @@ const char * const mi_lttng_element_version_commit = "commit"; const char * const mi_lttng_element_version_license = "license"; const char * const mi_lttng_element_version_patch_level = "patchLevel"; const char * const mi_lttng_element_version_description = "description"; +const char * const mi_lttng_element_command_snapshot = "snapshot"; +const char * const mi_lttng_element_command_list_snapshot = "list_snapshot"; +const char * const mi_lttng_element_command_del_snapshot = "del_snapshot"; +const char * const mi_lttng_element_command_add_snapshot = "add_snapshot"; +const char * const mi_lttng_element_command_record_snapshot = "record_snapshot"; /* Strings related to pid */ const char * const mi_lttng_element_pids = "pids"; const char * const mi_lttng_element_pid = "pid"; -const char * const mi_lttng_element_pid_id = "id"; /* Strings related to save command */ const char * const mi_lttng_element_save = "save"; @@ -85,6 +92,8 @@ const char * const mi_lttng_element_type_float = "FLOAT"; const char * const mi_lttng_element_type_string = "STRING"; const char * const mi_lttng_element_nowrite = "nowrite"; const char * const mi_lttng_element_success = "success"; +const char * const mi_lttng_element_id = "id"; +const char * const mi_lttng_element_empty = ""; /* String related to loglevel */ const char * const mi_lttng_loglevel_str_alert = "TRACE_ALERT"; @@ -114,7 +123,13 @@ const char * const mi_lttng_loglevel_type_unknown = "UNKNOWN"; const char * const mi_lttng_element_calibrate = "calibrate"; const char * const mi_lttng_element_calibrate_function = "FUNCTION"; -const char * const mi_lttng_element_empty = ""; +/* String related to a lttng_snapshot_output */ +const char * const mi_lttng_element_snapshots = "snapshots"; +const char * const mi_lttng_element_snapshot_session_name = "session_name"; +const char * const mi_lttng_element_snapshot_n_ptr = "n_ptr"; +const char * const mi_lttng_element_snapshot_data_url = "data_url"; +const char * const mi_lttng_element_snapshot_ctrl_url = "ctrl_url"; +const char * const mi_lttng_element_snapshot_max_size = "max_size"; const char *mi_lttng_loglevel_string(int value) { @@ -1151,3 +1166,238 @@ int mi_lttng_perf_counter_context(struct mi_writer *writer, end: return ret; } + +LTTNG_HIDDEN +int mi_lttng_snapshot_output_session_name(struct mi_writer *writer, + const char *session_name) +{ + int ret; + + /* Open session element */ + ret = mi_lttng_writer_open_element(writer, config_element_session); + if (ret) { + goto end; + } + + /* Snapshot output list for current session name */ + ret = mi_lttng_writer_write_element_string(writer, config_element_name, + session_name); + + /* Open element snapshots (sequence one snapshot) */ + ret = mi_lttng_writer_open_element(writer, mi_lttng_element_snapshots); + if (ret) { + goto end; + } + +end: + return ret; +} + +LTTNG_HIDDEN +int mi_lttng_snapshot_list_output(struct mi_writer *writer, + struct lttng_snapshot_output *output) +{ + int ret; + + /* Open element snapshot output */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_snapshot); + if (ret) { + goto end; + } + + /* ID of the snapshot output */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_id, output->id); + if (ret) { + goto end; + } + + /* Name of the output */ + ret = mi_lttng_writer_write_element_string(writer, config_element_name, + output->name); + if (ret) { + goto end; + } + + /* Destination of the output (ctrl_url)*/ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_ctrl_url, output->ctrl_url); + if (ret) { + goto end; + } + + /* Destination of the output (data_url) */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_data_url, output->data_url); + if (ret) { + goto end; + } + + /* total size of all stream combined */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_snapshot_max_size, output->max_size); + if (ret) { + goto end; + } + + /* Close snapshot output element */ + ret = mi_lttng_writer_close_element(writer); + +end: + return ret; +} + +LTTNG_HIDDEN +int mi_lttng_snapshot_del_output(struct mi_writer *writer, int id, + const char *name, const char *current_session_name) +{ + int ret; + + /* Open element del_snapshot */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_snapshot); + if (ret) { + goto end; + } + + + if (id != UINT32_MAX) { + /* "Snapshot output "id" successfully deleted + * for "current_session_name" + * ID of the snapshot output + */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_id, id); + if (ret) { + goto end; + } + } else { + /* "Snapshot output "name" successfully deleted + * for session "current_session_name" + * Name of the output + */ + ret = mi_lttng_writer_write_element_string(writer, config_element_name, + name); + if (ret) { + goto end; + } + } + + /* Snapshot was deleted for session "current_session_name"*/ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_session_name, + current_session_name); + if (ret) { + goto end; + } + + /* Close snapshot element */ + ret = mi_lttng_writer_close_element(writer); + +end: + return ret; +} + +LTTNG_HIDDEN +int mi_lttng_snapshot_add_output(struct mi_writer *writer, + const char *current_session_name, const char *n_ptr, + struct lttng_snapshot_output *output) +{ + int ret; + + /* Open element snapshot */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_snapshot); + if (ret) { + goto end; + } + + /* Snapshot output id */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_id, output->id); + if (ret) { + goto end; + } + + /* Snapshot output names */ + ret = mi_lttng_writer_write_element_string(writer, + config_element_name, n_ptr); + if (ret) { + goto end; + } + + /* Destination of the output (ctrl_url)*/ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_ctrl_url, output->ctrl_url); + if (ret) { + goto end; + } + + /* Snapshot added for session "current_session_name"*/ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_session_name, current_session_name); + if (ret) { + goto end; + } + + /* total size of all stream combined */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_snapshot_max_size, output->max_size); + if (ret) { + goto end; + } + + /* Close snapshot element */ + ret = mi_lttng_writer_close_element(writer); + +end: + return ret; +} + +LTTNG_HIDDEN +int mi_lttng_snapshot_record(struct mi_writer *writer, + const char *current_session_name, const char *url, + const char *cmdline_ctrl_url, const char *cmdline_data_url) +{ + int ret; + + /* Open element snapshot */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_snapshot); + if (ret) { + goto end; + } + + /* + * If a valid an URL was given, serialize it, + * else take the command line data and ctrl urls*/ + if (url) { + /* Destination of the output (ctrl_url)*/ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_ctrl_url, url); + if (ret) { + goto end; + } + } else if (cmdline_ctrl_url) { + /* Destination of the output (ctrl_url)*/ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_ctrl_url, cmdline_ctrl_url); + if (ret) { + goto end; + } + + /* Destination of the output (data_url) */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_data_url, cmdline_data_url); + if (ret) { + goto end; + } + } + + /* Close record_snapshot element */ + ret = mi_lttng_writer_close_element(writer); + +end: + return ret; +} diff --git a/src/common/mi-lttng.h b/src/common/mi-lttng.h index 9d7edaf44..6215df567 100644 --- a/src/common/mi-lttng.h +++ b/src/common/mi-lttng.h @@ -26,6 +26,9 @@ #include #include +/* Don't want to reference snapshot-internal.h here */ +struct lttng_snapshot_output; + /* Instance of a machine interface writer. */ struct mi_writer { struct config_writer *writer; @@ -48,6 +51,7 @@ struct mi_lttng_version { /* Strings related to command */ const char * const mi_lttng_element_command; const char * const mi_lttng_element_command_name; +const char * const mi_lttng_element_command_action; const char * const mi_lttng_element_command_version; const char * const mi_lttng_element_command_enable_event; const char * const mi_lttng_element_command_list; @@ -62,6 +66,12 @@ const char * const mi_lttng_element_command_add_context; const char * const mi_lttng_element_command_enable_channels; const char * const mi_lttng_element_command_set_session; const char * const mi_lttng_element_command_disable_event; +const char * const mi_lttng_element_command_disable_channel; +const char * const mi_lttng_element_command_snapshot; +const char * const mi_lttng_element_command_list_snapshot; +const char * const mi_lttng_element_command_del_snapshot; +const char * const mi_lttng_element_command_add_snapshot; +const char * const mi_lttng_element_command_record_snapshot; const char * const mi_lttng_element_command_output; const char * const mi_lttng_element_command_success; @@ -136,6 +146,14 @@ const char * const mi_lttng_loglevel_type_unknown; const char * const mi_lttng_element_calibrate; const char * const mi_lttng_element_calibrate_function; +/* String related to a lttng_snashot */ +const char * const mi_lttng_element_snapshots; +const char * const mi_lttng_element_snapshot_session_name; +const char * const mi_lttng_element_snapshot_n_ptr; +const char * const mi_lttng_element_snapshot_data_url; +const char * const mi_lttng_element_snapshot_ctrl_url; +const char * const mi_lttng_element_snapshot_max_size; + /* Utility string function */ const char *mi_lttng_loglevel_string(int value); const char *mi_lttng_logleveltype_string(enum lttng_loglevel_type value); @@ -553,8 +571,6 @@ int mi_lttng_calibrate(struct mi_writer *writer, * is_open Define if we close the context element * This should be used carefully and the client * need to close the context element. - * 0-> False - * 1-> True * Returns zero if the element's value could be written. * Negative values indicate an error. */ @@ -574,4 +590,117 @@ int mi_lttng_context(struct mi_writer *writer, int mi_lttng_perf_counter_context(struct mi_writer *writer, struct lttng_event_perf_counter_ctx *perf_context); +/* + * Machine interface of the snapshot list_output. + * It specifies the session for which we are listing snapshots, + * and it opens a snapshots element to list a sequence + * of snapshots. + * + * writer An instance of a machine interface writer. + * + * session_name: Snapshot output for session "session_name". + * + * Note: The client has to close the session and the snapshots elements after + * having listed every lttng_snapshot_output. + * + * Returns zero if the element's value could be written. + * Negative values indicate an error. + */ +int mi_lttng_snapshot_output_session_name(struct mi_writer *writer, + const char *session_name); + +/* + * Machine interface of the snapshot output. + * The machine interface serializes the following attributes: + * - id: ID of the snapshot output. + * - name: Name of the output. + * - data_url : Destination of the output. + * - ctrl_url: Destination of the output. + * - max_size: total size of all stream combined. + * + * writer An instance of a machine interface writer. + * + * output: A list of snapshot_output. + * + * Returns zero if the element's value could be written. + * Negative values indicate an error. + */ +int mi_lttng_snapshot_list_output(struct mi_writer *writer, + struct lttng_snapshot_output *output); + +/* + * Machine interface of the output of the command snapshot del output + * when deleting a snapshot either by id or by name. + * If the snapshot was found and successfully deleted using its id, + * it return the id of the snapshot and the current session name on which it + * was attached. + * + * Otherwise, it do the same process with the name of the snapshot, if the + * snapshot output id is undefined. + * + * writer An instance of a machine interface writer. + * + * id: ID of the snapshot output. + * + * name: Name of the snapshot. + * + * current_session_name: Session to which the snapshot belongs. + * + * Returns zero if the element's value could be written. + * Negative values indicate an error. + */ +int mi_lttng_snapshot_del_output(struct mi_writer *writer, int id, + const char *name, const char *current_session_name); + +/* + * Machine interface of the output of the command snapshot add output + * when adding a snapshot from a user URL. + * + * If the snapshot was successfully added, the machine interface lists + * these information: + * - id: ID of the newly add snapshot output. + * - current_session_name: Name of the session to which the output was added. + * - ctrl_url: Destination of the output. + * - max_size: total size of all stream combined. + * + * writer An instance of a machine interface writer. + * + * current_session_name: Session to which the snapshot belongs. + * + * n_ptr: + * + * output: iterator over a lttng_snapshot_output_list which contain + * the snapshot output informations. + * + * Returns zero if the element's value could be written. + * Negative values indicate an error. + */ +int mi_lttng_snapshot_add_output(struct mi_writer *writer, + const char *current_session_name, const char *n_ptr, + struct lttng_snapshot_output *output); + +/* + * Machine interface of the output of the command snapshot + * record from a URL (if given). + * + * If the snapshot is successfully recorded from a url, the machine interface + * output the following information: + * - url: Destination of the output stored in the snapshot. + * + * Otherwise, the machine interface output the data and ctrl url received + * from the command-line. + * + * writer An instance of a machine interface writer. + * + * current_session_name: Snapshot record for session "current_session_name". + * + * ctrl_url, data_url: Destination of the output receive from the command-line. + * + * Returns zero if the element's value could be written. + * Negative values indicate an error. + */ +int mi_lttng_snapshot_record(struct mi_writer *writer, + const char *current_session_name, const char *url, + const char *cmdline_ctrl_url, const char *cmdline_data_url); + #endif /* _MI_LTTNG_H */ diff --git a/src/common/mi_lttng.xsd b/src/common/mi_lttng.xsd index 4535040bc..2b28a314b 100644 --- a/src/common/mi_lttng.xsd +++ b/src/common/mi_lttng.xsd @@ -285,6 +285,24 @@ THE SOFTWARE. + + + + + + + + + + + + + + + + + + @@ -300,6 +318,7 @@ THE SOFTWARE. + @@ -377,11 +396,30 @@ THE SOFTWARE. + + + + + + + + + + + + + + + + + + + @@ -390,6 +428,7 @@ THE SOFTWARE. + @@ -398,6 +437,7 @@ THE SOFTWARE. + @@ -410,6 +450,7 @@ THE SOFTWARE. + -- 2.34.1