2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <sys/types.h>
29 #include <lttng/snapshot.h>
31 #include "../command.h"
33 static const char *opt_session_name
;
34 static const char *opt_output_name
;
35 static const char *opt_data_url
;
36 static const char *opt_ctrl_url
;
37 static const char *current_session_name
;
38 static uint64_t opt_max_size
;
40 /* Stub for the cmd struct actions. */
41 static int cmd_add_output(int argc
, const char **argv
);
42 static int cmd_del_output(int argc
, const char **argv
);
43 static int cmd_list_output(int argc
, const char **argv
);
44 static int cmd_record(int argc
, const char **argv
);
46 static const char *indent4
= " ";
54 static struct poptOption snapshot_opts
[] = {
55 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
56 {"help", 'h', POPT_ARG_NONE
, 0, OPT_HELP
, 0, 0},
57 {"session", 's', POPT_ARG_STRING
, &opt_session_name
, 0, 0, 0},
58 {"ctrl-url", 'C', POPT_ARG_STRING
, &opt_ctrl_url
, 0, 0, 0},
59 {"data-url", 'D', POPT_ARG_STRING
, &opt_data_url
, 0, 0, 0},
60 {"name", 'n', POPT_ARG_STRING
, &opt_output_name
, 0, 0, 0},
61 {"max-size", 'm', POPT_ARG_DOUBLE
, 0, OPT_MAX_SIZE
, 0, 0},
62 {"list-options", 0, POPT_ARG_NONE
, NULL
, OPT_LIST_OPTIONS
, NULL
, NULL
},
66 static struct cmd_struct actions
[] = {
67 { "add-output", cmd_add_output
},
68 { "del-output", cmd_del_output
},
69 { "list-output", cmd_list_output
},
70 { "record", cmd_record
},
71 { NULL
, NULL
} /* Array closure */
77 static void usage(FILE *ofp
)
79 fprintf(ofp
, "usage: lttng snapshot [ACTION]\n");
81 fprintf(ofp
, "Actions:\n");
82 fprintf(ofp
, " add-output [-m <SIZE>] [-s <NAME>] [-n <NAME>] <URL> | -C <URL> -D <URL>\n");
83 fprintf(ofp
, " Setup and add an snapshot output for a session.\n");
85 fprintf(ofp
, " del-output ID [-s <NAME>]\n");
86 fprintf(ofp
, " Delete an output for a session using the ID.\n");
88 fprintf(ofp
, " list-output [-s <NAME>]\n");
89 fprintf(ofp
, " List the output of a session.\n");
91 fprintf(ofp
, " record [-m <SIZE>] [-s <NAME>] [-n <NAME>] [<URL> | -C <URL> -D <URL>]\n");
92 fprintf(ofp
, " Snapshot a session's buffer(s) for all domains. If an URL is\n");
93 fprintf(ofp
, " specified, it is used instead of a previously added output.\n");
94 fprintf(ofp
, " The snapshot is saved in the session directory in snapshot/ with\n");
95 fprintf(ofp
, " the top directory being NAME or the default: snapshot-ID/\n");
97 fprintf(ofp
, "Options:\n");
98 fprintf(ofp
, " -h, --help Show this help\n");
99 fprintf(ofp
, " --list-options Simple listing of options\n");
100 fprintf(ofp
, " -s, --session NAME Apply to session name\n");
101 fprintf(ofp
, " -n, --name NAME Name of the output or snapshot\n");
102 fprintf(ofp
, " -m, --max-size SIZE Maximum bytes size of the snapshot\n");
103 fprintf(ofp
, " -C, --ctrl-url URL Set control path URL. (Must use -D also)\n");
104 fprintf(ofp
, " -D, --data-url URL Set data path URL. (Must use -C also)\n");
109 * Count and return the number of arguments in argv.
111 static int count_arguments(const char **argv
)
117 while (argv
[i
] != NULL
) {
125 * Create a snapshot output object from arguments using the given URL.
127 * Return a newly allocated object or NULL on error.
129 static struct lttng_snapshot_output
*create_output_from_args(const char *url
)
132 struct lttng_snapshot_output
*output
= NULL
;
134 output
= lttng_snapshot_output_create();
140 ret
= lttng_snapshot_output_set_ctrl_url(url
, output
);
144 } else if (opt_ctrl_url
) {
145 ret
= lttng_snapshot_output_set_ctrl_url(opt_ctrl_url
, output
);
152 ret
= lttng_snapshot_output_set_data_url(opt_data_url
, output
);
159 ret
= lttng_snapshot_output_set_size(opt_max_size
, output
);
165 if (opt_output_name
) {
166 ret
= lttng_snapshot_output_set_name(opt_output_name
, output
);
175 lttng_snapshot_output_destroy(output
);
180 static int list_output(void)
182 int ret
, output_seen
= 0;
183 struct lttng_snapshot_output
*s_iter
;
184 struct lttng_snapshot_output_list
*list
;
186 ret
= lttng_snapshot_list_output(current_session_name
, &list
);
191 MSG("Snapshot output list for session %s", current_session_name
);
193 while ((s_iter
= lttng_snapshot_output_list_get_next(list
)) != NULL
) {
194 MSG("%s[%" PRIu32
"] %s: %s", indent4
,
195 lttng_snapshot_output_get_id(s_iter
),
196 lttng_snapshot_output_get_name(s_iter
),
197 lttng_snapshot_output_get_ctrl_url(s_iter
));
201 lttng_snapshot_output_list_destroy(list
);
204 MSG("%sNone", indent4
);
212 * Delete output by ID.
214 static int del_output(uint32_t id
)
217 struct lttng_snapshot_output
*output
= NULL
;
219 output
= lttng_snapshot_output_create();
225 ret
= lttng_snapshot_output_set_id(id
, output
);
231 ret
= lttng_snapshot_del_output(current_session_name
, output
);
236 MSG("Snapshot output id %" PRIu32
" successfully deleted for session %s",
237 id
, current_session_name
);
240 lttng_snapshot_output_destroy(output
);
245 * Add output from the user URL.
247 static int add_output(const char *url
)
250 struct lttng_snapshot_output
*output
= NULL
;
252 if (!url
&& (!opt_data_url
|| !opt_ctrl_url
)) {
257 output
= create_output_from_args(url
);
263 /* This call, if successful, populates the id of the output object. */
264 ret
= lttng_snapshot_add_output(current_session_name
, output
);
269 MSG("Snapshot output successfully added for session %s",
270 current_session_name
);
271 MSG(" [%" PRIu32
"] %s: %s (max-size: %" PRId64
")",
272 lttng_snapshot_output_get_id(output
),
273 lttng_snapshot_output_get_name(output
),
274 lttng_snapshot_output_get_ctrl_url(output
),
275 lttng_snapshot_output_get_maxsize(output
));
277 lttng_snapshot_output_destroy(output
);
281 static int cmd_add_output(int argc
, const char **argv
)
283 int ret
= CMD_SUCCESS
;
285 if (argc
< 2 && (!opt_data_url
|| !opt_ctrl_url
)) {
291 ret
= add_output(argv
[1]);
297 static int cmd_del_output(int argc
, const char **argv
)
299 int ret
= CMD_SUCCESS
;
307 ret
= del_output(atoi(argv
[1]));
313 static int cmd_list_output(int argc
, const char **argv
)
315 return list_output();
319 * Do a snapshot record with the URL if one is given.
321 static int record(const char *url
)
324 struct lttng_snapshot_output
*output
= NULL
;
326 output
= create_output_from_args(url
);
332 ret
= lttng_snapshot_record(current_session_name
, output
, 0);
337 MSG("Snapshot recorded successfully for session %s", current_session_name
);
340 MSG("Snapshot written at: %s", url
);
341 } else if (opt_ctrl_url
) {
342 MSG("Snapshot written to ctrl: %s, data: %s", opt_ctrl_url
,
347 lttng_snapshot_output_destroy(output
);
351 static int cmd_record(int argc
, const char **argv
)
356 /* With a given URL */
357 ret
= record(argv
[1]);
365 static int handle_command(const char **argv
)
367 int ret
, i
= 0, argc
;
368 struct cmd_struct
*cmd
;
370 if (argv
== NULL
|| (!opt_ctrl_url
&& opt_data_url
) ||
371 (opt_ctrl_url
&& !opt_data_url
)) {
377 argc
= count_arguments(argv
);
380 while (cmd
->func
!= NULL
) {
382 if (strcmp(argv
[0], cmd
->name
) == 0) {
383 ret
= cmd
->func(argc
, argv
);
390 /* Command not found */
398 * The 'snapshot <cmd> <options>' first level command
400 int cmd_snapshot(int argc
, const char **argv
)
402 int opt
, ret
= CMD_SUCCESS
;
403 char *session_name
= NULL
;
404 static poptContext pc
;
406 pc
= poptGetContext(NULL
, argc
, argv
, snapshot_opts
, 0);
407 poptReadDefaultConfig(pc
, 0);
409 while ((opt
= poptGetNextOpt(pc
)) != -1) {
414 case OPT_LIST_OPTIONS
:
415 list_cmd_options(stdout
, snapshot_opts
);
421 const char *opt
= poptGetOptArg(pc
);
423 /* Documented by the man page of strtoll(3). */
425 val
= strtoll(opt
, &endptr
, 10);
426 if ((errno
== ERANGE
&& (val
== LLONG_MAX
|| val
== LONG_MIN
))
427 || (errno
!= 0 && val
== 0)) {
428 ERR("Unable to handle max-size value %s", opt
);
434 ERR("No digits were found in %s", opt
);
449 if (!opt_session_name
) {
450 session_name
= get_session_name();
451 if (session_name
== NULL
) {
455 current_session_name
= session_name
;
457 current_session_name
= opt_session_name
;
460 ret
= handle_command(poptGetArgs(pc
));
462 if (ret
== -LTTNG_ERR_EPERM
) {
463 ERR("The session needs to be set in no output mode (--no-output)");
465 ERR("%s", lttng_strerror(ret
));
470 if (!opt_session_name
) {