lttng: Add list-triggers command
[lttng-tools.git] / src / bin / lttng / commands / disable_rotation.c
1 /*
2 * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include <popt.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <inttypes.h>
17 #include <ctype.h>
18
19 #include <common/sessiond-comm/sessiond-comm.h>
20 #include <common/mi-lttng.h>
21
22 #include "../command.h"
23 #include <lttng/lttng.h>
24
25 static char *opt_session_name;
26 static struct mi_writer *writer;
27
28 #ifdef LTTNG_EMBED_HELP
29 static const char help_msg[] =
30 #include <lttng-disable-rotation.1.h>
31 ;
32 #endif
33
34 enum {
35 OPT_HELP = 1,
36 OPT_LIST_OPTIONS,
37 OPT_TIMER,
38 OPT_SIZE,
39 };
40
41 static struct poptOption long_options[] = {
42 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
43 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
44 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
45 {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
46 {"timer", 0, POPT_ARG_NONE, 0, OPT_TIMER, 0, 0},
47 {"size", 0, POPT_ARG_NONE, 0, OPT_SIZE, 0, 0},
48 {0, 0, 0, 0, 0, 0, 0}
49 };
50
51 static const char *schedule_type_str[] = {
52 [LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC] = "periodic",
53 [LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD] = "size-based",
54 };
55
56 static const struct lttng_rotation_schedule *get_schedule(
57 const char *session_name,
58 const struct lttng_rotation_schedules *schedules,
59 enum lttng_rotation_schedule_type schedule_type)
60 {
61 unsigned int count, i;
62 enum lttng_rotation_status status;
63 const struct lttng_rotation_schedule *ret = NULL;
64
65 status = lttng_rotation_schedules_get_count(schedules, &count);
66 if (status != LTTNG_ROTATION_STATUS_OK) {
67 ERR("Unable to determine the number of rotation schedules of session %s",
68 session_name);
69 goto end;
70 }
71
72 for (i = 0; i < count; i++) {
73 const struct lttng_rotation_schedule *schedule = NULL;
74
75 schedule = lttng_rotation_schedules_get_at_index(schedules, i);
76 if (!schedule) {
77 ERR("Unable to retrieve rotation schedule at index %u",
78 i);
79 goto end;
80 }
81
82 if (lttng_rotation_schedule_get_type(schedule) ==
83 schedule_type) {
84 ret = schedule;
85 break;
86 }
87 }
88
89 if (!ret) {
90 ERR("No %s rotation schedule active on session %s",
91 schedule_type_str[schedule_type], session_name);
92 }
93 end:
94 return ret;
95 }
96
97 static struct lttng_rotation_schedule *create_empty_schedule(
98 enum lttng_rotation_schedule_type type)
99 {
100 struct lttng_rotation_schedule *schedule = NULL;
101
102 switch (type) {
103 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
104 schedule = lttng_rotation_schedule_periodic_create();
105 break;
106 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
107 schedule = lttng_rotation_schedule_size_threshold_create();
108 break;
109 default:
110 abort();
111 }
112 return schedule;
113 }
114
115 static enum cmd_error_code remove_schedule(const char *session_name,
116 enum lttng_rotation_schedule_type schedule_type)
117 {
118 enum cmd_error_code cmd_ret;
119 int ret;
120 const struct lttng_rotation_schedule *schedule = NULL;
121 struct lttng_rotation_schedules *schedules = NULL;
122 enum lttng_rotation_status status;
123 const char *schedule_type_name;
124 struct lttng_rotation_schedule *empty_schedule = NULL;
125
126 switch (schedule_type) {
127 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
128 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
129 break;
130 default:
131 ERR("Unknown schedule type");
132 abort();
133 }
134
135 schedule_type_name = schedule_type_str[schedule_type];
136
137 ret = lttng_session_list_rotation_schedules(session_name, &schedules);
138 if (ret != LTTNG_OK) {
139 ERR("Failed to list rotation schedules of session %s",
140 session_name);
141 goto error;
142 }
143
144 schedule = get_schedule(session_name, schedules, schedule_type);
145 if (!schedule) {
146 cmd_ret = CMD_ERROR;
147 /*
148 * get_schedule() logs its own errors.
149 * A temporaty schedule is created to serialize an MI rotation
150 * schedule descriptor of the appropriate type that has no
151 * attributes set.
152 */
153 empty_schedule = create_empty_schedule(schedule_type);
154 if (!empty_schedule) {
155 goto error;
156 }
157 goto skip_removal;
158 }
159
160 status = lttng_session_remove_rotation_schedule(session_name, schedule);
161 switch (status) {
162 case LTTNG_ROTATION_STATUS_OK:
163 MSG("Disabled %s rotation on session %s",
164 schedule_type_name, session_name);
165 cmd_ret = CMD_SUCCESS;
166 break;
167 case LTTNG_ROTATION_STATUS_SCHEDULE_NOT_SET:
168 ERR("No %s rotation schedule set on session %s",
169 schedule_type_name,
170 session_name);
171 cmd_ret = CMD_ERROR;
172 break;
173 case LTTNG_ROTATION_STATUS_ERROR:
174 case LTTNG_ROTATION_STATUS_INVALID:
175 default:
176 ERR("Failed to disable %s rotation schedule on session %s",
177 schedule_type_name, session_name);
178 cmd_ret = CMD_ERROR;
179 break;
180 }
181
182 skip_removal:
183 if (lttng_opt_mi) {
184 ret = mi_lttng_rotation_schedule_result(writer,
185 schedule ? schedule : empty_schedule,
186 cmd_ret == CMD_SUCCESS);
187 if (ret < 0) {
188 goto error;
189 }
190 }
191
192 end:
193 lttng_rotation_schedules_destroy(schedules);
194 lttng_rotation_schedule_destroy(empty_schedule);
195 return cmd_ret;
196 error:
197 cmd_ret = CMD_ERROR;
198 goto end;
199 }
200
201 /*
202 * cmd_disable_rotation
203 *
204 * The 'disable-rotation <options>' first level command
205 */
206 int cmd_disable_rotation(int argc, const char **argv)
207 {
208 int popt_ret, opt, ret = 0;
209 enum cmd_error_code cmd_ret = CMD_SUCCESS;
210 static poptContext pc;
211 char *session_name = NULL;
212 bool free_session_name = false;
213 bool periodic_rotation = false, size_rotation = false;
214
215 pc = poptGetContext(NULL, argc, argv, long_options, 0);
216 popt_ret = poptReadDefaultConfig(pc, 0);
217 if (popt_ret) {
218 cmd_ret = CMD_ERROR;
219 ERR("poptReadDefaultConfig");
220 goto end;
221 }
222
223 while ((opt = poptGetNextOpt(pc)) != -1) {
224 switch (opt) {
225 case OPT_HELP:
226 SHOW_HELP();
227 goto end;
228 case OPT_LIST_OPTIONS:
229 list_cmd_options(stdout, long_options);
230 goto end;
231 case OPT_TIMER:
232 periodic_rotation = true;
233 break;
234 case OPT_SIZE:
235 size_rotation = true;
236 break;
237 default:
238 cmd_ret = CMD_UNDEFINED;
239 goto end;
240 }
241 }
242
243 if (opt_session_name == NULL) {
244 session_name = get_session_name();
245 if (session_name == NULL) {
246 goto error;
247 }
248 free_session_name = true;
249 } else {
250 session_name = opt_session_name;
251 }
252
253 /* Mi check */
254 if (lttng_opt_mi) {
255 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
256 if (!writer) {
257 goto error;
258 }
259
260 /* Open command element */
261 ret = mi_lttng_writer_command_open(writer,
262 mi_lttng_element_command_disable_rotation);
263 if (ret) {
264 goto error;
265 }
266
267 /* Open output element */
268 ret = mi_lttng_writer_open_element(writer,
269 mi_lttng_element_command_output);
270 if (ret) {
271 goto error;
272 }
273 }
274
275 if (!periodic_rotation && !size_rotation) {
276 ERR("No session rotation schedule type provided.");
277 cmd_ret = CMD_ERROR;
278 goto close_command;
279 }
280
281 if (lttng_opt_mi) {
282 ret = mi_lttng_writer_open_element(writer,
283 mi_lttng_element_rotation_schedule_results);
284 if (ret) {
285 goto error;
286 }
287
288 ret = mi_lttng_writer_write_element_string(writer,
289 mi_lttng_element_session_name,
290 session_name);
291 if (ret) {
292 goto error;
293 }
294 }
295
296 if (periodic_rotation) {
297 /*
298 * Continue processing even on error as multiple schedules can
299 * be specified at once.
300 */
301 cmd_ret = remove_schedule(session_name,
302 LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC);
303 }
304
305 if (size_rotation) {
306 enum cmd_error_code tmp_ret;
307
308 /* Don't overwrite cmd_ret if it already indicates an error. */
309 tmp_ret = remove_schedule(session_name,
310 LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD);
311 cmd_ret = cmd_ret ? cmd_ret : tmp_ret;
312 }
313
314 if (lttng_opt_mi) {
315 /* Close rotation schedule results element */
316 ret = mi_lttng_writer_close_element(writer);
317 if (ret) {
318 goto error;
319 }
320 }
321
322 close_command:
323 /* Mi closing */
324 if (lttng_opt_mi) {
325 /* Close output element */
326 ret = mi_lttng_writer_close_element(writer);
327 if (ret) {
328 goto error;
329 }
330
331 /* Success ? */
332 ret = mi_lttng_writer_write_element_bool(writer,
333 mi_lttng_element_command_success,
334 cmd_ret == CMD_SUCCESS);
335 if (ret) {
336 goto error;
337 }
338
339 /* Command element close */
340 ret = mi_lttng_writer_command_close(writer);
341 if (ret) {
342 goto error;
343 }
344 }
345
346 end:
347 (void) mi_lttng_writer_destroy(writer);
348 poptFreeContext(pc);
349 if (free_session_name) {
350 free(session_name);
351 }
352 return cmd_ret;
353 error:
354 cmd_ret = CMD_ERROR;
355 goto end;
356 }
This page took 0.035916 seconds and 4 git commands to generate.