Implement create command --default-name option
[lttng-tools.git] / src / bin / lttng / commands / create.c
CommitLineData
f3ed775e
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
d14d33bf
AM
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
f3ed775e
DG
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
d14d33bf
AM
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
f3ed775e
DG
16 */
17
6c1c0768 18#define _LGPL_SOURCE
a4b92340 19#include <assert.h>
ecc48a90 20#include <ctype.h>
f3ed775e
DG
21#include <popt.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <time.h>
28#include <unistd.h>
92360082 29#include <signal.h>
bbd44cae 30#include <sys/wait.h>
f3ed775e 31
37d03ff7 32#include <common/mi-lttng.h>
4a102b75 33#include <common/config/session-config.h>
37d03ff7 34
c399183f 35#include "../command.h"
679b4943 36#include "../utils.h"
f3ed775e 37
00e2e675 38#include <common/defaults.h>
42224349 39#include <common/sessiond-comm/sessiond-comm.h>
00e2e675 40#include <common/uri.h>
81b86775 41#include <common/utils.h>
16f6f820 42#include <lttng/snapshot.h>
42224349 43
f3ed775e
DG
44static char *opt_output_path;
45static char *opt_session_name;
a4b92340
DG
46static char *opt_url;
47static char *opt_ctrl_url;
48static char *opt_data_url;
d7ba1388 49static char *opt_shm_path;
4a102b75 50static char *opt_template_path;
a4b92340 51static int opt_no_consumer;
96fe6b8d 52static int opt_no_output;
16f6f820 53static int opt_snapshot;
ecc48a90 54static unsigned int opt_live_timer;
e51a4200 55static bool opt_default_name;
f3ed775e
DG
56
57enum {
58 OPT_HELP = 1,
679b4943 59 OPT_LIST_OPTIONS,
ecc48a90 60 OPT_LIVE_TIMER,
e51a4200 61 OPT_DEFAULT_NAME,
f3ed775e
DG
62};
63
05ca94c0 64enum output_type {
101fa438 65 OUTPUT_UNKNOWN = -1,
227bc702
JR
66 OUTPUT_NONE,
67 OUTPUT_LOCAL,
68 OUTPUT_NET,
69};
05ca94c0 70enum session_type {
101fa438 71 SESSION_UNKNOWN = -1,
227bc702
JR
72 SESSION_NORMAL,
73 SESSION_LIVE,
74 SESSION_SNAPSHOT,
75};
76
77
37d03ff7
JRJ
78static struct mi_writer *writer;
79
f3ed775e
DG
80static struct poptOption long_options[] = {
81 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
679b4943
SM
82 {"help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL},
83 {"output", 'o', POPT_ARG_STRING, &opt_output_path, 0, NULL, NULL},
84 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
23d14dff
DG
85 {"set-url", 'U', POPT_ARG_STRING, &opt_url, 0, 0, 0},
86 {"ctrl-url", 'C', POPT_ARG_STRING, &opt_ctrl_url, 0, 0, 0},
87 {"data-url", 'D', POPT_ARG_STRING, &opt_data_url, 0, 0, 0},
96fe6b8d 88 {"no-output", 0, POPT_ARG_VAL, &opt_no_output, 1, 0, 0},
2bba9e53 89 {"no-consumer", 0, POPT_ARG_VAL, &opt_no_consumer, 1, 0, 0},
16f6f820 90 {"snapshot", 0, POPT_ARG_VAL, &opt_snapshot, 1, 0, 0},
d73c5802 91 {"live", 0, POPT_ARG_INT | POPT_ARGFLAG_OPTIONAL, 0, OPT_LIVE_TIMER, 0, 0},
d7ba1388 92 {"shm-path", 0, POPT_ARG_STRING, &opt_shm_path, 0, 0, 0},
4a102b75 93 {"template-path", 0, POPT_ARG_STRING, &opt_template_path, 0, 0, 0},
e51a4200 94 {"default-name", 0, POPT_ARG_NONE, NULL, OPT_DEFAULT_NAME, 0, 0},
f3ed775e
DG
95 {0, 0, 0, 0, 0, 0, 0}
96};
97
16de1a24
DG
98/*
99 * Please have a look at src/lib/lttng-ctl/lttng-ctl.c for more information on
100 * why this declaration exists and used ONLY in for this command.
101 */
07424f16 102extern int _lttng_create_session_ext(const char *name, const char *url,
d1edd8a8 103 const char *datetime);
07424f16 104
37d03ff7 105/*
485ca16f 106 * Retrieve the created session and mi output it based on provided argument
37d03ff7
JRJ
107 * This is currently a summary of what was pretty printed and is subject to
108 * enhancements.
37d03ff7
JRJ
109 */
110static int mi_created_session(const char *session_name)
111{
112 int ret, i, count, found;
113 struct lttng_session *sessions;
114
115 /* session_name should not be null */
116 assert(session_name);
117 assert(writer);
118
119 count = lttng_list_sessions(&sessions);
120 if (count < 0) {
121 ret = count;
122 ERR("%s", lttng_strerror(ret));
123 goto error;
124 }
125
126 if (count == 0) {
127 ERR("Error session creation failed: session %s not found", session_name);
128 ret = -LTTNG_ERR_SESS_NOT_FOUND;
129 goto end;
130 }
131
132 found = 0;
133 for (i = 0; i < count; i++) {
134 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
135 found = 1;
136 ret = mi_lttng_session(writer, &sessions[i], 0);
137 if (ret) {
138 goto error;
139 }
140 break;
141 }
142 }
143
144 if (!found) {
145 ret = -LTTNG_ERR_SESS_NOT_FOUND;
146 } else {
147 ret = CMD_SUCCESS;
148 }
149
150error:
151 free(sessions);
152end:
153 return ret;
154}
155
00e2e675 156/*
a4b92340 157 * For a session name, set the consumer URLs.
00e2e675 158 */
a4b92340
DG
159static int set_consumer_url(const char *session_name, const char *ctrl_url,
160 const char *data_url)
00e2e675 161{
a4b92340
DG
162 int ret;
163 struct lttng_handle *handle;
a4b92340
DG
164
165 assert(session_name);
166
167 /*
95681498
JG
168 * Set handle with the session_name, but no domain. This implies that
169 * the actions taken with this handle apply on the tracing session
170 * rather then the domain-specific session.
a4b92340 171 */
95681498 172 handle = lttng_create_handle(session_name, NULL);
a4b92340
DG
173 if (handle == NULL) {
174 ret = CMD_FATAL;
175 goto error;
176 }
00e2e675 177
a4b92340
DG
178 ret = lttng_set_consumer_url(handle, ctrl_url, data_url);
179 if (ret < 0) {
180 goto error;
00e2e675
DG
181 }
182
a4b92340
DG
183error:
184 lttng_destroy_handle(handle);
185 return ret;
186}
187
16f6f820
DG
188static int add_snapshot_output(const char *session_name, const char *ctrl_url,
189 const char *data_url)
190{
191 int ret;
192 struct lttng_snapshot_output *output = NULL;
193
194 assert(session_name);
195
196 output = lttng_snapshot_output_create();
197 if (!output) {
198 ret = CMD_FATAL;
199 goto error_create;
200 }
201
202 if (ctrl_url) {
203 ret = lttng_snapshot_output_set_ctrl_url(ctrl_url, output);
204 if (ret < 0) {
205 goto error;
206 }
207 }
208
209 if (data_url) {
210 ret = lttng_snapshot_output_set_data_url(data_url, output);
211 if (ret < 0) {
212 goto error;
213 }
214 }
215
216 /* This call, if successful, populates the id of the output object. */
217 ret = lttng_snapshot_add_output(session_name, output);
218 if (ret < 0) {
219 goto error;
220 }
221
222error:
223 lttng_snapshot_output_destroy(output);
224error_create:
225 return ret;
226}
227
227bc702
JR
228/*
229 * Validate the combinations of passed options
230 *
231 * CMD_ERROR on error
232 * CMD_SUCCESS on success
233 */
05ca94c0 234static int validate_command_options(enum session_type type)
227bc702
JR
235{
236 int ret = CMD_SUCCESS;
dd4b646b 237
227bc702
JR
238 if (opt_snapshot && opt_live_timer) {
239 ERR("Snapshot and live modes are mutually exclusive.");
240 ret = CMD_ERROR;
241 goto error;
242 }
243
244 if ((!opt_ctrl_url && opt_data_url) || (opt_ctrl_url && !opt_data_url)) {
dd4b646b 245 ERR("Control and data URLs must both be set.");
227bc702
JR
246 ret = CMD_ERROR;
247 goto error;
248 }
249
4a102b75
JR
250 if (opt_template_path) {
251 /* Restriction on flags exist when using template */
252 /* Session type flags are not permitted */
253 /* --live & --snapshot */
05ca94c0
JR
254 if ((opt_live_timer && type != SESSION_LIVE) ||
255 (opt_snapshot && type != SESSION_SNAPSHOT)) {
4a102b75
JR
256 ERR("It is not possible to change the session type of a template");
257 ret = CMD_ERROR;
258 goto error;
259 }
260 }
261
e51a4200
JG
262 if (opt_session_name && opt_default_name) {
263 ERR("A session name must not be provided if the --default-name option is used");
264 ret = CMD_ERROR;
265 goto error;
266 }
227bc702
JR
267error:
268 return ret;
269}
270
271/*
d49b7031 272 * Create a session using direct calls to liblttng-ctl.
227bc702
JR
273 *
274 * Return CMD_SUCCESS on success, negative value on internal lttng errors and positive
275 * value on command errors.
276 */
277static int create_session_basic (const char *session_name,
05ca94c0 278 enum session_type session_type,
227bc702 279 int live_timer,
05ca94c0 280 enum output_type output_type,
227bc702
JR
281 const char* url,
282 const char* ctrl_url,
283 const char* data_url,
284 const char* shm_path,
285 const char* datetime)
286{
287 /* Create session based on session creation */
288 int ret = CMD_SUCCESS;
289 const char *pathname;
290
291 assert(datetime);
292
293 if (opt_relayd_path) {
294 pathname = opt_relayd_path;
295 } else {
296 pathname = INSTALL_BIN_PATH "/lttng-relayd";
297 }
298
299 switch (session_type) {
300 case SESSION_NORMAL:
301 ret = _lttng_create_session_ext(session_name, url, datetime);
302 break;
303 case SESSION_SNAPSHOT:
304 if (output_type == OUTPUT_NONE) {
305 ERR("--no-output on a snapshot session is invalid");
306 ret = CMD_UNSUPPORTED;
307 goto error;
308 }
309 ret = lttng_create_session_snapshot(session_name, url);
310 break;
311 case SESSION_LIVE:
312 if (output_type == OUTPUT_NONE) {
313 ERR("--no-output on a live session is invalid");
314 ret = CMD_UNSUPPORTED;
315 goto error;
316 }
317
318 if (output_type == OUTPUT_LOCAL) {
319 ERR("Local file output on a live session is invalid");
320 ret = CMD_UNSUPPORTED;
321 goto error;
322 }
323 if (output_type != OUTPUT_NET && !check_relayd() &&
324 spawn_relayd(pathname, 0) < 0) {
325 ret = CMD_FATAL;
326 goto error;
327 }
328 ret = lttng_create_session_live(session_name, url, live_timer);
329 break;
330 default:
331 ERR("Unknown session type");
332 ret = CMD_UNDEFINED;
333 goto error;
334 }
335
336 if (ret < 0) {
8ad05258 337 /* Don't set ret so the sessiond error is propagated. */
227bc702
JR
338 switch (-ret) {
339 case LTTNG_ERR_EXIST_SESS:
340 WARN("Session %s already exists", session_name);
341 break;
342 default:
343 break;
344 }
345 goto error;
346 }
347
348 /* Configure the session based on the output type */
349 switch (output_type) {
350 case OUTPUT_LOCAL:
351 break;
352 case OUTPUT_NET:
19ed6174
JR
353 if (!ctrl_url || !data_url) {
354 break;
355 }
356
227bc702
JR
357 if (session_type == SESSION_SNAPSHOT) {
358 ret = add_snapshot_output(session_name, ctrl_url,
359 data_url);
19ed6174 360 } else {
227bc702
JR
361 /*
362 * Normal sessions and live sessions behave the same way
363 * regarding consumer url.
364 */
365 ret = set_consumer_url(session_name, ctrl_url, data_url);
366 }
367 if (ret < 0) {
368 /* Destroy created session on errors */
369 lttng_destroy_session(session_name);
370 goto error;
371 }
372 break;
373 case OUTPUT_NONE:
374 break;
375 default:
376 ERR("Unknown output type");
377 ret = CMD_UNDEFINED;
378 goto error;
379 }
380
381 /*
382 * Set the session shared memory path
383 */
384 if (shm_path) {
385 ret = lttng_set_session_shm_path(session_name, shm_path);
386 if (ret < 0) {
387 lttng_destroy_session(session_name);
388 goto error;
389 }
390 }
391error:
392 return ret;
393}
394
395static int generate_output(const char *session_name,
05ca94c0 396 enum session_type session_type,
227bc702 397 int live_timer,
05ca94c0 398 enum output_type output_type,
227bc702
JR
399 const char* url,
400 const char* ctrl_url,
401 const char* data_url,
402 const char* shm_path)
403{
404 int ret = CMD_SUCCESS;
405
406 /*
407 * TODO move this to after session name
408 * for now we only emulate previous behaviour.
409 */
410 if (session_type != SESSION_SNAPSHOT) {
411 if (ctrl_url) {
412 MSG("Control URL %s set for session %s", ctrl_url, session_name);
413 }
414
415 if (data_url) {
416 MSG("Data URL %s set for session %s", data_url, session_name);
417 }
418 }
419
420 if (url && output_type == OUTPUT_LOCAL) {
421 /* Remove the file:// */
422 if (strlen(url) > strlen("file://")){
423 url = url + strlen("file://");
424 }
425 }
426
427 MSG("Session %s created.", session_name);
428 if (url && session_type != SESSION_SNAPSHOT) {
429 MSG("Traces will be written in %s", url);
430
431 if (live_timer) {
432 MSG("Live timer set to %u usec", live_timer);
433 }
434 } else if (session_type == SESSION_SNAPSHOT) {
435 if (url) {
436 MSG("Default snapshot output set to: %s", url);
437 }
438 MSG("Snapshot mode set. Every channel enabled for that session will "
439 "be set to mmap output, and default to overwrite mode.");
440 }
441
442 if (shm_path) {
443 MSG("Session %s set to shm_path: %s.", session_name,
444 shm_path);
445 }
446
447 /* Mi output */
448 if (lttng_opt_mi) {
449 ret = mi_created_session(session_name);
450 if (ret) {
451 ret = CMD_ERROR;
452 goto error;
453 }
454 }
455error:
456 return ret;
457}
458
4a102b75
JR
459static int parse_template (struct config_document *template,
460 char **session_name,
05ca94c0 461 enum session_type *session_type,
4a102b75 462 int *live_timer,
05ca94c0 463 enum output_type *output_type,
4a102b75
JR
464 char **url,
465 char **ctrl_url,
466 char **data_url,
467 char **shm_path)
468{
469 int ret = 0;
b37959c7 470 int printed_bytes;
4a102b75
JR
471 char *raw_value = NULL;
472
473 assert(template);
474
475 /* Session name */
476 *session_name = config_document_get_element_value(template,"/sessions/session/name");
477
478 /* Check the type of session we have in the template */
479 if(config_document_element_exist(template, "/sessions/session/attributes/snapshot_mode")) {
480 *session_type = SESSION_SNAPSHOT;
481 } else if (config_document_element_exist(template, "/sessions/session/attributes/live_timer_interval")) {
482 *session_type = SESSION_LIVE;
483 raw_value = config_document_get_element_value(template,"/sessions/session/attributes/live_timer_interval");
484 *live_timer = config_parse_value(raw_value);
485 free(raw_value);
486 raw_value = NULL;
487 } else {
488 *session_type = SESSION_NORMAL;
489 }
490
491 /* Output */
492 switch (*session_type) {
493 case SESSION_NORMAL:
494 case SESSION_LIVE:
495 if (!config_document_element_exist(template, "/sessions/session/output/consumer_output/destination")){
496 break;
497 }
498 if (config_document_element_exist(template, "/sessions/session/output/consumer_output/destination/path")){
499 raw_value = config_document_get_element_value(template, "/sessions/session/output/consumer_output/destination/path");
500 if (!raw_value) {
501 ret = -1;
502 goto error;
503 }
504
505 if (strlen(raw_value) > 0) {
506 *output_type = OUTPUT_LOCAL;
b37959c7
JR
507 printed_bytes = asprintf(url, "file://%s", raw_value);
508 if (printed_bytes < 0) {
4a102b75
JR
509 ret = -1;
510 goto error;
511 }
512 } else {
513 *output_type = OUTPUT_NONE;
514 }
515
516 free(raw_value);
517 raw_value = NULL;
518 break;
519 } else if(config_document_element_exist(template, "/sessions/session/output/consumer_output/destination/net_output")) {
520 *ctrl_url = config_document_get_element_value(template, "/sessions/session/output/consumer_output/destination/net_output/control_uri");
521 *data_url = config_document_get_element_value(template, "/sessions/session/output/consumer_output/destination/net_output/data_uri");
522 if (!*ctrl_url || ! *data_url) {
523 ret = -1;
524 goto error;
525 }
526 *output_type = OUTPUT_NET;
527 } else {
528 /* There is no output definition */
529 }
530 break;
531 case SESSION_SNAPSHOT:
532 if (!config_document_element_exist(template, "/sessions/session/output/snapshot_outputs/output/consumer_output/destination")){
533 break;
534 }
535 if (config_document_element_exist(template, "/sessions/session/output/snapshot_outputs/output/consumer_output/destination/path")){
536 raw_value = config_document_get_element_value(template, "/sessions/session/output/snapshot_outputs/output/consumer_output/destination/path");
537 if (!raw_value) {
538 ret = -1;
539 goto error;
540 }
541
542 if (strlen(raw_value) > 0) {
543 *output_type = OUTPUT_LOCAL;
b37959c7
JR
544 printed_bytes = asprintf(url, "file://%s", raw_value);
545 if (printed_bytes < 0) {
4a102b75
JR
546 ret = -1;
547 goto error;
548 }
549 } else {
550 *output_type = OUTPUT_NONE;
551 }
552
553 free(raw_value);
554 raw_value = NULL;
555 break;
556 } else if(config_document_element_exist(template, "/sessions/session/output/snapshot_outputs/output/consumer_output/destination/net_output")) {
557 *ctrl_url = config_document_get_element_value(template, "/sessions/session/output/snapshot_outputs/output/consumer_output/destination/net_output/control_uri");
558 *data_url = config_document_get_element_value(template, "/sessions/session/output/snapshot_outputs/output/consumer_output/destination/net_output/data_uri");
559 if (!*ctrl_url || ! *data_url) {
560 ret = -1;
561 goto error;
562 }
563 *output_type = OUTPUT_NET;
564 } else {
565 /* There is no output definition */
566 }
567 break;
05ca94c0
JR
568 case SESSION_UNKNOWN:
569 ret = -1;
570 goto error;
4a102b75
JR
571 }
572
573
574 /* shared memory path */
575 *shm_path = config_document_get_element_value(template,"/sessions/session/shared_memory_path");
576
577error:
578 free(raw_value);
579 return ret;
580
581}
582static int create_session_from_template(struct config_document *template,
583 const char *session_name,
05ca94c0 584 enum session_type session_type,
4a102b75 585 int live_timer,
05ca94c0 586 enum output_type output_type,
4a102b75
JR
587 const char *url,
588 const char *ctrl_url,
589 const char *data_url,
590 const char *shm_path,
591 const char *datetime)
592{
593 int ret = CMD_SUCCESS;
b37959c7 594 int printed_bytes;
4a102b75
JR
595 struct config_element *temp_element = NULL;
596 struct config_element *temp_element_child = NULL;
597 char tmp_ctrl_uri[PATH_MAX];
598 char tmp_data_uri[PATH_MAX];
599 struct lttng_uri *uris = NULL;
600 ssize_t uri_array_size = 0;
601 char *tmp_string = NULL;
602
603 assert(template);
604 assert(session_name);
605
606 memset(tmp_ctrl_uri, 0, sizeof(tmp_ctrl_uri));
607 memset(tmp_data_uri, 0, sizeof(tmp_data_uri));
608
609 /* Session name */
610 if (config_document_element_exist(template, "/sessions/session/name")) {
611 /* Replace the node value */
612 config_document_replace_element_value(template, "/sessions/session/name", session_name);
613 } else {
614 /* insert the node */
615 temp_element = config_element_create("name", session_name);
616 if (!temp_element) {
617 ERR("Could not create session name node configuration");
618 ret = CMD_ERROR;
619 goto error;
620 }
621 ret = config_document_insert_element(template, "/sessions/session", temp_element);
622 if (ret) {
623 ERR("Could not insert session name node configuration");
624 ret = CMD_ERROR;
625 goto error;
626 }
627 config_element_free(temp_element);
628 }
629
630 /*
631 * Live timer
632 */
633 if (session_type == SESSION_LIVE) {
634 if (config_document_element_exist(template, "/sessions/session/attributes/live_timer_interval")) {
b37959c7
JR
635 printed_bytes = asprintf(&tmp_string, "%d", live_timer);
636 if (printed_bytes < 0) {
af7f3c88
JR
637 ERR("Asprintf failed for live timer");
638 ret = CMD_ERROR;
639 goto error;
640 }
641 ret = config_document_replace_element_value(template, "/sessions/session/attributes/live_timer_interval", tmp_string);
642
643 if (ret) {
644 printf("error: %d\n", ret);
645 ERR("Replacement of live_timer_interval failed");
646 ret = CMD_ERROR;
647 goto error;
648 }
649
4a102b75
JR
650 free(tmp_string);
651 tmp_string = NULL;
652 } else {
653 ERR("Invalid live timer template. Missing live timer node");
654 ret = CMD_ERROR;
655 goto error;
656 }
657
658 }
659
660 /*
661 * Generate the output node
662 */
663
664 /* Get output from urls */
665 if (url) {
666 /* Get lttng uris from single url */
667 uri_array_size = uri_parse_str_urls(url, NULL, &uris);
668 if (uri_array_size < 0) {
669 ret = CMD_ERROR;
670 goto error;
671 }
672 } else if (ctrl_url && data_url) {
673 uri_array_size = uri_parse_str_urls(ctrl_url, data_url, &uris);
674 if (uri_array_size < 0) {
675 ret = CMD_ERROR;
676 goto error;
677 }
678 } else {
679 /* --no-output */
680 uri_array_size = 0;
681 }
682
683 /* Validate if the session output type still match the passed data */
684 if ( (uri_array_size == 0 && output_type != OUTPUT_NONE) ||
685 (uri_array_size == 1 && output_type != OUTPUT_LOCAL) ||
686 (uri_array_size == 2 && output_type != OUTPUT_NET)) {
687 ERR("Overwriting value for output do not match the base output type");
688 ret = CMD_ERROR;
689 goto error;
690 }
691
692 switch (output_type) {
693 case OUTPUT_NONE:
694 temp_element_child = config_element_create("path", "");
695 if (!temp_element_child) {
696 ERR("Could not create empty path node configuration");
697 ret = CMD_ERROR;
698 goto error;
699 }
700 break;
701 case OUTPUT_LOCAL:
702 temp_element_child = config_element_create("path", uris[0].dst.path);
703 if (!temp_element_child) {
704 ERR("Could not create local path node configuration");
705 ret = CMD_ERROR;
706 goto error;
707 }
708 break;
709 case OUTPUT_NET:
710 uri_to_str_url(&uris[0], tmp_ctrl_uri, sizeof(tmp_ctrl_uri));
711 uri_to_str_url(&uris[1], tmp_data_uri, sizeof(tmp_data_uri));
712
713 temp_element_child = config_element_create("net_output", NULL);
714 if (!temp_element_child) {
715 ERR("Could not create net_output node configuration");
716 ret = CMD_ERROR;
717 goto error;
718 }
719
720 temp_element = config_element_create("control_uri", tmp_ctrl_uri);
721 if (!temp_element_child) {
722 ERR("Could not create ctrl uri node configuration");
723 ret = CMD_ERROR;
724 goto error;
725 }
726
727 ret = config_element_add_child(temp_element_child, temp_element);
728 if (ret) {
729 ERR("Could not append control uri to the net_output node configuration");
730 ret = CMD_ERROR;
731 goto error;
732 }
2f0e04ab 733
4a102b75 734 config_element_free(temp_element);
2f0e04ab 735 temp_element = NULL;
4a102b75
JR
736
737 temp_element = config_element_create("data_uri", tmp_data_uri);
738
739 if (!temp_element_child) {
740 ERR("Could not create data_uri configuration");
741 ret = CMD_ERROR;
742 goto error;
743 }
744
745 ret = config_element_add_child(temp_element_child, temp_element);
746 if (ret) {
747 ERR("Could not append data uri to the net_output node configuration");
748 ret = CMD_ERROR;
749 goto error;
750 }
751 config_element_free(temp_element);
2f0e04ab 752 temp_element = NULL;
4a102b75
JR
753 break;
754 default:
755 ret = CMD_ERROR;
756 goto error;
757 }
758
759 temp_element = config_element_create("destination", NULL);
760 if (!temp_element) {
761 ERR("Could not create destination node configuration");
762 ret = CMD_ERROR;
763 goto error;
764 }
765
766 ret = config_element_add_child(temp_element, temp_element_child);
767 if (ret) {
768 ERR("Could not append output data to the destination node configuration");
769 ret = CMD_ERROR;
770 goto error;
771 }
772
2f0e04ab
JR
773 config_element_free(temp_element_child);
774 temp_element_child = NULL;
775
e0988a8c
JR
776 /* Construct the output/consumer_output/ node*/
777 temp_element_child = temp_element;
778 temp_element = config_element_create("consumer_output", NULL);
779 if (!temp_element) {
780 ERR("Could not create consumer_output node configuration");
781 ret = CMD_ERROR;
782 goto error;
783 }
784
785 ret = config_element_add_child(temp_element, temp_element_child);
786 if (ret) {
787 ERR("Could not append output data to the consumer_output node configuration");
788 ret = CMD_ERROR;
789 goto error;
790 }
791
792 config_element_free(temp_element_child);
793 temp_element_child = config_element_create("enabled", "true");
794 if (!temp_element_child) {
795 ERR("Could not create enbaled node configuration");
796 ret = CMD_ERROR;
797 goto error;
798 }
799
800 ret = config_element_add_child(temp_element, temp_element_child);
801 if (ret) {
802 ERR("Could not append node to the consumer_output node configuration");
803 ret = CMD_ERROR;
804 goto error;
805 }
806
807 config_element_free(temp_element_child);
808 temp_element_child = NULL;
809
810
811 temp_element_child = temp_element;
812 temp_element = config_element_create("output", NULL);
813 if (!temp_element) {
814 ERR("Could not create output node configuration");
815 ret = CMD_ERROR;
816 goto error;
817 }
818
819 ret = config_element_add_child(temp_element, temp_element_child);
820 if (ret) {
821 ERR("Could not append output data to the output node configuration");
822 ret = CMD_ERROR;
823 goto error;
824 }
825
826 config_element_free(temp_element_child);
827 temp_element_child = NULL;
828
2f0e04ab 829
4a102b75
JR
830 /*
831 * validate and replace the destination node for each session type
832 * TODO: export string as const and simply assign a base path for the
833 * destination node based on the session type
834 **/
835 switch (session_type) {
836 case SESSION_NORMAL:
837 case SESSION_LIVE:
e0988a8c
JR
838 break;
839 case SESSION_SNAPSHOT:
840 /* construct the output/snapshots_outputs/ */
841 temp_element_child = temp_element;
842 temp_element = config_element_create("snapshot_outputs", NULL);
843 if (!temp_element) {
844 ERR("Could not create snapshot_outputs node configuration");
4a102b75
JR
845 ret = CMD_ERROR;
846 goto error;
847 }
848
e0988a8c
JR
849 ret = config_element_add_child(temp_element, temp_element_child);
850 if (ret) {
851 ERR("Could not append output data to the snapshot_outputs node configuration");
4a102b75
JR
852 ret = CMD_ERROR;
853 goto error;
854 }
855
e0988a8c
JR
856 config_element_free(temp_element_child);
857 temp_element_child = NULL;
858
859 temp_element_child = temp_element;
860 temp_element = config_element_create("output", NULL);
861 if (!temp_element) {
862 ERR("Could not create output node configuration");
863 ret = CMD_ERROR;
864 goto error;
865 }
866
867 ret = config_element_add_child(temp_element, temp_element_child);
868 if (ret) {
869 ERR("Could not append output data to the output node configuration");
870 ret = CMD_ERROR;
871 goto error;
872 }
873
874 config_element_free(temp_element_child);
875 temp_element_child = NULL;
4a102b75
JR
876 break;
877 default:
878 ERR("Invalid session type");
879 ret = CMD_UNDEFINED;
880 goto error;
881 }
882
e0988a8c
JR
883 if (!config_document_element_exist(template, "/sessions/session/output")) {
884 ret = config_document_insert_element(template, "/sessions/session", temp_element);
885 } else {
886 ret = config_document_replace_element(template, "/sessions/session/output", temp_element);
887 }
888
2f0e04ab
JR
889 config_element_free(temp_element);
890 temp_element = NULL;
4a102b75 891
0709e00e
JR
892 if (ret) {
893 ERR("%s", lttng_strerror(ret));
894 ret = CMD_ERROR;
895 goto error;
896 }
897
4a102b75
JR
898
899 /* Shm path */
900 if (shm_path && config_document_element_exist(template, "/sessions/session/shared_memory_path")) {
901 /* Replace the node value */
902 config_document_replace_element_value(template, "/sessions/session/shared_memory_path", shm_path);
903 } else if (shm_path) {
904 /* insert the node */
905 temp_element = config_element_create("shared_memory_path", shm_path);
906 if (!temp_element) {
907 ERR("Could not create shared_memory_path node configuration");
908 ret = CMD_ERROR;
909 goto error;
910 }
911 ret = config_document_insert_element(template, "/sessions/session", temp_element);
912 if (ret) {
913 ERR("Could not insert shared_memory_path node configuration");
914 ret = CMD_ERROR;
915 goto error;
916 }
2f0e04ab
JR
917
918 config_element_free(temp_element);
919 temp_element = NULL;
4a102b75
JR
920 }
921
922 ret = config_load_configuration_sessions(template, session_name, 0);
923
924
925error:
926 config_element_free(temp_element);
927 config_element_free(temp_element_child);
928 free(tmp_string);
929 free(uris);
930 return ret;
931
932}
933
f3ed775e 934/*
1c8d13c8
TD
935 * Create a tracing session.
936 * If no name is specified, a default name is generated.
f3ed775e 937 *
1c8d13c8 938 * Returns one of the CMD_* result constants.
f3ed775e 939 */
a4b92340 940static int create_session(void)
f3ed775e 941{
a4b92340 942 int ret;
b37959c7 943 int printed_bytes;
227bc702 944
4a102b75
JR
945
946 /* Template */
947 struct config_document *template = NULL;
948
227bc702 949 /* Base data */
05ca94c0
JR
950 enum session_type base_session_type = SESSION_UNKNOWN;
951 enum output_type base_output_type = OUTPUT_UNKNOWN;
227bc702
JR
952 char *base_session_name = NULL;
953 char *base_url = NULL;
954 char *base_ctrl_url = NULL;
955 char *base_data_url = NULL;
956 char *base_shm_path = NULL;
957 int base_live_timer = 0;
958
959 /* Time data */
960 char datetime[16];
f3ed775e 961 time_t rawtime;
227bc702
JR
962 struct tm *timeinfo = NULL;
963
964 /* Temporary variables */
965 char *traces_path = NULL;
966 char *temp_url = NULL;
967 char *session_name_date = NULL;
968 char *tmp_url = NULL;
969 char *tmp_home_path = NULL;
970 struct lttng_uri *uris = NULL;
971 ssize_t uri_array_size = 0;
972
f3ed775e 973
d6175221
DG
974 /* Get date and time for automatic session name/path */
975 time(&rawtime);
976 timeinfo = localtime(&rawtime);
977 strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo);
978
4a102b75
JR
979 if (opt_template_path) {
980 /* Restriction on flags exist when using template */
981 /* Session type flags are not permitted */
982 /* --live & --snapshot */
983 template = config_document_get(opt_template_path);
984 if (!template) {
985 ERR("Template could not be parsed");
986 ret = CMD_ERROR;
987 goto error;
988 }
989 /* Load info from template if any */
990 /* TODO: might want to use a struct in the end for the session... */
991 ret = parse_template(template, &base_session_name,
992 &base_session_type,
993 &base_live_timer,
994 &base_output_type,
995 &base_url,
996 &base_ctrl_url,
997 &base_data_url,
998 &base_shm_path);
8e4afd43
JR
999 if (ret) {
1000 goto error;
1001 }
4a102b75
JR
1002 }
1003
1004 /* Option validation */
1005 if (validate_command_options(base_session_type) != CMD_SUCCESS) {
1006 ret = CMD_ERROR;
1007 goto error;
1008 }
1009
227bc702
JR
1010 /* Find the session type based on options */
1011 if(base_session_type == SESSION_UNKNOWN) {
1012 if (opt_snapshot) {
1013 base_session_type = SESSION_SNAPSHOT;
1014 } else if (opt_live_timer) {
1015 base_session_type = SESSION_LIVE;
1016 } else {
1017 base_session_type = SESSION_NORMAL;
07424f16 1018 }
227bc702
JR
1019 }
1020
1021 /*
1022 * Session name handling
1023 */
1024 if (opt_session_name) {
1025 /* Override the session name */
487b253b
DG
1026 if (strlen(opt_session_name) > NAME_MAX) {
1027 ERR("Session name too long. Length must be lower or equal to %d",
1028 NAME_MAX);
1029 ret = LTTNG_ERR_SESSION_FAIL;
227bc702 1030 free(session_name_date);
487b253b
DG
1031 goto error;
1032 }
4b861950
DG
1033 /*
1034 * Check if the session name begins with "auto-" or is exactly "auto".
1035 * Both are reserved for the default session name. See bug #449 to
1036 * understand why we need to check both here.
1037 */
1038 if ((strncmp(opt_session_name, DEFAULT_SESSION_NAME "-",
227bc702
JR
1039 strlen(DEFAULT_SESSION_NAME) + 1) == 0) ||
1040 (strncmp(opt_session_name, DEFAULT_SESSION_NAME,
1041 strlen(DEFAULT_SESSION_NAME)) == 0 &&
67238b20 1042 strlen(opt_session_name) == strlen(DEFAULT_SESSION_NAME))) {
61b35a5a
DG
1043 ERR("%s is a reserved keyword for default session(s)",
1044 DEFAULT_SESSION_NAME);
227bc702
JR
1045
1046 ret = CMD_ERROR;
1047 goto error;
1048 }
1049
1050 base_session_name = strndup(opt_session_name, NAME_MAX);
1051 if (!base_session_name) {
1052 PERROR("Strdup session name");
61b35a5a
DG
1053 ret = CMD_ERROR;
1054 goto error;
1055 }
227bc702 1056
b37959c7
JR
1057 printed_bytes = asprintf(&session_name_date, "%s-%s", base_session_name, datetime);
1058 if (printed_bytes < 0) {
227bc702 1059 PERROR("Asprintf session name");
af7f3c88 1060 ret = CMD_ERROR;
227bc702
JR
1061 goto error;
1062 }
1063 DBG("Session name from command option set to %s", base_session_name);
e51a4200 1064 } else if (base_session_name && !opt_default_name) {
b37959c7
JR
1065 printed_bytes = asprintf(&session_name_date, "%s-%s", base_session_name, datetime);
1066 if (printed_bytes < 0) {
227bc702 1067 PERROR("Asprintf session name");
af7f3c88 1068 ret = CMD_ERROR;
227bc702
JR
1069 goto error;
1070 }
1071 } else {
1072 /* Generate a name */
b37959c7
JR
1073 printed_bytes = asprintf(&base_session_name, DEFAULT_SESSION_NAME "-%s", datetime);
1074 if (printed_bytes < 0) {
6af1d7e6 1075 PERROR("Asprintf session name");
af7f3c88 1076 ret = CMD_ERROR;
07424f16
DG
1077 goto error;
1078 }
227bc702
JR
1079 session_name_date = strdup(base_session_name);
1080 DBG("Auto session name set to %s", base_session_name);
f3ed775e
DG
1081 }
1082
227bc702
JR
1083
1084 /*
1085 * Output handling
1086 */
1087
1088 /*
1089 * If any of those options are present clear all output related data.
1090 */
1091 if (opt_output_path || opt_url || (opt_ctrl_url && opt_data_url) || opt_no_output) {
1092 /* Overwrite output */
1093 free(base_url);
1094 free(base_ctrl_url);
1095 free(base_data_url);
1096 base_url = NULL;
1097 base_ctrl_url = NULL;
1098 base_data_url = NULL;
1a241656
DG
1099 }
1100
227bc702
JR
1101 if (opt_output_path) {
1102
81b86775 1103 traces_path = utils_expand_path(opt_output_path);
227bc702 1104 if (!traces_path) {
00e2e675
DG
1105 ret = CMD_ERROR;
1106 goto error;
1107 }
1108
37d03ff7 1109 /* Create URL string from the local file system path */
b37959c7
JR
1110 printed_bytes = asprintf(&temp_url, "file://%s", traces_path);
1111 if (printed_bytes < 0) {
a4b92340 1112 PERROR("asprintf url path");
00e2e675
DG
1113 ret = CMD_FATAL;
1114 goto error;
1115 }
227bc702
JR
1116
1117 base_url = temp_url;
a4b92340 1118 } else if (opt_url) { /* Handling URL (-U opt) */
227bc702 1119 base_url = strdup(opt_url);
1a241656
DG
1120 } else if (opt_data_url && opt_ctrl_url) {
1121 /*
227bc702
JR
1122 * With both control and data, we'll be setting the consumer URL
1123 * after session creation thus use no URL.
1a241656 1124 */
227bc702
JR
1125 base_ctrl_url = strdup(opt_ctrl_url);
1126 base_data_url = strdup(opt_data_url);
1127 } else if (!(opt_no_output || base_output_type == OUTPUT_NONE ||
1128 base_url || base_ctrl_url || base_data_url)) {
1129 /* Generate default output depending on the session type */
1130 switch (base_session_type) {
1131 case SESSION_NORMAL:
1132 /* fallthrough */
1133 case SESSION_SNAPSHOT:
1134 /* Default to a local path */
1135 tmp_home_path = utils_get_home_dir();
1136 if (tmp_home_path == NULL) {
1137 ERR("HOME path not found.\n \
1138 Please specify an output path using -o, --output PATH");
1139 ret = CMD_FATAL;
1140 goto error;
1141 }
ecc48a90 1142
b37959c7 1143 printed_bytes = asprintf(&tmp_url,
227bc702
JR
1144 "file://%s/" DEFAULT_TRACE_DIR_NAME "/%s",
1145 tmp_home_path, session_name_date);
16f6f820 1146
b37959c7 1147 if (printed_bytes < 0) {
227bc702
JR
1148 PERROR("asprintf trace dir name");
1149 ret = CMD_FATAL;
1150 goto error;
1151 }
8960e9cd 1152
227bc702 1153 base_url = tmp_url ;
42224349 1154 break;
227bc702
JR
1155 case SESSION_LIVE:
1156 /* Default to a net output */
b37959c7
JR
1157 printed_bytes = asprintf(&tmp_url, "net://127.0.0.1");
1158 if (printed_bytes < 0) {
227bc702
JR
1159 PERROR("asprintf default live URL");
1160 ret = CMD_FATAL;
1161 goto error;
1162 }
1163 base_url = tmp_url ;
60e835ca 1164 break;
227bc702
JR
1165 default:
1166 ERR("Unknown session type");
1167 ret = CMD_FATAL;
a4b92340
DG
1168 goto error;
1169 }
4f50c803
DG
1170 }
1171
227bc702
JR
1172 /*
1173 * Shared memory path handling
1174 */
d7ba1388 1175 if (opt_shm_path) {
af7f3c88
JR
1176 /* Overwrite shm_path so clear any previously defined one */
1177 free(base_shm_path);
b37959c7
JR
1178 printed_bytes = asprintf(&base_shm_path, "%s/%s", opt_shm_path, session_name_date);
1179 if (printed_bytes < 0) {
227bc702 1180 PERROR("asprintf shm_path");
af7f3c88 1181 ret = CMD_FATAL;
d7ba1388
MD
1182 goto error;
1183 }
1184 }
1185
227bc702
JR
1186 /*
1187 * Live timer handling
1188 */
1189 if (opt_live_timer) {
1190 base_live_timer = opt_live_timer;
1191 }
d73c5802 1192
227bc702 1193 /* Get output type from urls */
b37959c7 1194 /* TODO: Find a better way of inferring output type */
227bc702
JR
1195 if (base_url) {
1196 /* Get lttng uris from single url */
1197 uri_array_size = uri_parse_str_urls(base_url, NULL, &uris);
1198 if (uri_array_size < 0) {
1199 ret = CMD_ERROR;
1200 goto error;
d73c5802 1201 }
227bc702
JR
1202 } else if (base_ctrl_url && base_data_url) {
1203 uri_array_size = uri_parse_str_urls(base_ctrl_url, base_data_url, &uris);
1204 if (uri_array_size < 0) {
1205 ret = CMD_ERROR;
1206 goto error;
16f6f820 1207 }
227bc702
JR
1208 } else {
1209 /* --no-output */
1210 uri_array_size = 0;
1211 }
1212
1213 switch (uri_array_size) {
1214 case 0:
1215 base_output_type = OUTPUT_NONE;
1216 break;
1217 case 1:
1218 base_output_type = OUTPUT_LOCAL;
1219 break;
1220 case 2:
1221 base_output_type = OUTPUT_NET;
1222 break;
1223 default:
1224 ret = CMD_ERROR;
1225 goto error;
a4b92340 1226 }
227bc702 1227
4a102b75
JR
1228 if (template) {
1229 ret = create_session_from_template(template,
1230 base_session_name,
1231 base_session_type,
1232 base_live_timer,
1233 base_output_type,
1234 base_url,
1235 base_ctrl_url,
1236 base_data_url,
1237 base_shm_path,
1238 datetime);
1239 } else {
b37959c7 1240 ret = create_session_basic(base_session_name,
4a102b75
JR
1241 base_session_type,
1242 base_live_timer,
1243 base_output_type,
1244 base_url,
1245 base_ctrl_url,
1246 base_data_url,
1247 base_shm_path,
1248 datetime);
1249 }
227bc702
JR
1250 if (ret) {
1251 goto error;
d7ba1388 1252 }
a4b92340 1253
b37959c7 1254 ret = generate_output(base_session_name,
227bc702
JR
1255 base_session_type,
1256 base_live_timer,
1257 base_output_type,
1258 base_url,
1259 base_ctrl_url,
1260 base_data_url,
1261 base_shm_path);
1262 if (ret) {
1263 goto error;
37d03ff7
JRJ
1264 }
1265
58a97671 1266 /* Init lttng session config */
227bc702 1267 ret = config_init(base_session_name);
f3ed775e 1268 if (ret < 0) {
27089920 1269 ret = CMD_ERROR;
f3ed775e
DG
1270 goto error;
1271 }
1272
f3ed775e
DG
1273 ret = CMD_SUCCESS;
1274
1275error:
227bc702 1276 /* Session temp stuff */
2f0e04ab 1277 config_document_free(template);
227bc702 1278 free(session_name_date);
227bc702 1279 free(uris);
2f0e04ab 1280 free(traces_path);
a4b92340
DG
1281
1282 if (ret < 0) {
1283 ERR("%s", lttng_strerror(ret));
1284 }
67238b20 1285
227bc702
JR
1286 free(base_session_name);
1287 free(base_url);
1288 free(base_ctrl_url);
1289 free(base_data_url);
1290 free(base_shm_path);
f3ed775e
DG
1291 return ret;
1292}
1293
92360082
JG
1294/*
1295 * spawn_sessiond
1296 *
1297 * Spawn a session daemon by forking and execv.
1298 */
1299static int spawn_sessiond(char *pathname)
1300{
1301 int ret = 0;
1302 pid_t pid;
1303
1304 MSG("Spawning a session daemon");
92360082
JG
1305 pid = fork();
1306 if (pid == 0) {
1307 /*
bbd44cae 1308 * Spawn session daemon in daemon mode.
92360082 1309 */
bbd44cae
PP
1310 execlp(pathname, "lttng-sessiond",
1311 "--daemonize", NULL);
92360082
JG
1312 /* execlp only returns if error happened */
1313 if (errno == ENOENT) {
1314 ERR("No session daemon found. Use --sessiond-path.");
1315 } else {
1316 PERROR("execlp");
1317 }
1318 kill(getppid(), SIGTERM); /* wake parent */
1319 exit(EXIT_FAILURE);
1320 } else if (pid > 0) {
92360082 1321 /*
bbd44cae
PP
1322 * In daemon mode (--daemonize), sessiond only exits when
1323 * it's ready to accept commands.
92360082 1324 */
bbd44cae 1325 for (;;) {
81527d36
JG
1326 int status;
1327 pid_t wait_pid_ret = waitpid(pid, &status, 0);
1328
1329 if (wait_pid_ret < 0) {
1330 if (errno == EINTR) {
1331 continue;
1332 }
1333 PERROR("waitpid");
1334 ret = -errno;
1335 goto end;
1336 }
bbd44cae
PP
1337
1338 if (WIFSIGNALED(status)) {
1339 ERR("Session daemon was killed by signal %d",
1340 WTERMSIG(status));
1341 ret = -1;
1342 goto end;
1343 } else if (WIFEXITED(status)) {
1344 DBG("Session daemon terminated normally (exit status: %d)",
1345 WEXITSTATUS(status));
1346
1347 if (WEXITSTATUS(status) != 0) {
1348 ERR("Session daemon terminated with an error (exit status: %d)",
1349 WEXITSTATUS(status));
1350 ret = -1;
1351 goto end;
1352 }
1353 break;
1354 }
92360082 1355 }
bbd44cae 1356
92360082
JG
1357 goto end;
1358 } else {
1359 PERROR("fork");
1360 ret = -1;
1361 goto end;
1362 }
1363
1364end:
1365 return ret;
1366}
1367
1368/*
1369 * launch_sessiond
1370 *
1371 * Check if the session daemon is available using
1372 * the liblttngctl API for the check. If not, try to
1373 * spawn a daemon.
1374 */
1375static int launch_sessiond(void)
1376{
1377 int ret;
1378 char *pathname = NULL;
1379
1380 ret = lttng_session_daemon_alive();
1381 if (ret) {
1382 /* Sessiond is alive, not an error */
1383 ret = 0;
1384 goto end;
1385 }
1386
1387 /* Try command line option path */
1388 pathname = opt_sessiond_path;
1389
1390 /* Try LTTNG_SESSIOND_PATH env variable */
1391 if (pathname == NULL) {
1392 pathname = getenv(DEFAULT_SESSIOND_PATH_ENV);
1393 }
1394
1395 /* Try with configured path */
1396 if (pathname == NULL) {
1397 if (CONFIG_SESSIOND_BIN[0] != '\0') {
1398 pathname = CONFIG_SESSIOND_BIN;
1399 }
1400 }
1401
1402 /* Try the default path */
1403 if (pathname == NULL) {
1404 pathname = INSTALL_BIN_PATH "/lttng-sessiond";
1405 }
1406
1407 DBG("Session daemon binary path: %s", pathname);
1408
1409 /* Check existence and permissions */
1410 ret = access(pathname, F_OK | X_OK);
1411 if (ret < 0) {
1412 ERR("No such file or access denied: %s", pathname);
1413 goto end;
1414 }
1415
1416 ret = spawn_sessiond(pathname);
92360082 1417end:
0f4fa0d2
JG
1418 if (ret) {
1419 ERR("Problem occurred while launching session daemon (%s)",
1420 pathname);
1421 }
92360082
JG
1422 return ret;
1423}
1424
f3ed775e 1425/*
74cc1d0f 1426 * The 'create <options>' first level command
1c8d13c8
TD
1427 *
1428 * Returns one of the CMD_* result constants.
f3ed775e
DG
1429 */
1430int cmd_create(int argc, const char **argv)
1431{
37d03ff7 1432 int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
ecc48a90 1433 char *opt_arg = NULL;
f3ed775e
DG
1434 static poptContext pc;
1435
1436 pc = poptGetContext(NULL, argc, argv, long_options, 0);
1437 poptReadDefaultConfig(pc, 0);
1438
1439 while ((opt = poptGetNextOpt(pc)) != -1) {
1440 switch (opt) {
1441 case OPT_HELP:
4ba92f18 1442 SHOW_HELP();
f3ed775e 1443 goto end;
679b4943
SM
1444 case OPT_LIST_OPTIONS:
1445 list_cmd_options(stdout, long_options);
679b4943 1446 goto end;
ecc48a90
JD
1447 case OPT_LIVE_TIMER:
1448 {
1449 unsigned long v;
1450
1451 errno = 0;
1452 opt_arg = poptGetOptArg(pc);
d73c5802
DG
1453 if (!opt_arg) {
1454 /* Set up default values. */
1455 opt_live_timer = (uint32_t) DEFAULT_LTTNG_LIVE_TIMER;
1456 DBG("Session live timer interval set to default value %d",
1457 opt_live_timer);
1458 break;
1459 }
1460
ecc48a90
JD
1461 v = strtoul(opt_arg, NULL, 0);
1462 if (errno != 0 || !isdigit(opt_arg[0])) {
1463 ERR("Wrong value in --live parameter: %s", opt_arg);
1464 ret = CMD_ERROR;
1465 goto end;
1466 }
1467 if (v != (uint32_t) v) {
1468 ERR("32-bit overflow in --live parameter: %s", opt_arg);
1469 ret = CMD_ERROR;
1470 goto end;
1471 }
0ed9e0be
JG
1472 if (v == 0) {
1473 ERR("Live timer interval must be greater than zero");
1474 ret = CMD_ERROR;
1475 goto end;
1476 }
ecc48a90
JD
1477 opt_live_timer = (uint32_t) v;
1478 DBG("Session live timer interval set to %d", opt_live_timer);
1479 break;
1480 }
e51a4200
JG
1481 case OPT_DEFAULT_NAME:
1482 opt_default_name = true;
1483 break;
f3ed775e 1484 default:
f3ed775e
DG
1485 ret = CMD_UNDEFINED;
1486 goto end;
1487 }
1488 }
1489
785d2d0d 1490 if (opt_no_consumer) {
96fe6b8d 1491 MSG("The option --no-consumer is obsolete. Use --no-output now.");
785d2d0d
DG
1492 ret = CMD_WARNING;
1493 goto end;
1494 }
1495
92360082
JG
1496 /* Spawn a session daemon if needed */
1497 if (!opt_no_sessiond) {
1498 ret = launch_sessiond();
1499 if (ret) {
1500 ret = CMD_ERROR;
1501 goto end;
1502 }
1503 }
1504
acc09215 1505 /* MI initialization */
37d03ff7
JRJ
1506 if (lttng_opt_mi) {
1507 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
1508 if (!writer) {
1509 ret = -LTTNG_ERR_NOMEM;
1510 goto end;
1511 }
1512
1513 /* Open command element */
1514 ret = mi_lttng_writer_command_open(writer,
1515 mi_lttng_element_command_create);
1516 if (ret) {
1517 ret = CMD_ERROR;
1518 goto end;
1519 }
1520
1521 /* Open output element */
1522 ret = mi_lttng_writer_open_element(writer,
1523 mi_lttng_element_command_output);
1524 if (ret) {
1525 ret = CMD_ERROR;
1526 goto end;
1527 }
1528 }
f3ed775e
DG
1529 opt_session_name = (char*) poptGetArg(pc);
1530
37d03ff7 1531 command_ret = create_session();
227bc702 1532
37d03ff7
JRJ
1533 if (command_ret) {
1534 success = 0;
1535 }
1536
1537 if (lttng_opt_mi) {
1538 /* Close output element */
1539 ret = mi_lttng_writer_close_element(writer);
1540 if (ret) {
1541 ret = CMD_ERROR;
1542 goto end;
1543 }
1544
1545 /* Success ? */
1546 ret = mi_lttng_writer_write_element_bool(writer,
1547 mi_lttng_element_command_success, success);
1548 if (ret) {
1549 ret = CMD_ERROR;
1550 goto end;
1551 }
1552
1553 /* Command element close */
1554 ret = mi_lttng_writer_command_close(writer);
1555 if (ret) {
1556 ret = CMD_ERROR;
1557 goto end;
1558 }
1559 }
f3ed775e
DG
1560
1561end:
37d03ff7
JRJ
1562 /* Mi clean-up */
1563 if (writer && mi_lttng_writer_destroy(writer)) {
1564 /* Preserve original error code */
1565 ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
1566 }
1567
acc09215 1568 /* Overwrite ret if an error occurred in create_session() */
37d03ff7
JRJ
1569 ret = command_ret ? command_ret : ret;
1570
ca1c3607 1571 poptFreeContext(pc);
f3ed775e
DG
1572 return ret;
1573}
This page took 0.129965 seconds and 5 git commands to generate.