lttctl : size + n subbufs + align options
[lttv.git] / ltt / branches / poly / lttctl / lttctl.c
1 /* lttctl
2 *
3 * Linux Trace Toolkit Control
4 *
5 * Small program that controls LTT through libltt.
6 *
7 * Copyright 2005 -
8 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
9 */
10
11 #ifdef HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <libltt/libltt.h>
16 #include <errno.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <signal.h>
22
23 enum trace_ctl_op {
24 CTL_OP_CREATE,
25 CTL_OP_DESTROY,
26 CTL_OP_START,
27 CTL_OP_STOP,
28 CTL_OP_DAEMON,
29 CTL_OP_ALIGN,
30 CTL_OP_NONE
31 };
32
33 static char *trace_name = NULL;
34 static char *mode_name = NULL;
35 static unsigned subbuf_size = 0;
36 static unsigned n_subbufs = 0;
37 static enum trace_mode mode = LTT_TRACE_NORMAL;
38 static enum trace_ctl_op op = CTL_OP_NONE;
39 static char *channel_root = NULL;
40 static char *trace_root = NULL;
41 static unsigned alignment = 0;
42
43 static int sigio_received = 0;
44
45 void handler(int signo)
46 {
47 printf("signal %d received\n", signo);
48 sigio_received = 1;
49 }
50
51
52 /* Args :
53 *
54 */
55 void show_arguments(void)
56 {
57 printf("Please use the following arguments :\n");
58 printf("\n");
59 printf("-n name Name of the trace.\n");
60 printf("-c mode Create trace channels in mode normal or flight recorder.\n");
61 printf(" Mode values : normal (default) or flight.\n");
62 printf("-r Destroy trace channels.\n");
63 printf("-s Start tracing.\n");
64 //printf(" Note : will automatically create a normal trace if "
65 // "none exists.\n");
66 printf("-q Stop tracing.\n");
67 printf("-d Create trace, spawn a lttd daemon, start tracing.\n");
68 printf(" (optionnaly, you can set LTT_DAEMON env. var.)\n");
69 printf("-t Trace root path. (ex. /root/traces/example_trace)\n");
70 printf("-l LTT channels root path. (ex. /mnt/relayfs/ltt)\n");
71 printf("-a Alignment of a new or existing trace\n");
72 printf("-z Size of the subbuffers (will be rounded to next page size)\n");
73 printf("-x Number of subbuffers\n");
74 printf("\n");
75 }
76
77
78 /* parse_arguments
79 *
80 * Parses the command line arguments.
81 *
82 * Returns 1 if the arguments were correct, but doesn't ask for program
83 * continuation. Returns -1 if the arguments are incorrect, or 0 if OK.
84 */
85 int parse_arguments(int argc, char **argv)
86 {
87 int ret = 0;
88 int argn = 1;
89
90 if(argc == 2) {
91 if(strcmp(argv[1], "-h") == 0) {
92 return 1;
93 }
94 }
95
96 while(argn < argc) {
97
98 switch(argv[argn][0]) {
99 case '-':
100 switch(argv[argn][1]) {
101 case 'n':
102 if(argn+1 < argc) {
103 trace_name = argv[argn+1];
104 argn++;
105 } else {
106 printf("Specify a trace name after -n.\n", argv[argn]);
107 printf("\n");
108 ret = -1;
109 }
110
111 break;
112 case 'c':
113 op = CTL_OP_CREATE;
114 if(argn+1 < argc) {
115 mode_name = argv[argn+1];
116 argn++;
117 if(strcmp(mode_name, "normal") == 0)
118 mode = LTT_TRACE_NORMAL;
119 else if(strcmp(mode_name, "flight") == 0)
120 mode = LTT_TRACE_FLIGHT;
121 else {
122 printf("Invalid mode '%s'.\n", argv[argn]);
123 printf("\n");
124 ret = -1;
125 }
126 } else {
127 printf("Specify a mode after -c.\n");
128 printf("\n");
129 ret = -1;
130 }
131 break;
132 case 'r':
133 op = CTL_OP_DESTROY;
134 break;
135 case 's':
136 op = CTL_OP_START;
137 break;
138 case 'q':
139 op = CTL_OP_STOP;
140 break;
141 case 'a':
142 if(op == CTL_OP_NONE) op = CTL_OP_ALIGN;
143 if(argn+1 < argc) {
144 alignment = (unsigned)atoi(argv[argn+1]);
145 argn++;
146 } else {
147 printf("Specify an alignment after -a.\n");
148 printf("\n");
149 ret = -1;
150 }
151 break;
152 case 'z':
153 if(argn+1 < argc) {
154 subbuf_size = (unsigned)atoi(argv[argn+1]);
155 argn++;
156 } else {
157 printf("Specify a number of subbuffers after -z.\n");
158 printf("\n");
159 ret = -1;
160 }
161 break;
162 case 'x':
163 if(argn+1 < argc) {
164 n_subbufs = (unsigned)atoi(argv[argn+1]);
165 argn++;
166 } else {
167 printf("Specify a subbuffer size after -x.\n");
168 printf("\n");
169 ret = -1;
170 }
171 break;
172 case 'd':
173 op = CTL_OP_DAEMON;
174 break;
175 case 't':
176 if(argn+1 < argc) {
177 trace_root = argv[argn+1];
178 argn++;
179 } else {
180 printf("Specify a trace root path after -t.\n");
181 printf("\n");
182 ret = -1;
183 }
184 break;
185 case 'l':
186 if(argn+1 < argc) {
187 channel_root = argv[argn+1];
188 argn++;
189 } else {
190 printf("Specify a channel root path after -l.\n");
191 printf("\n");
192 ret = -1;
193 }
194 break;
195 default:
196 printf("Invalid argument '%s'.\n", argv[argn]);
197 printf("\n");
198 ret = -1;
199 }
200 break;
201 default:
202 printf("Invalid argument '%s'.\n", argv[argn]);
203 printf("\n");
204 ret = -1;
205 }
206 argn++;
207 }
208
209 if(trace_name == NULL) {
210 printf("Please specify a trace name.\n");
211 printf("\n");
212 ret = -1;
213 }
214
215 if(op == CTL_OP_NONE) {
216 printf("Please specify an operation.\n");
217 printf("\n");
218 ret = -1;
219 }
220
221 if(op == CTL_OP_DAEMON) {
222 if(trace_root == NULL) {
223 printf("Please specify -t trace_root_path with the -d option.\n");
224 printf("\n");
225 ret = -1;
226 }
227 if(channel_root == NULL) {
228 printf("Please specify -l ltt_root_path with the -d option.\n");
229 printf("\n");
230 ret = -1;
231 }
232 }
233
234 return ret;
235 }
236
237 void show_info(void)
238 {
239 printf("Linux Trace Toolkit Trace Control\n");
240 printf("\n");
241 printf("Controlling trace : %s\n", trace_name);
242 printf("\n");
243 }
244
245 int lttctl_daemon(struct lttctl_handle *handle, char *trace_name)
246 {
247 char channel_path[PATH_MAX] = "";
248 pid_t pid;
249 int ret;
250 char *lttd_path = getenv("LTT_DAEMON");
251 struct sigaction act;
252
253 if(lttd_path == NULL) lttd_path = "lttd";
254
255 strcat(channel_path, channel_root);
256 strcat(channel_path, "/");
257 strcat(channel_path, trace_name);
258
259
260 ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size, n_subbufs);
261 if(ret != 0) goto create_error;
262
263 act.sa_handler = handler;
264 sigemptyset(&(act.sa_mask));
265 sigaddset(&(act.sa_mask), SIGIO);
266 sigaction(SIGIO, &act, NULL);
267
268 sigio_received = 0;
269
270 pid = fork();
271
272 if(pid > 0) {
273 /* parent */
274 while(!sigio_received) pause();
275
276 /* Now the trace is created, go on and create the supplementary files... */
277 printf("Creating supplementary trace files\n");
278
279 } else if(pid == 0) {
280 /* child */
281 int ret =
282 execlp(lttd_path, lttd_path, "-t", trace_root, "-c", channel_path, "-s", NULL);
283 if(ret) {
284 perror("Error in executing the lttd daemon");
285 exit(-1);
286 }
287 } else {
288 /* error */
289 perror("Error in forking for lttd daemon");
290
291 }
292
293 ret = lttctl_start(handle, trace_name);
294 if(ret != 0) goto start_error;
295
296 return 0;
297
298 /* error handling */
299 start_error:
300 ret |= lttctl_destroy_trace(handle, trace_name);
301 create_error:
302 return ret;
303 }
304
305 int main(int argc, char ** argv)
306 {
307 int ret;
308 struct lttctl_handle *handle;
309
310 ret = parse_arguments(argc, argv);
311
312 if(ret != 0) show_arguments();
313 if(ret < 0) return EINVAL;
314 if(ret > 0) return 0;
315
316 show_info();
317
318 handle = lttctl_create_handle();
319
320 if(handle == NULL) return -1;
321
322 switch(op) {
323 case CTL_OP_CREATE:
324 ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size,
325 n_subbufs);
326 break;
327 case CTL_OP_DESTROY:
328 ret = lttctl_destroy_trace(handle, trace_name);
329 break;
330 case CTL_OP_START:
331 ret = lttctl_start(handle, trace_name);
332 break;
333 case CTL_OP_STOP:
334 ret = lttctl_stop(handle, trace_name);
335 break;
336 case CTL_OP_DAEMON:
337 ret = lttctl_daemon(handle, trace_name);
338 break;
339 case CTL_OP_NONE:
340 break;
341 }
342
343 ret |= lttctl_destroy_handle(handle);
344
345 return ret;
346 }
This page took 0.047021 seconds and 5 git commands to generate.