+ mi_lttng_event(writer, &events[i], 0);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ /* close events, domain and domains */
+ ret = mi_lttng_close_multi_element(writer, 3);
+ if (ret) {
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Ask for all trace events in the kernel
+ */
+static int list_kernel_events(void)
+{
+ int i, size, ret = CMD_SUCCESS;
+ struct lttng_domain domain;
+ struct lttng_handle *handle;
+ struct lttng_event *event_list;
+
+ memset(&domain, 0, sizeof(domain));
+
+ DBG("Getting kernel tracing events");
+
+ domain.type = LTTNG_DOMAIN_KERNEL;
+
+ handle = lttng_create_handle(NULL, &domain);
+ if (handle == NULL) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+
+ size = lttng_list_tracepoints(handle, &event_list);
+ if (size < 0) {
+ ERR("Unable to list kernel events: %s", lttng_strerror(size));
+ lttng_destroy_handle(handle);
+ return CMD_ERROR;
+ }
+
+ if (lttng_opt_mi) {
+ /* Mi print */
+ ret = mi_list_kernel_events(event_list, size, &domain);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto end;
+ }
+ } else {
+ MSG("Kernel events:\n-------------");
+
+ for (i = 0; i < size; i++) {
+ print_events(&event_list[i]);
+ }
+
+ MSG("");
+ }
+
+end:
+ free(event_list);
+
+ lttng_destroy_handle(handle);
+ return ret;
+
+error:
+ lttng_destroy_handle(handle);
+ return ret;
+}
+
+/*
+ * Machine Interface
+ * Print a list of jul events
+ */
+static int mi_list_session_jul_events(struct lttng_event *events, int count)
+{
+ int ret, i;
+
+ /* Open events element */
+ ret = mi_lttng_events_open(writer);
+ if (ret) {
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = mi_lttng_event(writer, &events[i], 0);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ /* Close events element */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+/*
+ * List JUL events for a specific session using the handle.
+ *
+ * Return CMD_SUCCESS on success else a negative value.
+ */
+static int list_session_jul_events(void)
+{
+ int ret = CMD_SUCCESS, count, i;
+ struct lttng_event *events = NULL;
+
+ count = lttng_list_events(handle, "", &events);
+ if (count < 0) {
+ ret = CMD_ERROR;
+ ERR("%s", lttng_strerror(count));
+ goto error;
+ }
+
+ if (lttng_opt_mi) {
+ /* Mi print */
+ ret = mi_list_session_jul_events(events, count);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto end;
+ }
+ } else {
+ /* Pretty print */
+ MSG("Events (Logger name):\n---------------------");
+ if (count == 0) {
+ MSG("%sNone\n", indent6);
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ MSG("%s- %s%s (loglevel%s %s)", indent4, events[i].name,
+ enabled_string(events[i].enabled),
+ logleveltype_string(events[i].loglevel_type),
+ mi_lttng_loglevel_string(events[i].loglevel));
+ }
+
+ MSG("");
+ }
+
+end:
+ free(events);
+error:
+ return ret;
+}
+
+/*
+ * Machine interface
+ * print a list of event
+ */
+static int mi_list_events(struct lttng_event *events, int count)
+{
+ int ret, i;
+
+ /* Open events element */
+ ret = mi_lttng_events_open(writer);
+ if (ret) {
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = mi_lttng_event(writer, &events[i], 0);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ /* Close events element */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+/*
+ * List events of channel of session and domain.
+ */
+static int list_events(const char *channel_name)
+{
+ int ret = CMD_SUCCESS, count, i;
+ struct lttng_event *events = NULL;
+
+ count = lttng_list_events(handle, channel_name, &events);
+ if (count < 0) {
+ ret = CMD_ERROR;
+ ERR("%s", lttng_strerror(count));
+ goto error;
+ }
+
+ if (lttng_opt_mi) {
+ /* Mi print */
+ ret = mi_list_events(events, count);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto end;
+ }
+ } else {
+ /* Pretty print */
+ MSG("\n%sEvents:", indent4);
+ if (count == 0) {
+ MSG("%sNone\n", indent6);
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ print_events(&events[i]);
+ }
+
+ MSG("");
+ }
+end:
+ free(events);
+error:
+ return ret;
+}
+
+/*
+ * Pretty print channel
+ */
+static void print_channel(struct lttng_channel *channel)
+{
+ MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
+
+ MSG("%sAttributes:", indent4);
+ MSG("%soverwrite mode: %d", indent6, channel->attr.overwrite);
+ MSG("%ssubbufers size: %" PRIu64, indent6, channel->attr.subbuf_size);
+ MSG("%snumber of subbufers: %" PRIu64, indent6, channel->attr.num_subbuf);
+ MSG("%sswitch timer interval: %u", indent6, channel->attr.switch_timer_interval);
+ MSG("%sread timer interval: %u", indent6, channel->attr.read_timer_interval);
+ MSG("%strace file count: %" PRIu64, indent6, channel->attr.tracefile_count);
+ MSG("%strace file size (bytes): %" PRIu64, indent6, channel->attr.tracefile_size);
+ switch (channel->attr.output) {
+ case LTTNG_EVENT_SPLICE:
+ MSG("%soutput: splice()", indent6);
+ break;
+ case LTTNG_EVENT_MMAP:
+ MSG("%soutput: mmap()", indent6);
+ break;
+ }
+}
+
+/*
+ * Machine interface
+ * Print a list of channel
+ *
+ */
+static int mi_list_channels(struct lttng_channel *channels, int count,
+ const char *channel_name)
+{
+ int i, ret;
+ unsigned int chan_found = 0;
+
+ /* Open channels element */
+ ret = mi_lttng_channels_open(writer);
+ if (ret) {
+ goto error;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (channel_name != NULL) {
+ if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
+ chan_found = 1;
+ } else {
+ continue;