build system: support rotation example
[lttng-tools.git] / doc / examples / rotation / rotate-client-example.c
... / ...
CommitLineData
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
34#include <lttng/lttng.h>
35#include <signal.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40
41#define DEFAULT_DATA_AVAILABILITY_WAIT_TIME 200000 /* usec */
42
43static volatile int quit = 0;
44
45static void sighandler(int signal)
46{
47 printf("Signal caught, exiting\n");
48 quit = 1;
49}
50
51static int setup_session(const char *session_name, const char *path)
52{
53 int ret;
54 struct lttng_domain dom;
55 struct lttng_event ev;
56 struct lttng_handle *chan_handle;
57
58 printf("Creating session %s\n", session_name);
59 ret = lttng_create_session(session_name, path);
60 if (ret) {
61 fprintf(stderr, "Failed to create session, ret = %d\n", ret);
62 goto end;
63 }
64
65 dom.type = LTTNG_DOMAIN_KERNEL;
66 dom.buf_type = LTTNG_BUFFER_GLOBAL;
67
68 chan_handle = lttng_create_handle(session_name, &dom);
69 if (chan_handle == NULL) {
70 ret = -1;
71 goto end;
72 }
73
74 memset(&ev, 0, sizeof(ev));
75 ev.type = LTTNG_EVENT_SYSCALL;
76 strcpy(ev.name, "*");
77 ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
78
79 ret = lttng_enable_event_with_exclusions(
80 chan_handle, &ev, "mychan", NULL, 0, NULL);
81 if (ret < 0) {
82 fprintf(stderr, "Failed to enable events (ret = %i)\n", ret);
83 goto end;
84 }
85 printf("Enabled all system call kernel events\n");
86
87 ret = lttng_start_tracing(session_name);
88 if (ret < 0) {
89 fprintf(stderr, "Failed to start tracing\n");
90 goto end;
91 }
92
93 lttng_destroy_handle(chan_handle);
94
95 ret = 0;
96
97end:
98 return ret;
99}
100
101static int cleanup_session(const char *session_name)
102{
103 int ret;
104
105 printf("Stopping session %s", session_name);
106 ret = lttng_stop_tracing_no_wait(session_name);
107 if (ret) {
108 fprintf(stderr, "Failed to stop tracing\n");
109 goto end;
110 }
111
112 fflush(stdout);
113 do {
114 ret = lttng_data_pending(session_name);
115 if (ret < 0) {
116 /* Return the data available call error. */
117 goto end;
118 }
119
120 /*
121 * Data sleep time before retrying (in usec). Don't sleep if the
122 * call returned value indicates availability.
123 */
124 if (ret) {
125 usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME);
126 printf(".");
127 fflush(stdout);
128 }
129 } while (ret != 0);
130 printf("\n");
131
132 printf("Destroying session %s\n", session_name);
133 ret = lttng_destroy_session(session_name);
134 if (ret) {
135 fprintf(stderr, "Failed to destroy the session\n");
136 goto end;
137 }
138
139 ret = 0;
140
141end:
142 return ret;
143}
144
145static int rotate_session(const char *session_name, const char *ext_program)
146{
147 int ret;
148 struct lttng_rotation_handle *handle = NULL;
149 enum lttng_rotation_status rotation_status;
150 enum lttng_rotation_state rotation_state = LTTNG_ROTATION_STATE_ONGOING;
151 char cmd[PATH_MAX];
152
153 printf("Rotating the output files of session %s", session_name);
154
155 ret = lttng_rotate_session(session_name, NULL, &handle);
156 if (ret < 0) {
157 fprintf(stderr, "Failed to rotate session, %s\n",
158 lttng_strerror(ret));
159 goto end;
160 }
161
162 fflush(stdout);
163
164 do {
165 rotation_status = lttng_rotation_handle_get_state(
166 handle, &rotation_state);
167 if (rotation_status != LTTNG_ROTATION_STATUS_OK) {
168 ret = -1;
169 fprintf(stderr, "Failed to get the current rotation's state\n");
170 goto end;
171 }
172
173 /*
174 * Data sleep time before retrying (in usec). Don't
175 * sleep if the call returned value indicates
176 * availability.
177 */
178 if (rotation_state == LTTNG_ROTATION_STATE_ONGOING) {
179 usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME);
180 printf(".");
181 fflush(stdout);
182 }
183 } while (rotation_state == LTTNG_ROTATION_STATE_ONGOING);
184 printf("\n");
185
186 switch (rotation_state) {
187 case LTTNG_ROTATION_STATE_COMPLETED:
188 {
189 const struct lttng_trace_archive_location *location;
190 const char *absolute_path;
191 enum lttng_trace_archive_location_status location_status;
192
193 rotation_status = lttng_rotation_handle_get_archive_location(
194 handle, &location);
195 if (rotation_status != LTTNG_ROTATION_STATUS_OK) {
196 fprintf(stderr, "Failed to retrieve the rotation's completed chunk archive location\n");
197 ret = -1;
198 goto end;
199 }
200
201 location_status =
202 lttng_trace_archive_location_local_get_absolute_path(
203 location, &absolute_path);
204 if (location_status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) {
205 fprintf(stderr, "Failed to get absolute path of completed chunk archive");
206 ret = -1;
207 goto end;
208 }
209
210 printf("Output files of session %s rotated to %s\n",
211 session_name, absolute_path);
212 ret = snprintf(cmd, PATH_MAX, "%s %s", ext_program,
213 absolute_path);
214 if (ret < 0) {
215 fprintf(stderr, "Failed to prepare command string\n");
216 goto end;
217 }
218 ret = system(cmd);
219 goto end;
220 }
221 case LTTNG_ROTATION_STATE_EXPIRED:
222 printf("Output files of session %s rotated, but the handle expired\n",
223 session_name);
224 ret = 0;
225 goto end;
226 case LTTNG_ROTATION_STATE_ERROR:
227 fprintf(stderr, "An error occurred with the rotation of session %s\n",
228 session_name);
229 ret = -1;
230 goto end;
231 case LTTNG_ROTATION_STATE_ONGOING:
232 abort();
233 goto end;
234 case LTTNG_ROTATION_STATE_NO_ROTATION:
235 fprintf(stderr, "No rotation was performed on rotation request for session %s\n",
236 session_name);
237 ret = -1;
238 goto end;
239 }
240
241end:
242 lttng_rotation_handle_destroy(handle);
243 return ret;
244}
245
246static int cleanup_dir(const char *path)
247{
248 char cmd[PATH_MAX];
249 int ret;
250
251 ret = snprintf(cmd, PATH_MAX, "rm -rf %s", path);
252 if (ret < 0) {
253 fprintf(stderr, "Failed to prepare rm -rf command string\n");
254 goto end;
255 }
256 ret = system(cmd);
257
258end:
259 return ret;
260}
261
262static void usage(const char *prog_name)
263{
264 fprintf(stderr, "Usage: %s <session-name> <delay-sec> <nr-rotate> <program>\n",
265 prog_name);
266 fprintf(stderr, " <session-name>: the name of the session you want to create\n");
267 fprintf(stderr, " <delay-sec>: the delay in seconds between each rotation\n");
268 fprintf(stderr,
269 " <nr-rotate>: the number of rotation you want to perform, "
270 "-1 for infinite until ctrl-c\n");
271 fprintf(stderr,
272 " <program>: program to run on each chunk, it must be "
273 "executable, and expect a trace folder as only argument\n");
274 fprintf(stderr, "\nThe trace folder is deleted when this program completes.\n");
275}
276
277int main(int argc, char **argv)
278{
279 int ret;
280 char tmppath[] = "/tmp/lttng-rotate-XXXXXX";
281 char *session_name, *path, *ext_program;
282 int delay, nr;
283
284 if (argc != 5) {
285 usage(argv[0]);
286 ret = -1;
287 goto end;
288 }
289
290 session_name = argv[1];
291 delay = atoi(argv[2]);
292 nr = atoi(argv[3]);
293 ext_program = argv[4];
294
295 if (delay < 0) {
296 fprintf(stderr, "delay-sec must be a positive values\n");
297 ret = -1;
298 goto end;
299 }
300
301 if (signal(SIGINT, sighandler) == SIG_ERR) {
302 ret = -1;
303 perror("signal handler");
304 goto end;
305 }
306
307 path = mkdtemp(tmppath);
308 if (!path) {
309 fprintf(stderr, "Failed to create temporary path\n");
310 }
311
312 printf("Output directory: %s\n", path);
313
314 ret = setup_session(session_name, path);
315 if (ret) {
316 goto end_cleanup_dir;
317 }
318
319 if (nr > 0) {
320 unsigned int sleep_time;
321 int i;
322
323 for (i = 0; i < nr; i++) {
324 ret = rotate_session(session_name, ext_program);
325 if (ret) {
326 goto end_cleanup;
327 }
328 sleep_time = delay;
329 while (sleep_time > 0) {
330 sleep_time = sleep(sleep_time);
331 }
332 }
333 } else {
334 for (;;) {
335 if (quit) {
336 break;
337 }
338 ret = rotate_session(session_name, ext_program);
339 if (ret) {
340 goto end_cleanup;
341 }
342 sleep(delay);
343 }
344 }
345
346end_cleanup:
347 ret = cleanup_session(session_name);
348 if (ret) {
349 goto end;
350 }
351end_cleanup_dir:
352 ret = cleanup_dir(path);
353end:
354 return ret;
355}
This page took 0.023239 seconds and 4 git commands to generate.