clang-tidy: add most bugprone warnings
[lttng-tools.git] / doc / examples / rotation / rotate-client-example.c
CommitLineData
7779bc96
JD
1/*
2 * Session rotation example control application
3 *
4 * Copyright 2017, Julien Desfossez <jdesfossez@efficios.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25/*
26 * Compile with:
27 * gcc -o rotate-client rotate-client-example.c -llttng-ctl
28 *
29 * Run with the following command to rotate the session every second and
30 * compress the chunk, until ctrl-c:
31 * ./rotate-client mysession 1 -1 ./rotate-client-compress.sh
32 */
33
95ce9d29
JR
34#include <lttng/lttng.h>
35#include <signal.h>
7779bc96
JD
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
5c7248cd 40#include <assert.h>
7779bc96 41
95ce9d29 42#define DEFAULT_DATA_AVAILABILITY_WAIT_TIME 200000 /* usec */
7779bc96
JD
43
44static volatile int quit = 0;
45
f46376a1 46static void sighandler(int signal __attribute__((unused)))
7779bc96 47{
5c7248cd
JG
48 const char msg[] = "Signal caught, exiting\n";
49 const int ret = write(STDOUT_FILENO, msg, sizeof(msg));
50
51 assert(ret == 0); /* NOLINT assert is not async signal safe */
7779bc96
JD
52 quit = 1;
53}
54
95ce9d29 55static int setup_session(const char *session_name, const char *path)
7779bc96
JD
56{
57 int ret;
58 struct lttng_domain dom;
59 struct lttng_event ev;
878fea90 60 struct lttng_handle *chan_handle = NULL;
7779bc96
JD
61
62 printf("Creating session %s\n", session_name);
63 ret = lttng_create_session(session_name, path);
64 if (ret) {
65 fprintf(stderr, "Failed to create session, ret = %d\n", ret);
66 goto end;
67 }
68
69 dom.type = LTTNG_DOMAIN_KERNEL;
70 dom.buf_type = LTTNG_BUFFER_GLOBAL;
71
72 chan_handle = lttng_create_handle(session_name, &dom);
73 if (chan_handle == NULL) {
74 ret = -1;
75 goto end;
76 }
77
78 memset(&ev, 0, sizeof(ev));
79 ev.type = LTTNG_EVENT_SYSCALL;
80 strcpy(ev.name, "*");
81 ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
82
95ce9d29
JR
83 ret = lttng_enable_event_with_exclusions(
84 chan_handle, &ev, "mychan", NULL, 0, NULL);
7779bc96 85 if (ret < 0) {
61e4fc8e 86 fprintf(stderr, "Failed to enable events (ret = %i)\n", ret);
7779bc96
JD
87 goto end;
88 }
89 printf("Enabled all system call kernel events\n");
90
91 ret = lttng_start_tracing(session_name);
92 if (ret < 0) {
93 fprintf(stderr, "Failed to start tracing\n");
94 goto end;
95 }
96
7779bc96
JD
97 ret = 0;
98
99end:
878fea90 100 lttng_destroy_handle(chan_handle);
7779bc96
JD
101 return ret;
102}
103
95ce9d29 104static int cleanup_session(const char *session_name)
7779bc96
JD
105{
106 int ret;
107
108 printf("Stopping session %s", session_name);
109 ret = lttng_stop_tracing_no_wait(session_name);
110 if (ret) {
111 fprintf(stderr, "Failed to stop tracing\n");
112 goto end;
113 }
114
115 fflush(stdout);
116 do {
117 ret = lttng_data_pending(session_name);
118 if (ret < 0) {
119 /* Return the data available call error. */
120 goto end;
121 }
122
123 /*
95ce9d29
JR
124 * Data sleep time before retrying (in usec). Don't sleep if the
125 * call returned value indicates availability.
7779bc96
JD
126 */
127 if (ret) {
128 usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME);
129 printf(".");
130 fflush(stdout);
131 }
132 } while (ret != 0);
133 printf("\n");
134
135 printf("Destroying session %s\n", session_name);
136 ret = lttng_destroy_session(session_name);
137 if (ret) {
138 fprintf(stderr, "Failed to destroy the session\n");
139 goto end;
140 }
141
142 ret = 0;
143
144end:
145 return ret;
146}
147
95ce9d29 148static int rotate_session(const char *session_name, const char *ext_program)
7779bc96
JD
149{
150 int ret;
7779bc96
JD
151 struct lttng_rotation_handle *handle = NULL;
152 enum lttng_rotation_status rotation_status;
61e4fc8e 153 enum lttng_rotation_state rotation_state = LTTNG_ROTATION_STATE_ONGOING;
7779bc96
JD
154 char cmd[PATH_MAX];
155
7779bc96
JD
156 printf("Rotating the output files of session %s", session_name);
157
61e4fc8e 158 ret = lttng_rotate_session(session_name, NULL, &handle);
7779bc96 159 if (ret < 0) {
95ce9d29
JR
160 fprintf(stderr, "Failed to rotate session, %s\n",
161 lttng_strerror(ret));
7779bc96
JD
162 goto end;
163 }
164
165 fflush(stdout);
61e4fc8e 166
7779bc96 167 do {
95ce9d29
JR
168 rotation_status = lttng_rotation_handle_get_state(
169 handle, &rotation_state);
61e4fc8e
JG
170 if (rotation_status != LTTNG_ROTATION_STATUS_OK) {
171 ret = -1;
172 fprintf(stderr, "Failed to get the current rotation's state\n");
7779bc96
JD
173 goto end;
174 }
175
176 /*
61e4fc8e
JG
177 * Data sleep time before retrying (in usec). Don't
178 * sleep if the call returned value indicates
179 * availability.
7779bc96 180 */
61e4fc8e 181 if (rotation_state == LTTNG_ROTATION_STATE_ONGOING) {
7779bc96
JD
182 usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME);
183 printf(".");
184 fflush(stdout);
185 }
61e4fc8e 186 } while (rotation_state == LTTNG_ROTATION_STATE_ONGOING);
7779bc96
JD
187 printf("\n");
188
61e4fc8e
JG
189 switch (rotation_state) {
190 case LTTNG_ROTATION_STATE_COMPLETED:
191 {
192 const struct lttng_trace_archive_location *location;
193 const char *absolute_path;
194 enum lttng_trace_archive_location_status location_status;
195
196 rotation_status = lttng_rotation_handle_get_archive_location(
197 handle, &location);
198 if (rotation_status != LTTNG_ROTATION_STATUS_OK) {
199 fprintf(stderr, "Failed to retrieve the rotation's completed chunk archive location\n");
200 ret = -1;
201 goto end;
202 }
203
95ce9d29
JR
204 location_status =
205 lttng_trace_archive_location_local_get_absolute_path(
206 location, &absolute_path);
61e4fc8e
JG
207 if (location_status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) {
208 fprintf(stderr, "Failed to get absolute path of completed chunk archive");
209 ret = -1;
210 goto end;
211 }
212
213 printf("Output files of session %s rotated to %s\n",
214 session_name, absolute_path);
95ce9d29
JR
215 ret = snprintf(cmd, PATH_MAX, "%s %s", ext_program,
216 absolute_path);
7779bc96
JD
217 if (ret < 0) {
218 fprintf(stderr, "Failed to prepare command string\n");
219 goto end;
220 }
221 ret = system(cmd);
222 goto end;
61e4fc8e
JG
223 }
224 case LTTNG_ROTATION_STATE_EXPIRED:
95ce9d29
JR
225 printf("Output files of session %s rotated, but the handle expired\n",
226 session_name);
7779bc96
JD
227 ret = 0;
228 goto end;
61e4fc8e 229 case LTTNG_ROTATION_STATE_ERROR:
95ce9d29
JR
230 fprintf(stderr, "An error occurred with the rotation of session %s\n",
231 session_name);
232 ret = -1;
233 goto end;
234 case LTTNG_ROTATION_STATE_ONGOING:
235 abort();
236 goto end;
237 case LTTNG_ROTATION_STATE_NO_ROTATION:
238 fprintf(stderr, "No rotation was performed on rotation request for session %s\n",
239 session_name);
7779bc96
JD
240 ret = -1;
241 goto end;
242 }
243
244end:
245 lttng_rotation_handle_destroy(handle);
7779bc96
JD
246 return ret;
247}
248
95ce9d29 249static int cleanup_dir(const char *path)
7779bc96
JD
250{
251 char cmd[PATH_MAX];
252 int ret;
253
254 ret = snprintf(cmd, PATH_MAX, "rm -rf %s", path);
255 if (ret < 0) {
256 fprintf(stderr, "Failed to prepare rm -rf command string\n");
257 goto end;
258 }
259 ret = system(cmd);
260
261end:
262 return ret;
263}
264
95ce9d29 265static void usage(const char *prog_name)
7779bc96
JD
266{
267 fprintf(stderr, "Usage: %s <session-name> <delay-sec> <nr-rotate> <program>\n",
268 prog_name);
269 fprintf(stderr, " <session-name>: the name of the session you want to create\n");
270 fprintf(stderr, " <delay-sec>: the delay in seconds between each rotation\n");
95ce9d29
JR
271 fprintf(stderr,
272 " <nr-rotate>: the number of rotation you want to perform, "
7779bc96 273 "-1 for infinite until ctrl-c\n");
95ce9d29
JR
274 fprintf(stderr,
275 " <program>: program to run on each chunk, it must be "
7779bc96
JD
276 "executable, and expect a trace folder as only argument\n");
277 fprintf(stderr, "\nThe trace folder is deleted when this program completes.\n");
278}
279
280int main(int argc, char **argv)
281{
282 int ret;
283 char tmppath[] = "/tmp/lttng-rotate-XXXXXX";
284 char *session_name, *path, *ext_program;
285 int delay, nr;
286
287 if (argc != 5) {
288 usage(argv[0]);
289 ret = -1;
290 goto end;
291 }
292
293 session_name = argv[1];
294 delay = atoi(argv[2]);
295 nr = atoi(argv[3]);
296 ext_program = argv[4];
297
298 if (delay < 0) {
299 fprintf(stderr, "delay-sec must be a positive values\n");
300 ret = -1;
301 goto end;
302 }
303
95ce9d29
JR
304 if (signal(SIGINT, sighandler) == SIG_ERR) {
305 ret = -1;
7779bc96
JD
306 perror("signal handler");
307 goto end;
308 }
309
310 path = mkdtemp(tmppath);
311 if (!path) {
312 fprintf(stderr, "Failed to create temporary path\n");
313 }
314
315 printf("Output directory: %s\n", path);
316
317 ret = setup_session(session_name, path);
318 if (ret) {
319 goto end_cleanup_dir;
320 }
321
322 if (nr > 0) {
323 unsigned int sleep_time;
324 int i;
325
326 for (i = 0; i < nr; i++) {
327 ret = rotate_session(session_name, ext_program);
328 if (ret) {
329 goto end_cleanup;
330 }
331 sleep_time = delay;
332 while (sleep_time > 0) {
333 sleep_time = sleep(sleep_time);
334 }
335 }
336 } else {
95ce9d29 337 for (;;) {
7779bc96
JD
338 if (quit) {
339 break;
340 }
341 ret = rotate_session(session_name, ext_program);
342 if (ret) {
343 goto end_cleanup;
344 }
345 sleep(delay);
346 }
347 }
348
349end_cleanup:
350 ret = cleanup_session(session_name);
351 if (ret) {
352 goto end;
353 }
354end_cleanup_dir:
355 ret = cleanup_dir(path);
356end:
357 return ret;
358}
This page took 0.05903 seconds and 4 git commands to generate.