2 * Copyright (C) 2017 - Julien Desfossez <jdesfossez@efficios.com>
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.
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.
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.
24 #include <sys/types.h>
29 #include <common/sessiond-comm/sessiond-comm.h>
30 #include <common/mi-lttng.h>
32 #include "../command.h"
33 #include <lttng/rotation.h>
35 static char *opt_session_name
;
36 static struct mi_writer
*writer
;
38 #ifdef LTTNG_EMBED_HELP
39 static const char help_msg
[] =
40 #include <lttng-disable-rotation.1.h>
51 static struct poptOption long_options
[] = {
52 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
53 {"help", 'h', POPT_ARG_NONE
, 0, OPT_HELP
, 0, 0},
54 {"list-options", 0, POPT_ARG_NONE
, NULL
, OPT_LIST_OPTIONS
, NULL
, NULL
},
55 {"session", 's', POPT_ARG_STRING
, &opt_session_name
, 0, 0, 0},
56 {"timer", 0, POPT_ARG_NONE
, 0, OPT_TIMER
, 0, 0},
57 {"size", 0, POPT_ARG_NONE
, 0, OPT_SIZE
, 0, 0},
61 static const char *schedule_type_str
[] = {
62 [LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC
] = "periodic",
63 [LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD
] = "size-based",
66 static const struct lttng_rotation_schedule
*get_schedule(
67 const char *session_name
,
68 const struct lttng_rotation_schedules
*schedules
,
69 enum lttng_rotation_schedule_type schedule_type
)
71 unsigned int count
, i
;
72 enum lttng_rotation_status status
;
73 const struct lttng_rotation_schedule
*ret
= NULL
;
75 status
= lttng_rotation_schedules_get_count(schedules
, &count
);
76 if (status
!= LTTNG_ROTATION_STATUS_OK
) {
77 ERR("Unable to determine the number of rotation schedules of session %s",
82 for (i
= 0; i
< count
; i
++) {
83 const struct lttng_rotation_schedule
*schedule
= NULL
;
85 schedule
= lttng_rotation_schedules_get_at_index(schedules
, i
);
87 ERR("Unable to retrieve rotation schedule at index %u",
92 if (lttng_rotation_schedule_get_type(schedule
) ==
100 ERR("No %s rotation schedule active on session %s",
101 schedule_type_str
[schedule_type
], session_name
);
107 static struct lttng_rotation_schedule
*create_empty_schedule(
108 enum lttng_rotation_schedule_type type
)
110 struct lttng_rotation_schedule
*schedule
= NULL
;
113 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC
:
114 schedule
= lttng_rotation_schedule_periodic_create();
116 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD
:
117 schedule
= lttng_rotation_schedule_size_threshold_create();
125 static enum cmd_error_code
remove_schedule(const char *session_name
,
126 enum lttng_rotation_schedule_type schedule_type
)
128 enum cmd_error_code cmd_ret
;
130 const struct lttng_rotation_schedule
*schedule
= NULL
;
131 struct lttng_rotation_schedules
*schedules
= NULL
;
132 enum lttng_rotation_status status
;
133 const char *schedule_type_name
;
134 struct lttng_rotation_schedule
*empty_schedule
= NULL
;
136 switch (schedule_type
) {
137 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC
:
138 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD
:
141 ERR("Unknown schedule type");
145 schedule_type_name
= schedule_type_str
[schedule_type
];
147 ret
= lttng_session_list_rotation_schedules(session_name
, &schedules
);
148 if (ret
!= LTTNG_OK
) {
149 ERR("Failed to list rotation schedules of session %s",
154 schedule
= get_schedule(session_name
, schedules
, schedule_type
);
158 * get_schedule() logs its own errors.
159 * A temporaty schedule is created to serialize an MI rotation
160 * schedule descriptor of the appropriate type that has no
163 empty_schedule
= create_empty_schedule(schedule_type
);
164 if (!empty_schedule
) {
170 status
= lttng_session_remove_rotation_schedule(session_name
, schedule
);
172 case LTTNG_ROTATION_STATUS_OK
:
173 MSG("Disabled %s rotation on session %s",
174 schedule_type_name
, session_name
);
175 cmd_ret
= CMD_SUCCESS
;
177 case LTTNG_ROTATION_STATUS_SCHEDULE_NOT_SET
:
178 ERR("No %s rotation schedule set on session %s",
183 case LTTNG_ROTATION_STATUS_ERROR
:
184 case LTTNG_ROTATION_STATUS_INVALID
:
186 ERR("Failed to disable %s rotation schedule on session %s",
187 schedule_type_name
, session_name
);
194 ret
= mi_lttng_rotation_schedule_result(writer
,
195 schedule
? schedule
: empty_schedule
,
196 cmd_ret
== CMD_SUCCESS
);
203 lttng_rotation_schedules_destroy(schedules
);
204 lttng_rotation_schedule_destroy(empty_schedule
);
212 * cmd_disable_rotation
214 * The 'disable-rotation <options>' first level command
216 int cmd_disable_rotation(int argc
, const char **argv
)
218 int popt_ret
, opt
, ret
= 0;
219 enum cmd_error_code cmd_ret
= CMD_SUCCESS
;
220 static poptContext pc
;
221 char *session_name
= NULL
;
222 bool free_session_name
= false;
223 bool periodic_rotation
= false, size_rotation
= false;
225 pc
= poptGetContext(NULL
, argc
, argv
, long_options
, 0);
226 popt_ret
= poptReadDefaultConfig(pc
, 0);
229 ERR("poptReadDefaultConfig");
233 while ((opt
= poptGetNextOpt(pc
)) != -1) {
238 case OPT_LIST_OPTIONS
:
239 list_cmd_options(stdout
, long_options
);
242 periodic_rotation
= true;
245 size_rotation
= true;
253 if (opt_session_name
== NULL
) {
254 session_name
= get_session_name();
255 if (session_name
== NULL
) {
258 free_session_name
= true;
260 session_name
= opt_session_name
;
265 writer
= mi_lttng_writer_create(fileno(stdout
), lttng_opt_mi
);
270 /* Open command element */
271 ret
= mi_lttng_writer_command_open(writer
,
272 mi_lttng_element_command_disable_rotation
);
277 /* Open output element */
278 ret
= mi_lttng_writer_open_element(writer
,
279 mi_lttng_element_command_output
);
285 if (!periodic_rotation
&& !size_rotation
) {
286 ERR("No session rotation schedule type provided.");
292 ret
= mi_lttng_writer_open_element(writer
,
293 mi_lttng_element_rotation_schedule_results
);
298 ret
= mi_lttng_writer_write_element_string(writer
,
299 mi_lttng_element_session_name
,
306 if (periodic_rotation
) {
308 * Continue processing even on error as multiple schedules can
309 * be specified at once.
311 cmd_ret
= remove_schedule(session_name
,
312 LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC
);
316 enum cmd_error_code tmp_ret
;
318 /* Don't overwrite cmd_ret if it already indicates an error. */
319 tmp_ret
= remove_schedule(session_name
,
320 LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD
);
321 cmd_ret
= cmd_ret
? cmd_ret
: tmp_ret
;
325 /* Close rotation schedule results element */
326 ret
= mi_lttng_writer_close_element(writer
);
335 /* Close output element */
336 ret
= mi_lttng_writer_close_element(writer
);
342 ret
= mi_lttng_writer_write_element_bool(writer
,
343 mi_lttng_element_command_success
,
344 cmd_ret
== CMD_SUCCESS
);
349 /* Command element close */
350 ret
= mi_lttng_writer_command_close(writer
);
357 (void) mi_lttng_writer_destroy(writer
);
359 if (free_session_name
) {