Fix: bad file descriptor on close in health check
[lttng-tools.git] / src / bin / lttng / commands / create.c
index 0765c823b4209bf4b947a61772837cf1ca7e4947..354a68dcfbc461ab09ff86cb64f672b3bc8f0ae8 100644 (file)
@@ -1,19 +1,18 @@
 /*
  * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; only version 2
- * of the License.
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * 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.
  */
 
 #define _GNU_SOURCE
 #include "../command.h"
 #include "../utils.h"
 
+#include <common/defaults.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/uri.h>
+#include <common/utils.h>
+
 static char *opt_output_path;
 static char *opt_session_name;
+static char *opt_uris;
+static char *opt_ctrl_uris;
+static char *opt_data_uris;
+static int opt_no_consumer = 1;
 
 enum {
        OPT_HELP = 1,
@@ -42,6 +50,10 @@ static struct poptOption long_options[] = {
        {"help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL},
        {"output", 'o', POPT_ARG_STRING, &opt_output_path, 0, NULL, NULL},
        {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
+       {"set-uri",        'U', POPT_ARG_STRING, &opt_uris, 0, 0, 0},
+       {"ctrl-uri",       'C', POPT_ARG_STRING, &opt_ctrl_uris, 0, 0, 0},
+       {"data-uri",       'D', POPT_ARG_STRING, &opt_data_uris, 0, 0, 0},
+       {"no-consumer",      0, POPT_ARG_NONE, &opt_no_consumer, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0}
 };
 
@@ -52,25 +64,100 @@ static void usage(FILE *ofp)
 {
        fprintf(ofp, "usage: lttng create [options] [NAME]\n");
        fprintf(ofp, "\n");
+       fprintf(ofp, "  The default NAME is 'auto-yyyymmdd-hhmmss'\n");
        fprintf(ofp, "  -h, --help           Show this help\n");
-       fprintf(ofp, "      --list-options       Simple listing of options\n");
+       fprintf(ofp, "      --list-options   Simple listing of options\n");
        fprintf(ofp, "  -o, --output PATH    Specify output path for traces\n");
+       fprintf(ofp, "  -U, --set-uri=URI    Set URI for the enable-consumer destination.\n");
+       fprintf(ofp, "                       It is persistent for the session lifetime.\n");
+       fprintf(ofp, "                       Redo the command to change it.\n");
+       fprintf(ofp, "                       This will set both data and control URI for network.\n");
+       fprintf(ofp, "  -C, --ctrl-uri=URI   Set control path URI.\n");
+       fprintf(ofp, "  -D, --data-uri=URI   Set data path URI.\n");
+       fprintf(ofp, "      --no-consumer    Disable consumer for entire tracing session.\n");
        fprintf(ofp, "\n");
 }
 
 /*
- *  create_session
+ * Parse URI from string to lttng_uri object array.
+ */
+static ssize_t parse_uri_from_str(const char *str_uri, struct lttng_uri **uris)
+{
+       int i;
+       ssize_t size;
+       struct lttng_uri *uri;
+
+       if (*uris != NULL) {
+               free(*uris);
+       }
+
+       size = uri_parse(str_uri, uris);
+       if (size < 1) {
+               ERR("Bad URI %s. Either the hostname or IP is invalid", str_uri);
+               size = -1;
+       }
+
+       for (i = 0; i < size; i++) {
+               uri = (struct lttng_uri *) &uris[i];
+               /* Set default port if none was given */
+               if (uri->port == 0) {
+                       if (uri->stype == LTTNG_STREAM_CONTROL) {
+                               uri->port = DEFAULT_NETWORK_CONTROL_PORT;
+                       } else if (uri->stype == LTTNG_STREAM_DATA) {
+                               uri->port = DEFAULT_NETWORK_DATA_PORT;
+                       }
+               }
+       }
+
+       return size;
+}
+
+/*
+ * Print URI message.
+ */
+static void print_uri_msg(struct lttng_uri *uri)
+{
+       char *dst;
+
+       switch (uri->dtype) {
+       case LTTNG_DST_IPV4:
+               dst = uri->dst.ipv4;
+               break;
+       case LTTNG_DST_IPV6:
+               dst = uri->dst.ipv6;
+               break;
+       case LTTNG_DST_PATH:
+               dst = uri->dst.path;
+               MSG("Consumer destination set to %s", dst);
+               goto end;
+       default:
+               DBG("Unknown URI destination");
+               goto end;
+       }
+
+       MSG("Consumer %s stream set to %s with the %s protocol on port %d",
+                       uri->stype == LTTNG_STREAM_CONTROL ? "control" : "data",
+                       dst, uri->proto == LTTNG_TCP ? "TCP" : "UNK", uri->port);
+
+end:
+       return;
+}
+
+/*
+ *  Create a tracing session.
+ *  If no name is specified, a default name is generated.
  *
- *  Create a tracing session. If no name specified, a default name will be
- *  generated.
+ *  Returns one of the CMD_* result constants.
  */
 static int create_session()
 {
-       int ret, have_name = 0;
+       int ret, have_name = 0, i;
        char datetime[16];
        char *session_name, *traces_path = NULL, *alloc_path = NULL;
        time_t rawtime;
+       ssize_t size;
        struct tm *timeinfo;
+       struct lttng_uri *uris = NULL, *ctrl_uri = NULL, *data_uri = NULL;
 
        /* Get date and time for automatic session name/path */
        time(&rawtime);
@@ -90,52 +177,168 @@ static int create_session()
                have_name = 1;
        }
 
-       /* Auto output path */
-       if (opt_output_path == NULL) {
-               alloc_path = strdup(config_get_default_path());
+       if (opt_output_path != NULL) {
+               traces_path = utils_expand_path(opt_output_path);
+               if (traces_path == NULL) {
+                       ret = CMD_ERROR;
+                       goto error;
+               }
+
+               ret = asprintf(&alloc_path, "file://%s", traces_path);
+               if (ret < 0) {
+                       PERROR("asprintf expand path");
+                       ret = CMD_FATAL;
+                       goto error;
+               }
+
+               ret = uri_parse(alloc_path, &ctrl_uri);
+               if (ret < 1) {
+                       ret = CMD_FATAL;
+                       goto error;
+               }
+       } else if (opt_uris) { /* Handling URIs (-U opt) */
+               size = parse_uri_from_str(opt_uris, &uris);
+               if (size < 1) {
+                       ret = CMD_ERROR;
+                       goto error;
+               } else if (size == 1 && uris[0].dtype != LTTNG_DST_PATH) {
+                       ERR("Only net:// and file:// are supported. "
+                                       "Use -C and -D for more fine grained control");
+                       ret = CMD_ERROR;
+                       goto error;
+               } else if (size == 2) {
+                       uris[0].stype = LTTNG_STREAM_CONTROL;
+                       uris[1].stype = LTTNG_STREAM_DATA;
+
+                       for (i = 0; i < size; i++) {
+                               /* Set default port if none was given */
+                               if (uris[i].port == 0) {
+                                       if (uris[i].stype == LTTNG_STREAM_CONTROL) {
+                                               uris[i].port = DEFAULT_NETWORK_CONTROL_PORT;
+                                       } else {
+                                               uris[i].port = DEFAULT_NETWORK_DATA_PORT;
+                                       }
+                               }
+                       }
+
+                       ctrl_uri = &uris[0];
+                       print_uri_msg(ctrl_uri);
+                       data_uri = &uris[1];
+                       print_uri_msg(data_uri);
+               } else {
+                       ctrl_uri = &uris[0];
+                       print_uri_msg(ctrl_uri);
+               }
+       } else if (opt_ctrl_uris || opt_data_uris) {
+               /* Setting up control URI (-C opt) */
+               if (opt_ctrl_uris) {
+                       size = parse_uri_from_str(opt_ctrl_uris, &uris);
+                       if (size < 1) {
+                               ret = CMD_ERROR;
+                               goto error;
+                       }
+                       ctrl_uri = &uris[0];
+                       ctrl_uri->stype = LTTNG_STREAM_CONTROL;
+                       /* Set default port if none specified */
+                       if (ctrl_uri->port == 0) {
+                               ctrl_uri->port = DEFAULT_NETWORK_CONTROL_PORT;
+                       }
+                       print_uri_msg(ctrl_uri);
+               }
+
+               /* Setting up data URI (-D opt) */
+               if (opt_data_uris) {
+                       size = parse_uri_from_str(opt_data_uris, &uris);
+                       if (size < 1) {
+                               ret = CMD_ERROR;
+                               goto error;
+                       }
+                       data_uri = &uris[0];
+                       data_uri->stype = LTTNG_STREAM_DATA;
+                       /* Set default port if none specified */
+                       if (data_uri->port == 0) {
+                               data_uri->port = DEFAULT_NETWORK_DATA_PORT;
+                       }
+                       print_uri_msg(data_uri);
+               }
+       } else {
+               /* Auto output path */
+               alloc_path = config_get_default_path();
                if (alloc_path == NULL) {
-                       ERR("Home path not found.\n \
-                                Please specify an output path using -o, --output PATH");
+                       ERR("HOME path not found.\n \
+                                       Please specify an output path using -o, --output PATH");
                        ret = CMD_FATAL;
                        goto error;
                }
+               alloc_path = strdup(alloc_path);
 
                if (have_name) {
-                       ret = asprintf(&traces_path, "%s/" LTTNG_DEFAULT_TRACE_DIR_NAME
+                       ret = asprintf(&traces_path, "file://%s/" DEFAULT_TRACE_DIR_NAME
                                        "/%s-%s", alloc_path, session_name, datetime);
                } else {
-                       ret = asprintf(&traces_path, "%s/" LTTNG_DEFAULT_TRACE_DIR_NAME
+                       ret = asprintf(&traces_path, "file://%s/" DEFAULT_TRACE_DIR_NAME
                                        "/%s", alloc_path, session_name);
                }
+               if (ret < 0) {
+                       PERROR("asprintf trace dir name");
+                       ret = CMD_FATAL;
+                       goto error;
+               }
 
+               ret = uri_parse(traces_path, &ctrl_uri);
+               if (ret < 1) {
+                       ret = CMD_FATAL;
+                       goto error;
+               }
+       }
+
+       /* If there is no subdir specified and the URI are network */
+       if (strlen(ctrl_uri->subdir) == 0) {
+               if (have_name) {
+                       ret = snprintf(ctrl_uri->subdir, sizeof(ctrl_uri->subdir), "%s-%s",
+                                       session_name, datetime);
+               } else {
+                       ret = snprintf(ctrl_uri->subdir, sizeof(ctrl_uri->subdir), "%s",
+                                       session_name);
+               }
                if (ret < 0) {
-                       perror("asprintf trace dir name");
+                       PERROR("snprintf subdir");
                        goto error;
                }
-       } else {
-               traces_path = opt_output_path;
+               DBG("Subdir update to %s", ctrl_uri->subdir);
        }
 
-       ret = lttng_create_session(session_name, traces_path);
+       ret = lttng_create_session_uri(session_name, ctrl_uri, data_uri,
+                       opt_no_consumer);
        if (ret < 0) {
+               /* Don't set ret so lttng can interpret the sessiond error. */
+               switch (-ret) {
+               case LTTCOMM_EXIST_SESS:
+                       WARN("Session %s already exists", session_name);
+                       break;
+               }
                goto error;
        }
 
        /* Init lttng session config */
        ret = config_init(session_name);
        if (ret < 0) {
-               if (ret == -1) {
-                       ret = CMD_ERROR;
-               }
+               ret = CMD_ERROR;
                goto error;
        }
 
        MSG("Session %s created.", session_name);
-       MSG("Traces will be written in %s" , traces_path);
+       if (ctrl_uri->dtype == LTTNG_DST_PATH) {
+               MSG("Traces will be written in %s" , ctrl_uri->dst.path);
+       }
 
        ret = CMD_SUCCESS;
 
 error:
+       if (opt_session_name == NULL) {
+               free(session_name);
+       }
+
        if (alloc_path) {
                free(alloc_path);
        }
@@ -147,9 +350,9 @@ error:
 }
 
 /*
- *  cmd_create
- *
  *  The 'create <options>' first level command
+ *
+ *  Returns one of the CMD_* result constants.
  */
 int cmd_create(int argc, const char **argv)
 {
@@ -162,11 +365,10 @@ int cmd_create(int argc, const char **argv)
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case OPT_HELP:
-                       usage(stderr);
+                       usage(stdout);
                        goto end;
                case OPT_LIST_OPTIONS:
                        list_cmd_options(stdout, long_options);
-                       ret = CMD_SUCCESS;
                        goto end;
                default:
                        usage(stderr);
@@ -180,5 +382,6 @@ int cmd_create(int argc, const char **argv)
        ret = create_session();
 
 end:
+       poptFreeContext(pc);
        return ret;
 }
This page took 0.027387 seconds and 4 git commands to generate.