From: Jonathan Rajotte Julien Date: Wed, 18 Jun 2014 19:22:11 +0000 (-0400) Subject: Mi add-context command: support and validation X-Git-Tag: v2.6.0-rc1~122 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=89b725777551ead53c60d1bd56ee7182fe539251 Mi add-context command: support and validation Signed-off-by: Jonathan Rajotte Julien --- diff --git a/src/bin/lttng/commands/add_context.c b/src/bin/lttng/commands/add_context.c index 2f7559c30..e50ed84b6 100644 --- a/src/bin/lttng/commands/add_context.c +++ b/src/bin/lttng/commands/add_context.c @@ -27,6 +27,8 @@ #include +#include + #include "../command.h" #define PRINT_LINE_LEN 80 @@ -36,6 +38,7 @@ static char *opt_session_name; static int opt_kernel; static int opt_userspace; static char *opt_type; + #if 0 /* Not implemented yet */ static char *opt_cmd_name; @@ -50,6 +53,7 @@ enum { }; static struct lttng_handle *handle; +static struct mi_writer *writer; /* * Taken from the LTTng ABI @@ -549,7 +553,7 @@ end: */ static int add_context(char *session_name) { - int ret = CMD_SUCCESS, warn = 0; + int ret = CMD_SUCCESS, warn = 0, success = 0; struct lttng_event_context context; struct lttng_domain dom; struct ctx_type *type; @@ -574,6 +578,14 @@ static int add_context(char *session_name) goto error; } + if (lttng_opt_mi) { + /* Open a contexts element */ + ret = mi_lttng_writer_open_element(writer, config_element_contexts); + if (ret) { + goto error; + } + } + /* Iterate over all the context types given */ cds_list_for_each_entry(type, &ctx_type_list.head, list) { context.ctx = (enum lttng_event_context_type) type->opt->ctx_type; @@ -599,11 +611,20 @@ static int add_context(char *session_name) } DBG("Adding context..."); + if (lttng_opt_mi) { + /* We leave context open the update the success of the command */ + ret = mi_lttng_context(writer, &context, 1); + if (ret) { + ret = CMD_ERROR; + goto error; + } + } + ret = lttng_add_context(handle, &context, NULL, opt_channel_name); if (ret < 0) { ERR("%s: %s", type->opt->symbol, lttng_strerror(ret)); warn = 1; - continue; + success = 0; } else { if (opt_channel_name) { MSG("%s context %s added to channel %s", @@ -613,6 +634,32 @@ static int add_context(char *session_name) MSG("%s context %s added to all channels", opt_kernel ? "kernel" : "UST", type->opt->symbol) } + success = 1; + } + + if (lttng_opt_mi) { + /* Is the single operation a success ? */ + ret = mi_lttng_writer_write_element_bool(writer, + mi_lttng_element_success, success); + if (ret) { + ret = CMD_ERROR; + goto error; + } + + /* Close the context element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + ret = CMD_ERROR; + goto error; + } + } + } + + if (lttng_opt_mi) { + /* Close contexts element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto error; } } @@ -625,7 +672,7 @@ error: * This means that at least one add_context failed and tells the user to * look on stderr for error(s). */ - if (warn) { + if (!ret && warn) { ret = CMD_WARNING; } return ret; @@ -636,7 +683,8 @@ error: */ int cmd_add_context(int argc, const char **argv) { - int index, opt, ret = CMD_SUCCESS; + int index, opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS; + int success = 1; static poptContext pc; struct ctx_type *type, *tmptype; char *session_name = NULL; @@ -647,13 +695,6 @@ int cmd_add_context(int argc, const char **argv) goto end; } - /* TODO: mi support */ - if (lttng_opt_mi) { - ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED; - ERR("mi option not supported"); - goto end; - } - pc = poptGetContext(NULL, argc, argv, long_options, 0); poptReadDefaultConfig(pc, 0); @@ -724,18 +765,80 @@ int cmd_add_context(int argc, const char **argv) session_name = opt_session_name; } - ret = add_context(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_add_context); + 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 = add_context(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_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: if (!opt_session_name) { free(session_name); } -end: + /* Mi clean-up */ + if (writer && mi_lttng_writer_destroy(writer)) { + /* Preserve original error code */ + ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL; + } + /* Cleanup allocated memory */ cds_list_for_each_entry_safe(type, tmptype, &ctx_type_list.head, list) { free(type); } + /* Overwrite ret if an error occurred during add_context() */ + 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 2fb1c1905..515f16941 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -35,6 +35,7 @@ const char * const mi_lttng_element_command_stop = "stop"; const char * const mi_lttng_element_command_create = "create"; const char * const mi_lttng_element_command_destroy = "destroy"; const char * const mi_lttng_element_command_calibrate = "calibrate"; +const char * const mi_lttng_element_command_add_context = "add-context"; const char * const mi_lttng_element_command_output = "output"; const char * const mi_lttng_element_command_success = "success"; @@ -64,6 +65,14 @@ const char * const mi_lttng_element_load = "load"; const char * const mi_lttng_element_event_field = "event_field"; const char * const mi_lttng_element_event_fields = "event_fields"; +/* String related to lttng_event_context */ +const char * const mi_lttng_context_type_perf_counter = "PERF_COUNTER"; +const char * const mi_lttng_context_type_perf_cpu_counter = "PERF_CPU_COUNTER"; +const char * const mi_lttng_context_type_perf_thread_counter = "PERF_THREAD_COUNTER"; + +/* String related to lttng_event_perf_counter_ctx */ +const char * const mi_lttng_element_perf_counter_context = "perf_counter_context"; + /* General elements of mi_lttng */ const char * const mi_lttng_element_type_other = "OTHER"; const char * const mi_lttng_element_type_integer = "INTEGER"; @@ -71,6 +80,7 @@ const char * const mi_lttng_element_type_enum = "ENUM"; 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"; /* String related to loglevel */ const char * const mi_lttng_loglevel_str_alert = "TRACE_ALERT"; @@ -178,6 +188,44 @@ const char *mi_lttng_eventtype_string(enum lttng_event_type value) } } +const char *mi_lttng_event_contexttype_string(enum lttng_event_context_type val) +{ + switch (val) { + case LTTNG_EVENT_CONTEXT_PID: + return config_event_context_pid; + case LTTNG_EVENT_CONTEXT_PERF_COUNTER: + return mi_lttng_context_type_perf_counter; + case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER: + return mi_lttng_context_type_perf_thread_counter; + case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER: + return mi_lttng_context_type_perf_cpu_counter; + case LTTNG_EVENT_CONTEXT_PROCNAME: + return config_event_context_procname; + case LTTNG_EVENT_CONTEXT_PRIO: + return config_event_context_prio; + case LTTNG_EVENT_CONTEXT_NICE: + return config_event_context_nice; + case LTTNG_EVENT_CONTEXT_VPID: + return config_event_context_vpid; + case LTTNG_EVENT_CONTEXT_TID: + return config_event_context_tid; + case LTTNG_EVENT_CONTEXT_VTID: + return config_event_context_vtid; + case LTTNG_EVENT_CONTEXT_PPID: + return config_event_context_ppid; + case LTTNG_EVENT_CONTEXT_VPPID: + return config_event_context_vppid; + case LTTNG_EVENT_CONTEXT_PTHREAD_ID: + return config_event_context_pthread_id; + case LTTNG_EVENT_CONTEXT_HOSTNAME: + return config_event_context_hostname; + case LTTNG_EVENT_CONTEXT_IP: + return config_event_context_ip; + default: + return NULL; + } +} + const char *mi_lttng_eventfieldtype_string(enum lttng_event_field_type val) { switch (val) { @@ -1014,3 +1062,90 @@ int mi_lttng_calibrate(struct mi_writer *writer, end: return ret; } +LTTNG_HIDDEN +int mi_lttng_context(struct mi_writer *writer, + struct lttng_event_context *context, int is_open) +{ + int ret; + const char *type_string; + struct lttng_event_perf_counter_ctx *perf_context; + /* Open context */ + ret = mi_lttng_writer_open_element(writer , config_element_context); + if (ret) { + goto end; + } + + type_string = mi_lttng_event_contexttype_string(context->ctx); + if (!type_string) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + /* Print context type */ + ret = mi_lttng_writer_write_element_string(writer, config_element_type, + type_string); + + /* Special case for PERF_*_COUNTER + * print the lttng_event_perf_counter_ctx*/ + switch (context->ctx) { + case LTTNG_EVENT_CONTEXT_PERF_COUNTER: + case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER: + case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER: + perf_context = &context->u.perf_counter; + ret = mi_lttng_perf_counter_context(writer, perf_context); + if (ret) { + goto end; + } + break; + default: + break; + } + + /* Close context */ + if (!is_open) { + ret = mi_lttng_writer_close_element(writer); + } + +end: + return ret; +} + +LTTNG_HIDDEN +int mi_lttng_perf_counter_context(struct mi_writer *writer, + struct lttng_event_perf_counter_ctx *perf_context) +{ + int ret; + + /* Open perf_counter_context */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_perf_counter_context); + if (ret) { + goto end; + } + + /* Type */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + config_element_type, perf_context->type); + if (ret) { + goto end; + } + + /* Config */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + config_element_config, perf_context->config); + if (ret) { + goto end; + } + + /* Name of the perf counter */ + ret = mi_lttng_writer_write_element_string(writer, + config_element_name, perf_context->name); + if (ret) { + goto end; + } + + /* Close perf_counter_context */ + 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 1c2a653a4..a3a087036 100644 --- a/src/common/mi-lttng.h +++ b/src/common/mi-lttng.h @@ -57,6 +57,7 @@ const char * const mi_lttng_element_command_start; const char * const mi_lttng_element_command_create; const char * const mi_lttng_element_command_destroy; const char * const mi_lttng_element_command_calibrate; +const char * const mi_lttng_element_command_add_context; const char * const mi_lttng_element_command_output; const char * const mi_lttng_element_command_success; @@ -75,6 +76,14 @@ const char * const mi_lttng_element_version_description; const char * const mi_lttng_element_event_field; const char * const mi_lttng_element_event_fields; +/* String related to lttng_event_context */ +const char * const mi_lttng_context_type_perf_counter; +const char * const mi_lttng_context_type_perf_cpu_counter; +const char * const mi_lttng_context_type_perf_thread_counter; + +/* String related to lttng_event_perf_counter_ctx */ +const char * const mi_lttng_element_perf_counter_context; + /* Strings related to pid */ const char * const mi_lttng_element_pids; const char * const mi_lttng_element_pid; @@ -93,6 +102,7 @@ const char * const mi_lttng_element_type_enum; const char * const mi_lttng_element_type_float; const char * const mi_lttng_element_type_string; const char * const mi_lttng_element_nowrite; +const char * const mi_lttng_element_success; /* String related to loglevel */ const char * const mi_lttng_loglevel_str_alert; @@ -483,7 +493,7 @@ int mi_lttng_event_field(struct mi_writer *writer, * * writer An instance of a machine interface writer. * - * Returns zero if the element's value could be written. + * Returns zero if the element could be written. * Negative values indicate an error. */ int mi_lttng_event_fields_open(struct mi_writer *writer); @@ -529,4 +539,35 @@ int mi_lttng_pid(struct mi_writer *writer, pid_t pid , const char *cmdline, int mi_lttng_calibrate(struct mi_writer *writer, struct lttng_calibrate *calibrate); +/* + * Machine interface of a context. + * + * writer An instance of a machine interface writer + * + * context An instance of a lttng_event_context + * + * 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. + */ +int mi_lttng_context(struct mi_writer *writer, + struct lttng_event_context *context, int is_open); + +/* + * Machine interface of a perf_counter_context. + * + * writer An instance of a machine interface writer + * + * contest An instance of a lttng_event_perf_counter_ctx + * + * Returns zero if the element's value could be written. + * Negative values indicate an error. + */ +int mi_lttng_perf_counter_context(struct mi_writer *writer, + struct lttng_event_perf_counter_ctx *perf_context); + #endif /* _MI_LTTNG_H */ diff --git a/src/common/mi_lttng.xsd b/src/common/mi_lttng.xsd index 884830d1c..ebf20854b 100644 --- a/src/common/mi_lttng.xsd +++ b/src/common/mi_lttng.xsd @@ -83,6 +83,27 @@ THE SOFTWARE. + + + + + + + + + + + + + + + + + + + + + @@ -305,6 +326,25 @@ THE SOFTWARE. + + + + + + + + + + + + + + + + + + + @@ -323,6 +363,12 @@ THE SOFTWARE. + + + + + + @@ -332,6 +378,7 @@ THE SOFTWARE. + @@ -347,6 +394,7 @@ THE SOFTWARE. +