SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng-sessiond / ust-registry.c
CommitLineData
d0b96690 1/*
ab5be9fa 2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
d0b96690 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
d0b96690 5 *
d0b96690 6 */
890d8fe4 7
ebdb334b 8#include "bin/lttng-sessiond/event-notifier-error-accounting.h"
6c1c0768 9#define _LGPL_SOURCE
d0b96690 10#include <assert.h>
7972aab2 11#include <inttypes.h>
d0b96690
DG
12
13#include <common/common.h>
7972aab2
DG
14#include <common/hashtable/utils.h>
15#include <lttng/lttng.h>
ebdb334b
JR
16#include <lttng/map-key.h>
17#include <lttng/map-key-internal.h>
7972aab2 18
d0b96690 19#include "ust-registry.h"
8494bda5 20#include "ust-app.h"
98b73e88 21#include "ust-field-utils.h"
0b2dc8df 22#include "utils.h"
e9404c27
JG
23#include "lttng-sessiond.h"
24#include "notification-thread-commands.h"
d0b96690 25
98b73e88 26
d0b96690
DG
27/*
28 * Hash table match function for event in the registry.
29 */
30static int ht_match_event(struct cds_lfht_node *node, const void *_key)
31{
d0b96690 32 const struct ust_registry_event *key;
98b73e88
FD
33 struct ust_registry_event *event;
34 int i;
d0b96690
DG
35
36 assert(node);
37 assert(_key);
38
39 event = caa_container_of(node, struct ust_registry_event, node.node);
40 assert(event);
41 key = _key;
42
98b73e88 43 /* It has to be a perfect match. First, compare the event names. */
b4d096a6 44 if (strncmp(event->name, key->name, sizeof(event->name))) {
d0b96690
DG
45 goto no_match;
46 }
47
98b73e88
FD
48 /* Compare log levels. */
49 if (event->loglevel_value != key->loglevel_value) {
50 goto no_match;
51 }
52
53 /* Compare the number of fields. */
54 if (event->nr_fields != key->nr_fields) {
55 goto no_match;
56 }
57
58 /* Compare each field individually. */
59 for (i = 0; i < event->nr_fields; i++) {
60 if (!match_ustctl_field(&event->fields[i], &key->fields[i])) {
61 goto no_match;
62 }
63 }
64
65 /* Compare model URI. */
66 if (event->model_emf_uri != NULL && key->model_emf_uri == NULL) {
67 goto no_match;
68 } else if(event->model_emf_uri == NULL && key->model_emf_uri != NULL) {
d0b96690 69 goto no_match;
98b73e88
FD
70 } else if (event->model_emf_uri != NULL && key->model_emf_uri != NULL) {
71 if (strcmp(event->model_emf_uri, key->model_emf_uri)) {
72 goto no_match;
73 }
d0b96690
DG
74 }
75
76 /* Match */
77 return 1;
78
79no_match:
80 return 0;
81}
82
bcd52dd9 83static unsigned long ht_hash_event(const void *_key, unsigned long seed)
7972aab2 84{
98b73e88 85 uint64_t hashed_key;
bcd52dd9 86 const struct ust_registry_event *key = _key;
7972aab2
DG
87
88 assert(key);
89
98b73e88 90 hashed_key = (uint64_t) hash_key_str(key->name, seed);
7972aab2 91
98b73e88 92 return hash_key_u64(&hashed_key, seed);
7972aab2
DG
93}
94
10b56aef
MD
95static int compare_enums(const struct ust_registry_enum *reg_enum_a,
96 const struct ust_registry_enum *reg_enum_b)
97{
98 int ret = 0;
99 size_t i;
100
101 assert(strcmp(reg_enum_a->name, reg_enum_b->name) == 0);
102 if (reg_enum_a->nr_entries != reg_enum_b->nr_entries) {
103 ret = -1;
104 goto end;
105 }
106 for (i = 0; i < reg_enum_a->nr_entries; i++) {
107 const struct ustctl_enum_entry *entries_a, *entries_b;
108
109 entries_a = &reg_enum_a->entries[i];
110 entries_b = &reg_enum_b->entries[i];
3b016e58 111 if (entries_a->start.value != entries_b->start.value) {
10b56aef
MD
112 ret = -1;
113 goto end;
114 }
3b016e58 115 if (entries_a->end.value != entries_b->end.value) {
10b56aef
MD
116 ret = -1;
117 goto end;
118 }
3b016e58
MD
119 if (entries_a->start.signedness != entries_b->start.signedness) {
120 ret = -1;
121 goto end;
122 }
123 if (entries_a->end.signedness != entries_b->end.signedness) {
124 ret = -1;
125 goto end;
126 }
127
10b56aef
MD
128 if (strcmp(entries_a->string, entries_b->string)) {
129 ret = -1;
130 goto end;
131 }
132 }
133end:
134 return ret;
135}
136
137/*
138 * Hash table match function for enumerations in the session. Match is
139 * performed on enumeration name, and confirmed by comparing the enum
140 * entries.
141 */
142static int ht_match_enum(struct cds_lfht_node *node, const void *_key)
143{
144 struct ust_registry_enum *_enum;
145 const struct ust_registry_enum *key;
146
147 assert(node);
148 assert(_key);
149
150 _enum = caa_container_of(node, struct ust_registry_enum,
151 node.node);
152 assert(_enum);
153 key = _key;
154
155 if (strncmp(_enum->name, key->name, LTTNG_UST_SYM_NAME_LEN)) {
156 goto no_match;
157 }
158 if (compare_enums(_enum, key)) {
159 goto no_match;
160 }
161
162 /* Match. */
163 return 1;
164
165no_match:
166 return 0;
167}
168
169/*
170 * Hash table match function for enumerations in the session. Match is
171 * performed by enumeration ID.
172 */
173static int ht_match_enum_id(struct cds_lfht_node *node, const void *_key)
174{
175 struct ust_registry_enum *_enum;
176 const struct ust_registry_enum *key = _key;
177
178 assert(node);
179 assert(_key);
180
181 _enum = caa_container_of(node, struct ust_registry_enum, node.node);
182 assert(_enum);
183
184 if (_enum->id != key->id) {
185 goto no_match;
186 }
187
188 /* Match. */
189 return 1;
190
191no_match:
192 return 0;
193}
194
195/*
196 * Hash table hash function for enumerations in the session. The
197 * enumeration name is used for hashing.
198 */
199static unsigned long ht_hash_enum(void *_key, unsigned long seed)
200{
201 struct ust_registry_enum *key = _key;
202
203 assert(key);
204 return hash_key_str(key->name, seed);
205}
206
8494bda5
MD
207/*
208 * Return negative value on error, 0 if OK.
209 *
210 * TODO: we could add stricter verification of more types to catch
211 * errors in liblttng-ust implementation earlier than consumption by the
212 * trace reader.
213 */
214static
215int validate_event_field(struct ustctl_field *field,
216 const char *event_name,
217 struct ust_app *app)
218{
da860cab
MD
219 int ret = 0;
220
8494bda5
MD
221 switch(field->type.atype) {
222 case ustctl_atype_integer:
223 case ustctl_atype_enum:
224 case ustctl_atype_array:
225 case ustctl_atype_sequence:
226 case ustctl_atype_string:
da860cab 227 case ustctl_atype_variant:
0d32d1a9
MD
228 case ustctl_atype_array_nestable:
229 case ustctl_atype_sequence_nestable:
230 case ustctl_atype_enum_nestable:
231 case ustctl_atype_variant_nestable:
da860cab
MD
232 break;
233 case ustctl_atype_struct:
0d32d1a9
MD
234 if (field->type.u.legacy._struct.nr_fields != 0) {
235 WARN("Unsupported non-empty struct field.");
236 ret = -EINVAL;
237 goto end;
238 }
239 break;
240 case ustctl_atype_struct_nestable:
241 if (field->type.u.struct_nestable.nr_fields != 0) {
da860cab
MD
242 WARN("Unsupported non-empty struct field.");
243 ret = -EINVAL;
244 goto end;
245 }
8494bda5
MD
246 break;
247
248 case ustctl_atype_float:
0d32d1a9 249 switch (field->type.u._float.mant_dig) {
8494bda5
MD
250 case 0:
251 WARN("UST application '%s' (pid: %d) has unknown float mantissa '%u' "
252 "in field '%s', rejecting event '%s'",
253 app->name, app->pid,
0d32d1a9 254 field->type.u._float.mant_dig,
8494bda5
MD
255 field->name,
256 event_name);
da860cab
MD
257 ret = -EINVAL;
258 goto end;
8494bda5
MD
259 default:
260 break;
261 }
262 break;
263
264 default:
da860cab
MD
265 ret = -ENOENT;
266 goto end;
8494bda5 267 }
da860cab
MD
268end:
269 return ret;
8494bda5
MD
270}
271
272static
273int validate_event_fields(size_t nr_fields, struct ustctl_field *fields,
274 const char *event_name, struct ust_app *app)
275{
276 unsigned int i;
277
278 for (i = 0; i < nr_fields; i++) {
279 if (validate_event_field(&fields[i], event_name, app) < 0)
280 return -EINVAL;
281 }
282 return 0;
283}
284
d0b96690
DG
285/*
286 * Allocate event and initialize it. This does NOT set a valid event id from a
287 * registry.
288 */
289static struct ust_registry_event *alloc_event(int session_objd,
ebdb334b 290 int container_objd, char *name, char *sig, size_t nr_fields,
2106efa0
PP
291 struct ustctl_field *fields, int loglevel_value,
292 char *model_emf_uri, struct ust_app *app)
d0b96690
DG
293{
294 struct ust_registry_event *event = NULL;
295
8494bda5
MD
296 /*
297 * Ensure that the field content is valid.
298 */
299 if (validate_event_fields(nr_fields, fields, name, app) < 0) {
300 return NULL;
301 }
302
d0b96690
DG
303 event = zmalloc(sizeof(*event));
304 if (!event) {
305 PERROR("zmalloc ust registry event");
306 goto error;
307 }
308
309 event->session_objd = session_objd;
ebdb334b 310 event->container_objd = container_objd;
d0b96690
DG
311 /* Allocated by ustctl. */
312 event->signature = sig;
313 event->nr_fields = nr_fields;
314 event->fields = fields;
2106efa0 315 event->loglevel_value = loglevel_value;
d0b96690
DG
316 event->model_emf_uri = model_emf_uri;
317 if (name) {
318 /* Copy event name and force NULL byte. */
319 strncpy(event->name, name, sizeof(event->name));
320 event->name[sizeof(event->name) - 1] = '\0';
321 }
7972aab2 322 cds_lfht_node_init(&event->node.node);
d0b96690
DG
323
324error:
325 return event;
326}
327
328/*
329 * Free event data structure. This does NOT delete it from any hash table. It's
330 * safe to pass a NULL pointer. This shoudl be called inside a call RCU if the
331 * event is previously deleted from a rcu hash table.
332 */
333static void destroy_event(struct ust_registry_event *event)
334{
335 if (!event) {
336 return;
337 }
338
339 free(event->fields);
340 free(event->model_emf_uri);
341 free(event->signature);
342 free(event);
343}
344
345/*
346 * Destroy event function call of the call RCU.
347 */
348static void destroy_event_rcu(struct rcu_head *head)
349{
7972aab2
DG
350 struct lttng_ht_node_u64 *node =
351 caa_container_of(head, struct lttng_ht_node_u64, head);
d0b96690
DG
352 struct ust_registry_event *event =
353 caa_container_of(node, struct ust_registry_event, node);
354
355 destroy_event(event);
356}
357
ebdb334b
JR
358/*
359 * Destroy ust_registry_map_key_ht_entry function call of the call RCU.
360 */
361static void destroy_ust_registry_map_key_ht_entry(struct rcu_head *head)
362{
363 struct lttng_ht_node_u64 *node =
364 caa_container_of(head, struct lttng_ht_node_u64, head);
365 struct ust_registry_map_key_ht_entry *entry =
366 caa_container_of(node, struct ust_registry_map_key_ht_entry, node);
367
368 lttng_map_key_put(entry->key);
369 free(entry);
370}
371
372/*
373 * Destroy ust_registry_map_index_ht_entry function call of the call RCU.
374 */
375static void destroy_ust_registry_map_index_ht_entry(struct rcu_head *head)
376{
377 struct lttng_ht_node_str *node =
378 caa_container_of(head, struct lttng_ht_node_str, head);
379 struct ust_registry_map_index_ht_entry *entry =
380 caa_container_of(node, struct ust_registry_map_index_ht_entry, node);
381
382 free(entry);
383}
384
d0b96690
DG
385/*
386 * Find an event using the name and signature in the given registry. RCU read
387 * side lock MUST be acquired before calling this function and as long as the
388 * event reference is kept by the caller.
389 *
390 * On success, the event pointer is returned else NULL.
391 */
ebdb334b 392struct ust_registry_event *ust_registry_chan_find_event(
d0b96690
DG
393 struct ust_registry_channel *chan, char *name, char *sig)
394{
7972aab2 395 struct lttng_ht_node_u64 *node;
d0b96690
DG
396 struct lttng_ht_iter iter;
397 struct ust_registry_event *event = NULL;
398 struct ust_registry_event key;
399
400 assert(chan);
401 assert(name);
402 assert(sig);
403
404 /* Setup key for the match function. */
405 strncpy(key.name, name, sizeof(key.name));
406 key.name[sizeof(key.name) - 1] = '\0';
407 key.signature = sig;
408
7972aab2 409 cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed),
d0b96690 410 chan->ht->match_fct, &key, &iter.iter);
7972aab2 411 node = lttng_ht_iter_get_node_u64(&iter);
d0b96690
DG
412 if (!node) {
413 goto end;
414 }
415 event = caa_container_of(node, struct ust_registry_event, node);
416
417end:
418 return event;
419}
420
421/*
422 * Create a ust_registry_event from the given parameters and add it to the
423 * registry hash table. If event_id is valid, it is set with the newly created
424 * event id.
425 *
426 * On success, return 0 else a negative value. The created event MUST be unique
427 * so on duplicate entry -EINVAL is returned. On error, event_id is untouched.
428 *
429 * Should be called with session registry mutex held.
430 */
ebdb334b 431int ust_registry_chan_create_event(struct ust_registry_session *session,
45893984 432 uint64_t chan_key, int session_objd, int channel_objd, char *name,
2106efa0
PP
433 char *sig, size_t nr_fields, struct ustctl_field *fields,
434 int loglevel_value, char *model_emf_uri, int buffer_type,
435 uint32_t *event_id_p, struct ust_app *app)
d0b96690
DG
436{
437 int ret;
7972aab2 438 uint32_t event_id;
d0b96690
DG
439 struct cds_lfht_node *nptr;
440 struct ust_registry_event *event = NULL;
45893984 441 struct ust_registry_channel *chan;
d0b96690
DG
442
443 assert(session);
d0b96690
DG
444 assert(name);
445 assert(sig);
7972aab2 446 assert(event_id_p);
d0b96690 447
d5d629b5
DG
448 rcu_read_lock();
449
d0b96690
DG
450 /*
451 * This should not happen but since it comes from the UST tracer, an
452 * external party, don't assert and simply validate values.
453 */
454 if (session_objd < 0 || channel_objd < 0) {
455 ret = -EINVAL;
d5d629b5 456 goto error_free;
d0b96690
DG
457 }
458
45893984
DG
459 chan = ust_registry_channel_find(session, chan_key);
460 if (!chan) {
461 ret = -EINVAL;
d5d629b5 462 goto error_free;
45893984
DG
463 }
464
d0b96690
DG
465 /* Check if we've reached the maximum possible id. */
466 if (ust_registry_is_max_id(chan->used_event_id)) {
467 ret = -ENOENT;
d5d629b5 468 goto error_free;
d0b96690
DG
469 }
470
471 event = alloc_event(session_objd, channel_objd, name, sig, nr_fields,
2106efa0 472 fields, loglevel_value, model_emf_uri, app);
d0b96690
DG
473 if (!event) {
474 ret = -ENOMEM;
d5d629b5 475 goto error_free;
d0b96690
DG
476 }
477
d0b96690 478 DBG3("UST registry creating event with event: %s, sig: %s, id: %u, "
7972aab2 479 "chan_objd: %u, sess_objd: %u, chan_id: %u", event->name,
ebdb334b 480 event->signature, event->id, event->container_objd,
7972aab2 481 event->session_objd, chan->chan_id);
d0b96690 482
d0b96690
DG
483 /*
484 * This is an add unique with a custom match function for event. The node
485 * are matched using the event name and signature.
486 */
7972aab2 487 nptr = cds_lfht_add_unique(chan->ht->ht, chan->ht->hash_fct(event,
d0b96690
DG
488 lttng_ht_seed), chan->ht->match_fct, event, &event->node.node);
489 if (nptr != &event->node.node) {
7972aab2
DG
490 if (buffer_type == LTTNG_BUFFER_PER_UID) {
491 /*
492 * This is normal, we just have to send the event id of the
493 * returned node and make sure we destroy the previously allocated
494 * event object.
495 */
496 destroy_event(event);
497 event = caa_container_of(nptr, struct ust_registry_event,
498 node.node);
499 assert(event);
500 event_id = event->id;
501 } else {
502 ERR("UST registry create event add unique failed for event: %s, "
503 "sig: %s, id: %u, chan_objd: %u, sess_objd: %u",
504 event->name, event->signature, event->id,
ebdb334b 505 event->container_objd, event->session_objd);
7972aab2
DG
506 ret = -EINVAL;
507 goto error_unlock;
508 }
509 } else {
510 /* Request next event id if the node was successfully added. */
ebdb334b 511 event_id = event->id = ust_registry_channel_get_next_event_id(chan);
d0b96690
DG
512 }
513
7972aab2 514 *event_id_p = event_id;
d0b96690 515
7972aab2
DG
516 if (!event->metadata_dumped) {
517 /* Append to metadata */
518 ret = ust_metadata_event_statedump(session, chan, event);
519 if (ret) {
520 ERR("Error appending event metadata (errno = %d)", ret);
521 rcu_read_unlock();
522 return ret;
523 }
d0b96690
DG
524 }
525
45893984 526 rcu_read_unlock();
d0b96690
DG
527 return 0;
528
d5d629b5
DG
529error_free:
530 free(sig);
531 free(fields);
532 free(model_emf_uri);
d0b96690
DG
533error_unlock:
534 rcu_read_unlock();
d0b96690
DG
535 destroy_event(event);
536 return ret;
537}
538
ebdb334b
JR
539static
540int format_event_key(const struct lttng_map_key *key,
541 const char *full_event_name, char **formated_key)
542{
543 int ret;
544 char _key[LTTNG_UST_KEY_TOKEN_STRING_LEN_MAX] = {0};
545 enum lttng_map_key_status key_status;
546 unsigned int i, token_count;
547 char *cloned_full_event_name;
548 const char *provider_name, *event_name;
549
550 assert(key);
551 assert(full_event_name);
552
553 cloned_full_event_name = strdup(full_event_name);
554
555 provider_name = strtok(cloned_full_event_name, ":");
556 event_name = strtok(NULL, ":");
557
558 key_status = lttng_map_key_get_token_count(key, &token_count);
559 if (key_status != LTTNG_MAP_KEY_STATUS_OK) {
560 ERR("Error getting map key token count");
561 ret = -1;
562 goto end;
563 }
564
565 if (token_count == 0) {
566 ERR("Map key token number is zero");
567 ret = -1;
568 goto end;
569 }
570
571 for (i = 0; i < token_count; i++) {
572 const struct lttng_map_key_token *token =
573 lttng_map_key_get_token_at_index(key, i);
574 switch (token->type) {
575 case LTTNG_MAP_KEY_TOKEN_TYPE_STRING:
576 {
577 struct lttng_map_key_token_string *str_token =
578 (struct lttng_map_key_token_string *) token;
579 DBG("Appending a string type key token: str = '%s'", str_token->string);
580
581 strcat(_key, lttng_map_key_token_string_get_string(str_token));
582
583 break;
584 }
585 case LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE:
586 {
587 struct lttng_map_key_token_variable *var_token =
588 (struct lttng_map_key_token_variable *) token;
589
590 switch (var_token->type) {
591 case LTTNG_MAP_KEY_TOKEN_VARIABLE_TYPE_EVENT_NAME:
592 DBG("Serializing a event name variable type key token: event_name = '%s'",
593 event_name);
594 strcat(_key, event_name);
595 break;
596 case LTTNG_MAP_KEY_TOKEN_VARIABLE_TYPE_PROVIDER_NAME:
597 DBG("Serializing a provider name variable type key token: provider_name = '%s'",
598 provider_name);
599 strcat(_key, provider_name);
600 break;
601 default:
602 abort();
603 }
604 break;
605 }
606 default:
607 abort();
608 }
609 }
610
611 *formated_key = strdup(_key);
612
613 ret = 0;
614end:
615 free(cloned_full_event_name);
616 return ret;
617}
618
619static
620const struct lttng_map_key *ust_registry_map_find_key_for_token(
621 struct ust_registry_map *map,
622 uint64_t tracer_token)
623{
624 struct lttng_ht_iter iter;
625 struct lttng_ht_node_u64 *key_node;
626 struct ust_registry_map_key_ht_entry *key_entry;
627 const struct lttng_map_key *key = NULL;;
628
629 assert(map);
630 lttng_ht_lookup(map->tracer_token_to_map_key_ht,
631 (void *) &tracer_token, &iter);
632
633 key_node = lttng_ht_iter_get_node_u64(&iter);
634 if (!key_node) {
635 goto end;
636 }
637
638 /*
639 * It's already mapped. Return the key we allocated already.
640 */
641 key_entry = caa_container_of(key_node,
642 struct ust_registry_map_key_ht_entry, node);
643 assert(key_entry);
644
645 key = key_entry->key;
646
647 DBG("Returning map key object associated to the tracer token: key = %p, tracer_token = %"PRIu64,
648 key_entry->key, tracer_token);
649
650end:
651 return key;
652}
653
654int ust_registry_map_add_token_key_mapping(struct ust_registry_session *session,
655 uint64_t map_key, uint64_t tracer_token,
656 struct lttng_map_key *key)
657{
658 int ret;
659 struct ust_registry_map_key_ht_entry *key_entry;
660 struct ust_registry_map *map;
661 const struct lttng_map_key *existing_mapping = NULL;
662
663 rcu_read_lock();
664 map = ust_registry_map_find(session, map_key);
665 if (!map) {
666 ret = -EINVAL;
667 goto end;
668 }
669 rcu_read_unlock();
670
671 /* JORAJ check if the mapping already exist, we might want to *move this
672 * to the caller or at least provide more check if for some scenario
673 * (PID) this should never happen
674 */
675 existing_mapping = ust_registry_map_find_key_for_token(map, tracer_token);
676 if (existing_mapping != NULL) {
677 assert(existing_mapping == key);
678 ret = 0;
679 goto end;
680 }
681
682 key_entry = zmalloc(sizeof(struct ust_registry_map_key_ht_entry));
683 if (!key_entry) {
684 ret = -ENOMEM;
685 goto end;
686 }
687 key_entry->key = key;
688
689 /* Ensure the lifetime of the lttng_map_key object. */
690 lttng_map_key_get(key);
691
692 rcu_read_lock();
693
694 lttng_ht_node_init_u64(&key_entry->node, tracer_token);
695 lttng_ht_add_unique_u64(map->tracer_token_to_map_key_ht,
696 &key_entry->node);
697
698 rcu_read_unlock();
699
700
701 ret = 0;
702end:
703 return ret;
704
705}
706
707static
708int ust_registry_map_find_or_create_index_for_key(struct ust_registry_map *map,
709 const char *formated_key, uint64_t *index)
710{
711 int ret;
712 struct lttng_ht_iter iter;
713 struct lttng_ht_node_str *index_node;
714 struct ust_registry_map_index_ht_entry *index_entry;
715
716 assert(map);
717 assert(formated_key);
718
719 /*
720 * First try to check if we already mapped this formated key to an
721 * index.
722 */
723 lttng_ht_lookup(map->key_string_to_bucket_index_ht,
724 (void *) formated_key, &iter);
725
726 index_node = lttng_ht_iter_get_node_str(&iter);
727 if (index_node) {
728 /*
729 * It's already mapped. Return the index we allocated already.
730 */
731 index_entry = caa_container_of(index_node,
732 struct ust_registry_map_index_ht_entry, node);
733 assert(index_entry);
734
735 *index = index_entry->index;
736
737 DBG("Returning an already allocated index for formated key: key = '%s', index = %"PRIu64,
738 formated_key, *index);
739 } else {
740 /*
741 * It's not mapped. Create a new mapping, add it to the
742 * hashtable and return it.
743 */
744 index_entry = zmalloc(sizeof(struct ust_registry_map_index_ht_entry));
745 if (!index_entry) {
746 ret = -1;
747 goto end;
748 }
749
750 index_entry->index = ust_registry_map_get_next_event_id(map);
751 index_entry->formated_key = strdup(formated_key);
752 lttng_ht_node_init_str(&index_entry->node, index_entry->formated_key);
753
754 lttng_ht_add_unique_str(map->key_string_to_bucket_index_ht,
755 &index_entry->node);
756
757 *index = index_entry->index;
758 DBG("Allocated counter index for new formated_key: key = '%s', index = %"PRIu64,
759 formated_key, *index);
760 }
761
762 ret = 0;
763end:
764 return ret;
765}
766
767/*
768 * Create a ust_registry_event from the given parameters and add it to the
769 * registry hash table. If event_id is valid, it is set with the newly created
770 * event id.
771 *
772 * On success, return 0 else a negative value. The created event MUST be unique
773 * so on duplicate entry -EINVAL is returned. On error, event_id is untouched.
774 *
775 * Should be called with session registry mutex held.
776 */
777int ust_registry_map_create_event(struct ust_registry_session *session,
778 uint64_t map_key, int session_objd, int map_objd, char *name,
779 char *sig, size_t nr_fields, struct ustctl_field *fields,
780 int loglevel_value, char *model_emf_uri, int buffer_type,
781 uint64_t tracer_token, uint64_t *counter_index_p,
782 struct ust_app *app)
783{
784 int ret;
785 uint64_t counter_index;
786 struct ust_registry_map *map;
787 char *formated_key;
788 const struct lttng_map_key *key;
789
790 assert(session);
791 assert(name);
792 assert(sig);
793 assert(counter_index_p);
794
795 rcu_read_lock();
796
797 /*
798 * This should not happen but since it comes from the UST tracer, an
799 * external party, don't assert and simply validate values.
800 */
801 if (session_objd < 0 || map_objd < 0) {
802 ret = -EINVAL;
803 goto error_free;
804 }
805
806 map = ust_registry_map_find(session, map_key);
807 if (!map) {
808 ret = -EINVAL;
809 goto error_free;
810 }
811
812 /* Check if we've reached the maximum possible id. */
813 if (ust_registry_is_max_id(map->used_event_id)) {
814 ret = -ENOENT;
815 goto error_free;
816 }
817
818 key = ust_registry_map_find_key_for_token(map, tracer_token);
819 if (!key) {
820 ERR("Tracer token %"PRIu64" not found for map id = %"PRIu32,
821 tracer_token, map->map_id);
822 ret = -EINVAL;
823 goto error_unlock;
824 }
825
826 ret = format_event_key(key, name, &formated_key);
827 if (ret) {
828 ERR("Error formating key");
829 ret = -EINVAL;
830 goto error_unlock;
831 }
832
833 ret = ust_registry_map_find_or_create_index_for_key(map, formated_key,
834 &counter_index);
835 if (ret) {
836 ERR("Error finding or creating index for formated_key = '%s'",
837 formated_key);
838 free(formated_key);
839 ret = -EINVAL;
840 goto error_unlock;
841 }
842
843 DBG3("UST registry allocating counter index %"PRIu64 " to event: %s, "
844 "signature: %s, sess_objd: %u, map_objd: %u, map_id: %u",
845 counter_index, name, sig, session_objd, map_objd, map->map_id);
846
847 *counter_index_p = counter_index;
848
849 rcu_read_unlock();
850 return 0;
851
852error_free:
853 free(sig);
854 free(fields);
855 free(model_emf_uri);
856error_unlock:
857 rcu_read_unlock();
858 return ret;
859}
860
861
d0b96690
DG
862/*
863 * For a given event in a registry, delete the entry and destroy the event.
864 * This MUST be called within a RCU read side lock section.
865 */
ebdb334b 866void ust_registry_chan_destroy_event(struct ust_registry_channel *chan,
d0b96690
DG
867 struct ust_registry_event *event)
868{
869 int ret;
870 struct lttng_ht_iter iter;
871
872 assert(chan);
873 assert(event);
874
875 /* Delete the node first. */
876 iter.iter.node = &event->node.node;
877 ret = lttng_ht_del(chan->ht, &iter);
878 assert(!ret);
879
880 call_rcu(&event->node.head, destroy_event_rcu);
881
882 return;
883}
884
ebdb334b
JR
885/*
886 * This MUST be called within a RCU read side lock section.
887 */
888static void ust_registry_map_key_entry_destroy(struct lttng_ht *ht,
889 struct ust_registry_map_key_ht_entry *entry)
890{
891 int ret;
892 struct lttng_ht_iter iter;
893
894 assert(ht);
895 assert(entry);
896
897 /* Delete the node first. */
898 iter.iter.node = &entry->node.node;
899 ret = lttng_ht_del(ht, &iter);
900 assert(!ret);
901
902 call_rcu(&entry->node.head, destroy_ust_registry_map_key_ht_entry);
903
904 return;
905}
906
907/*
908 * This MUST be called within a RCU read side lock section.
909 */
910static void ust_registry_map_index_ht_entry_destroy(struct lttng_ht *ht,
911 struct ust_registry_map_index_ht_entry *entry)
912{
913 int ret;
914 struct lttng_ht_iter iter;
915
916 assert(ht);
917 assert(entry);
918
919 /* Delete the node first. */
920 iter.iter.node = &entry->node.node;
921 ret = lttng_ht_del(ht, &iter);
922 assert(!ret);
923
924 call_rcu(&entry->node.head, destroy_ust_registry_map_index_ht_entry);
925
926 return;
927}
928
929/*
930 * For a given event in a registry, delete the entry and destroy the event.
931 * This MUST be called within a RCU read side lock section.
932 */
933void ust_registry_map_destroy_event(struct ust_registry_map *map,
934 struct ust_registry_event *event)
935{
936 int ret;
937 struct lttng_ht_iter iter;
938
939 assert(map);
940 assert(event);
941
942 /* Delete the node first. */
943 iter.iter.node = &event->node.node;
944 ret = lttng_ht_del(map->events_ht, &iter);
945 assert(!ret);
946
947 call_rcu(&event->node.head, destroy_event_rcu);
948
949 return;
950}
951
10b56aef
MD
952static void destroy_enum(struct ust_registry_enum *reg_enum)
953{
954 if (!reg_enum) {
955 return;
956 }
957 free(reg_enum->entries);
958 free(reg_enum);
959}
960
961static void destroy_enum_rcu(struct rcu_head *head)
962{
963 struct ust_registry_enum *reg_enum =
964 caa_container_of(head, struct ust_registry_enum, rcu_head);
965
966 destroy_enum(reg_enum);
967}
968
969/*
970 * Lookup enumeration by name and comparing enumeration entries.
971 * Needs to be called from RCU read-side critical section.
972 */
10dc2d10
SM
973static struct ust_registry_enum *ust_registry_lookup_enum(
974 struct ust_registry_session *session,
10b56aef
MD
975 const struct ust_registry_enum *reg_enum_lookup)
976{
977 struct ust_registry_enum *reg_enum = NULL;
978 struct lttng_ht_node_str *node;
979 struct lttng_ht_iter iter;
980
981 cds_lfht_lookup(session->enums->ht,
a752d6fa
FD
982 ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed),
983 ht_match_enum, reg_enum_lookup, &iter.iter);
10b56aef
MD
984 node = lttng_ht_iter_get_node_str(&iter);
985 if (!node) {
986 goto end;
987 }
988 reg_enum = caa_container_of(node, struct ust_registry_enum, node);
989end:
990 return reg_enum;
991}
992
993/*
994 * Lookup enumeration by enum ID.
995 * Needs to be called from RCU read-side critical section.
996 */
997struct ust_registry_enum *
998 ust_registry_lookup_enum_by_id(struct ust_registry_session *session,
999 const char *enum_name, uint64_t enum_id)
1000{
1001 struct ust_registry_enum *reg_enum = NULL;
1002 struct lttng_ht_node_str *node;
1003 struct lttng_ht_iter iter;
1004 struct ust_registry_enum reg_enum_lookup;
1005
1006 memset(&reg_enum_lookup, 0, sizeof(reg_enum_lookup));
1007 strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_SYM_NAME_LEN);
1008 reg_enum_lookup.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
1009 reg_enum_lookup.id = enum_id;
1010 cds_lfht_lookup(session->enums->ht,
1011 ht_hash_enum((void *) &reg_enum_lookup, lttng_ht_seed),
1012 ht_match_enum_id, &reg_enum_lookup, &iter.iter);
1013 node = lttng_ht_iter_get_node_str(&iter);
1014 if (!node) {
1015 goto end;
1016 }
1017 reg_enum = caa_container_of(node, struct ust_registry_enum, node);
1018end:
1019 return reg_enum;
1020}
1021
1022/*
1023 * Create a ust_registry_enum from the given parameters and add it to the
1024 * registry hash table, or find it if already there.
1025 *
1026 * On success, return 0 else a negative value.
1027 *
1028 * Should be called with session registry mutex held.
1029 *
1030 * We receive ownership of entries.
1031 */
1032int ust_registry_create_or_find_enum(struct ust_registry_session *session,
1033 int session_objd, char *enum_name,
1034 struct ustctl_enum_entry *entries, size_t nr_entries,
1035 uint64_t *enum_id)
1036{
1037 int ret = 0;
1038 struct cds_lfht_node *nodep;
1039 struct ust_registry_enum *reg_enum = NULL, *old_reg_enum;
1040
1041 assert(session);
1042 assert(enum_name);
1043
1044 rcu_read_lock();
1045
1046 /*
1047 * This should not happen but since it comes from the UST tracer, an
1048 * external party, don't assert and simply validate values.
1049 */
1050 if (session_objd < 0) {
1051 ret = -EINVAL;
1052 goto end;
1053 }
1054
1055 /* Check if the enumeration was already dumped */
1056 reg_enum = zmalloc(sizeof(*reg_enum));
1057 if (!reg_enum) {
1058 PERROR("zmalloc ust registry enumeration");
1059 ret = -ENOMEM;
1060 goto end;
1061 }
1062 strncpy(reg_enum->name, enum_name, LTTNG_UST_SYM_NAME_LEN);
1063 reg_enum->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
1064 /* entries will be owned by reg_enum. */
1065 reg_enum->entries = entries;
1066 reg_enum->nr_entries = nr_entries;
1067 entries = NULL;
1068
1069 old_reg_enum = ust_registry_lookup_enum(session, reg_enum);
1070 if (old_reg_enum) {
1071 DBG("enum %s already in sess_objd: %u", enum_name, session_objd);
1072 /* Fall through. Use prior enum. */
1073 destroy_enum(reg_enum);
1074 reg_enum = old_reg_enum;
1075 } else {
1076 DBG("UST registry creating enum: %s, sess_objd: %u",
1077 enum_name, session_objd);
1078 if (session->next_enum_id == -1ULL) {
1079 ret = -EOVERFLOW;
1080 destroy_enum(reg_enum);
1081 goto end;
1082 }
1083 reg_enum->id = session->next_enum_id++;
1084 cds_lfht_node_init(&reg_enum->node.node);
1085 nodep = cds_lfht_add_unique(session->enums->ht,
1086 ht_hash_enum(reg_enum, lttng_ht_seed),
1087 ht_match_enum_id, reg_enum,
1088 &reg_enum->node.node);
1089 assert(nodep == &reg_enum->node.node);
1090 }
1091 DBG("UST registry reply with enum %s with id %" PRIu64 " in sess_objd: %u",
1092 enum_name, reg_enum->id, session_objd);
1093 *enum_id = reg_enum->id;
1094end:
1095 free(entries);
1096 rcu_read_unlock();
1097 return ret;
1098}
1099
1100/*
1101 * For a given enumeration in a registry, delete the entry and destroy
1102 * the enumeration.
1103 * This MUST be called within a RCU read side lock section.
1104 */
10dc2d10 1105static void ust_registry_destroy_enum(struct ust_registry_session *reg_session,
10b56aef
MD
1106 struct ust_registry_enum *reg_enum)
1107{
1108 int ret;
1109 struct lttng_ht_iter iter;
1110
1111 assert(reg_session);
1112 assert(reg_enum);
1113
1114 /* Delete the node first. */
1115 iter.iter.node = &reg_enum->node.node;
1116 ret = lttng_ht_del(reg_session->enums, &iter);
1117 assert(!ret);
1118 call_rcu(&reg_enum->rcu_head, destroy_enum_rcu);
1119}
1120
36b588ed
MD
1121/*
1122 * We need to execute ht_destroy outside of RCU read-side critical
0b2dc8df
MD
1123 * section and outside of call_rcu thread, so we postpone its execution
1124 * using ht_cleanup_push. It is simpler than to change the semantic of
1125 * the many callers of delete_ust_app_session().
36b588ed
MD
1126 */
1127static
1128void destroy_channel_rcu(struct rcu_head *head)
1129{
1130 struct ust_registry_channel *chan =
1131 caa_container_of(head, struct ust_registry_channel, rcu_head);
1132
9dbcf332 1133 if (chan->ht) {
0b2dc8df 1134 ht_cleanup_push(chan->ht);
9dbcf332 1135 }
3295105b 1136 free(chan->ctx_fields);
36b588ed
MD
1137 free(chan);
1138}
1139
ebdb334b
JR
1140/*
1141 * We need to execute ht_destroy outside of RCU read-side critical
1142 * section and outside of call_rcu thread, so we postpone its execution
1143 * using ht_cleanup_push. It is simpler than to mapge the semantic of
1144 * the many callers of delete_ust_app_session().
1145 */
1146static
1147void destroy_map_rcu(struct rcu_head *head)
1148{
1149 struct ust_registry_map *map =
1150 caa_container_of(head, struct ust_registry_map, rcu_head);
1151
1152 if (map->events_ht) {
1153 ht_cleanup_push(map->events_ht);
1154 }
1155
1156 if (map->tracer_token_to_map_key_ht) {
1157 ht_cleanup_push(map->tracer_token_to_map_key_ht);
1158 }
1159
1160 if (map->key_string_to_bucket_index_ht) {
1161 ht_cleanup_push(map->key_string_to_bucket_index_ht);
1162 }
1163
1164 free(map);
1165}
1166
d0b96690
DG
1167/*
1168 * Destroy every element of the registry and free the memory. This does NOT
1169 * free the registry pointer since it might not have been allocated before so
1170 * it's the caller responsability.
d0b96690 1171 */
e9404c27 1172static void destroy_channel(struct ust_registry_channel *chan, bool notif)
d0b96690
DG
1173{
1174 struct lttng_ht_iter iter;
1175 struct ust_registry_event *event;
e9404c27 1176 enum lttng_error_code cmd_ret;
d0b96690
DG
1177
1178 assert(chan);
1179
e9404c27
JG
1180 if (notif) {
1181 cmd_ret = notification_thread_command_remove_channel(
1182 notification_thread_handle, chan->consumer_key,
1183 LTTNG_DOMAIN_UST);
1184 if (cmd_ret != LTTNG_OK) {
1185 ERR("Failed to remove channel from notification thread");
1186 }
1187 }
1188
70987ead
JG
1189 if (chan->ht) {
1190 rcu_read_lock();
1191 /* Destroy all event associated with this registry. */
1192 cds_lfht_for_each_entry(
1193 chan->ht->ht, &iter.iter, event, node.node) {
1194 /* Delete the node from the ht and free it. */
ebdb334b 1195 ust_registry_chan_destroy_event(chan, event);
70987ead
JG
1196 }
1197 rcu_read_unlock();
d0b96690 1198 }
36b588ed 1199 call_rcu(&chan->rcu_head, destroy_channel_rcu);
d0b96690
DG
1200}
1201
ebdb334b
JR
1202/*
1203 * Destroy every element of the registry and free the memory. This does NOT
1204 * free the registry pointer since it might not have been allocated before so
1205 * it's the caller responsability.
1206 */
1207static void destroy_map(struct ust_registry_map *map)
1208{
1209 struct lttng_ht_iter iter;
1210 struct ust_registry_event *event;
1211 struct ust_registry_map_key_ht_entry *key_entry;
1212 struct ust_registry_map_index_ht_entry *index_entry;
1213
1214 assert(map);
1215
1216 rcu_read_lock();
1217 if (map->events_ht) {
1218 /* Destroy all event associated with this registry. */
1219 cds_lfht_for_each_entry(map->events_ht->ht, &iter.iter, event, node.node) {
1220 /* Delete the node from the ht and free it. */
1221 ust_registry_map_destroy_event(map, event);
1222 }
1223 }
1224
1225 /* Destroy all map_key entries associated with this registry. */
1226 cds_lfht_for_each_entry (map->tracer_token_to_map_key_ht->ht,
1227 &iter.iter, key_entry, node.node) {
1228 ust_registry_map_key_entry_destroy(
1229 map->tracer_token_to_map_key_ht,
1230 key_entry);
1231 }
1232
1233 /* Destroy all index entry associated with this registry. */
1234 cds_lfht_for_each_entry(map->key_string_to_bucket_index_ht->ht,
1235 &iter.iter, index_entry, node.node) {
1236 ust_registry_map_index_ht_entry_destroy(
1237 map->key_string_to_bucket_index_ht,
1238 index_entry);
1239 }
1240 rcu_read_unlock();
1241 call_rcu(&map->rcu_head, destroy_map_rcu);
1242}
1243
d0b96690
DG
1244/*
1245 * Initialize registry with default values.
1246 */
45893984
DG
1247int ust_registry_channel_add(struct ust_registry_session *session,
1248 uint64_t key)
1249{
1250 int ret = 0;
1251 struct ust_registry_channel *chan;
1252
1253 assert(session);
1254
1255 chan = zmalloc(sizeof(*chan));
1256 if (!chan) {
1257 PERROR("zmalloc ust registry channel");
1258 ret = -ENOMEM;
9dbcf332 1259 goto error_alloc;
45893984
DG
1260 }
1261
1262 chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
1263 if (!chan->ht) {
1264 ret = -ENOMEM;
1265 goto error;
1266 }
1267
1268 /* Set custom match function. */
1269 chan->ht->match_fct = ht_match_event;
7972aab2
DG
1270 chan->ht->hash_fct = ht_hash_event;
1271
1272 /*
1273 * Assign a channel ID right now since the event notification comes
1274 * *before* the channel notify so the ID needs to be set at this point so
1275 * the metadata can be dumped for that event.
1276 */
1277 if (ust_registry_is_max_id(session->used_channel_id)) {
1278 ret = -1;
1279 goto error;
1280 }
1281 chan->chan_id = ust_registry_get_next_chan_id(session);
45893984
DG
1282
1283 rcu_read_lock();
1284 lttng_ht_node_init_u64(&chan->node, key);
1285 lttng_ht_add_unique_u64(session->channels, &chan->node);
1286 rcu_read_unlock();
1287
9dbcf332
DG
1288 return 0;
1289
45893984 1290error:
e9404c27 1291 destroy_channel(chan, false);
9dbcf332 1292error_alloc:
45893984
DG
1293 return ret;
1294}
1295
ebdb334b
JR
1296/*
1297 * Initialize registry map entry with default values.
1298 */
1299int ust_registry_map_add(struct ust_registry_session *session,
1300 uint64_t key)
1301{
1302 int ret = 0;
1303 struct ust_registry_map *map;
1304
1305 assert(session);
1306
1307 map = zmalloc(sizeof(*map));
1308 if (!map) {
1309 PERROR("zmalloc ust registry map");
1310 ret = -ENOMEM;
1311 goto error_alloc;
1312 }
1313
1314 map->events_ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
1315 if (!map->events_ht) {
1316 ret = -ENOMEM;
1317 goto error;
1318 }
1319
1320 /* Set custom match function. */
1321 map->events_ht->match_fct = ht_match_event;
1322 map->events_ht->hash_fct = ht_hash_event;
1323
1324 map->tracer_token_to_map_key_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
1325 if (!map->tracer_token_to_map_key_ht) {
1326 ret = -ENOMEM;
1327 goto error;
1328 }
1329
1330 map->key_string_to_bucket_index_ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
1331 if (!map->key_string_to_bucket_index_ht) {
1332 ret = -ENOMEM;
1333 goto error;
1334 }
1335
1336 /*
1337 * FIXME frdeso: fix this comment
1338 * Assign a map ID right now since the event notification comes
1339 * *before* the map notify so the ID needs to be set at this point so
1340 * the metadata can be dumped for that event.
1341 */
1342 if (ust_registry_is_max_id(session->used_map_id)) {
1343 ret = -1;
1344 goto error;
1345 }
1346 map->map_id = ust_registry_get_next_map_id(session);
1347
1348 rcu_read_lock();
1349 lttng_ht_node_init_u64(&map->node, key);
1350 lttng_ht_add_unique_u64(session->maps, &map->node);
1351 rcu_read_unlock();
1352
1353 return 0;
1354
1355error:
1356 destroy_map(map);
1357error_alloc:
1358 return ret;
1359}
1360
45893984
DG
1361/*
1362 * Find a channel in the given registry. RCU read side lock MUST be acquired
1363 * before calling this function and as long as the event reference is kept by
1364 * the caller.
1365 *
1366 * On success, the pointer is returned else NULL.
1367 */
1368struct ust_registry_channel *ust_registry_channel_find(
1369 struct ust_registry_session *session, uint64_t key)
1370{
1371 struct lttng_ht_node_u64 *node;
1372 struct lttng_ht_iter iter;
1373 struct ust_registry_channel *chan = NULL;
1374
1375 assert(session);
1376 assert(session->channels);
1377
7972aab2
DG
1378 DBG3("UST registry channel finding key %" PRIu64, key);
1379
45893984
DG
1380 lttng_ht_lookup(session->channels, &key, &iter);
1381 node = lttng_ht_iter_get_node_u64(&iter);
1382 if (!node) {
1383 goto end;
1384 }
1385 chan = caa_container_of(node, struct ust_registry_channel, node);
1386
1387end:
1388 return chan;
1389}
1390
ebdb334b
JR
1391/*
1392 * Find a map in the given registry. RCU read side lock MUST be acquired
1393 * before calling this function and as long as the event reference is kept by
1394 * the caller.
1395 *
1396 * On success, the pointer is returned else NULL.
1397 */
1398struct ust_registry_map *ust_registry_map_find(
1399 struct ust_registry_session *session, uint64_t key)
1400{
1401 struct lttng_ht_node_u64 *node;
1402 struct lttng_ht_iter iter;
1403 struct ust_registry_map *map = NULL;
1404
1405 assert(session);
1406 assert(session->maps);
1407
1408 DBG3("UST registry map finding key %" PRIu64, key);
1409
1410 lttng_ht_lookup(session->maps, &key, &iter);
1411 node = lttng_ht_iter_get_node_u64(&iter);
1412 if (!node) {
1413 goto end;
1414 }
1415 map = caa_container_of(node, struct ust_registry_map, node);
1416
1417end:
1418 return map;
1419}
1420
45893984
DG
1421/*
1422 * Remove channel using key from registry and free memory.
1423 */
1424void ust_registry_channel_del_free(struct ust_registry_session *session,
e9404c27 1425 uint64_t key, bool notif)
45893984
DG
1426{
1427 struct lttng_ht_iter iter;
1428 struct ust_registry_channel *chan;
9209cee7 1429 int ret;
45893984
DG
1430
1431 assert(session);
1432
1433 rcu_read_lock();
1434 chan = ust_registry_channel_find(session, key);
1435 if (!chan) {
9209cee7 1436 rcu_read_unlock();
45893984
DG
1437 goto end;
1438 }
1439
1440 iter.iter.node = &chan->node.node;
9209cee7
MD
1441 ret = lttng_ht_del(session->channels, &iter);
1442 assert(!ret);
1443 rcu_read_unlock();
e9404c27 1444 destroy_channel(chan, notif);
45893984
DG
1445
1446end:
45893984
DG
1447 return;
1448}
1449
ebdb334b
JR
1450/*
1451 * Remove map using key from registry and free memory.
1452 */
1453void ust_registry_map_del_free(struct ust_registry_session *session,
1454 uint64_t key)
1455{
1456 struct lttng_ht_iter iter;
1457 struct ust_registry_map *map;
1458 int ret;
1459
1460 assert(session);
1461
1462 rcu_read_lock();
1463 map = ust_registry_map_find(session, key);
1464 if (!map) {
1465 rcu_read_unlock();
1466 goto end;
1467 }
1468
1469 iter.iter.node = &map->node.node;
1470 ret = lttng_ht_del(session->maps, &iter);
1471 assert(!ret);
1472 rcu_read_unlock();
1473 destroy_map(map);
1474
1475end:
1476 return;
1477}
1478
45893984
DG
1479/*
1480 * Initialize registry with default values and set the newly allocated session
1481 * pointer to sessionp.
1482 *
1483 * Return 0 on success and sessionp is set or else return -1 and sessionp is
1484 * kept untouched.
1485 */
1486int ust_registry_session_init(struct ust_registry_session **sessionp,
d0b96690
DG
1487 struct ust_app *app,
1488 uint32_t bits_per_long,
1489 uint32_t uint8_t_alignment,
1490 uint32_t uint16_t_alignment,
1491 uint32_t uint32_t_alignment,
1492 uint32_t uint64_t_alignment,
1493 uint32_t long_alignment,
af6142cf
MD
1494 int byte_order,
1495 uint32_t major,
d7ba1388 1496 uint32_t minor,
3d071855 1497 const char *root_shm_path,
d7ba1388
MD
1498 const char *shm_path,
1499 uid_t euid,
8de88061
JR
1500 gid_t egid,
1501 uint64_t tracing_id,
1502 uid_t tracing_uid)
d0b96690
DG
1503{
1504 int ret;
45893984 1505 struct ust_registry_session *session;
d0b96690 1506
45893984 1507 assert(sessionp);
d0b96690 1508
45893984
DG
1509 session = zmalloc(sizeof(*session));
1510 if (!session) {
1511 PERROR("zmalloc ust registry session");
9dbcf332 1512 goto error_alloc;
45893984 1513 }
d0b96690
DG
1514
1515 pthread_mutex_init(&session->lock, NULL);
1516 session->bits_per_long = bits_per_long;
1517 session->uint8_t_alignment = uint8_t_alignment;
1518 session->uint16_t_alignment = uint16_t_alignment;
1519 session->uint32_t_alignment = uint32_t_alignment;
1520 session->uint64_t_alignment = uint64_t_alignment;
1521 session->long_alignment = long_alignment;
1522 session->byte_order = byte_order;
d7ba1388 1523 session->metadata_fd = -1;
4628484a
MD
1524 session->uid = euid;
1525 session->gid = egid;
10b56aef 1526 session->next_enum_id = 0;
7062f070
JD
1527 session->major = major;
1528 session->minor = minor;
3d071855
MD
1529 strncpy(session->root_shm_path, root_shm_path,
1530 sizeof(session->root_shm_path));
1531 session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0';
d7ba1388
MD
1532 if (shm_path[0]) {
1533 strncpy(session->shm_path, shm_path,
1534 sizeof(session->shm_path));
1535 session->shm_path[sizeof(session->shm_path) - 1] = '\0';
1536 strncpy(session->metadata_path, shm_path,
1537 sizeof(session->metadata_path));
1538 session->metadata_path[sizeof(session->metadata_path) - 1] = '\0';
1539 strncat(session->metadata_path, "/metadata",
1540 sizeof(session->metadata_path)
1541 - strlen(session->metadata_path) - 1);
1542 }
1543 if (session->shm_path[0]) {
1544 ret = run_as_mkdir_recursive(session->shm_path,
1545 S_IRWXU | S_IRWXG,
1546 euid, egid);
1547 if (ret) {
1548 PERROR("run_as_mkdir_recursive");
1549 goto error;
1550 }
1551 }
1552 if (session->metadata_path[0]) {
1553 /* Create metadata file */
4628484a 1554 ret = run_as_open(session->metadata_path,
d7ba1388 1555 O_WRONLY | O_CREAT | O_EXCL,
4628484a 1556 S_IRUSR | S_IWUSR, euid, egid);
d7ba1388
MD
1557 if (ret < 0) {
1558 PERROR("Opening metadata file");
1559 goto error;
1560 }
1561 session->metadata_fd = ret;
1562 }
d0b96690 1563
10b56aef
MD
1564 session->enums = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
1565 if (!session->enums) {
de64322e 1566 ERR("Failed to create enums hash table");
10b56aef
MD
1567 goto error;
1568 }
1569 /* hash/match functions are specified at call site. */
1570 session->enums->match_fct = NULL;
1571 session->enums->hash_fct = NULL;
1572
45893984
DG
1573 session->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
1574 if (!session->channels) {
1575 goto error;
1576 }
1577
ebdb334b
JR
1578 session->maps = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
1579 if (!session->maps) {
1580 lttng_ht_destroy(session->channels);
1581 goto error;
1582 }
1583
d0b96690
DG
1584 ret = lttng_uuid_generate(session->uuid);
1585 if (ret) {
1586 ERR("Failed to generate UST uuid (errno = %d)", ret);
1587 goto error;
1588 }
1589
8de88061
JR
1590 session->tracing_id = tracing_id;
1591 session->tracing_uid = tracing_uid;
1592
d0b96690 1593 pthread_mutex_lock(&session->lock);
af6142cf 1594 ret = ust_metadata_session_statedump(session, app, major, minor);
d0b96690
DG
1595 pthread_mutex_unlock(&session->lock);
1596 if (ret) {
1597 ERR("Failed to generate session metadata (errno = %d)", ret);
1598 goto error;
1599 }
1600
45893984
DG
1601 *sessionp = session;
1602
d0b96690
DG
1603 return 0;
1604
1605error:
9dbcf332 1606 ust_registry_session_destroy(session);
d24ff3fd 1607 free(session);
9dbcf332 1608error_alloc:
d0b96690
DG
1609 return -1;
1610}
1611
1612/*
1613 * Destroy session registry. This does NOT free the given pointer since it
1614 * might get passed as a reference. The registry lock should NOT be acquired.
1615 */
1616void ust_registry_session_destroy(struct ust_registry_session *reg)
1617{
1618 int ret;
45893984
DG
1619 struct lttng_ht_iter iter;
1620 struct ust_registry_channel *chan;
10b56aef 1621 struct ust_registry_enum *reg_enum;
d0b96690 1622
286c991a
MD
1623 if (!reg) {
1624 return;
1625 }
9d8efb0e 1626
d0b96690
DG
1627 /* On error, EBUSY can be returned if lock. Code flow error. */
1628 ret = pthread_mutex_destroy(&reg->lock);
1629 assert(!ret);
1630
9d8efb0e
DG
1631 if (reg->channels) {
1632 rcu_read_lock();
1633 /* Destroy all event associated with this registry. */
1634 cds_lfht_for_each_entry(reg->channels->ht, &iter.iter, chan,
1635 node.node) {
1636 /* Delete the node from the ht and free it. */
1637 ret = lttng_ht_del(reg->channels, &iter);
1638 assert(!ret);
e9404c27 1639 destroy_channel(chan, true);
9d8efb0e
DG
1640 }
1641 rcu_read_unlock();
1642 ht_cleanup_push(reg->channels);
45893984 1643 }
45893984 1644
d0b96690 1645 free(reg->metadata);
d7ba1388
MD
1646 if (reg->metadata_fd >= 0) {
1647 ret = close(reg->metadata_fd);
1648 if (ret) {
1649 PERROR("close");
1650 }
4628484a
MD
1651 ret = run_as_unlink(reg->metadata_path,
1652 reg->uid, reg->gid);
d7ba1388
MD
1653 if (ret) {
1654 PERROR("unlink");
1655 }
1656 }
3d071855
MD
1657 if (reg->root_shm_path[0]) {
1658 /*
1659 * Try deleting the directory hierarchy.
1660 */
602766ec 1661 (void) run_as_rmdir_recursive(reg->root_shm_path,
f75c5439
MD
1662 reg->uid, reg->gid,
1663 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
3d071855 1664 }
10b56aef
MD
1665 /* Destroy the enum hash table */
1666 if (reg->enums) {
1667 rcu_read_lock();
1668 /* Destroy all enum entries associated with this registry. */
1669 cds_lfht_for_each_entry(reg->enums->ht, &iter.iter, reg_enum,
1670 node.node) {
1671 ust_registry_destroy_enum(reg, reg_enum);
1672 }
1673 rcu_read_unlock();
1674 ht_cleanup_push(reg->enums);
1675 }
d0b96690 1676}
This page took 0.148417 seconds and 5 git commands to generate.