2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
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.
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
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.
20 #include <urcu/uatomic.h>
22 #include <common/common.h>
23 #include <common/sessiond-comm/jul.h>
30 * Match function for the events hash table lookup by name.
32 static int ht_match_event_by_name(struct cds_lfht_node
*node
,
35 struct jul_event
*event
;
36 const struct jul_ht_key
*key
;
41 event
= caa_container_of(node
, struct jul_event
, node
.node
);
44 /* Match 1 elements of the key: name. */
47 if (strncmp(event
->name
, key
->name
, sizeof(event
->name
)) != 0) {
58 * Match function for the events hash table lookup by name and loglevel.
60 static int ht_match_event(struct cds_lfht_node
*node
,
63 struct jul_event
*event
;
64 const struct jul_ht_key
*key
;
69 event
= caa_container_of(node
, struct jul_event
, node
.node
);
72 /* Match 2 elements of the key: name and loglevel. */
75 if (strncmp(event
->name
, key
->name
, sizeof(event
->name
)) != 0) {
79 if (event
->loglevel
!= key
->loglevel
) {
80 if (event
->loglevel_type
== LTTNG_EVENT_LOGLEVEL_ALL
&&
81 key
->loglevel
== 0 && event
->loglevel
== -1) {
94 * Add unique JUL event based on the event name and loglevel.
96 static void add_unique_jul_event(struct lttng_ht
*ht
, struct jul_event
*event
)
98 struct cds_lfht_node
*node_ptr
;
99 struct jul_ht_key key
;
105 key
.name
= event
->name
;
106 key
.loglevel
= event
->loglevel
;
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
);
115 * URCU delayed JUL event reclaim.
117 static void destroy_event_jul_rcu(struct rcu_head
*head
)
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
);
128 * URCU delayed JUL app reclaim.
130 static void destroy_app_jul_rcu(struct rcu_head
*head
)
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
);
141 * Communication with Java agent. Send the message header to the given
142 * socket in big endian.
144 * Return 0 on success or else a negative errno message of sendmsg() op.
146 static int send_header(struct lttcomm_sock
*sock
, uint64_t data_size
,
147 uint32_t cmd
, uint32_t cmd_version
)
151 struct lttcomm_jul_hdr msg
;
155 memset(&msg
, 0, sizeof(msg
));
156 msg
.data_size
= htobe64(data_size
);
157 msg
.cmd
= htobe32(cmd
);
158 msg
.cmd_version
= htobe32(cmd_version
);
160 size
= sock
->ops
->sendmsg(sock
, &msg
, sizeof(msg
), 0);
161 if (size
< sizeof(msg
)) {
172 * Communication call with the Java agent. Send the payload to the given
173 * socket. The header MUST be sent prior to this call.
175 * Return 0 on success or else a negative errno value of sendmsg() op.
177 static int send_payload(struct lttcomm_sock
*sock
, void *data
,
186 len
= sock
->ops
->sendmsg(sock
, data
, size
, 0);
198 * Communication call with the Java agent. Receive reply from the agent using
201 * Return 0 on success or else a negative errno value from recvmsg() op.
203 static int recv_reply(struct lttcomm_sock
*sock
, void *buf
, size_t size
)
211 len
= sock
->ops
->recvmsg(sock
, buf
, size
, 0);
224 * Internal event listing for a given app. Populate events.
226 * Return number of element in the list or else a negative LTTNG_ERR* code.
227 * On success, the caller is responsible for freeing the memory
228 * allocated for "events".
230 static ssize_t
list_events(struct jul_app
*app
, struct lttng_event
**events
)
232 int ret
, i
, len
= 0, offset
= 0;
235 struct lttng_event
*tmp_events
= NULL
;
236 struct lttcomm_jul_list_reply
*reply
= NULL
;
237 struct lttcomm_jul_list_reply_hdr reply_hdr
;
243 DBG2("JUL listing events for app pid: %d and socket %d", app
->pid
,
246 ret
= send_header(app
->sock
, 0, JUL_CMD_LIST
, 0);
251 /* Get list header so we know how much we'll receive. */
252 ret
= recv_reply(app
->sock
, &reply_hdr
, sizeof(reply_hdr
));
257 switch (be32toh(reply_hdr
.ret_code
)) {
258 case JUL_RET_CODE_SUCCESS
:
259 data_size
= be32toh(reply_hdr
.data_size
) + sizeof(*reply
);
262 ERR("Java agent returned an unknown code: %" PRIu32
,
263 be32toh(reply_hdr
.ret_code
));
264 ret
= LTTNG_ERR_FATAL
;
268 reply
= zmalloc(data_size
);
270 ret
= LTTNG_ERR_NOMEM
;
274 /* Get the list with the appropriate data size. */
275 ret
= recv_reply(app
->sock
, reply
, data_size
);
280 nb_event
= be32toh(reply
->nb_event
);
281 tmp_events
= zmalloc(sizeof(*tmp_events
) * nb_event
);
283 ret
= LTTNG_ERR_NOMEM
;
287 for (i
= 0; i
< nb_event
; i
++) {
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;
296 *events
= tmp_events
;
302 ret
= LTTNG_ERR_UST_LIST_FAIL
;
311 * Internal enable JUL event on a JUL application. This function
312 * communicates with the Java agent to enable a given event (Logger name).
314 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
316 static int enable_event(struct jul_app
*app
, struct jul_event
*event
)
320 struct lttcomm_jul_enable msg
;
321 struct lttcomm_jul_generic_reply reply
;
327 DBG2("JUL enabling event %s for app pid: %d and socket %d", event
->name
,
328 app
->pid
, app
->sock
->fd
);
330 data_size
= sizeof(msg
);
332 ret
= send_header(app
->sock
, data_size
, JUL_CMD_ENABLE
, 0);
337 memset(&msg
, 0, sizeof(msg
));
338 msg
.loglevel
= event
->loglevel
;
339 msg
.loglevel_type
= event
->loglevel_type
;
340 strncpy(msg
.name
, event
->name
, sizeof(msg
.name
));
341 ret
= send_payload(app
->sock
, &msg
, sizeof(msg
));
346 ret
= recv_reply(app
->sock
, &reply
, sizeof(reply
));
351 switch (be32toh(reply
.ret_code
)) {
352 case JUL_RET_CODE_SUCCESS
:
354 case JUL_RET_CODE_UNKNOWN_NAME
:
355 ret
= LTTNG_ERR_UST_EVENT_NOT_FOUND
;
358 ERR("Java agent returned an unknown code: %" PRIu32
,
359 be32toh(reply
.ret_code
));
360 ret
= LTTNG_ERR_FATAL
;
367 ret
= LTTNG_ERR_UST_ENABLE_FAIL
;
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).
376 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
378 static int disable_event(struct jul_app
*app
, struct jul_event
*event
)
382 struct lttcomm_jul_disable msg
;
383 struct lttcomm_jul_generic_reply reply
;
389 DBG2("JUL disabling event %s for app pid: %d and socket %d", event
->name
,
390 app
->pid
, app
->sock
->fd
);
392 data_size
= sizeof(msg
);
394 ret
= send_header(app
->sock
, data_size
, JUL_CMD_DISABLE
, 0);
399 memset(&msg
, 0, sizeof(msg
));
400 strncpy(msg
.name
, event
->name
, sizeof(msg
.name
));
401 ret
= send_payload(app
->sock
, &msg
, sizeof(msg
));
406 ret
= recv_reply(app
->sock
, &reply
, sizeof(reply
));
411 switch (be32toh(reply
.ret_code
)) {
412 case JUL_RET_CODE_SUCCESS
:
414 case JUL_RET_CODE_UNKNOWN_NAME
:
415 ret
= LTTNG_ERR_UST_EVENT_NOT_FOUND
;
418 ERR("Java agent returned an unknown code: %" PRIu32
,
419 be32toh(reply
.ret_code
));
420 ret
= LTTNG_ERR_FATAL
;
427 ret
= LTTNG_ERR_UST_DISABLE_FAIL
;
433 * Send back the registration DONE command to a given JUL application.
435 * Return 0 on success or else a negative value.
437 int jul_send_registration_done(struct jul_app
*app
)
442 DBG("JUL sending registration done to app socket %d", app
->sock
->fd
);
444 return send_header(app
->sock
, 0, JUL_CMD_REG_DONE
, 0);
448 * Enable JUL event on every JUL applications registered with the session
451 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
453 int jul_enable_event(struct jul_event
*event
)
457 struct lttng_ht_iter iter
;
463 cds_lfht_for_each_entry(jul_apps_ht_by_sock
->ht
, &iter
.iter
, app
,
465 /* Enable event on JUL application through TCP socket. */
466 ret
= enable_event(app
, event
);
467 if (ret
!= LTTNG_OK
) {
481 * Disable JUL event on every JUL applications registered with the session
484 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
486 int jul_disable_event(struct jul_event
*event
)
490 struct lttng_ht_iter iter
;
496 cds_lfht_for_each_entry(jul_apps_ht_by_sock
->ht
, &iter
.iter
, app
,
498 /* Enable event on JUL application through TCP socket. */
499 ret
= disable_event(app
, event
);
500 if (ret
!= LTTNG_OK
) {
514 * Ask every java agent for the list of possible event (logger name). Events is
515 * allocated with the events of every JUL application.
517 * Return the number of events or else a negative value.
519 int jul_list_events(struct lttng_event
**events
)
522 size_t nbmem
, count
= 0;
524 struct lttng_event
*tmp_events
= NULL
;
525 struct lttng_ht_iter iter
;
529 nbmem
= UST_APP_EVENT_LIST_SIZE
;
530 tmp_events
= zmalloc(nbmem
* sizeof(*tmp_events
));
532 PERROR("zmalloc jul list events");
538 cds_lfht_for_each_entry(jul_apps_ht_by_sock
->ht
, &iter
.iter
, app
,
541 struct lttng_event
*jul_events
;
543 nb_ev
= list_events(app
, &jul_events
);
549 if (count
+ nb_ev
> nbmem
) {
550 /* In case the realloc fails, we free the memory */
551 struct lttng_event
*new_tmp_events
;
554 new_nbmem
= max_t(size_t, count
+ nb_ev
, nbmem
<< 1);
555 DBG2("Reallocating JUL event list from %zu to %zu entries",
557 new_tmp_events
= realloc(tmp_events
,
558 new_nbmem
* sizeof(*new_tmp_events
));
559 if (!new_tmp_events
) {
560 PERROR("realloc JUL events");
565 /* Zero the new memory */
566 memset(new_tmp_events
+ nbmem
, 0,
567 (new_nbmem
- nbmem
) * sizeof(*new_tmp_events
));
569 tmp_events
= new_tmp_events
;
571 memcpy(tmp_events
+ count
, jul_events
,
572 nb_ev
* sizeof(*tmp_events
));
579 *events
= tmp_events
;
590 * Create a JUL app object using the given PID.
592 * Return newly allocated object or else NULL on error.
594 struct jul_app
*jul_create_app(pid_t pid
, struct lttcomm_sock
*sock
)
600 app
= zmalloc(sizeof(*app
));
602 PERROR("zmalloc JUL create");
608 lttng_ht_node_init_ulong(&app
->node
, (unsigned long) app
->sock
->fd
);
615 * Lookup JUL app by socket in the global hash table.
617 * RCU read side lock MUST be acquired.
619 * Return object if found else NULL.
621 struct jul_app
*jul_find_app_by_sock(int sock
)
623 struct lttng_ht_node_ulong
*node
;
624 struct lttng_ht_iter iter
;
629 lttng_ht_lookup(jul_apps_ht_by_sock
, (void *)((unsigned long) sock
), &iter
);
630 node
= lttng_ht_iter_get_node_ulong(&iter
);
634 app
= caa_container_of(node
, struct jul_app
, node
);
636 DBG3("JUL app pid %d found by sock %d.", app
->pid
, sock
);
640 DBG3("JUL app NOT found by sock %d.", sock
);
645 * Add JUL application object to a given hash table.
647 void jul_add_app(struct jul_app
*app
)
651 DBG3("JUL adding app sock: %d and pid: %d to ht", app
->sock
->fd
, app
->pid
);
654 lttng_ht_add_unique_ulong(jul_apps_ht_by_sock
, &app
->node
);
659 * Delete JUL application from the global hash table.
661 void jul_delete_app(struct jul_app
*app
)
664 struct lttng_ht_iter iter
;
668 DBG3("JUL deleting app pid: %d and sock: %d", app
->pid
, app
->sock
->fd
);
670 iter
.iter
.node
= &app
->node
.node
;
672 ret
= lttng_ht_del(jul_apps_ht_by_sock
, &iter
);
678 * Destroy a JUL application object by detaching it from its corresponding UST
679 * app if one is connected by closing the socket. Finally, perform a
680 * delayed memory reclaim.
682 void jul_destroy_app(struct jul_app
*app
)
687 app
->sock
->ops
->close(app
->sock
);
688 lttcomm_destroy_sock(app
->sock
);
691 call_rcu(&app
->node
.head
, destroy_app_jul_rcu
);
695 * Initialize an already allocated JUL domain object.
697 * Return 0 on success or else a negative errno value.
699 int jul_init_domain(struct jul_domain
*dom
)
705 dom
->events
= lttng_ht_new(0, LTTNG_HT_TYPE_STRING
);
718 * Create a newly allocated JUL event data structure. If name is valid, it's
719 * copied into the created event.
721 * Return a new object else NULL on error.
723 struct jul_event
*jul_create_event(const char *name
)
725 struct jul_event
*event
;
727 DBG3("JUL create new event with name %s", name
);
729 event
= zmalloc(sizeof(*event
));
735 strncpy(event
->name
, name
, sizeof(event
->name
));
736 event
->name
[sizeof(event
->name
) - 1] = '\0';
737 lttng_ht_node_init_str(&event
->node
, event
->name
);
745 * Unique add of a JUL event to a given domain.
747 void jul_add_event(struct jul_event
*event
, struct jul_domain
*dom
)
753 DBG3("JUL adding event %s to domain", event
->name
);
756 add_unique_jul_event(dom
->events
, event
);
762 * Find a JUL event in the given domain using name and loglevel.
764 * RCU read side lock MUST be acquired.
766 * Return object if found else NULL.
768 struct jul_event
*jul_find_event_by_name(const char *name
,
769 struct jul_domain
*dom
)
771 struct lttng_ht_node_str
*node
;
772 struct lttng_ht_iter iter
;
774 struct jul_ht_key key
;
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
);
790 DBG3("JUL event found %s by name.", name
);
791 return caa_container_of(node
, struct jul_event
, node
);
794 DBG3("JUL NOT found by name %s.", name
);
799 * Find a JUL event in the given domain using name and loglevel.
801 * RCU read side lock MUST be acquired.
803 * Return object if found else NULL.
805 struct jul_event
*jul_find_event(const char *name
,
806 enum lttng_loglevel_jul loglevel
, struct jul_domain
*dom
)
808 struct lttng_ht_node_str
*node
;
809 struct lttng_ht_iter iter
;
811 struct jul_ht_key key
;
819 key
.loglevel
= loglevel
;
821 cds_lfht_lookup(ht
->ht
, ht
->hash_fct((void *) name
, lttng_ht_seed
),
822 ht_match_event
, &key
, &iter
.iter
);
823 node
= lttng_ht_iter_get_node_str(&iter
);
828 DBG3("JUL event found %s.", name
);
829 return caa_container_of(node
, struct jul_event
, node
);
832 DBG3("JUL NOT found %s.", name
);
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.
841 void jul_destroy_event(struct jul_event
*event
)
849 * Destroy a JUL domain completely. Note that the given pointer is NOT freed
850 * thus a reference to static or stack data can be passed to this function.
852 void jul_destroy_domain(struct jul_domain
*dom
)
854 struct lttng_ht_node_str
*node
;
855 struct lttng_ht_iter iter
;
859 DBG3("JUL destroy domain");
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.
870 cds_lfht_for_each_entry(dom
->events
->ht
, &iter
.iter
, node
, node
) {
873 ret
= lttng_ht_del(dom
->events
, &iter
);
875 call_rcu(&node
->head
, destroy_event_jul_rcu
);
879 lttng_ht_destroy(dom
->events
);
883 * Initialize JUL subsystem.
887 jul_apps_ht_by_sock
= lttng_ht_new(0, LTTNG_HT_TYPE_ULONG
);
888 if (!jul_apps_ht_by_sock
) {
896 * Update a JUL application (given socket) using the given domain.
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).
901 void jul_update(struct jul_domain
*domain
, int sock
)
905 struct jul_event
*event
;
906 struct lttng_ht_iter iter
;
911 DBG("JUL updating app socket %d", sock
);
914 cds_lfht_for_each_entry(domain
->events
->ht
, &iter
.iter
, event
, node
.node
) {
915 /* Skip event if disabled. */
916 if (!event
->enabled
) {
920 app
= jul_find_app_by_sock(sock
);
922 * We are in the registration path thus if the application is gone,
923 * there is a serious code flow error.
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. */