Reorder functions _lttng_cmd_* functions in bash completion
[lttng-tools.git] / src / bin / lttng / commands / snapshot.c
CommitLineData
57f272ed
DG
1/*
2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
3 *
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.
7 *
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
11 * more details.
12 *
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.
16 */
17
18#define _GNU_SOURCE
19#include <assert.h>
20#include <inttypes.h>
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 <unistd.h>
28
a8f307d8 29#include <common/utils.h>
57f272ed
DG
30#include <lttng/snapshot.h>
31
32#include "../command.h"
33
34static const char *opt_session_name;
35static const char *opt_output_name;
36static const char *opt_data_url;
37static const char *opt_ctrl_url;
38static const char *current_session_name;
39static uint64_t opt_max_size;
40
41/* Stub for the cmd struct actions. */
42static int cmd_add_output(int argc, const char **argv);
43static int cmd_del_output(int argc, const char **argv);
44static int cmd_list_output(int argc, const char **argv);
45static int cmd_record(int argc, const char **argv);
46
47static const char *indent4 = " ";
48
49enum {
50 OPT_HELP = 1,
51 OPT_LIST_OPTIONS,
52 OPT_MAX_SIZE,
53};
54
55static struct poptOption snapshot_opts[] = {
56 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
57 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
58 {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
59 {"ctrl-url", 'C', POPT_ARG_STRING, &opt_ctrl_url, 0, 0, 0},
60 {"data-url", 'D', POPT_ARG_STRING, &opt_data_url, 0, 0, 0},
61 {"name", 'n', POPT_ARG_STRING, &opt_output_name, 0, 0, 0},
a8f307d8 62 {"max-size", 'm', POPT_ARG_STRING, 0, OPT_MAX_SIZE, 0, 0},
57f272ed
DG
63 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
64 {0, 0, 0, 0, 0, 0, 0}
65};
66
67static struct cmd_struct actions[] = {
68 { "add-output", cmd_add_output },
69 { "del-output", cmd_del_output },
70 { "list-output", cmd_list_output },
71 { "record", cmd_record },
72 { NULL, NULL } /* Array closure */
73};
74
75/*
76 * usage
77 */
78static void usage(FILE *ofp)
79{
8df3bfe9 80 fprintf(ofp, "usage: lttng snapshot [OPTION] ACTION\n");
57f272ed
DG
81 fprintf(ofp, "\n");
82 fprintf(ofp, "Actions:\n");
83 fprintf(ofp, " add-output [-m <SIZE>] [-s <NAME>] [-n <NAME>] <URL> | -C <URL> -D <URL>\n");
84 fprintf(ofp, " Setup and add an snapshot output for a session.\n");
85 fprintf(ofp, "\n");
e0dcb8bf 86 fprintf(ofp, " del-output ID | NAME [-s <NAME>]\n");
57f272ed
DG
87 fprintf(ofp, " Delete an output for a session using the ID.\n");
88 fprintf(ofp, "\n");
89 fprintf(ofp, " list-output [-s <NAME>]\n");
90 fprintf(ofp, " List the output of a session.\n");
91 fprintf(ofp, "\n");
92 fprintf(ofp, " record [-m <SIZE>] [-s <NAME>] [-n <NAME>] [<URL> | -C <URL> -D <URL>]\n");
93 fprintf(ofp, " Snapshot a session's buffer(s) for all domains. If an URL is\n");
94 fprintf(ofp, " specified, it is used instead of a previously added output.\n");
e0dcb8bf
DG
95 fprintf(ofp, " Specifying only a name or/a size will override the current output value.\n");
96 fprintf(ofp, " For instance, you can record a snapshot with a custom maximum size\n");
97 fprintf(ofp, " or with a different name.\n");
57f272ed
DG
98 fprintf(ofp, "\n");
99 fprintf(ofp, "Options:\n");
100 fprintf(ofp, " -h, --help Show this help\n");
101 fprintf(ofp, " --list-options Simple listing of options\n");
102 fprintf(ofp, " -s, --session NAME Apply to session name\n");
103 fprintf(ofp, " -n, --name NAME Name of the output or snapshot\n");
a8f307d8 104 fprintf(ofp, " -m, --max-size SIZE Maximum bytes size of the snapshot {+k,+M,+G}\n");
57f272ed
DG
105 fprintf(ofp, " -C, --ctrl-url URL Set control path URL. (Must use -D also)\n");
106 fprintf(ofp, " -D, --data-url URL Set data path URL. (Must use -C also)\n");
107 fprintf(ofp, "\n");
108}
109
110/*
111 * Count and return the number of arguments in argv.
112 */
113static int count_arguments(const char **argv)
114{
115 int i = 0;
116
117 assert(argv);
118
119 while (argv[i] != NULL) {
120 i++;
121 }
122
123 return i;
124}
125
126/*
127 * Create a snapshot output object from arguments using the given URL.
128 *
129 * Return a newly allocated object or NULL on error.
130 */
131static struct lttng_snapshot_output *create_output_from_args(const char *url)
132{
133 int ret = 0;
134 struct lttng_snapshot_output *output = NULL;
135
136 output = lttng_snapshot_output_create();
137 if (!output) {
138 goto error_create;
139 }
140
141 if (url) {
142 ret = lttng_snapshot_output_set_ctrl_url(url, output);
143 if (ret < 0) {
144 goto error;
145 }
146 } else if (opt_ctrl_url) {
147 ret = lttng_snapshot_output_set_ctrl_url(opt_ctrl_url, output);
148 if (ret < 0) {
149 goto error;
150 }
151 }
152
153 if (opt_data_url) {
154 ret = lttng_snapshot_output_set_data_url(opt_data_url, output);
155 if (ret < 0) {
156 goto error;
157 }
158 }
159
160 if (opt_max_size) {
161 ret = lttng_snapshot_output_set_size(opt_max_size, output);
162 if (ret < 0) {
163 goto error;
164 }
165 }
166
167 if (opt_output_name) {
168 ret = lttng_snapshot_output_set_name(opt_output_name, output);
169 if (ret < 0) {
170 goto error;
171 }
172 }
173
174 return output;
175
176error:
177 lttng_snapshot_output_destroy(output);
178error_create:
179 return NULL;
180}
181
182static int list_output(void)
183{
184 int ret, output_seen = 0;
185 struct lttng_snapshot_output *s_iter;
186 struct lttng_snapshot_output_list *list;
187
188 ret = lttng_snapshot_list_output(current_session_name, &list);
189 if (ret < 0) {
190 goto error;
191 }
192
193 MSG("Snapshot output list for session %s", current_session_name);
194
195 while ((s_iter = lttng_snapshot_output_list_get_next(list)) != NULL) {
196 MSG("%s[%" PRIu32 "] %s: %s", indent4,
197 lttng_snapshot_output_get_id(s_iter),
198 lttng_snapshot_output_get_name(s_iter),
199 lttng_snapshot_output_get_ctrl_url(s_iter));
200 output_seen = 1;
201 }
202
203 lttng_snapshot_output_list_destroy(list);
204
205 if (!output_seen) {
206 MSG("%sNone", indent4);
207 }
208
209error:
210 return ret;
211}
212
213/*
214 * Delete output by ID.
215 */
eb240553 216static int del_output(uint32_t id, const char *name)
57f272ed
DG
217{
218 int ret;
219 struct lttng_snapshot_output *output = NULL;
220
221 output = lttng_snapshot_output_create();
222 if (!output) {
223 ret = CMD_FATAL;
224 goto error;
225 }
226
eb240553
DG
227 if (name) {
228 ret = lttng_snapshot_output_set_name(name, output);
229 } else if (id != UINT32_MAX) {
230 ret = lttng_snapshot_output_set_id(id, output);
231 } else {
232 ret = CMD_ERROR;
233 goto error;
234 }
57f272ed
DG
235 if (ret < 0) {
236 ret = CMD_FATAL;
237 goto error;
238 }
239
240 ret = lttng_snapshot_del_output(current_session_name, output);
241 if (ret < 0) {
242 goto error;
243 }
244
eb240553
DG
245 if (id != UINT32_MAX) {
246 MSG("Snapshot output id %" PRIu32 " successfully deleted for session %s",
247 id, current_session_name);
248 } else {
249 MSG("Snapshot output %s successfully deleted for session %s",
250 name, current_session_name);
251 }
57f272ed
DG
252
253error:
254 lttng_snapshot_output_destroy(output);
255 return ret;
256}
257
258/*
259 * Add output from the user URL.
260 */
261static int add_output(const char *url)
262{
263 int ret;
264 struct lttng_snapshot_output *output = NULL;
265
266 if (!url && (!opt_data_url || !opt_ctrl_url)) {
267 ret = CMD_ERROR;
268 goto error;
269 }
270
271 output = create_output_from_args(url);
272 if (!output) {
273 ret = CMD_FATAL;
274 goto error;
275 }
276
277 /* This call, if successful, populates the id of the output object. */
278 ret = lttng_snapshot_add_output(current_session_name, output);
279 if (ret < 0) {
280 goto error;
281 }
282
283 MSG("Snapshot output successfully added for session %s",
284 current_session_name);
285 MSG(" [%" PRIu32 "] %s: %s (max-size: %" PRId64 ")",
286 lttng_snapshot_output_get_id(output),
287 lttng_snapshot_output_get_name(output),
288 lttng_snapshot_output_get_ctrl_url(output),
289 lttng_snapshot_output_get_maxsize(output));
290error:
291 lttng_snapshot_output_destroy(output);
292 return ret;
293}
294
295static int cmd_add_output(int argc, const char **argv)
296{
297 int ret = CMD_SUCCESS;
298
299 if (argc < 2 && (!opt_data_url || !opt_ctrl_url)) {
300 usage(stderr);
301 ret = CMD_ERROR;
302 goto end;
303 }
304
305 ret = add_output(argv[1]);
306
307end:
308 return ret;
309}
310
311static int cmd_del_output(int argc, const char **argv)
312{
313 int ret = CMD_SUCCESS;
eb240553
DG
314 char *name;
315 long id;
57f272ed
DG
316
317 if (argc < 2) {
318 usage(stderr);
319 ret = CMD_ERROR;
320 goto end;
321 }
322
eb240553
DG
323 errno = 0;
324 id = strtol(argv[1], &name, 10);
325 if (id == 0 && errno == 0) {
326 ret = del_output(UINT32_MAX, name);
327 } else if (errno == 0 && *name == '\0') {
328 ret = del_output(id, NULL);
329 } else {
330 ERR("Argument %s not recognized", argv[1]);
331 ret = -1;
332 goto end;
333 }
57f272ed
DG
334
335end:
336 return ret;
337}
338
339static int cmd_list_output(int argc, const char **argv)
340{
341 return list_output();
342}
343
344/*
345 * Do a snapshot record with the URL if one is given.
346 */
347static int record(const char *url)
348{
349 int ret;
350 struct lttng_snapshot_output *output = NULL;
351
e1986656
DG
352 output = create_output_from_args(url);
353 if (!output) {
354 ret = CMD_FATAL;
355 goto error;
57f272ed
DG
356 }
357
358 ret = lttng_snapshot_record(current_session_name, output, 0);
359 if (ret < 0) {
360 goto error;
361 }
362
363 MSG("Snapshot recorded successfully for session %s", current_session_name);
364
365 if (url) {
366 MSG("Snapshot written at: %s", url);
367 } else if (opt_ctrl_url) {
368 MSG("Snapshot written to ctrl: %s, data: %s", opt_ctrl_url,
369 opt_data_url);
57f272ed
DG
370 }
371
372error:
cdcdb9dd 373 lttng_snapshot_output_destroy(output);
57f272ed
DG
374 return ret;
375}
376
377static int cmd_record(int argc, const char **argv)
378{
379 int ret;
380
381 if (argc == 2) {
382 /* With a given URL */
383 ret = record(argv[1]);
384 } else {
385 ret = record(NULL);
386 }
387
388 return ret;
389}
390
391static int handle_command(const char **argv)
392{
393 int ret, i = 0, argc;
394 struct cmd_struct *cmd;
395
396 if (argv == NULL || (!opt_ctrl_url && opt_data_url) ||
397 (opt_ctrl_url && !opt_data_url)) {
398 usage(stderr);
399 ret = CMD_ERROR;
400 goto end;
401 }
402
403 argc = count_arguments(argv);
404
405 cmd = &actions[i];
406 while (cmd->func != NULL) {
407 /* Find command */
408 if (strcmp(argv[0], cmd->name) == 0) {
409 ret = cmd->func(argc, argv);
410 goto end;
411 }
412 i++;
413 cmd = &actions[i];
414 }
415
416 /* Command not found */
417 ret = CMD_UNDEFINED;
418
419end:
420 return ret;
421}
422
423/*
424 * The 'snapshot <cmd> <options>' first level command
425 */
426int cmd_snapshot(int argc, const char **argv)
427{
428 int opt, ret = CMD_SUCCESS;
429 char *session_name = NULL;
430 static poptContext pc;
431
432 pc = poptGetContext(NULL, argc, argv, snapshot_opts, 0);
433 poptReadDefaultConfig(pc, 0);
434
435 while ((opt = poptGetNextOpt(pc)) != -1) {
436 switch (opt) {
437 case OPT_HELP:
438 usage(stdout);
439 goto end;
440 case OPT_LIST_OPTIONS:
441 list_cmd_options(stdout, snapshot_opts);
442 goto end;
443 case OPT_MAX_SIZE:
444 {
a8f307d8 445 uint64_t val;
57f272ed
DG
446 const char *opt = poptGetOptArg(pc);
447
a8f307d8 448 if (utils_parse_size_suffix((char *) opt, &val) < 0) {
57f272ed
DG
449 ERR("Unable to handle max-size value %s", opt);
450 ret = CMD_ERROR;
451 goto end;
452 }
453
57f272ed
DG
454 opt_max_size = val;
455
456 break;
457 }
458 default:
459 usage(stderr);
460 ret = CMD_UNDEFINED;
461 goto end;
462 }
463 }
464
465 if (!opt_session_name) {
466 session_name = get_session_name();
467 if (session_name == NULL) {
468 ret = CMD_ERROR;
469 goto end;
470 }
471 current_session_name = session_name;
472 } else {
473 current_session_name = opt_session_name;
474 }
475
476 ret = handle_command(poptGetArgs(pc));
477 if (ret < 0) {
6dc3064a
DG
478 if (ret == -LTTNG_ERR_EPERM) {
479 ERR("The session needs to be set in no output mode (--no-output)");
480 }
57f272ed
DG
481 ERR("%s", lttng_strerror(ret));
482 goto end;
483 }
484
485end:
486 if (!opt_session_name) {
487 free(session_name);
488 }
489 poptFreeContext(pc);
490 return ret;
491}
This page took 0.040841 seconds and 4 git commands to generate.