Clarify limitations of the --syscall flag with enable-event command
[lttng-tools.git] / src / bin / lttng-sessiond / jul.c
CommitLineData
0475c50c
DG
1/*
2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _GNU_SOURCE
19#include <assert.h>
f20baf8e 20#include <urcu/uatomic.h>
0475c50c
DG
21
22#include <common/common.h>
f20baf8e 23#include <common/sessiond-comm/jul.h>
0475c50c
DG
24
25#include "jul.h"
f20baf8e 26#include "ust-app.h"
0475c50c
DG
27#include "utils.h"
28
4a4ab2c3
DG
29/*
30 * Match function for the events hash table lookup by name.
31 */
32static int ht_match_event_by_name(struct cds_lfht_node *node,
33 const void *_key)
34{
35 struct jul_event *event;
36 const struct jul_ht_key *key;
37
38 assert(node);
39 assert(_key);
40
41 event = caa_container_of(node, struct jul_event, node.node);
42 key = _key;
43
44 /* Match 1 elements of the key: name. */
45
46 /* Event name */
47 if (strncmp(event->name, key->name, sizeof(event->name)) != 0) {
48 goto no_match;
49 }
50 /* Match. */
51 return 1;
52
53no_match:
54 return 0;
55}
56
57/*
58 * Match function for the events hash table lookup by name and loglevel.
59 */
60static int ht_match_event(struct cds_lfht_node *node,
61 const void *_key)
62{
63 struct jul_event *event;
64 const struct jul_ht_key *key;
65
66 assert(node);
67 assert(_key);
68
69 event = caa_container_of(node, struct jul_event, node.node);
70 key = _key;
71
72 /* Match 2 elements of the key: name and loglevel. */
73
74 /* Event name */
75 if (strncmp(event->name, key->name, sizeof(event->name)) != 0) {
76 goto no_match;
77 }
78
79 if (event->loglevel != key->loglevel) {
80 if (event->loglevel_type == LTTNG_EVENT_LOGLEVEL_ALL &&
81 key->loglevel == 0 && event->loglevel == -1) {
82 goto match;
83 }
84 goto no_match;
85 }
86match:
87 return 1;
88
89no_match:
90 return 0;
91}
92
93/*
94 * Add unique JUL event based on the event name and loglevel.
95 */
96static void add_unique_jul_event(struct lttng_ht *ht, struct jul_event *event)
97{
98 struct cds_lfht_node *node_ptr;
99 struct jul_ht_key key;
100
101 assert(ht);
102 assert(ht->ht);
103 assert(event);
104
105 key.name = event->name;
106 key.loglevel = event->loglevel;
107
108 node_ptr = cds_lfht_add_unique(ht->ht,
109 ht->hash_fct(event->node.key, lttng_ht_seed),
110 ht_match_event, &key, &event->node.node);
111 assert(node_ptr == &event->node.node);
112}
113
0475c50c 114/*
428de77a 115 * URCU delayed JUL event reclaim.
0475c50c
DG
116 */
117static void destroy_event_jul_rcu(struct rcu_head *head)
118{
119 struct lttng_ht_node_str *node =
120 caa_container_of(head, struct lttng_ht_node_str, head);
121 struct jul_event *event =
122 caa_container_of(node, struct jul_event, node);
123
124 free(event);
125}
126
f20baf8e 127/*
428de77a 128 * URCU delayed JUL app reclaim.
f20baf8e
DG
129 */
130static void destroy_app_jul_rcu(struct rcu_head *head)
131{
132 struct lttng_ht_node_ulong *node =
133 caa_container_of(head, struct lttng_ht_node_ulong, head);
134 struct jul_app *app =
135 caa_container_of(node, struct jul_app, node);
136
137 free(app);
138}
139
140/*
428de77a
MD
141 * Communication with Java agent. Send the message header to the given
142 * socket in big endian.
f20baf8e
DG
143 *
144 * Return 0 on success or else a negative errno message of sendmsg() op.
145 */
146static int send_header(struct lttcomm_sock *sock, uint64_t data_size,
147 uint32_t cmd, uint32_t cmd_version)
148{
149 int ret;
150 ssize_t size;
151 struct lttcomm_jul_hdr msg;
152
153 assert(sock);
154
53efb85a 155 memset(&msg, 0, sizeof(msg));
f20baf8e
DG
156 msg.data_size = htobe64(data_size);
157 msg.cmd = htobe32(cmd);
158 msg.cmd_version = htobe32(cmd_version);
159
160 size = sock->ops->sendmsg(sock, &msg, sizeof(msg), 0);
161 if (size < sizeof(msg)) {
162 ret = -errno;
163 goto error;
164 }
165 ret = 0;
166
167error:
168 return ret;
169}
170
171/*
172 * Communication call with the Java agent. Send the payload to the given
173 * socket. The header MUST be sent prior to this call.
174 *
175 * Return 0 on success or else a negative errno value of sendmsg() op.
176 */
177static int send_payload(struct lttcomm_sock *sock, void *data,
178 size_t size)
179{
180 int ret;
181 ssize_t len;
182
183 assert(sock);
184 assert(data);
185
186 len = sock->ops->sendmsg(sock, data, size, 0);
187 if (len < size) {
188 ret = -errno;
189 goto error;
190 }
191 ret = 0;
192
193error:
194 return ret;
195}
196
197/*
198 * Communication call with the Java agent. Receive reply from the agent using
199 * the given socket.
200 *
201 * Return 0 on success or else a negative errno value from recvmsg() op.
202 */
203static int recv_reply(struct lttcomm_sock *sock, void *buf, size_t size)
204{
205 int ret;
206 ssize_t len;
207
208 assert(sock);
209 assert(buf);
210
211 len = sock->ops->recvmsg(sock, buf, size, 0);
212 if (len < size) {
213 ret = -errno;
214 goto error;
215 }
216 ret = 0;
217
218error:
219 return ret;
220}
221
3c6a091f
DG
222
223/*
428de77a 224 * Internal event listing for a given app. Populate events.
3c6a091f
DG
225 *
226 * Return number of element in the list or else a negative LTTNG_ERR* code.
428de77a
MD
227 * On success, the caller is responsible for freeing the memory
228 * allocated for "events".
3c6a091f
DG
229 */
230static ssize_t list_events(struct jul_app *app, struct lttng_event **events)
231{
232 int ret, i, len = 0, offset = 0;
233 uint32_t nb_event;
234 size_t data_size;
235 struct lttng_event *tmp_events = NULL;
236 struct lttcomm_jul_list_reply *reply = NULL;
237 struct lttcomm_jul_list_reply_hdr reply_hdr;
238
239 assert(app);
240 assert(app->sock);
241 assert(events);
242
243 DBG2("JUL listing events for app pid: %d and socket %d", app->pid,
244 app->sock->fd);
245
246 ret = send_header(app->sock, 0, JUL_CMD_LIST, 0);
247 if (ret < 0) {
248 goto error_io;
249 }
250
251 /* Get list header so we know how much we'll receive. */
252 ret = recv_reply(app->sock, &reply_hdr, sizeof(reply_hdr));
253 if (ret < 0) {
254 goto error_io;
255 }
256
257 switch (be32toh(reply_hdr.ret_code)) {
258 case JUL_RET_CODE_SUCCESS:
259 data_size = be32toh(reply_hdr.data_size) + sizeof(*reply);
260 break;
261 default:
262 ERR("Java agent returned an unknown code: %" PRIu32,
263 be32toh(reply_hdr.ret_code));
264 ret = LTTNG_ERR_FATAL;
265 goto error;
266 }
267
268 reply = zmalloc(data_size);
269 if (!reply) {
270 ret = LTTNG_ERR_NOMEM;
271 goto error;
272 }
273
274 /* Get the list with the appropriate data size. */
275 ret = recv_reply(app->sock, reply, data_size);
276 if (ret < 0) {
277 goto error_io;
278 }
279
280 nb_event = be32toh(reply->nb_event);
281 tmp_events = zmalloc(sizeof(*tmp_events) * nb_event);
282 if (!tmp_events) {
283 ret = LTTNG_ERR_NOMEM;
284 goto error;
285 }
286
287 for (i = 0; i < nb_event; i++) {
288 offset += len;
289 strncpy(tmp_events[i].name, reply->payload + offset,
290 sizeof(tmp_events[i].name));
291 tmp_events[i].pid = app->pid;
292 tmp_events[i].enabled = -1;
293 len = strlen(reply->payload + offset) + 1;
294 }
295
296 *events = tmp_events;
297
298 free(reply);
299 return nb_event;
300
301error_io:
302 ret = LTTNG_ERR_UST_LIST_FAIL;
303error:
304 free(reply);
305 free(tmp_events);
306 return -ret;
307
308}
309
f20baf8e 310/*
428de77a 311 * Internal enable JUL event on a JUL application. This function
f20baf8e
DG
312 * communicates with the Java agent to enable a given event (Logger name).
313 *
314 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
315 */
316static int enable_event(struct jul_app *app, struct jul_event *event)
317{
318 int ret;
319 uint64_t data_size;
320 struct lttcomm_jul_enable msg;
321 struct lttcomm_jul_generic_reply reply;
322
323 assert(app);
324 assert(app->sock);
325 assert(event);
326
327 DBG2("JUL enabling event %s for app pid: %d and socket %d", event->name,
328 app->pid, app->sock->fd);
329
330 data_size = sizeof(msg);
331
332 ret = send_header(app->sock, data_size, JUL_CMD_ENABLE, 0);
333 if (ret < 0) {
334 goto error_io;
335 }
336
53efb85a 337 memset(&msg, 0, sizeof(msg));
b2064f54
DG
338 msg.loglevel = event->loglevel;
339 msg.loglevel_type = event->loglevel_type;
f20baf8e
DG
340 strncpy(msg.name, event->name, sizeof(msg.name));
341 ret = send_payload(app->sock, &msg, sizeof(msg));
342 if (ret < 0) {
343 goto error_io;
344 }
345
346 ret = recv_reply(app->sock, &reply, sizeof(reply));
347 if (ret < 0) {
348 goto error_io;
349 }
350
351 switch (be32toh(reply.ret_code)) {
352 case JUL_RET_CODE_SUCCESS:
353 break;
354 case JUL_RET_CODE_UNKNOWN_NAME:
355 ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
356 goto error;
357 default:
358 ERR("Java agent returned an unknown code: %" PRIu32,
359 be32toh(reply.ret_code));
360 ret = LTTNG_ERR_FATAL;
361 goto error;
362 }
363
364 return LTTNG_OK;
365
366error_io:
367 ret = LTTNG_ERR_UST_ENABLE_FAIL;
368error:
369 return ret;
370}
371
372/*
373 * Internal disable JUL event call on a JUL application. This function
374 * communicates with the Java agent to disable a given event (Logger name).
375 *
376 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
377 */
378static int disable_event(struct jul_app *app, struct jul_event *event)
379{
380 int ret;
381 uint64_t data_size;
382 struct lttcomm_jul_disable msg;
383 struct lttcomm_jul_generic_reply reply;
384
385 assert(app);
386 assert(app->sock);
387 assert(event);
388
389 DBG2("JUL disabling event %s for app pid: %d and socket %d", event->name,
390 app->pid, app->sock->fd);
391
392 data_size = sizeof(msg);
393
394 ret = send_header(app->sock, data_size, JUL_CMD_DISABLE, 0);
395 if (ret < 0) {
396 goto error_io;
397 }
398
53efb85a 399 memset(&msg, 0, sizeof(msg));
f20baf8e
DG
400 strncpy(msg.name, event->name, sizeof(msg.name));
401 ret = send_payload(app->sock, &msg, sizeof(msg));
402 if (ret < 0) {
403 goto error_io;
404 }
405
406 ret = recv_reply(app->sock, &reply, sizeof(reply));
407 if (ret < 0) {
408 goto error_io;
409 }
410
411 switch (be32toh(reply.ret_code)) {
412 case JUL_RET_CODE_SUCCESS:
413 break;
414 case JUL_RET_CODE_UNKNOWN_NAME:
415 ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
416 goto error;
417 default:
418 ERR("Java agent returned an unknown code: %" PRIu32,
419 be32toh(reply.ret_code));
420 ret = LTTNG_ERR_FATAL;
421 goto error;
422 }
423
424 return LTTNG_OK;
425
426error_io:
427 ret = LTTNG_ERR_UST_DISABLE_FAIL;
428error:
429 return ret;
430}
431
1b500e7a
DG
432/*
433 * Send back the registration DONE command to a given JUL application.
434 *
435 * Return 0 on success or else a negative value.
436 */
437int jul_send_registration_done(struct jul_app *app)
438{
439 assert(app);
440 assert(app->sock);
441
442 DBG("JUL sending registration done to app socket %d", app->sock->fd);
443
444 return send_header(app->sock, 0, JUL_CMD_REG_DONE, 0);
445}
446
f20baf8e
DG
447/*
448 * Enable JUL event on every JUL applications registered with the session
449 * daemon.
450 *
451 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
452 */
453int jul_enable_event(struct jul_event *event)
454{
455 int ret;
456 struct jul_app *app;
457 struct lttng_ht_iter iter;
458
459 assert(event);
460
461 rcu_read_lock();
462
463 cds_lfht_for_each_entry(jul_apps_ht_by_sock->ht, &iter.iter, app,
464 node.node) {
465 /* Enable event on JUL application through TCP socket. */
466 ret = enable_event(app, event);
467 if (ret != LTTNG_OK) {
468 goto error;
469 }
f20baf8e
DG
470 }
471
3c6a091f 472 event->enabled = 1;
f20baf8e
DG
473 ret = LTTNG_OK;
474
475error:
476 rcu_read_unlock();
477 return ret;
478}
479
480/*
481 * Disable JUL event on every JUL applications registered with the session
482 * daemon.
483 *
484 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
485 */
486int jul_disable_event(struct jul_event *event)
487{
488 int ret;
489 struct jul_app *app;
490 struct lttng_ht_iter iter;
491
492 assert(event);
493
494 rcu_read_lock();
495
496 cds_lfht_for_each_entry(jul_apps_ht_by_sock->ht, &iter.iter, app,
497 node.node) {
498 /* Enable event on JUL application through TCP socket. */
499 ret = disable_event(app, event);
500 if (ret != LTTNG_OK) {
501 goto error;
502 }
f20baf8e
DG
503 }
504
3c6a091f 505 event->enabled = 0;
f20baf8e
DG
506 ret = LTTNG_OK;
507
508error:
509 rcu_read_unlock();
510 return ret;
511}
512
513/*
514 * Ask every java agent for the list of possible event (logger name). Events is
515 * allocated with the events of every JUL application.
516 *
517 * Return the number of events or else a negative value.
518 */
519int jul_list_events(struct lttng_event **events)
520{
521 int ret;
522 size_t nbmem, count = 0;
523 struct jul_app *app;
aae6255e 524 struct lttng_event *tmp_events = NULL;
f20baf8e
DG
525 struct lttng_ht_iter iter;
526
527 assert(events);
528
529 nbmem = UST_APP_EVENT_LIST_SIZE;
530 tmp_events = zmalloc(nbmem * sizeof(*tmp_events));
531 if (!tmp_events) {
532 PERROR("zmalloc jul list events");
533 ret = -ENOMEM;
534 goto error;
535 }
536
537 rcu_read_lock();
538 cds_lfht_for_each_entry(jul_apps_ht_by_sock->ht, &iter.iter, app,
539 node.node) {
540 ssize_t nb_ev;
541 struct lttng_event *jul_events;
542
543 nb_ev = list_events(app, &jul_events);
544 if (nb_ev < 0) {
545 ret = nb_ev;
428de77a 546 goto error_unlock;
f20baf8e
DG
547 }
548
53efb85a 549 if (count + nb_ev > nbmem) {
f20baf8e 550 /* In case the realloc fails, we free the memory */
53efb85a
MD
551 struct lttng_event *new_tmp_events;
552 size_t new_nbmem;
553
554 new_nbmem = max_t(size_t, count + nb_ev, nbmem << 1);
555 DBG2("Reallocating JUL event list from %zu to %zu entries",
556 nbmem, new_nbmem);
557 new_tmp_events = realloc(tmp_events,
558 new_nbmem * sizeof(*new_tmp_events));
559 if (!new_tmp_events) {
f20baf8e 560 PERROR("realloc JUL events");
f20baf8e 561 ret = -ENOMEM;
c36441a9 562 free(jul_events);
428de77a 563 goto error_unlock;
f20baf8e 564 }
53efb85a
MD
565 /* Zero the new memory */
566 memset(new_tmp_events + nbmem, 0,
567 (new_nbmem - nbmem) * sizeof(*new_tmp_events));
568 nbmem = new_nbmem;
569 tmp_events = new_tmp_events;
f20baf8e 570 }
53efb85a
MD
571 memcpy(tmp_events + count, jul_events,
572 nb_ev * sizeof(*tmp_events));
f20baf8e
DG
573 free(jul_events);
574 count += nb_ev;
575 }
576 rcu_read_unlock();
577
578 ret = count;
579 *events = tmp_events;
aae6255e 580 return ret;
f20baf8e 581
428de77a
MD
582error_unlock:
583 rcu_read_unlock();
f20baf8e 584error:
aae6255e 585 free(tmp_events);
f20baf8e
DG
586 return ret;
587}
588
589/*
590 * Create a JUL app object using the given PID.
591 *
592 * Return newly allocated object or else NULL on error.
593 */
594struct jul_app *jul_create_app(pid_t pid, struct lttcomm_sock *sock)
595{
596 struct jul_app *app;
597
598 assert(sock);
599
600 app = zmalloc(sizeof(*app));
601 if (!app) {
602 PERROR("zmalloc JUL create");
603 goto error;
604 }
605
606 app->pid = pid;
607 app->sock = sock;
f20baf8e
DG
608 lttng_ht_node_init_ulong(&app->node, (unsigned long) app->sock->fd);
609
610error:
611 return app;
612}
613
614/*
615 * Lookup JUL app by socket in the global hash table.
616 *
617 * RCU read side lock MUST be acquired.
618 *
619 * Return object if found else NULL.
620 */
621struct jul_app *jul_find_app_by_sock(int sock)
622{
623 struct lttng_ht_node_ulong *node;
624 struct lttng_ht_iter iter;
625 struct jul_app *app;
626
627 assert(sock >= 0);
628
629 lttng_ht_lookup(jul_apps_ht_by_sock, (void *)((unsigned long) sock), &iter);
630 node = lttng_ht_iter_get_node_ulong(&iter);
631 if (node == NULL) {
632 goto error;
633 }
634 app = caa_container_of(node, struct jul_app, node);
635
636 DBG3("JUL app pid %d found by sock %d.", app->pid, sock);
637 return app;
638
639error:
640 DBG3("JUL app NOT found by sock %d.", sock);
641 return NULL;
642}
643
644/*
645 * Add JUL application object to a given hash table.
646 */
647void jul_add_app(struct jul_app *app)
648{
649 assert(app);
650
651 DBG3("JUL adding app sock: %d and pid: %d to ht", app->sock->fd, app->pid);
652
653 rcu_read_lock();
654 lttng_ht_add_unique_ulong(jul_apps_ht_by_sock, &app->node);
655 rcu_read_unlock();
656}
657
f20baf8e
DG
658/*
659 * Delete JUL application from the global hash table.
660 */
661void jul_delete_app(struct jul_app *app)
662{
663 int ret;
664 struct lttng_ht_iter iter;
665
666 assert(app);
667
668 DBG3("JUL deleting app pid: %d and sock: %d", app->pid, app->sock->fd);
669
670 iter.iter.node = &app->node.node;
671 rcu_read_lock();
672 ret = lttng_ht_del(jul_apps_ht_by_sock, &iter);
673 rcu_read_unlock();
674 assert(!ret);
675}
676
677/*
678 * Destroy a JUL application object by detaching it from its corresponding UST
428de77a
MD
679 * app if one is connected by closing the socket. Finally, perform a
680 * delayed memory reclaim.
f20baf8e
DG
681 */
682void jul_destroy_app(struct jul_app *app)
683{
684 assert(app);
685
686 if (app->sock) {
687 app->sock->ops->close(app->sock);
688 lttcomm_destroy_sock(app->sock);
689 }
690
691 call_rcu(&app->node.head, destroy_app_jul_rcu);
692}
693
0475c50c
DG
694/*
695 * Initialize an already allocated JUL domain object.
696 *
697 * Return 0 on success or else a negative errno value.
698 */
699int jul_init_domain(struct jul_domain *dom)
700{
701 int ret;
702
703 assert(dom);
704
705 dom->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
706 if (!dom->events) {
707 ret = -ENOMEM;
708 goto error;
709 }
710
711 return 0;
712
713error:
714 return ret;
715}
716
717/*
718 * Create a newly allocated JUL event data structure. If name is valid, it's
719 * copied into the created event.
720 *
721 * Return a new object else NULL on error.
722 */
723struct jul_event *jul_create_event(const char *name)
724{
725 struct jul_event *event;
726
727 DBG3("JUL create new event with name %s", name);
728
729 event = zmalloc(sizeof(*event));
730 if (!event) {
731 goto error;
732 }
733
734 if (name) {
735 strncpy(event->name, name, sizeof(event->name));
736 event->name[sizeof(event->name) - 1] = '\0';
f20baf8e 737 lttng_ht_node_init_str(&event->node, event->name);
0475c50c
DG
738 }
739
740error:
741 return event;
742}
743
744/*
745 * Unique add of a JUL event to a given domain.
746 */
747void jul_add_event(struct jul_event *event, struct jul_domain *dom)
748{
749 assert(event);
750 assert(dom);
751 assert(dom->events);
752
753 DBG3("JUL adding event %s to domain", event->name);
754
f20baf8e 755 rcu_read_lock();
4a4ab2c3 756 add_unique_jul_event(dom->events, event);
f20baf8e 757 rcu_read_unlock();
3c6a091f 758 dom->being_used = 1;
0475c50c
DG
759}
760
761/*
4a4ab2c3
DG
762 * Find a JUL event in the given domain using name and loglevel.
763 *
764 * RCU read side lock MUST be acquired.
765 *
766 * Return object if found else NULL.
767 */
768struct jul_event *jul_find_event_by_name(const char *name,
769 struct jul_domain *dom)
770{
771 struct lttng_ht_node_str *node;
772 struct lttng_ht_iter iter;
773 struct lttng_ht *ht;
774 struct jul_ht_key key;
775
776 assert(name);
777 assert(dom);
778 assert(dom->events);
779
780 ht = dom->events;
781 key.name = name;
782
783 cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed),
784 ht_match_event_by_name, &key, &iter.iter);
785 node = lttng_ht_iter_get_node_str(&iter);
786 if (node == NULL) {
787 goto error;
788 }
789
790 DBG3("JUL event found %s by name.", name);
791 return caa_container_of(node, struct jul_event, node);
792
793error:
794 DBG3("JUL NOT found by name %s.", name);
795 return NULL;
796}
797
798/*
799 * Find a JUL event in the given domain using name and loglevel.
0475c50c
DG
800 *
801 * RCU read side lock MUST be acquired.
802 *
803 * Return object if found else NULL.
804 */
4a4ab2c3
DG
805struct jul_event *jul_find_event(const char *name,
806 enum lttng_loglevel_jul loglevel, struct jul_domain *dom)
0475c50c
DG
807{
808 struct lttng_ht_node_str *node;
809 struct lttng_ht_iter iter;
4a4ab2c3
DG
810 struct lttng_ht *ht;
811 struct jul_ht_key key;
0475c50c
DG
812
813 assert(name);
814 assert(dom);
815 assert(dom->events);
816
4a4ab2c3
DG
817 ht = dom->events;
818 key.name = name;
819 key.loglevel = loglevel;
820
821 cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed),
822 ht_match_event, &key, &iter.iter);
0475c50c
DG
823 node = lttng_ht_iter_get_node_str(&iter);
824 if (node == NULL) {
825 goto error;
826 }
827
4a4ab2c3 828 DBG3("JUL event found %s.", name);
0475c50c
DG
829 return caa_container_of(node, struct jul_event, node);
830
831error:
4a4ab2c3 832 DBG3("JUL NOT found %s.", name);
0475c50c
DG
833 return NULL;
834}
835
0475c50c 836/*
428de77a
MD
837 * Free given JUL event. This event must not be globally visible at this
838 * point (only expected to be used on failure just after event
839 * creation). After this call, the pointer is not usable anymore.
0475c50c
DG
840 */
841void jul_destroy_event(struct jul_event *event)
842{
843 assert(event);
844
845 free(event);
846}
847
848/*
849 * Destroy a JUL domain completely. Note that the given pointer is NOT freed
428de77a 850 * thus a reference to static or stack data can be passed to this function.
0475c50c
DG
851 */
852void jul_destroy_domain(struct jul_domain *dom)
853{
854 struct lttng_ht_node_str *node;
855 struct lttng_ht_iter iter;
856
857 assert(dom);
858
859 DBG3("JUL destroy domain");
860
861 /*
862 * Just ignore if no events hash table exists. This is possible if for
863 * instance a JUL domain object was allocated but not initialized.
864 */
865 if (!dom->events) {
866 return;
867 }
868
869 rcu_read_lock();
870 cds_lfht_for_each_entry(dom->events->ht, &iter.iter, node, node) {
871 int ret;
872
873 ret = lttng_ht_del(dom->events, &iter);
874 assert(!ret);
875 call_rcu(&node->head, destroy_event_jul_rcu);
876 }
877 rcu_read_unlock();
878
f20baf8e
DG
879 lttng_ht_destroy(dom->events);
880}
881
882/*
883 * Initialize JUL subsystem.
884 */
885int jul_init(void)
886{
887 jul_apps_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
888 if (!jul_apps_ht_by_sock) {
889 return -1;
890 }
891
892 return 0;
893}
894
895/*
896 * Update a JUL application (given socket) using the given domain.
897 *
898 * Note that this function is most likely to be used with a tracing session
899 * thus the caller should make sure to hold the appropriate lock(s).
900 */
901void jul_update(struct jul_domain *domain, int sock)
902{
903 int ret;
904 struct jul_app *app;
905 struct jul_event *event;
906 struct lttng_ht_iter iter;
907
908 assert(domain);
909 assert(sock >= 0);
910
911 DBG("JUL updating app socket %d", sock);
912
913 rcu_read_lock();
914 cds_lfht_for_each_entry(domain->events->ht, &iter.iter, event, node.node) {
915 /* Skip event if disabled. */
916 if (!event->enabled) {
917 continue;
918 }
919
920 app = jul_find_app_by_sock(sock);
921 /*
922 * We are in the registration path thus if the application is gone,
923 * there is a serious code flow error.
924 */
925 assert(app);
926
927 ret = enable_event(app, event);
928 if (ret != LTTNG_OK) {
929 DBG2("JUL update unable to enable event %s on app pid: %d sock %d",
930 event->name, app->pid, app->sock->fd);
931 /* Let's try the others here and don't assume the app is dead. */
932 continue;
933 }
934 }
935 rcu_read_unlock();
0475c50c 936}
This page took 0.061401 seconds and 4 git commands to generate.