Mi: mi backend + mi for command version
authorJonathan Rajotte <jonathan.r.julien@gmail.com>
Sun, 6 Apr 2014 19:30:32 +0000 (15:30 -0400)
committerJonathan Rajotte Julien <jonathan.r.julien@gmail.com>
Tue, 22 Jul 2014 20:14:56 +0000 (16:14 -0400)
The machine interface option is now available for version. Other
commands will shortly follow. Mi backend is expected to grow with
addition of mi support to other commands.

How to use:
lttng --mi <mi_output_type> <command>

This syntax will be the same for all commands. Currently *only xml is
supported as machine interface output.*

As for errors handling, if an error/warning occurs while using mi it
will be reported on stderr as normal. The integrity of the mi output
cannot be guaranteed if an error/warning occurs. The error output format
is consistent and easy for a machine client to parse. Thus no mi output
format is required for error output.

Example:
lttng --mi xml version
Output:
<?xml version="1.0" encoding="UTF-8"?>
  <command>
    <name>version</name>
    <output>
      <string>2.4.0-rc2</string>
      <major>2</major>
      <minor>4</minor>
      <patchLevel>0</patchLevel>
      <name>Époque Opaque</name>
      <description>The Époque Opaque is a black IPA from Trou du Diable
      brewery. The nose is eerily reminiscent of the coffee crisp candy from
      of our childhood. These strong mocha accents are present on the palate,
      which are quickly subdued by Japanese and Australian hops leading to a
      final state of satisfaction enjoyable for any fan of bitter
      beer.</description>
      <url>http://lttng.org</url>
      <license>lttng is free software and under the GPL license and part
      LGPL</license>
  </output>
</command>

Signed-off-by: Olivier Cotte <olivier.cotte@polymtl.ca>
Signed-off-by: Jonathan Rajotte <jonathan.r.julien@gmail.com>
Signed-off-by: David Goulet <dgoulet@efficios.com>
34 files changed:
include/lttng/lttng-error.h
include/lttng/lttng.h
src/bin/lttng-consumerd/lttng-consumerd.c
src/bin/lttng/commands/add_context.c
src/bin/lttng/commands/calibrate.c
src/bin/lttng/commands/create.c
src/bin/lttng/commands/destroy.c
src/bin/lttng/commands/disable_channels.c
src/bin/lttng/commands/disable_events.c
src/bin/lttng/commands/enable_channels.c
src/bin/lttng/commands/enable_events.c
src/bin/lttng/commands/list.c
src/bin/lttng/commands/load.c
src/bin/lttng/commands/save.c
src/bin/lttng/commands/set_session.c
src/bin/lttng/commands/snapshot.c
src/bin/lttng/commands/start.c
src/bin/lttng/commands/stop.c
src/bin/lttng/commands/version.c
src/bin/lttng/commands/view.c
src/bin/lttng/lttng.c
src/common/Makefile.am
src/common/error.c
src/common/error.h
src/common/mi-lttng.c [new file with mode: 0644]
src/common/mi-lttng.h [new file with mode: 0644]
src/lib/lttng-ctl/lttng-ctl.c
tests/unit/ini_config/ini_config.c
tests/unit/test_kernel_data.c
tests/unit/test_session.c
tests/unit/test_uri.c
tests/unit/test_ust_data.c
tests/unit/test_utils_expand_path.c
tests/unit/test_utils_parse_size_suffix.c

index e18fb00e8bec8ceb6b64e4777b603ec6f9305afb..6083959131c68d3ba3324861d6eef2ad1bda3b02 100644 (file)
@@ -111,8 +111,9 @@ enum lttng_error_code {
        LTTNG_ERR_LOAD_IO_FAIL           = 88,  /* IO error while reading a session configuration */
        LTTNG_ERR_LOAD_SESSION_NOENT     = 89,  /* Session file not found */
        LTTNG_ERR_MAX_SIZE_INVALID       = 90,  /* Snapshot max size is invalid. */
-       /* 91 */
-       /* 92 */
+       LTTNG_ERR_MI_OUTPUT_TYPE         = 91, /* Invalid MI output format */
+       LTTNG_ERR_MI_IO_FAIL             = 92, /* IO error while writing machine interface output */
+       LTTNG_ERR_MI_NOT_IMPLEMENTED     = 93, /* Mi feature not implemented */
        /* 93 */
        /* 94 */
        /* 95 */
index 944675206bff11e6e3edb49d6cc416f8dd465ca6..c5be66128b60da0cc76c5972a095a5ccbd8a4f79 100644 (file)
@@ -43,6 +43,11 @@ enum lttng_calibrate_type {
        LTTNG_CALIBRATE_FUNCTION              = 0,
 };
 
+/* Machine interface output type */
+enum lttng_mi_output_type {
+       LTTNG_MI_XML                          = 1 /* XML output */
+};
+
 #define LTTNG_CALIBRATE_PADDING1           16
 struct lttng_calibrate {
        enum lttng_calibrate_type type;
index 88ce190190438725ec2316af84e28247819f7d43..5d5703064a110cac4dd8ea389430b878dd8ff302 100644 (file)
@@ -65,6 +65,8 @@ static int sigintcount = 0;
 /* Argument variables */
 int lttng_opt_quiet;    /* not static in error.h */
 int lttng_opt_verbose;  /* not static in error.h */
+int lttng_opt_mi;       /* not static in error.h */
+
 static int opt_daemon;
 static const char *progname;
 static char command_sock_path[PATH_MAX]; /* Global command socket path */
index b1f81e6b3176d19a49957847727bed1afb723ac4..2f7559c3017d66d4679b7265aad97166eb65b449 100644 (file)
@@ -647,6 +647,13 @@ 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);
 
index 092632cd78ffdea24da1261777d816d264e99c67..7d4de2909cf0f3fc45c1234c52b1f09e7fb2ec3f 100644 (file)
@@ -133,6 +133,13 @@ static int calibrate_lttng(void)
                goto error;
        }
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto error;
+       }
+
        handle = lttng_create_handle(NULL, &dom);
        if (handle == NULL) {
                ret = CMD_ERROR;
index e02b141420c075a1c0e687befade8192eb0d4721..c43ce59b906c7a5f43db8e5fed1f709262951ac6 100644 (file)
@@ -515,6 +515,13 @@ int cmd_create(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;
+       }
+
        if (opt_no_consumer) {
                MSG("The option --no-consumer is obsolete. Use --no-output now.");
                ret = CMD_WARNING;
index 3fb5fb232edb16184a4a7574de9b6e623668959f..26548b9e153521f1b74b2d5c10d44968e7179744 100644 (file)
@@ -148,6 +148,13 @@ int cmd_destroy(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;
+       }
+
        /* Ignore session name in case all sessions are to be destroyed */
        if (opt_destroy_all) {
                ret = destroy_all_sessions();
index 1aa3916aecb116a0122b50b2128b8111acc093ae..da53d25c9f54c061ad260bf197bb9a7096d19ad8 100644 (file)
@@ -167,6 +167,13 @@ 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");
index e71234342deb7f66bc751e5d33d73ebe26460354..fb96b8060bded913df0d4a0b00bdd50023a00639 100644 (file)
@@ -212,6 +212,13 @@ int cmd_disable_events(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_event_list = (char*) poptGetArg(pc);
        if (opt_event_list == NULL && opt_disable_all == 0) {
                ERR("Missing event name(s).\n");
index 7f25a6e91aa8bf96708e434358294026176aabff..1fdaada99f625a9418683b3e24ecd763a5437da1 100644 (file)
@@ -329,6 +329,13 @@ int cmd_enable_channels(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, long_options, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index 1547d7086f68be5fc60c311f968cb879bacd98b9..9b16d7c86ec7959230e83ac97160987e5b30d719 100644 (file)
@@ -975,6 +975,13 @@ int cmd_enable_events(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, long_options, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        /* Default event type */
        opt_event_type = LTTNG_EVENT_ALL;
 
index f56adf4821db71ca4d8d4f77bc7adabd36444302..d25b5632bb85513e40d028b21ae9c6335c8e5c20 100644 (file)
@@ -888,6 +888,13 @@ int cmd_list(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, long_options, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index 2a3c6579574b27224a1296cde2956b92d06a6c30..347e4ca08896b8507a9e0939c281a0046a946bec 100644 (file)
@@ -77,6 +77,13 @@ int cmd_load(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, load_opts, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index 9be710326349150a08bd9da5d5999152a777c6ab..fdc0da6bf2ee921b6438fef2df6676ed88f5ad20 100644 (file)
@@ -73,6 +73,13 @@ int cmd_save(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, save_opts, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index 4238016e40867c897299678d41097e2e497b33c6..54320df2a42a0988a1255eddbf19252ea8f36d7d 100644 (file)
@@ -92,6 +92,13 @@ int cmd_set_session(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, long_options, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index 2d250afc37cfb01df040159936dcbef24444f90d..564651e09c50480c22f45952e02833627f11364e 100644 (file)
@@ -452,6 +452,13 @@ int cmd_snapshot(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, snapshot_opts, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index 82122cc63a464b09642ba6faa7cc1e2a9c3c6042..82b3f5f867923dc1c16eaa7eff158331d4f5dc99 100644 (file)
@@ -118,6 +118,13 @@ int cmd_start(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, long_options, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index cb45f12ce56085a15bd2cdc5f52ca1fd41a69c72..965ab94feb66f45ca5d89752a3da5661f341d415 100644 (file)
@@ -141,6 +141,13 @@ int cmd_stop(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, long_options, 0);
        poptReadDefaultConfig(pc, 0);
 
+       /* TODO: mi support */
+       if (lttng_opt_mi) {
+               ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
+               ERR("mi option not supported");
+               goto end;
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index f2f435e4bf4c84fa6912450d252595633968d585..d27013689635aac7536b74db8c5cd753620e816b 100644 (file)
@@ -25,6 +25,8 @@
 #include <unistd.h>
 #include <config.h>
 
+#include <common/mi-lttng.h>
+
 #include "../command.h"
 
 enum {
@@ -32,6 +34,8 @@ enum {
        OPT_LIST_OPTIONS,
 };
 
+static const char *lttng_license = "lttng is free software and under the GPL license and part LGPL";
+
 static struct poptOption long_options[] = {
        /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
        {"help",      'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
@@ -52,6 +56,84 @@ static void usage(FILE *ofp)
        fprintf(ofp, "\n");
 }
 
+/*
+ *  create_version
+ */
+static void create_version(struct mi_lttng_version *version)
+{
+       strncpy(version->version, VERSION, NAME_MAX);
+       version->version_major = VERSION_MAJOR;
+       version->version_minor = VERSION_MINOR;
+       version->version_patchlevel = VERSION_PATCHLEVEL;
+       strncpy(version->version_name, VERSION_NAME, NAME_MAX);
+       strncpy(version->package_url, PACKAGE_URL, NAME_MAX);
+}
+
+/*
+ * Print the machine interface output of this command.
+ */
+static int print_mi()
+{
+       int ret = CMD_SUCCESS;
+       struct mi_writer *writer = NULL;
+       struct mi_lttng_version version;
+
+       create_version(&version);
+
+       writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
+       if (!writer) {
+               ret = -LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       /* Open the command element */
+       ret = mi_lttng_writer_command_open(writer,
+                       mi_lttng_element_command_version);
+       if (ret) {
+               ret = CMD_ERROR;
+               goto error;
+       }
+
+       /* Beginning of output */
+       ret = mi_lttng_writer_open_element(writer,
+                       mi_lttng_element_command_output);
+       if (ret) {
+               ret = CMD_ERROR;
+               goto error;
+       }
+
+       /* Print the machine interface of version */
+       ret = mi_lttng_version(writer, &version,
+                       VERSION_DESCRIPTION, lttng_license);
+       if (ret) {
+               ret = CMD_ERROR;
+               goto error;
+       }
+
+       /* Close the output element */
+       ret = mi_lttng_writer_close_element(writer);
+       if (ret) {
+               ret = CMD_ERROR;
+               goto error;
+       }
+
+       /* Close the command  */
+       ret = mi_lttng_writer_command_close(writer);
+       if (ret) {
+               ret = CMD_ERROR;
+       }
+
+error:
+       /* Cleanup */
+       if (writer && mi_lttng_writer_destroy(writer)) {
+               /* Preserve original error code */
+               ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
+       }
+
+end:
+       return ret;
+}
+
 /*
  *  cmd_version
  */
@@ -78,10 +160,14 @@ int cmd_version(int argc, const char **argv)
                }
        }
 
-       MSG("lttng version " FULL_VERSION " - " VERSION_NAME);
-       MSG("\n" VERSION_DESCRIPTION "\n");
-       MSG("Web site: http://lttng.org");
-       MSG("\nlttng is free software and under the GPL license and part LGPL");
+       if (lttng_opt_mi) {
+               ret = print_mi();
+       } else {
+               MSG("lttng version " FULL_VERSION " - " VERSION_NAME);
+               MSG("\n" VERSION_DESCRIPTION "\n");
+               MSG("Web site: http://lttng.org");
+               MSG("\n%s", lttng_license);
+       }
 
 end:
        poptFreeContext(pc);
index adedf298966c0c7fad786f13bb34a66f4698a6de..dcd4d66245fb5049fa241c00feb771fdf52d93ba 100644 (file)
@@ -445,6 +445,10 @@ int cmd_view(int argc, const char **argv)
        pc = poptGetContext(NULL, argc, argv, long_options, 0);
        poptReadDefaultConfig(pc, 0);
 
+       if (lttng_opt_mi) {
+               WARN("mi does not apply to view command");
+       }
+
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
index d4d40f07722ef8aad0097164af92456454418f90..bad57fd9a8a41487e33482ba5ad5e49187c4abd3 100644 (file)
@@ -55,6 +55,7 @@ static struct option long_options[] = {
        {"group",            1, NULL, 'g'},
        {"verbose",          0, NULL, 'v'},
        {"quiet",            0, NULL, 'q'},
+       {"mi",               1, NULL, 'm'},
        {"no-sessiond",      0, NULL, 'n'},
        {"sessiond-path",    1, NULL, OPT_SESSION_PATH},
        {"relayd-path",      1, NULL, OPT_RELAYD_PATH},
@@ -99,6 +100,8 @@ static void usage(FILE *ofp)
        fprintf(ofp, "      --list-commands        Simple listing of lttng commands\n");
        fprintf(ofp, "  -v, --verbose              Increase verbosity\n");
        fprintf(ofp, "  -q, --quiet                Quiet mode\n");
+       fprintf(ofp, "  -m, --mi TYPE              Machine Interface mode.\n");
+       fprintf(ofp, "                                 Type: xml\n");
        fprintf(ofp, "  -g, --group NAME           Unix tracing group name. (default: tracing)\n");
        fprintf(ofp, "  -n, --no-sessiond          Don't spawn a session daemon\n");
        fprintf(ofp, "      --sessiond-path PATH   Session daemon full path\n");
@@ -135,6 +138,25 @@ static void version(FILE *ofp)
                        progname);
 }
 
+/*
+ * Find the MI output type enum from a string. This function is for the support
+ * of machine interface output.
+ */
+static int mi_output_type(const char *output_type)
+{
+       int ret = 0;
+
+       if (!strncasecmp("xml", output_type, 3)) {
+               ret = LTTNG_MI_XML;
+       } else {
+               /* Invalid output format */
+               ERR("MI output format not supported");
+               ret = -LTTNG_ERR_MI_OUTPUT_TYPE;
+       }
+
+       return ret;
+}
+
 /*
  *  list_options
  *
@@ -426,7 +448,7 @@ static int parse_args(int argc, char **argv)
                clean_exit(EXIT_FAILURE);
        }
 
-       while ((opt = getopt_long(argc, argv, "+Vhnvqg:", long_options, NULL)) != -1) {
+       while ((opt = getopt_long(argc, argv, "+Vhnvqg:m:", long_options, NULL)) != -1) {
                switch (opt) {
                case 'V':
                        version(stdout);
@@ -445,6 +467,13 @@ static int parse_args(int argc, char **argv)
                case 'q':
                        lttng_opt_quiet = 1;
                        break;
+               case 'm':
+                       lttng_opt_mi = mi_output_type(optarg);
+                       if (lttng_opt_mi < 0) {
+                               ret = lttng_opt_mi;
+                               goto error;
+                       }
+                       break;
                case 'g':
                        lttng_set_tracing_group(optarg);
                        break;
index 6aa0a8ab09e85e8077daf1896884154c41d8f090..4b623c837db6bd2cd3e82802e9f01927d2205d02 100644 (file)
@@ -16,8 +16,12 @@ noinst_LTLIBRARIES = libcommon.la
 libcommon_la_SOURCES = error.h error.c utils.c utils.h runas.c runas.h \
                        common.h futex.c futex.h uri.c uri.h defaults.c \
                        pipe.c pipe.h readwrite.c readwrite.h \
+                       mi-lttng.h mi-lttng.c \
                        daemonize.c daemonize.h
-libcommon_la_LIBADD = -luuid -lrt
+libcommon_la_LIBADD = \
+               -luuid \
+               -lrt \
+               $(top_builddir)/src/common/config/libconfig.la
 
 # Consumer library
 noinst_LTLIBRARIES += libconsumer.la
index 26dc0679833b694edd87af2dfefcdf4ae9a3b500..6e283ccb6635be96e85b6b7bb2d60653a7ed8d19 100644 (file)
@@ -161,6 +161,9 @@ static const char *error_string_array[] = {
        [ ERROR_INDEX(LTTNG_ERR_LOAD_IO_FAIL) ] = "IO error while reading a session configuration",
        [ ERROR_INDEX(LTTNG_ERR_LOAD_SESSION_NOENT) ] = "Session file not found",
        [ ERROR_INDEX(LTTNG_ERR_MAX_SIZE_INVALID) ] = "Snapshot max size is invalid",
+       [ ERROR_INDEX(LTTNG_ERR_MI_OUTPUT_TYPE) ] = "Invalid MI output format",
+       [ ERROR_INDEX(LTTNG_ERR_MI_IO_FAIL) ] = "IO error while writing MI output",
+       [ ERROR_INDEX(LTTNG_ERR_MI_NOT_IMPLEMENTED) ] = "Mi feature not implemented",
 
        /* Last element */
        [ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code"
index 684ff5e5f4f9af9852c35e32d7182005c0985a38..1ee6e675a5b752eb600c0e2f4d19dc2891fcd6e7 100644 (file)
@@ -49,6 +49,7 @@ extern DECLARE_URCU_TLS(struct log_time, error_log_time);
 
 extern int lttng_opt_quiet;
 extern int lttng_opt_verbose;
+extern int lttng_opt_mi;
 
 /* Error type. */
 #define PRINT_ERR   0x1
@@ -61,12 +62,18 @@ extern int lttng_opt_verbose;
 
 /*
  * Macro for printing message depending on command line option and verbosity.
+ *
+ * Machine interface:
+ * We use lttng_opt_mi to suppress all normal msg to stdout. We don't
+ * want any nested msg to show up when printing mi to stdout(if it's the case).
+ * All warnings and errors should be printed to stderr as normal.
  */
 #define __lttng_print(type, fmt, args...)                           \
        do {                                                            \
-               if (lttng_opt_quiet == 0 && type == PRINT_MSG) {            \
+               if (lttng_opt_quiet == 0 && lttng_opt_mi == 0 &&            \
+                               type == PRINT_MSG) {                                \
                        fprintf(stdout, fmt, ## args);                          \
-               } else if (lttng_opt_quiet == 0 &&                          \
+               } else if (lttng_opt_quiet == 0 && lttng_opt_mi == 0 &&     \
                                (((type & PRINT_DBG) && lttng_opt_verbose == 1) ||  \
                                ((type & (PRINT_DBG | PRINT_DBG2)) &&               \
                                        lttng_opt_verbose == 2) ||                      \
diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c
new file mode 100644 (file)
index 0000000..052b542
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2014 - Jonathan Rajotte <jonathan.r.julien@gmail.com>
+ *                    - Olivier Cotte <olivier.cotte@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <include/config.h>
+#include <common/config/config.h>
+
+#include "mi-lttng.h"
+
+/* Strings related to command */
+const char * const mi_lttng_element_command = "command";
+const char * const mi_lttng_element_command_version = "version";
+const char * const mi_lttng_element_command_list = "list";
+const char * const mi_lttng_element_command_name = "name";
+const char * const mi_lttng_element_command_output = "output";
+
+/* Strings related to command: version */
+const char * const mi_lttng_element_version = "version";
+const char * const mi_lttng_element_version_str = "string";
+const char * const mi_lttng_element_version_web = "url";
+const char * const mi_lttng_element_version_major = "major";
+const char * const mi_lttng_element_version_minor = "minor";
+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";
+
+LTTNG_HIDDEN
+struct mi_writer *mi_lttng_writer_create(int fd_output, int mi_output_type)
+{
+       struct mi_writer *mi_writer;
+
+       mi_writer = zmalloc(sizeof(struct mi_writer));
+       if (!mi_writer) {
+               PERROR("zmalloc mi_writer_create");
+               goto end;
+       }
+       if (mi_output_type == LTTNG_MI_XML) {
+               mi_writer->writer = config_writer_create(fd_output);
+               if (!mi_writer->writer) {
+                       goto err_destroy;
+               }
+               mi_writer->type = LTTNG_MI_XML;
+       } else {
+               goto err_destroy;
+       }
+
+end:
+       return mi_writer;
+
+err_destroy:
+       free(mi_writer);
+       return NULL;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_destroy(struct mi_writer *writer)
+{
+       int ret;
+
+       if (!writer) {
+               ret = -EINVAL;
+               goto end;
+       }
+
+       ret = config_writer_destroy(writer->writer);
+       if (ret < 0) {
+               goto end;
+       }
+
+       free(writer);
+end:
+       return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_command_open(struct mi_writer *writer, const char *command)
+{
+       int ret;
+
+       ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command);
+       if (ret) {
+               goto end;
+       }
+       ret = mi_lttng_writer_write_element_string(writer,
+                       mi_lttng_element_command_name, command);
+end:
+       return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_command_close(struct mi_writer *writer)
+{
+       return mi_lttng_writer_close_element(writer);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_open_element(struct mi_writer *writer,
+               const char *element_name)
+{
+       return config_writer_open_element(writer->writer, element_name);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_close_element(struct mi_writer *writer)
+{
+       return config_writer_close_element(writer->writer);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_write_element_unsigned_int(struct mi_writer *writer,
+               const char *element_name, uint64_t value)
+{
+       return config_writer_write_element_unsigned_int(writer->writer,
+                       element_name, value);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_write_element_signed_int(struct mi_writer *writer,
+               const char *element_name, int64_t value)
+{
+       return config_writer_write_element_signed_int(writer->writer,
+                       element_name, value);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_write_element_bool(struct mi_writer *writer,
+               const char *element_name, int value)
+{
+       return config_writer_write_element_bool(writer->writer,
+                       element_name, value);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_writer_write_element_string(struct mi_writer *writer,
+               const char *element_name, const char *value)
+{
+       return config_writer_write_element_string(writer->writer,
+                       element_name, value);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_version(struct mi_writer *writer, struct mi_lttng_version *version,
+       const char *lttng_description, const char *lttng_license)
+{
+       int ret;
+
+       /* Open version */
+       ret = mi_lttng_writer_open_element(writer, mi_lttng_element_version);
+       if (ret) {
+               goto end;
+       }
+
+       /* Version string (contain info like rc etc.) */
+       ret = mi_lttng_writer_write_element_string(writer,
+                       mi_lttng_element_version_str, VERSION);
+       if (ret) {
+               goto end;
+       }
+
+       /* Major version number */
+       ret = mi_lttng_writer_write_element_unsigned_int(writer,
+                       mi_lttng_element_version_major, version->version_major);
+       if (ret) {
+               goto end;
+       }
+
+       /* Minor version number */
+       ret = mi_lttng_writer_write_element_unsigned_int(writer,
+                       mi_lttng_element_version_minor, version->version_minor);
+       if (ret) {
+               goto end;
+       }
+
+       /* Patch number */
+       ret = mi_lttng_writer_write_element_unsigned_int(writer,
+                       mi_lttng_element_version_patch_level, version->version_patchlevel);
+       if (ret) {
+               goto end;
+       }
+
+       /* Name of the version */
+       ret = mi_lttng_writer_write_element_string(writer,
+                       config_element_name, version->version_name);
+       if (ret) {
+               goto end;
+       }
+
+       /* Description mostly related to beer... */
+       ret = mi_lttng_writer_write_element_string(writer,
+                       mi_lttng_element_version_description, lttng_description);
+       if (ret) {
+               goto end;
+       }
+
+       /* url */
+       ret = mi_lttng_writer_write_element_string(writer,
+                       mi_lttng_element_version_web, version->package_url);
+       if (ret) {
+               goto end;
+       }
+
+       /* License: free as in free beer...no...*speech* */
+       ret = mi_lttng_writer_write_element_string(writer,
+                       mi_lttng_element_version_license, lttng_license);
+       if (ret) {
+               goto end;
+       }
+
+       /* Close version element */
+       ret = mi_lttng_writer_close_element(writer);
+
+end:
+       return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_session(struct mi_writer *writer,
+               struct lttng_session *session, int is_open)
+{
+       int ret;
+
+       /* open sessions element */
+       ret = mi_lttng_writer_open_element(writer,
+                       config_element_session);
+       if (ret) {
+               goto end;
+       }
+
+       /* Name of the session */
+       ret = mi_lttng_writer_write_element_string(writer,
+                       config_element_name, session->name);
+       if (ret) {
+               goto end;
+       }
+
+       /* path */
+       ret = mi_lttng_writer_write_element_string(writer,
+                       config_element_path, session->path);
+       if (ret) {
+               goto end;
+       }
+
+       /* enabled ? */
+       ret = mi_lttng_writer_write_element_unsigned_int(writer,
+                       config_element_enabled, session->enabled);
+       if (ret) {
+               goto end;
+       }
+
+       /* snapshot mode */
+       ret = mi_lttng_writer_write_element_unsigned_int(writer,
+                       config_element_snapshot_mode, session->snapshot_mode);
+       if (ret) {
+               goto end;
+       }
+
+       /* live timer interval in usec */
+       ret = mi_lttng_writer_write_element_unsigned_int(writer,
+                       config_element_live_timer_interval,
+                       session->live_timer_interval);
+       if (ret) {
+               goto end;
+       }
+
+       if (!is_open) {
+               /* Closing session 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
new file mode 100644 (file)
index 0000000..bdc4a05
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2014 - Jonathan Rajotte <jonathan.r.julien@gmail.com>
+ *                    - Olivier Cotte <olivier.cotte@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _MI_LTTNG_H
+#define _MI_LTTNG_H
+
+#include <stdint.h>
+
+#include <common/error.h>
+#include <common/macros.h>
+#include <common/config/config.h>
+#include <lttng/lttng.h>
+
+/* Instance of a machine interface writer. */
+struct mi_writer {
+       struct config_writer *writer;
+       enum lttng_mi_output_type type;
+};
+
+/*
+ * Version information for the machine interface.
+ */
+struct mi_lttng_version {
+       char version[NAME_MAX]; /* Version number of package */
+       uint32_t version_major; /* LTTng-Tools major version number */
+       uint32_t version_minor; /* LTTng-Tools minor version number */
+       uint32_t version_patchlevel; /* LTTng-Tools patchlevel version number */
+       char version_name[NAME_MAX];
+       char package_url[NAME_MAX]; /* Define to the home page for this package. */
+};
+
+/* Strings related to command */
+const char * const mi_lttng_element_command;
+const char * const mi_lttng_element_command_version;
+const char * const mi_lttng_element_command_list;
+const char * const mi_lttng_element_command_name;
+const char * const mi_lttng_element_command_output;
+
+/* Strings related to command: version */
+const char * const mi_lttng_element_version;
+const char * const mi_lttng_element_version_str;
+const char * const mi_lttng_element_version_web;
+const char * const mi_lttng_element_version_major;
+const char * const mi_lttng_element_version_minor;
+const char * const mi_lttng_element_version_license;
+const char * const mi_lttng_element_version_patch_level;
+const char * const mi_lttng_element_version_description;
+
+/*
+ * Create an instance of a machine interface writer.
+ *
+ * fd_output File to which the XML content must be written. The file will be
+ * closed once the mi_writer has been destroyed.
+ *
+ * Returns an instance of a machine interface writer on success, NULL on
+ * error.
+ */
+struct mi_writer *mi_lttng_writer_create(int fd_output, int mi_output_type);
+
+/*
+ * Destroy an instance of a machine interface writer.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the XML document could be closed cleanly. Negative values
+ * indicate an error.
+ */
+int mi_lttng_writer_destroy(struct mi_writer *writer);
+
+/*
+ * Open a command tag and add it's name node.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * command The command name.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_command_open(struct mi_writer *writer, const char *command);
+
+/*
+ * Close a command tag.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_command_close(struct mi_writer *writer);
+
+/*
+ * Open an element tag.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * element_name Element tag name.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_open_element(struct mi_writer *writer,
+               const char *element_name);
+
+/*
+ * Close the current element tag.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_close_element(struct mi_writer *writer);
+
+/*
+ * Write an element of type unsigned int.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * element_name Element name.
+ *
+ * value Unsigned int value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_unsigned_int(struct mi_writer *writer,
+               const char *element_name, uint64_t value);
+
+/*
+ * Write an element of type signed int.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * element_name Element name.
+ *
+ * value Signed int value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_signed_int(struct mi_writer *writer,
+               const char *element_name, int64_t value);
+
+/*
+ * Write an element of type boolean.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * element_name Element name.
+ *
+ * value Boolean value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_bool(struct mi_writer *writer,
+               const char *element_name, int value);
+
+/*
+ * Write an element of type string.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * element_name Element name.
+ *
+ * value String value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_string(struct mi_writer *writer,
+               const char *element_name, const char *value);
+
+/*
+ * Machine interface of struct version.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * version Version struct.
+ *
+ * lttng_description String value of the version description.
+ *
+ * lttng_license String value of the version license.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_version(struct mi_writer *writer, struct mi_lttng_version *version,
+               const char *lttng_description, const char *lttng_license);
+
+/*
+ * Machine interface of struct session.
+ *
+ * writer An instance of a machine interface writer
+ *
+ * session An instance of a session
+ *
+ * isOpen Define if we close the session element
+ *        This should be use carefully and the client
+ *        need to close the session element.
+ *        Use case: nested addition information on a session
+ *                  ex: domain,channel event.
+ *        0-> False
+ *        1-> True
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_session(struct mi_writer *writer,
+               struct lttng_session *session, int isOpen);
+
+#endif /* _MI_LTTNG_H */
index a92bf39125b287528d202d9160e09d7b7c7462f2..536d41baa2bc4848b334405afa598a210dc5422e 100644 (file)
@@ -74,6 +74,7 @@ static int connected;
  */
 int lttng_opt_quiet;
 int lttng_opt_verbose;
+int lttng_opt_mi;
 
 /*
  * Copy string from src to dst and enforce null terminated byte.
index 38fe5f4f2193a7770881ea65b02e5e3b43f87316..29935ef1c29a774c8b6313341e46fc8c84d4d39e 100644 (file)
@@ -31,6 +31,7 @@ struct state {
 
 int lttng_opt_quiet = 1;
 int lttng_opt_verbose = 0;
+int lttng_opt_mi;
 
 int entry_handler(const struct config_entry *entry,
                struct state *state)
index 5b82672d73206d5045dfd35a8d9c097b29238857..ca53c7d4853195d67aac1bd0ea673b640fb47f6a 100644 (file)
@@ -38,6 +38,7 @@
 /* For error.h */
 int lttng_opt_quiet = 1;
 int lttng_opt_verbose;
+int lttng_opt_mi;
 
 int ust_consumerd32_fd;
 int ust_consumerd64_fd;
index a0e84e9eadeae103b20be81697629d90d7ddf92e..4f90c3347ec13c7894030ac8d37dd846093b6497 100644 (file)
@@ -46,6 +46,7 @@ static struct ltt_session_list *session_list;
 /* For error.h */
 int lttng_opt_quiet = 1;
 int lttng_opt_verbose = 0;
+int lttng_opt_mi;
 
 int ust_consumerd32_fd;
 int ust_consumerd64_fd;
index 7cac95d98e099a567a9a2f2f68bf0697ef688b5e..432e2b3fcea1ed72775d2ae8d986c0eb9527c139 100644 (file)
@@ -25,6 +25,7 @@
 /* For error.h */
 int lttng_opt_quiet = 1;
 int lttng_opt_verbose = 3;
+int lttng_opt_mi;
 
 /* Number of TAP tests in this file */
 #define NUM_TESTS 11
index 150d5dafb70b785cd63cf6c5442b53584f1c0b97..dd00089266ad7770ce4c64e18b1340439f167c9b 100644 (file)
@@ -44,6 +44,7 @@
 /* For error.h */
 int lttng_opt_quiet = 1;
 int lttng_opt_verbose;
+int lttng_opt_mi;
 
 int ust_consumerd32_fd;
 int ust_consumerd64_fd;
index fe709acf554b81c9b32a13b41165b34cd97721e2..f863b5d9a344c33798936dbf60241eca8151bd22 100644 (file)
@@ -31,6 +31,7 @@
 /* For error.h */
 int lttng_opt_quiet = 1;
 int lttng_opt_verbose = 3;
+int lttng_opt_mi;
 
 struct valid_test_input {
        char *input;
index 45a87b06ce3641a89cc881afb145cb52c6c613f2..2d3bbfc450e3f37676bd8bcd018c0de32623fdaf 100644 (file)
@@ -26,6 +26,7 @@
 /* For error.h */
 int lttng_opt_quiet = 1;
 int lttng_opt_verbose = 3;
+int lttng_opt_mi;
 
 struct valid_test_input {
        char *input;
This page took 0.073168 seconds and 5 git commands to generate.