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.
21 #include <common/common.h>
22 #include <common/hashtable/utils.h>
23 #include <lttng/lttng.h>
25 #include "ust-registry.h"
30 * Hash table match function for event in the registry.
32 static int ht_match_event(struct cds_lfht_node
*node
, const void *_key
)
34 struct ust_registry_event
*event
;
35 const struct ust_registry_event
*key
;
40 event
= caa_container_of(node
, struct ust_registry_event
, node
.node
);
44 /* It has to be a perfect match. */
45 if (strncmp(event
->name
, key
->name
, sizeof(event
->name
)) != 0) {
49 /* It has to be a perfect match. */
50 if (strncmp(event
->signature
, key
->signature
,
51 strlen(event
->signature
) != 0)) {
62 static unsigned long ht_hash_event(void *_key
, unsigned long seed
)
65 struct ust_registry_event
*key
= _key
;
69 xored_key
= (uint64_t) (hash_key_str(key
->name
, seed
) ^
70 hash_key_str(key
->signature
, seed
));
72 return hash_key_u64(&xored_key
, seed
);
76 * Return negative value on error, 0 if OK.
78 * TODO: we could add stricter verification of more types to catch
79 * errors in liblttng-ust implementation earlier than consumption by the
83 int validate_event_field(struct ustctl_field
*field
,
84 const char *event_name
,
87 switch(field
->type
.atype
) {
88 case ustctl_atype_integer
:
89 case ustctl_atype_enum
:
90 case ustctl_atype_array
:
91 case ustctl_atype_sequence
:
92 case ustctl_atype_string
:
95 case ustctl_atype_float
:
96 switch (field
->type
.u
.basic
._float
.mant_dig
) {
98 WARN("UST application '%s' (pid: %d) has unknown float mantissa '%u' "
99 "in field '%s', rejecting event '%s'",
101 field
->type
.u
.basic
._float
.mant_dig
,
117 int validate_event_fields(size_t nr_fields
, struct ustctl_field
*fields
,
118 const char *event_name
, struct ust_app
*app
)
122 for (i
= 0; i
< nr_fields
; i
++) {
123 if (validate_event_field(&fields
[i
], event_name
, app
) < 0)
130 * Allocate event and initialize it. This does NOT set a valid event id from a
133 static struct ust_registry_event
*alloc_event(int session_objd
,
134 int channel_objd
, char *name
, char *sig
, size_t nr_fields
,
135 struct ustctl_field
*fields
, int loglevel
, char *model_emf_uri
,
138 struct ust_registry_event
*event
= NULL
;
141 * Ensure that the field content is valid.
143 if (validate_event_fields(nr_fields
, fields
, name
, app
) < 0) {
147 event
= zmalloc(sizeof(*event
));
149 PERROR("zmalloc ust registry event");
153 event
->session_objd
= session_objd
;
154 event
->channel_objd
= channel_objd
;
155 /* Allocated by ustctl. */
156 event
->signature
= sig
;
157 event
->nr_fields
= nr_fields
;
158 event
->fields
= fields
;
159 event
->loglevel
= loglevel
;
160 event
->model_emf_uri
= model_emf_uri
;
162 /* Copy event name and force NULL byte. */
163 strncpy(event
->name
, name
, sizeof(event
->name
));
164 event
->name
[sizeof(event
->name
) - 1] = '\0';
166 cds_lfht_node_init(&event
->node
.node
);
173 * Free event data structure. This does NOT delete it from any hash table. It's
174 * safe to pass a NULL pointer. This shoudl be called inside a call RCU if the
175 * event is previously deleted from a rcu hash table.
177 static void destroy_event(struct ust_registry_event
*event
)
184 free(event
->model_emf_uri
);
185 free(event
->signature
);
190 * Destroy event function call of the call RCU.
192 static void destroy_event_rcu(struct rcu_head
*head
)
194 struct lttng_ht_node_u64
*node
=
195 caa_container_of(head
, struct lttng_ht_node_u64
, head
);
196 struct ust_registry_event
*event
=
197 caa_container_of(node
, struct ust_registry_event
, node
);
199 destroy_event(event
);
203 * Find an event using the name and signature in the given registry. RCU read
204 * side lock MUST be acquired before calling this function and as long as the
205 * event reference is kept by the caller.
207 * On success, the event pointer is returned else NULL.
209 struct ust_registry_event
*ust_registry_find_event(
210 struct ust_registry_channel
*chan
, char *name
, char *sig
)
212 struct lttng_ht_node_u64
*node
;
213 struct lttng_ht_iter iter
;
214 struct ust_registry_event
*event
= NULL
;
215 struct ust_registry_event key
;
221 /* Setup key for the match function. */
222 strncpy(key
.name
, name
, sizeof(key
.name
));
223 key
.name
[sizeof(key
.name
) - 1] = '\0';
226 cds_lfht_lookup(chan
->ht
->ht
, chan
->ht
->hash_fct(&key
, lttng_ht_seed
),
227 chan
->ht
->match_fct
, &key
, &iter
.iter
);
228 node
= lttng_ht_iter_get_node_u64(&iter
);
232 event
= caa_container_of(node
, struct ust_registry_event
, node
);
239 * Create a ust_registry_event from the given parameters and add it to the
240 * registry hash table. If event_id is valid, it is set with the newly created
243 * On success, return 0 else a negative value. The created event MUST be unique
244 * so on duplicate entry -EINVAL is returned. On error, event_id is untouched.
246 * Should be called with session registry mutex held.
248 int ust_registry_create_event(struct ust_registry_session
*session
,
249 uint64_t chan_key
, int session_objd
, int channel_objd
, char *name
,
250 char *sig
, size_t nr_fields
, struct ustctl_field
*fields
, int loglevel
,
251 char *model_emf_uri
, int buffer_type
, uint32_t *event_id_p
,
256 struct cds_lfht_node
*nptr
;
257 struct ust_registry_event
*event
= NULL
;
258 struct ust_registry_channel
*chan
;
268 * This should not happen but since it comes from the UST tracer, an
269 * external party, don't assert and simply validate values.
271 if (session_objd
< 0 || channel_objd
< 0) {
276 chan
= ust_registry_channel_find(session
, chan_key
);
282 /* Check if we've reached the maximum possible id. */
283 if (ust_registry_is_max_id(chan
->used_event_id
)) {
288 event
= alloc_event(session_objd
, channel_objd
, name
, sig
, nr_fields
,
289 fields
, loglevel
, model_emf_uri
, app
);
295 DBG3("UST registry creating event with event: %s, sig: %s, id: %u, "
296 "chan_objd: %u, sess_objd: %u, chan_id: %u", event
->name
,
297 event
->signature
, event
->id
, event
->channel_objd
,
298 event
->session_objd
, chan
->chan_id
);
301 * This is an add unique with a custom match function for event. The node
302 * are matched using the event name and signature.
304 nptr
= cds_lfht_add_unique(chan
->ht
->ht
, chan
->ht
->hash_fct(event
,
305 lttng_ht_seed
), chan
->ht
->match_fct
, event
, &event
->node
.node
);
306 if (nptr
!= &event
->node
.node
) {
307 if (buffer_type
== LTTNG_BUFFER_PER_UID
) {
309 * This is normal, we just have to send the event id of the
310 * returned node and make sure we destroy the previously allocated
313 destroy_event(event
);
314 event
= caa_container_of(nptr
, struct ust_registry_event
,
317 event_id
= event
->id
;
319 ERR("UST registry create event add unique failed for event: %s, "
320 "sig: %s, id: %u, chan_objd: %u, sess_objd: %u",
321 event
->name
, event
->signature
, event
->id
,
322 event
->channel_objd
, event
->session_objd
);
327 /* Request next event id if the node was successfully added. */
328 event_id
= event
->id
= ust_registry_get_next_event_id(chan
);
331 *event_id_p
= event_id
;
333 if (!event
->metadata_dumped
) {
334 /* Append to metadata */
335 ret
= ust_metadata_event_statedump(session
, chan
, event
);
337 ERR("Error appending event metadata (errno = %d)", ret
);
352 destroy_event(event
);
357 * For a given event in a registry, delete the entry and destroy the event.
358 * This MUST be called within a RCU read side lock section.
360 void ust_registry_destroy_event(struct ust_registry_channel
*chan
,
361 struct ust_registry_event
*event
)
364 struct lttng_ht_iter iter
;
369 /* Delete the node first. */
370 iter
.iter
.node
= &event
->node
.node
;
371 ret
= lttng_ht_del(chan
->ht
, &iter
);
374 call_rcu(&event
->node
.head
, destroy_event_rcu
);
380 * We need to execute ht_destroy outside of RCU read-side critical
381 * section and outside of call_rcu thread, so we postpone its execution
382 * using ht_cleanup_push. It is simpler than to change the semantic of
383 * the many callers of delete_ust_app_session().
386 void destroy_channel_rcu(struct rcu_head
*head
)
388 struct ust_registry_channel
*chan
=
389 caa_container_of(head
, struct ust_registry_channel
, rcu_head
);
392 ht_cleanup_push(chan
->ht
);
394 free(chan
->ctx_fields
);
399 * Destroy every element of the registry and free the memory. This does NOT
400 * free the registry pointer since it might not have been allocated before so
401 * it's the caller responsability.
403 static void destroy_channel(struct ust_registry_channel
*chan
)
405 struct lttng_ht_iter iter
;
406 struct ust_registry_event
*event
;
411 /* Destroy all event associated with this registry. */
412 cds_lfht_for_each_entry(chan
->ht
->ht
, &iter
.iter
, event
, node
.node
) {
413 /* Delete the node from the ht and free it. */
414 ust_registry_destroy_event(chan
, event
);
417 call_rcu(&chan
->rcu_head
, destroy_channel_rcu
);
421 * Initialize registry with default values.
423 int ust_registry_channel_add(struct ust_registry_session
*session
,
427 struct ust_registry_channel
*chan
;
431 chan
= zmalloc(sizeof(*chan
));
433 PERROR("zmalloc ust registry channel");
438 chan
->ht
= lttng_ht_new(0, LTTNG_HT_TYPE_STRING
);
444 /* Set custom match function. */
445 chan
->ht
->match_fct
= ht_match_event
;
446 chan
->ht
->hash_fct
= ht_hash_event
;
449 * Assign a channel ID right now since the event notification comes
450 * *before* the channel notify so the ID needs to be set at this point so
451 * the metadata can be dumped for that event.
453 if (ust_registry_is_max_id(session
->used_channel_id
)) {
457 chan
->chan_id
= ust_registry_get_next_chan_id(session
);
460 lttng_ht_node_init_u64(&chan
->node
, key
);
461 lttng_ht_add_unique_u64(session
->channels
, &chan
->node
);
467 destroy_channel(chan
);
473 * Find a channel in the given registry. RCU read side lock MUST be acquired
474 * before calling this function and as long as the event reference is kept by
477 * On success, the pointer is returned else NULL.
479 struct ust_registry_channel
*ust_registry_channel_find(
480 struct ust_registry_session
*session
, uint64_t key
)
482 struct lttng_ht_node_u64
*node
;
483 struct lttng_ht_iter iter
;
484 struct ust_registry_channel
*chan
= NULL
;
487 assert(session
->channels
);
489 DBG3("UST registry channel finding key %" PRIu64
, key
);
491 lttng_ht_lookup(session
->channels
, &key
, &iter
);
492 node
= lttng_ht_iter_get_node_u64(&iter
);
496 chan
= caa_container_of(node
, struct ust_registry_channel
, node
);
503 * Remove channel using key from registry and free memory.
505 void ust_registry_channel_del_free(struct ust_registry_session
*session
,
508 struct lttng_ht_iter iter
;
509 struct ust_registry_channel
*chan
;
515 chan
= ust_registry_channel_find(session
, key
);
521 iter
.iter
.node
= &chan
->node
.node
;
522 ret
= lttng_ht_del(session
->channels
, &iter
);
525 destroy_channel(chan
);
532 * Initialize registry with default values and set the newly allocated session
533 * pointer to sessionp.
535 * Return 0 on success and sessionp is set or else return -1 and sessionp is
538 int ust_registry_session_init(struct ust_registry_session
**sessionp
,
540 uint32_t bits_per_long
,
541 uint32_t uint8_t_alignment
,
542 uint32_t uint16_t_alignment
,
543 uint32_t uint32_t_alignment
,
544 uint32_t uint64_t_alignment
,
545 uint32_t long_alignment
,
551 struct ust_registry_session
*session
;
555 session
= zmalloc(sizeof(*session
));
557 PERROR("zmalloc ust registry session");
561 pthread_mutex_init(&session
->lock
, NULL
);
562 session
->bits_per_long
= bits_per_long
;
563 session
->uint8_t_alignment
= uint8_t_alignment
;
564 session
->uint16_t_alignment
= uint16_t_alignment
;
565 session
->uint32_t_alignment
= uint32_t_alignment
;
566 session
->uint64_t_alignment
= uint64_t_alignment
;
567 session
->long_alignment
= long_alignment
;
568 session
->byte_order
= byte_order
;
570 session
->channels
= lttng_ht_new(0, LTTNG_HT_TYPE_U64
);
571 if (!session
->channels
) {
575 ret
= lttng_uuid_generate(session
->uuid
);
577 ERR("Failed to generate UST uuid (errno = %d)", ret
);
581 pthread_mutex_lock(&session
->lock
);
582 ret
= ust_metadata_session_statedump(session
, app
, major
, minor
);
583 pthread_mutex_unlock(&session
->lock
);
585 ERR("Failed to generate session metadata (errno = %d)", ret
);
594 ust_registry_session_destroy(session
);
601 * Destroy session registry. This does NOT free the given pointer since it
602 * might get passed as a reference. The registry lock should NOT be acquired.
604 void ust_registry_session_destroy(struct ust_registry_session
*reg
)
607 struct lttng_ht_iter iter
;
608 struct ust_registry_channel
*chan
;
612 /* On error, EBUSY can be returned if lock. Code flow error. */
613 ret
= pthread_mutex_destroy(®
->lock
);
618 /* Destroy all event associated with this registry. */
619 cds_lfht_for_each_entry(reg
->channels
->ht
, &iter
.iter
, chan
,
621 /* Delete the node from the ht and free it. */
622 ret
= lttng_ht_del(reg
->channels
, &iter
);
624 destroy_channel(chan
);
627 ht_cleanup_push(reg
->channels
);
This page took 0.041638 seconds and 4 git commands to generate.