prepare the 0.3 release
[lttngtop.git] / src / mmap-live.c
CommitLineData
b1acd2b3
JD
1#ifdef LTTNGTOP_MMAP_LIVE
2
3static
4ssize_t read_subbuffer(struct lttng_consumer_stream *kconsumerd_fd,
5 struct lttng_consumer_local_data *ctx)
6{
7 unsigned long len;
8 int err;
9 long ret = 0;
10 int infd = helper_get_lttng_consumer_stream_wait_fd(kconsumerd_fd);
11
12 if (helper_get_lttng_consumer_stream_output(kconsumerd_fd) == LTTNG_EVENT_SPLICE) {
13 /* Get the next subbuffer */
14 err = helper_kernctl_get_next_subbuf(infd);
15 if (err != 0) {
16 ret = errno;
17 perror("Reserving sub buffer failed (everything is normal, "
18 "it is due to concurrency)");
19 goto end;
20 }
21 /* read the whole subbuffer */
22 err = helper_kernctl_get_padded_subbuf_size(infd, &len);
23 if (err != 0) {
24 ret = errno;
25 perror("Getting sub-buffer len failed.");
26 goto end;
27 }
28
29 /* splice the subbuffer to the tracefile */
30 ret = helper_lttng_consumer_on_read_subbuffer_splice(ctx, kconsumerd_fd, len, 0);
31 if (ret < 0) {
32 /*
33 * display the error but continue processing to try
34 * to release the subbuffer
35 */
36 fprintf(stderr,"Error splicing to tracefile\n");
37 }
38 err = helper_kernctl_put_next_subbuf(infd);
39 if (err != 0) {
40 ret = errno;
41 perror("Reserving sub buffer failed (everything is normal, "
42 "it is due to concurrency)");
43 goto end;
44 }
45 sem_post(&metadata_available);
46 }
47
48end:
49 return 0;
50}
51
52static
53int on_update_fd(int key, uint32_t state)
54{
55 /* let the lib handle the metadata FD */
56 if (key == sessiond_metadata)
57 return 0;
58 return 1;
59}
60
61static
62int on_recv_fd(struct lttng_consumer_stream *kconsumerd_fd)
63{
64 int ret;
65 struct bt_mmap_stream *new_mmap_stream;
66
67 /* Opening the tracefile in write mode */
68 if (helper_get_lttng_consumer_stream_path_name(kconsumerd_fd) != NULL) {
69 ret = open(helper_get_lttng_consumer_stream_path_name(kconsumerd_fd),
70 O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU|S_IRWXG|S_IRWXO);
71 if (ret < 0) {
72 perror("open");
73 goto end;
74 }
75 helper_set_lttng_consumer_stream_out_fd(kconsumerd_fd, ret);
76 }
77
78 if (helper_get_lttng_consumer_stream_output(kconsumerd_fd) == LTTNG_EVENT_MMAP) {
79 new_mmap_stream = malloc(sizeof(struct bt_mmap_stream));
80 new_mmap_stream->fd = helper_get_lttng_consumer_stream_wait_fd(
81 kconsumerd_fd);
82 bt_list_add(&new_mmap_stream->list, &mmap_list.head);
83
84 g_ptr_array_add(lttng_consumer_stream_array, kconsumerd_fd);
85 /* keep mmap FDs internally */
86 ret = 1;
87 } else {
88 consumerd_metadata = helper_get_lttng_consumer_stream_wait_fd(kconsumerd_fd);
89 sessiond_metadata = helper_get_lttng_consumer_stream_key(kconsumerd_fd);
90 ret = 0;
91 }
92
93 reload_trace = 1;
94
95end:
96 return ret;
97}
98
99static
100void live_consume(struct bt_context **bt_ctx)
101{
102 int ret;
103 FILE *metadata_fp;
104
105 sem_wait(&metadata_available);
106 if (access("/tmp/livesession/kernel/metadata", F_OK) != 0) {
107 fprintf(stderr,"no metadata\n");
108 goto end;
109 }
110 metadata_fp = fopen("/tmp/livesession/kernel/metadata", "r");
111
112 *bt_ctx = bt_context_create();
113 ret = bt_context_add_trace(*bt_ctx, NULL, "ctf",
114 lttngtop_ctf_packet_seek, &mmap_list, metadata_fp);
115 if (ret < 0) {
116 printf("Error adding trace\n");
117 goto end;
118 }
119
120end:
121 return;
122}
123
124static
125int setup_consumer(char *command_sock_path, pthread_t *threads,
126 struct lttng_consumer_local_data *ctx)
127{
128 int ret = 0;
129
130 ctx = helper_lttng_consumer_create(HELPER_LTTNG_CONSUMER_KERNEL,
131 read_subbuffer, NULL, on_recv_fd, on_update_fd);
132 if (!ctx)
133 goto end;
134
135 unlink(command_sock_path);
136 helper_lttng_consumer_set_command_sock_path(ctx, command_sock_path);
137 helper_lttng_consumer_init();
138
139 /* Create the thread to manage the receive of fd */
140 ret = pthread_create(&threads[0], NULL, helper_lttng_consumer_thread_sessiond_poll,
141 (void *) ctx);
142 if (ret != 0) {
143 perror("pthread_create receive fd");
144 goto end;
145 }
146 /* Create thread to manage the polling/writing of traces */
147 ret = pthread_create(&threads[1], NULL, helper_lttng_consumer_thread_metadata_poll,
148 (void *) ctx);
149 if (ret != 0) {
150 perror("pthread_create poll fd");
151 goto end;
152 }
153
154end:
155 return ret;
156}
157
158static
159int enable_kprobes(struct lttng_handle *handle, char *channel_name)
160{
161 struct lttng_event ev;
162 struct kprobes *kprobe;
163 int ret = 0;
164 int i;
165
166 for (i = 0; i < lttngtop.kprobes_table->len; i++) {
167 kprobe = g_ptr_array_index(lttngtop.kprobes_table, i);
168
169 memset(&ev, '\0', sizeof(struct lttng_event));
170 ev.type = LTTNG_EVENT_PROBE;
171 if (kprobe->symbol_name)
172 sprintf(ev.attr.probe.symbol_name, "%s", kprobe->symbol_name);
173 sprintf(ev.name, "%s", kprobe->probe_name);
174 ev.attr.probe.addr = kprobe->probe_addr;
175 ev.attr.probe.offset = kprobe->probe_offset;
176 if ((ret = lttng_enable_event(handle, &ev, channel_name)) < 0) {
177 fprintf(stderr,"error enabling kprobes : %s\n",
178 helper_lttcomm_get_readable_code(ret));
179 goto end;
180 }
181 }
182
183end:
184 return ret;
185}
186
187static
188int setup_live_tracing()
189{
190 struct lttng_domain dom;
191 struct lttng_channel chan;
192 char *channel_name = "mmapchan";
193 struct lttng_event ev;
194 int ret = 0;
195 char *command_sock_path = "/tmp/consumerd_sock";
196 static pthread_t threads[2]; /* recv_fd, poll */
197 struct lttng_event_context kctxpid, kctxcomm, kctxppid, kctxtid,
198 kctxperf1, kctxperf2;
199
200 struct lttng_handle *handle;
201
202 BT_INIT_LIST_HEAD(&mmap_list.head);
203
204 lttng_consumer_stream_array = g_ptr_array_new();
205
206 if ((ret = setup_consumer(command_sock_path, threads, ctx)) < 0) {
207 fprintf(stderr,"error setting up consumer\n");
208 goto error;
209 }
210
211 available_snapshots = g_ptr_array_new();
212
213 /* setup the session */
214 dom.type = LTTNG_DOMAIN_KERNEL;
215
216 ret = unlink("/tmp/livesession");
217
218 lttng_destroy_session("test");
219 if ((ret = lttng_create_session("test", "/tmp/livesession")) < 0) {
220 fprintf(stderr,"error creating the session : %s\n",
221 helper_lttcomm_get_readable_code(ret));
222 goto error;
223 }
224
225 if ((handle = lttng_create_handle("test", &dom)) == NULL) {
226 fprintf(stderr,"error creating handle\n");
227 goto error_session;
228 }
229
230 /*
231 * FIXME : need to let the
232 * helper_lttng_consumer_thread_receive_fds create the
233 * socket.
234 * Cleaner solution ?
235 */
236 while (access(command_sock_path, F_OK)) {
237 sleep(0.1);
238 }
239
240 if ((ret = lttng_register_consumer(handle, command_sock_path)) < 0) {
241 fprintf(stderr,"error registering consumer : %s\n",
242 helper_lttcomm_get_readable_code(ret));
243 goto error_session;
244 }
245
246 strcpy(chan.name, channel_name);
247 chan.attr.overwrite = 0;
248 if (opt_tid && opt_textdump) {
249 chan.attr.subbuf_size = 32768;
250 chan.attr.num_subbuf = 8;
251 } else {
252 //chan.attr.subbuf_size = 1048576; /* 1MB */
253 chan.attr.subbuf_size = 2097152; /* 1MB */
254 chan.attr.num_subbuf = 4;
255 }
256 chan.attr.switch_timer_interval = 0;
257 chan.attr.read_timer_interval = 200;
258 chan.attr.output = LTTNG_EVENT_MMAP;
259
260 if ((ret = lttng_enable_channel(handle, &chan)) < 0) {
261 fprintf(stderr,"error creating channel : %s\n",
262 helper_lttcomm_get_readable_code(ret));
263 goto error_session;
264 }
265
266 memset(&ev, '\0', sizeof(struct lttng_event));
267 ev.type = LTTNG_EVENT_TRACEPOINT;
268 sprintf(ev.name, "sched_switch");
269 if ((ret = lttng_enable_event(handle, &ev, channel_name)) < 0) {
270 fprintf(stderr,"error enabling event %s : %s\n",
271 ev.name,
272 helper_lttcomm_get_readable_code(ret));
273 goto error_session;
274 }
275 sprintf(ev.name, "sched_process_free");
276 if ((ret = lttng_enable_event(handle, &ev, channel_name)) < 0) {
277 fprintf(stderr,"error enabling event %s : %s\n",
278 ev.name,
279 helper_lttcomm_get_readable_code(ret));
280 goto error_session;
281 }
282 sprintf(ev.name, "lttng_statedump_process_state");
283 if ((ret = lttng_enable_event(handle, &ev, channel_name)) < 0) {
284 fprintf(stderr,"error enabling event %s : %s\n",
285 ev.name,
286 helper_lttcomm_get_readable_code(ret));
287 goto error_session;
288 }
289 sprintf(ev.name, "lttng_statedump_file_descriptor");
290 if ((ret = lttng_enable_event(handle, &ev, channel_name)) < 0) {
291 fprintf(stderr,"error enabling event %s : %s\n",
292 ev.name,
293 helper_lttcomm_get_readable_code(ret));
294 goto error_session;
295 }
296
297 memset(&ev, '\0', sizeof(struct lttng_event));
298 ev.type = LTTNG_EVENT_SYSCALL;
299 if ((ret = lttng_enable_event(handle, &ev, channel_name)) < 0) {
300 fprintf(stderr,"error enabling syscalls : %s\n",
301 helper_lttcomm_get_readable_code(ret));
302 goto error_session;
303 }
304
305 if (lttngtop.kprobes_table) {
306 ret = enable_kprobes(handle, channel_name);
307 if (ret < 0) {
308 goto error_session;
309 }
310 }
311
312 kctxperf1.ctx = LTTNG_EVENT_CONTEXT_PERF_COUNTER;
313 kctxperf1.u.perf_counter.type = 0; /* PERF_TYPE_HARDWARE */
314 kctxperf1.u.perf_counter.config = 5; /* PERF_COUNT_HW_BRANCH_MISSES */
315 sprintf(kctxperf1.u.perf_counter.name, "perf_branch_misses");
316 ret = lttng_add_context(handle, &kctxperf1, NULL, NULL);
317 if (ret < 0) {
318 fprintf(stderr, "error enabling context %s\n",
319 kctxtid.u.perf_counter.name);
320 }
321
322 kctxperf2.ctx = LTTNG_EVENT_CONTEXT_PERF_COUNTER;
323 kctxperf2.u.perf_counter.type = 1; /* PERF_TYPE_SOFTWARE */
324 kctxperf2.u.perf_counter.config = 6; /* PERF_COUNT_SW_PAGE_FAULTS_MAJ */
325 sprintf(kctxperf2.u.perf_counter.name, "perf_major_faults");
326 ret = lttng_add_context(handle, &kctxperf2, NULL, NULL);
327 if (ret < 0) {
328 fprintf(stderr, "error enabling context %s\n",
329 kctxtid.u.perf_counter.name);
330 }
331
332 kctxpid.ctx = LTTNG_EVENT_CONTEXT_PID;
333 lttng_add_context(handle, &kctxpid, NULL, NULL);
334 kctxtid.ctx = LTTNG_EVENT_CONTEXT_TID;
335 lttng_add_context(handle, &kctxtid, NULL, NULL);
336 kctxppid.ctx = LTTNG_EVENT_CONTEXT_PPID;
337 lttng_add_context(handle, &kctxppid, NULL, NULL);
338 kctxcomm.ctx = LTTNG_EVENT_CONTEXT_PROCNAME;
339 lttng_add_context(handle, &kctxcomm, NULL, NULL);
340 kctxpid.ctx = LTTNG_EVENT_CONTEXT_VPID;
341 lttng_add_context(handle, &kctxpid, NULL, NULL);
342 kctxtid.ctx = LTTNG_EVENT_CONTEXT_VTID;
343 lttng_add_context(handle, &kctxtid, NULL, NULL);
344 kctxtid.ctx = LTTNG_EVENT_CONTEXT_HOSTNAME;
345 lttng_add_context(handle, &kctxtid, NULL, NULL);
346
347
348 if ((ret = lttng_start_tracing("test")) < 0) {
349 fprintf(stderr,"error starting tracing : %s\n",
350 helper_lttcomm_get_readable_code(ret));
351 goto error_session;
352 }
353
354 helper_kernctl_buffer_flush(consumerd_metadata);
355
356 /* block until metadata is ready */
357 sem_init(&metadata_available, 0, 0);
358
359 return 0;
360
361error_session:
362 lttng_destroy_session("test");
363error:
364 return -1;
365}
366
367int mmap_live_loop(struct bt_context *bt_ctx,
368 struct bt_mmap_stream_list mmap_list)
369{
370 struct bt_mmap_stream *mmap_info;
371
372 ret = setup_live_tracing();
373 if (ret < 0) {
374 goto end;
375 }
376
377 while (!quit) {
378 reload_trace = 0;
379 live_consume(&bt_ctx);
380 ret = check_requirements(bt_ctx);
381 if (ret < 0) {
382 fprintf(stderr, "[error] some mandatory contexts were missing, exiting.\n");
383 goto end;
384 }
385 iter_trace(bt_ctx);
386 /*
387 * FIXME : pb with cleanup in libbabeltrace
388 ret = bt_context_remove_trace(bt_ctx, 0);
389 if (ret != 0) {
390 fprintf(stderr, "error removing trace\n");
391 goto error;
392 }
393 */
394 if (bt_ctx) {
395 bt_context_put(bt_ctx);
396 }
397
398 /*
399 * since we receive all FDs every time there is an
400 * update and the FD number is different every time,
401 * we don't know which one are valid.
402 * so we check if all FDs are usable with a simple
403 * ioctl call.
404 */
405 bt_list_for_each_entry(mmap_info, &mmap_list.head, list) {
406 unsigned long mmap_len;
407
408 ret = helper_kernctl_get_mmap_len(mmap_info->fd, &mmap_len);
409 if (ret != 0) {
410 bt_list_del(&mmap_info->list);
411 }
412 }
413 sem_post(&metadata_available);
414 }
415
416}
417
418void mmap_live_flush(struct bt_mmap_stream_list mmap_list)
419{
420 struct bt_mmap_stream *mmap_info;
421
422 bt_list_for_each_entry(mmap_info, &mmap_list.head, list)
423 helper_kernctl_buffer_flush(mmap_info->fd);
424}
425#endif /* LTTNGTOP_MMAP_LIVE */
This page took 0.056268 seconds and 4 git commands to generate.