*/
#define _GNU_SOURCE
+#define _LGPL_SOURCE
#include <ctype.h>
#include <popt.h>
#include <stdio.h>
#include <urcu/list.h>
+#include <common/mi-lttng.h>
+
#include "../command.h"
#define PRINT_LINE_LEN 80
static int opt_kernel;
static int opt_userspace;
static char *opt_type;
+
#if 0
/* Not implemented yet */
static char *opt_cmd_name;
};
static struct lttng_handle *handle;
+static struct mi_writer *writer;
/*
* Taken from the LTTng ABI
*/
enum context_type {
CONTEXT_PID = 0,
- CONTEXT_PERF_COUNTER = 1,
+ CONTEXT_PERF_COUNTER = 1, /* Backward compat. */
CONTEXT_PROCNAME = 2,
CONTEXT_PRIO = 3,
CONTEXT_NICE = 4,
CONTEXT_PTHREAD_ID = 10,
CONTEXT_HOSTNAME = 11,
CONTEXT_IP = 12,
+ CONTEXT_PERF_CPU_COUNTER = 13,
+ CONTEXT_PERF_THREAD_COUNTER = 14,
};
/*
/*
* Context options
*/
-#define PERF_HW(opt, name) \
+#define PERF_HW(optstr, name, type, hide) \
{ \
- "perf:" #opt, CONTEXT_PERF_COUNTER, \
+ optstr, type, hide, \
.u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
}
-#define PERF_SW(opt, name) \
+#define PERF_SW(optstr, name, type, hide) \
{ \
- "perf:" #opt, CONTEXT_PERF_COUNTER, \
+ optstr, type, hide, \
.u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
}
-#define _PERF_HW_CACHE(optstr, name, op, result) \
+#define _PERF_HW_CACHE(optstr, name, type, op, result, hide) \
{ \
- "perf:" optstr, CONTEXT_PERF_COUNTER, \
+ optstr, type, hide, \
.u.perf = { \
PERF_TYPE_HW_CACHE, \
(uint64_t) PERF_COUNT_HW_CACHE_##name \
}, \
}
-#define PERF_HW_CACHE(opt, name) \
- _PERF_HW_CACHE(#opt "-loads", name, READ, ACCESS), \
- _PERF_HW_CACHE(#opt "-load-misses", name, READ, MISS), \
- _PERF_HW_CACHE(#opt "-stores", name, WRITE, ACCESS), \
- _PERF_HW_CACHE(#opt "-store-misses", name, WRITE, MISS), \
- _PERF_HW_CACHE(#opt "-prefetches", name, PREFETCH, ACCESS), \
- _PERF_HW_CACHE(#opt "-prefetch-misses", name, PREFETCH, MISS) \
+#define PERF_HW_CACHE(optstr, name, type, hide) \
+ _PERF_HW_CACHE(optstr "-loads", name, type, \
+ READ, ACCESS, hide), \
+ _PERF_HW_CACHE(optstr "-load-misses", name, type, \
+ READ, MISS, hide), \
+ _PERF_HW_CACHE(optstr "-stores", name, type, \
+ WRITE, ACCESS, hide), \
+ _PERF_HW_CACHE(optstr "-store-misses", name, type, \
+ WRITE, MISS, hide), \
+ _PERF_HW_CACHE(optstr "-prefetches", name, type, \
+ PREFETCH, ACCESS, hide), \
+ _PERF_HW_CACHE(optstr "-prefetch-misses", name, type, \
+ PREFETCH, MISS, hide)
static
const struct ctx_opts {
char *symbol;
enum context_type ctx_type;
+ int hide_help; /* Hide from --help */
union {
struct {
uint32_t type;
{ "vppid", CONTEXT_VPPID },
{ "hostname", CONTEXT_HOSTNAME },
{ "ip", CONTEXT_IP },
+
/* Perf options */
- PERF_HW(cpu-cycles, CPU_CYCLES),
- PERF_HW(cycles, CPU_CYCLES),
- PERF_HW(stalled-cycles-frontend, STALLED_CYCLES_FRONTEND),
- PERF_HW(idle-cycles-frontend, STALLED_CYCLES_FRONTEND),
- PERF_HW(stalled-cycles-backend, STALLED_CYCLES_BACKEND),
- PERF_HW(idle-cycles-backend, STALLED_CYCLES_BACKEND),
- PERF_HW(instructions, INSTRUCTIONS),
- PERF_HW(cache-references, CACHE_REFERENCES),
- PERF_HW(cache-misses, CACHE_MISSES),
- PERF_HW(branch-instructions, BRANCH_INSTRUCTIONS),
- PERF_HW(branches, BRANCH_INSTRUCTIONS),
- PERF_HW(branch-misses, BRANCH_MISSES),
- PERF_HW(bus-cycles, BUS_CYCLES),
-
- PERF_HW_CACHE(L1-dcache, L1D),
- PERF_HW_CACHE(L1-icache, L1I),
- PERF_HW_CACHE(LLC, LL),
- PERF_HW_CACHE(dTLB, DTLB),
- _PERF_HW_CACHE("iTLB-loads", ITLB, READ, ACCESS),
- _PERF_HW_CACHE("iTLB-load-misses", ITLB, READ, MISS),
- _PERF_HW_CACHE("branch-loads", BPU, READ, ACCESS),
- _PERF_HW_CACHE("branch-load-misses", BPU, READ, MISS),
-
-
- PERF_SW(cpu-clock, CPU_CLOCK),
- PERF_SW(task-clock, TASK_CLOCK),
- PERF_SW(page-fault, PAGE_FAULTS),
- PERF_SW(faults, PAGE_FAULTS),
- PERF_SW(major-faults, PAGE_FAULTS_MAJ),
- PERF_SW(minor-faults, PAGE_FAULTS_MIN),
- PERF_SW(context-switches, CONTEXT_SWITCHES),
- PERF_SW(cs, CONTEXT_SWITCHES),
- PERF_SW(cpu-migrations, CPU_MIGRATIONS),
- PERF_SW(migrations, CPU_MIGRATIONS),
- PERF_SW(alignment-faults, ALIGNMENT_FAULTS),
- PERF_SW(emulation-faults, EMULATION_FAULTS),
+
+ /* Perf per-CPU counters */
+ PERF_HW("perf:cpu:cpu-cycles", CPU_CYCLES,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:cycles", CPU_CYCLES,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:idle-cycles-backend", STALLED_CYCLES_BACKEND,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:instructions", INSTRUCTIONS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:cache-references", CACHE_REFERENCES,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:cache-misses", CACHE_MISSES,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:branch-instructions", BRANCH_INSTRUCTIONS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:branches", BRANCH_INSTRUCTIONS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:branch-misses", BRANCH_MISSES,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW("perf:cpu:bus-cycles", BUS_CYCLES,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+
+ PERF_HW_CACHE("perf:cpu:L1-dcache", L1D,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW_CACHE("perf:cpu:L1-icache", L1I,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW_CACHE("perf:cpu:LLC", LL,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_HW_CACHE("perf:cpu:dTLB", DTLB,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ _PERF_HW_CACHE("perf:cpu:iTLB-loads", ITLB,
+ CONTEXT_PERF_CPU_COUNTER, READ, ACCESS, 0),
+ _PERF_HW_CACHE("perf:cpu:iTLB-load-misses", ITLB,
+ CONTEXT_PERF_CPU_COUNTER, READ, MISS, 0),
+ _PERF_HW_CACHE("perf:cpu:branch-loads", BPU,
+ CONTEXT_PERF_CPU_COUNTER, READ, ACCESS, 0),
+ _PERF_HW_CACHE("perf:cpu:branch-load-misses", BPU,
+ CONTEXT_PERF_CPU_COUNTER, READ, MISS, 0),
+
+ PERF_SW("perf:cpu:cpu-clock", CPU_CLOCK,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:task-clock", TASK_CLOCK,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:page-fault", PAGE_FAULTS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:faults", PAGE_FAULTS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:major-faults", PAGE_FAULTS_MAJ,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:minor-faults", PAGE_FAULTS_MIN,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:context-switches", CONTEXT_SWITCHES,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:cs", CONTEXT_SWITCHES,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:cpu-migrations", CPU_MIGRATIONS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:migrations", CPU_MIGRATIONS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:alignment-faults", ALIGNMENT_FAULTS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+ PERF_SW("perf:cpu:emulation-faults", EMULATION_FAULTS,
+ CONTEXT_PERF_CPU_COUNTER, 0),
+
+ /* Perf per-thread counters */
+ PERF_HW("perf:thread:cpu-cycles", CPU_CYCLES,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:cycles", CPU_CYCLES,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:idle-cycles-backend", STALLED_CYCLES_BACKEND,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:instructions", INSTRUCTIONS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:cache-references", CACHE_REFERENCES,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:cache-misses", CACHE_MISSES,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:branch-instructions", BRANCH_INSTRUCTIONS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:branches", BRANCH_INSTRUCTIONS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:branch-misses", BRANCH_MISSES,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW("perf:thread:bus-cycles", BUS_CYCLES,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+
+ PERF_HW_CACHE("perf:thread:L1-dcache", L1D,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW_CACHE("perf:thread:L1-icache", L1I,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW_CACHE("perf:thread:LLC", LL,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_HW_CACHE("perf:thread:dTLB", DTLB,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ _PERF_HW_CACHE("perf:thread:iTLB-loads", ITLB,
+ CONTEXT_PERF_THREAD_COUNTER, READ, ACCESS, 0),
+ _PERF_HW_CACHE("perf:thread:iTLB-load-misses", ITLB,
+ CONTEXT_PERF_THREAD_COUNTER, READ, MISS, 0),
+ _PERF_HW_CACHE("perf:thread:branch-loads", BPU,
+ CONTEXT_PERF_THREAD_COUNTER, READ, ACCESS, 0),
+ _PERF_HW_CACHE("perf:thread:branch-load-misses", BPU,
+ CONTEXT_PERF_THREAD_COUNTER, READ, MISS, 0),
+
+ PERF_SW("perf:thread:cpu-clock", CPU_CLOCK,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:task-clock", TASK_CLOCK,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:page-fault", PAGE_FAULTS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:faults", PAGE_FAULTS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:major-faults", PAGE_FAULTS_MAJ,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:minor-faults", PAGE_FAULTS_MIN,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:context-switches", CONTEXT_SWITCHES,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:cs", CONTEXT_SWITCHES,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:cpu-migrations", CPU_MIGRATIONS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:migrations", CPU_MIGRATIONS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:alignment-faults", ALIGNMENT_FAULTS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+ PERF_SW("perf:thread:emulation-faults", EMULATION_FAULTS,
+ CONTEXT_PERF_THREAD_COUNTER, 0),
+
+ /*
+ * Perf per-CPU counters, backward compatibilty for names.
+ * Hidden from help listing.
+ */
+ PERF_HW("perf:cpu-cycles", CPU_CYCLES,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:cycles", CPU_CYCLES,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:idle-cycles-backend", STALLED_CYCLES_BACKEND,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:instructions", INSTRUCTIONS,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:cache-references", CACHE_REFERENCES,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:cache-misses", CACHE_MISSES,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:branch-instructions", BRANCH_INSTRUCTIONS,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:branches", BRANCH_INSTRUCTIONS,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:branch-misses", BRANCH_MISSES,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW("perf:bus-cycles", BUS_CYCLES,
+ CONTEXT_PERF_COUNTER, 1),
+
+ PERF_HW_CACHE("perf:L1-dcache", L1D,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW_CACHE("perf:L1-icache", L1I,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW_CACHE("perf:LLC", LL,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_HW_CACHE("perf:dTLB", DTLB,
+ CONTEXT_PERF_COUNTER, 1),
+ _PERF_HW_CACHE("perf:iTLB-loads", ITLB,
+ CONTEXT_PERF_COUNTER, READ, ACCESS, 1),
+ _PERF_HW_CACHE("perf:iTLB-load-misses", ITLB,
+ CONTEXT_PERF_COUNTER, READ, MISS, 1),
+ _PERF_HW_CACHE("perf:branch-loads", BPU,
+ CONTEXT_PERF_COUNTER, READ, ACCESS, 1),
+ _PERF_HW_CACHE("perf:branch-load-misses", BPU,
+ CONTEXT_PERF_COUNTER, READ, MISS, 1),
+
+ PERF_SW("perf:cpu-clock", CPU_CLOCK,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:task-clock", TASK_CLOCK,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:page-fault", PAGE_FAULTS,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:faults", PAGE_FAULTS,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:major-faults", PAGE_FAULTS_MAJ,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:minor-faults", PAGE_FAULTS_MIN,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:context-switches", CONTEXT_SWITCHES,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:cs", CONTEXT_SWITCHES,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:cpu-migrations", CPU_MIGRATIONS,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:migrations", CPU_MIGRATIONS,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:alignment-faults", ALIGNMENT_FAULTS,
+ CONTEXT_PERF_COUNTER, 1),
+ PERF_SW("perf:emulation-faults", EMULATION_FAULTS,
+ CONTEXT_PERF_COUNTER, 1),
+
{ NULL, -1 }, /* Closure */
};
+#undef PERF_HW_CACHE
+#undef _PERF_HW_CACHE
#undef PERF_SW
#undef PERF_HW
fprintf(ofp, "%s", indent);
len = indent_len;
while (ctx_opts[i].symbol != NULL) {
- if (len > indent_len) {
- if (len + strlen(ctx_opts[i].symbol) + 2
- >= PRINT_LINE_LEN) {
- fprintf(ofp, ",\n");
- fprintf(ofp, "%s", indent);
- len = indent_len;
- } else {
- len += fprintf(ofp, ", ");
+ if (!ctx_opts[i].hide_help) {
+ if (len > indent_len) {
+ if (len + strlen(ctx_opts[i].symbol) + 2
+ >= PRINT_LINE_LEN) {
+ fprintf(ofp, ",\n");
+ fprintf(ofp, "%s", indent);
+ len = indent_len;
+ } else {
+ len += fprintf(ofp, ", ");
+ }
}
+ len += fprintf(ofp, "%s", ctx_opts[i].symbol);
}
- len += fprintf(ofp, "%s", ctx_opts[i].symbol);
i++;
}
}
fprintf(ofp, " TYPE can be one of the strings below:\n");
print_ctx_type(ofp);
fprintf(ofp, "\n");
+ fprintf(ofp, "Note that the vpid, vppid and vtid context types represent the virtual process id,\n"
+ "virtual parent process id and virtual thread id as seen from the current execution context\n"
+ "as opposed to the pid, ppid and tid which are kernel internal data structures.\n\n");
fprintf(ofp, "Example:\n");
- fprintf(ofp, "This command will add the context information 'prio' and two perf\n"
- "counters (hardware branch misses and cache misses), to all channels\n"
+ fprintf(ofp, "This command will add the context information 'prio' and two per-cpu\n"
+ "perf counters (hardware branch misses and cache misses), to all channels\n"
"in the trace data output:\n");
- fprintf(ofp, "# lttng add-context -k -t prio -t perf:branch-misses -t perf:cache-misses\n");
+ fprintf(ofp, "# lttng add-context -k -t prio -t perf:cpu:branch-misses -t perf:cpu:cache-misses\n");
fprintf(ofp, "\n");
}
*/
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;
} else if (opt_userspace) {
dom.type = LTTNG_DOMAIN_UST;
} else {
- ERR("Please specify a tracer (-k/--kernel or -u/--userspace)");
+ print_missing_domain();
ret = CMD_ERROR;
goto error;
}
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;
- if (context.ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER) {
+ switch (context.ctx) {
+ case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
+ case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
+ case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
context.u.perf_counter.type = type->opt->u.perf.type;
context.u.perf_counter.config = type->opt->u.perf.config;
strncpy(context.u.perf_counter.name, type->opt->symbol,
while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) {
*ptr = '_';
}
+ break;
+ default:
+ break;
}
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",
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;
}
}
* 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;
*/
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;
goto end;
}
- type = malloc(sizeof(struct ctx_type));
+ type = zmalloc(sizeof(struct ctx_type));
if (type == NULL) {
- perror("malloc ctx_type");
+ PERROR("malloc ctx_type");
ret = CMD_FATAL;
goto end;
}
type->opt = &ctx_opts[index];
- if (type->opt->ctx_type == -1) {
+ if (type->opt->symbol == NULL) {
ERR("Unknown context type %s", opt_type);
free(type);
ret = CMD_ERROR;
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;
}