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 * URCU intermediate call to complete destroy a JUL event.
32 static void destroy_event_jul_rcu(struct rcu_head
*head
)
34 struct lttng_ht_node_str
*node
=
35 caa_container_of(head
, struct lttng_ht_node_str
, head
);
36 struct jul_event
*event
=
37 caa_container_of(node
, struct jul_event
, node
);
43 * URCU intermediate call to complete destroy a JUL event.
45 static void destroy_app_jul_rcu(struct rcu_head
*head
)
47 struct lttng_ht_node_ulong
*node
=
48 caa_container_of(head
, struct lttng_ht_node_ulong
, head
);
50 caa_container_of(node
, struct jul_app
, node
);
56 * Communication with Java agent call. Send the message header to the given
57 * socket all in big endian.
59 * Return 0 on success or else a negative errno message of sendmsg() op.
61 static int send_header(struct lttcomm_sock
*sock
, uint64_t data_size
,
62 uint32_t cmd
, uint32_t cmd_version
)
66 struct lttcomm_jul_hdr msg
;
70 msg
.data_size
= htobe64(data_size
);
71 msg
.cmd
= htobe32(cmd
);
72 msg
.cmd_version
= htobe32(cmd_version
);
74 size
= sock
->ops
->sendmsg(sock
, &msg
, sizeof(msg
), 0);
75 if (size
< sizeof(msg
)) {
86 * Communication call with the Java agent. Send the payload to the given
87 * socket. The header MUST be sent prior to this call.
89 * Return 0 on success or else a negative errno value of sendmsg() op.
91 static int send_payload(struct lttcomm_sock
*sock
, void *data
,
100 len
= sock
->ops
->sendmsg(sock
, data
, size
, 0);
112 * Communication call with the Java agent. Receive reply from the agent using
115 * Return 0 on success or else a negative errno value from recvmsg() op.
117 static int recv_reply(struct lttcomm_sock
*sock
, void *buf
, size_t size
)
125 len
= sock
->ops
->recvmsg(sock
, buf
, size
, 0);
137 * Internal enable JUL event call on a JUL application. This function
138 * communicates with the Java agent to enable a given event (Logger name).
140 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
142 static int enable_event(struct jul_app
*app
, struct jul_event
*event
)
146 struct lttcomm_jul_enable msg
;
147 struct lttcomm_jul_generic_reply reply
;
153 DBG2("JUL enabling event %s for app pid: %d and socket %d", event
->name
,
154 app
->pid
, app
->sock
->fd
);
156 data_size
= sizeof(msg
);
158 ret
= send_header(app
->sock
, data_size
, JUL_CMD_ENABLE
, 0);
163 strncpy(msg
.name
, event
->name
, sizeof(msg
.name
));
164 ret
= send_payload(app
->sock
, &msg
, sizeof(msg
));
169 ret
= recv_reply(app
->sock
, &reply
, sizeof(reply
));
174 switch (be32toh(reply
.ret_code
)) {
175 case JUL_RET_CODE_SUCCESS
:
177 case JUL_RET_CODE_UNKNOWN_NAME
:
178 ret
= LTTNG_ERR_UST_EVENT_NOT_FOUND
;
181 ERR("Java agent returned an unknown code: %" PRIu32
,
182 be32toh(reply
.ret_code
));
183 ret
= LTTNG_ERR_FATAL
;
190 ret
= LTTNG_ERR_UST_ENABLE_FAIL
;
196 * Internal disable JUL event call on a JUL application. This function
197 * communicates with the Java agent to disable a given event (Logger name).
199 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
201 static int disable_event(struct jul_app
*app
, struct jul_event
*event
)
205 struct lttcomm_jul_disable msg
;
206 struct lttcomm_jul_generic_reply reply
;
212 DBG2("JUL disabling event %s for app pid: %d and socket %d", event
->name
,
213 app
->pid
, app
->sock
->fd
);
215 data_size
= sizeof(msg
);
217 ret
= send_header(app
->sock
, data_size
, JUL_CMD_DISABLE
, 0);
222 strncpy(msg
.name
, event
->name
, sizeof(msg
.name
));
223 ret
= send_payload(app
->sock
, &msg
, sizeof(msg
));
228 ret
= recv_reply(app
->sock
, &reply
, sizeof(reply
));
233 switch (be32toh(reply
.ret_code
)) {
234 case JUL_RET_CODE_SUCCESS
:
236 case JUL_RET_CODE_UNKNOWN_NAME
:
237 ret
= LTTNG_ERR_UST_EVENT_NOT_FOUND
;
240 ERR("Java agent returned an unknown code: %" PRIu32
,
241 be32toh(reply
.ret_code
));
242 ret
= LTTNG_ERR_FATAL
;
249 ret
= LTTNG_ERR_UST_DISABLE_FAIL
;
255 * Enable JUL event on every JUL applications registered with the session
258 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
260 int jul_enable_event(struct jul_event
*event
)
264 struct lttng_ht_iter iter
;
270 cds_lfht_for_each_entry(jul_apps_ht_by_sock
->ht
, &iter
.iter
, app
,
272 /* Enable event on JUL application through TCP socket. */
273 ret
= enable_event(app
, event
);
274 if (ret
!= LTTNG_OK
) {
288 * Disable JUL event on every JUL applications registered with the session
291 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
293 int jul_disable_event(struct jul_event
*event
)
297 struct lttng_ht_iter iter
;
303 cds_lfht_for_each_entry(jul_apps_ht_by_sock
->ht
, &iter
.iter
, app
,
305 /* Enable event on JUL application through TCP socket. */
306 ret
= disable_event(app
, event
);
307 if (ret
!= LTTNG_OK
) {
321 * Ask every java agent for the list of possible event (logger name). Events is
322 * allocated with the events of every JUL application.
324 * Return the number of events or else a negative value.
326 int jul_list_events(struct lttng_event
**events
)
329 size_t nbmem
, count
= 0;
331 struct lttng_event
*tmp_events
;
332 struct lttng_ht_iter iter
;
336 nbmem
= UST_APP_EVENT_LIST_SIZE
;
337 tmp_events
= zmalloc(nbmem
* sizeof(*tmp_events
));
339 PERROR("zmalloc jul list events");
345 cds_lfht_for_each_entry(jul_apps_ht_by_sock
->ht
, &iter
.iter
, app
,
348 struct lttng_event
*jul_events
;
350 nb_ev
= list_events(app
, &jul_events
);
357 if (count
>= nbmem
) {
358 /* In case the realloc fails, we free the memory */
361 DBG2("Reallocating JUL event list from %zu to %zu entries", nbmem
,
364 ptr
= realloc(tmp_events
, nbmem
* sizeof(*tmp_events
));
366 PERROR("realloc JUL events");
374 memcpy(tmp_events
+ (count
* sizeof(*tmp_events
)), jul_events
,
375 nb_ev
* sizeof(*tmp_events
));
382 *events
= tmp_events
;
389 * Create a JUL app object using the given PID.
391 * Return newly allocated object or else NULL on error.
393 struct jul_app
*jul_create_app(pid_t pid
, struct lttcomm_sock
*sock
)
399 app
= zmalloc(sizeof(*app
));
401 PERROR("zmalloc JUL create");
407 /* Flag it invalid until assignation. */
408 app
->ust_app_sock
= -1;
409 lttng_ht_node_init_ulong(&app
->node
, (unsigned long) app
->sock
->fd
);
416 * Lookup JUL app by socket in the global hash table.
418 * RCU read side lock MUST be acquired.
420 * Return object if found else NULL.
422 struct jul_app
*jul_find_app_by_sock(int sock
)
424 struct lttng_ht_node_ulong
*node
;
425 struct lttng_ht_iter iter
;
430 lttng_ht_lookup(jul_apps_ht_by_sock
, (void *)((unsigned long) sock
), &iter
);
431 node
= lttng_ht_iter_get_node_ulong(&iter
);
435 app
= caa_container_of(node
, struct jul_app
, node
);
437 DBG3("JUL app pid %d found by sock %d.", app
->pid
, sock
);
441 DBG3("JUL app NOT found by sock %d.", sock
);
446 * Add JUL application object to a given hash table.
448 void jul_add_app(struct jul_app
*app
)
452 DBG3("JUL adding app sock: %d and pid: %d to ht", app
->sock
->fd
, app
->pid
);
455 lttng_ht_add_unique_ulong(jul_apps_ht_by_sock
, &app
->node
);
460 * Attach a given JUL application to an UST app object. This is done by copying
461 * the socket fd value into the ust app obj. atomically.
463 void jul_attach_app(struct jul_app
*japp
)
465 struct ust_app
*uapp
;
470 uapp
= ust_app_find_by_pid(japp
->pid
);
475 uatomic_set(&uapp
->jul_app_sock
, japp
->sock
->fd
);
477 DBG3("JUL app pid: %d, sock: %d attached to UST app.", japp
->pid
,
486 * Remove JUL app. reference from an UST app object and set it to NULL.
488 void jul_detach_app(struct jul_app
*japp
)
490 struct ust_app
*uapp
;
496 if (japp
->ust_app_sock
< 0) {
500 uapp
= ust_app_find_by_sock(japp
->ust_app_sock
);
505 uapp
->jul_app_sock
= -1;
513 * Delete JUL application from the global hash table.
515 void jul_delete_app(struct jul_app
*app
)
518 struct lttng_ht_iter iter
;
522 DBG3("JUL deleting app pid: %d and sock: %d", app
->pid
, app
->sock
->fd
);
524 iter
.iter
.node
= &app
->node
.node
;
526 ret
= lttng_ht_del(jul_apps_ht_by_sock
, &iter
);
532 * Destroy a JUL application object by detaching it from its corresponding UST
533 * app if one, closing the socket and freeing the memory.
535 void jul_destroy_app(struct jul_app
*app
)
540 app
->sock
->ops
->close(app
->sock
);
541 lttcomm_destroy_sock(app
->sock
);
544 call_rcu(&app
->node
.head
, destroy_app_jul_rcu
);
548 * Initialize an already allocated JUL domain object.
550 * Return 0 on success or else a negative errno value.
552 int jul_init_domain(struct jul_domain
*dom
)
558 dom
->events
= lttng_ht_new(0, LTTNG_HT_TYPE_STRING
);
571 * Create a newly allocated JUL event data structure. If name is valid, it's
572 * copied into the created event.
574 * Return a new object else NULL on error.
576 struct jul_event
*jul_create_event(const char *name
)
578 struct jul_event
*event
;
580 DBG3("JUL create new event with name %s", name
);
582 event
= zmalloc(sizeof(*event
));
588 strncpy(event
->name
, name
, sizeof(event
->name
));
589 event
->name
[sizeof(event
->name
) - 1] = '\0';
590 lttng_ht_node_init_str(&event
->node
, event
->name
);
598 * Unique add of a JUL event to a given domain.
600 void jul_add_event(struct jul_event
*event
, struct jul_domain
*dom
)
606 DBG3("JUL adding event %s to domain", event
->name
);
609 lttng_ht_add_unique_str(dom
->events
, &event
->node
);
614 * Find a JUL event in the given domain using name.
616 * RCU read side lock MUST be acquired.
618 * Return object if found else NULL.
620 struct jul_event
*jul_find_by_name(const char *name
, struct jul_domain
*dom
)
622 struct lttng_ht_node_str
*node
;
623 struct lttng_ht_iter iter
;
629 lttng_ht_lookup(dom
->events
, (void *)name
, &iter
);
630 node
= lttng_ht_iter_get_node_str(&iter
);
635 DBG3("JUL found by name %s in domain.", name
);
636 return caa_container_of(node
, struct jul_event
, node
);
639 DBG3("JUL NOT found by name %s in domain.", name
);
644 * Delete JUL event from given domain. Events hash table MUST be initialized.
646 void jul_delete_event(struct jul_event
*event
, struct jul_domain
*dom
)
649 struct lttng_ht_iter iter
;
655 DBG3("JUL deleting event %s from domain", event
->name
);
657 iter
.iter
.node
= &event
->node
.node
;
659 ret
= lttng_ht_del(dom
->events
, &iter
);
665 * Free given JUl event. After this call, the pointer is not usable anymore.
667 void jul_destroy_event(struct jul_event
*event
)
675 * Destroy a JUL domain completely. Note that the given pointer is NOT freed
676 * thus a reference can be passed to this function.
678 void jul_destroy_domain(struct jul_domain
*dom
)
680 struct lttng_ht_node_str
*node
;
681 struct lttng_ht_iter iter
;
685 DBG3("JUL destroy domain");
688 * Just ignore if no events hash table exists. This is possible if for
689 * instance a JUL domain object was allocated but not initialized.
696 cds_lfht_for_each_entry(dom
->events
->ht
, &iter
.iter
, node
, node
) {
699 ret
= lttng_ht_del(dom
->events
, &iter
);
701 call_rcu(&node
->head
, destroy_event_jul_rcu
);
705 lttng_ht_destroy(dom
->events
);
709 * Initialize JUL subsystem.
713 jul_apps_ht_by_sock
= lttng_ht_new(0, LTTNG_HT_TYPE_ULONG
);
714 if (!jul_apps_ht_by_sock
) {
722 * Update a JUL application (given socket) using the given domain.
724 * Note that this function is most likely to be used with a tracing session
725 * thus the caller should make sure to hold the appropriate lock(s).
727 void jul_update(struct jul_domain
*domain
, int sock
)
731 struct jul_event
*event
;
732 struct lttng_ht_iter iter
;
737 DBG("JUL updating app socket %d", sock
);
740 cds_lfht_for_each_entry(domain
->events
->ht
, &iter
.iter
, event
, node
.node
) {
741 /* Skip event if disabled. */
742 if (!event
->enabled
) {
746 app
= jul_find_app_by_sock(sock
);
748 * We are in the registration path thus if the application is gone,
749 * there is a serious code flow error.
753 ret
= enable_event(app
, event
);
754 if (ret
!= LTTNG_OK
) {
755 DBG2("JUL update unable to enable event %s on app pid: %d sock %d",
756 event
->name
, app
->pid
, app
->sock
->fd
);
757 /* Let's try the others here and don't assume the app is dead. */