Fix: add UST context in the same order the user enabled them
[lttng-tools.git] / src / bin / lttng-sessiond / ust-registry.c
CommitLineData
d0b96690
DG
1/*
2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17#define _GNU_SOURCE
18#include <assert.h>
7972aab2 19#include <inttypes.h>
d0b96690
DG
20
21#include <common/common.h>
7972aab2
DG
22#include <common/hashtable/utils.h>
23#include <lttng/lttng.h>
24
d0b96690 25#include "ust-registry.h"
0b2dc8df 26#include "utils.h"
d0b96690
DG
27
28/*
29 * Hash table match function for event in the registry.
30 */
31static int ht_match_event(struct cds_lfht_node *node, const void *_key)
32{
33 struct ust_registry_event *event;
34 const struct ust_registry_event *key;
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
43 /* It has to be a perfect match. */
44 if (strncmp(event->name, key->name, sizeof(event->name)) != 0) {
45 goto no_match;
46 }
47
48 /* It has to be a perfect match. */
49 if (strncmp(event->signature, key->signature,
50 strlen(event->signature) != 0)) {
51 goto no_match;
52 }
53
54 /* Match */
55 return 1;
56
57no_match:
58 return 0;
59}
60
7972aab2
DG
61static unsigned long ht_hash_event(void *_key, unsigned long seed)
62{
63 uint64_t xored_key;
64 struct ust_registry_event *key = _key;
65
66 assert(key);
67
68 xored_key = (uint64_t) (hash_key_str(key->name, seed) ^
69 hash_key_str(key->signature, seed));
70
71 return hash_key_u64(&xored_key, seed);
72}
73
d0b96690
DG
74/*
75 * Allocate event and initialize it. This does NOT set a valid event id from a
76 * registry.
77 */
78static struct ust_registry_event *alloc_event(int session_objd,
79 int channel_objd, char *name, char *sig, size_t nr_fields,
80 struct ustctl_field *fields, int loglevel, char *model_emf_uri)
81{
82 struct ust_registry_event *event = NULL;
83
84 event = zmalloc(sizeof(*event));
85 if (!event) {
86 PERROR("zmalloc ust registry event");
87 goto error;
88 }
89
90 event->session_objd = session_objd;
91 event->channel_objd = channel_objd;
92 /* Allocated by ustctl. */
93 event->signature = sig;
94 event->nr_fields = nr_fields;
95 event->fields = fields;
96 event->loglevel = loglevel;
97 event->model_emf_uri = model_emf_uri;
98 if (name) {
99 /* Copy event name and force NULL byte. */
100 strncpy(event->name, name, sizeof(event->name));
101 event->name[sizeof(event->name) - 1] = '\0';
102 }
7972aab2 103 cds_lfht_node_init(&event->node.node);
d0b96690
DG
104
105error:
106 return event;
107}
108
109/*
110 * Free event data structure. This does NOT delete it from any hash table. It's
111 * safe to pass a NULL pointer. This shoudl be called inside a call RCU if the
112 * event is previously deleted from a rcu hash table.
113 */
114static void destroy_event(struct ust_registry_event *event)
115{
116 if (!event) {
117 return;
118 }
119
120 free(event->fields);
121 free(event->model_emf_uri);
122 free(event->signature);
123 free(event);
124}
125
126/*
127 * Destroy event function call of the call RCU.
128 */
129static void destroy_event_rcu(struct rcu_head *head)
130{
7972aab2
DG
131 struct lttng_ht_node_u64 *node =
132 caa_container_of(head, struct lttng_ht_node_u64, head);
d0b96690
DG
133 struct ust_registry_event *event =
134 caa_container_of(node, struct ust_registry_event, node);
135
136 destroy_event(event);
137}
138
139/*
140 * Find an event using the name and signature in the given registry. RCU read
141 * side lock MUST be acquired before calling this function and as long as the
142 * event reference is kept by the caller.
143 *
144 * On success, the event pointer is returned else NULL.
145 */
146struct ust_registry_event *ust_registry_find_event(
147 struct ust_registry_channel *chan, char *name, char *sig)
148{
7972aab2 149 struct lttng_ht_node_u64 *node;
d0b96690
DG
150 struct lttng_ht_iter iter;
151 struct ust_registry_event *event = NULL;
152 struct ust_registry_event key;
153
154 assert(chan);
155 assert(name);
156 assert(sig);
157
158 /* Setup key for the match function. */
159 strncpy(key.name, name, sizeof(key.name));
160 key.name[sizeof(key.name) - 1] = '\0';
161 key.signature = sig;
162
7972aab2 163 cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed),
d0b96690 164 chan->ht->match_fct, &key, &iter.iter);
7972aab2 165 node = lttng_ht_iter_get_node_u64(&iter);
d0b96690
DG
166 if (!node) {
167 goto end;
168 }
169 event = caa_container_of(node, struct ust_registry_event, node);
170
171end:
172 return event;
173}
174
175/*
176 * Create a ust_registry_event from the given parameters and add it to the
177 * registry hash table. If event_id is valid, it is set with the newly created
178 * event id.
179 *
180 * On success, return 0 else a negative value. The created event MUST be unique
181 * so on duplicate entry -EINVAL is returned. On error, event_id is untouched.
182 *
183 * Should be called with session registry mutex held.
184 */
185int ust_registry_create_event(struct ust_registry_session *session,
45893984
DG
186 uint64_t chan_key, int session_objd, int channel_objd, char *name,
187 char *sig, size_t nr_fields, struct ustctl_field *fields, int loglevel,
7972aab2 188 char *model_emf_uri, int buffer_type, uint32_t *event_id_p)
d0b96690
DG
189{
190 int ret;
7972aab2 191 uint32_t event_id;
d0b96690
DG
192 struct cds_lfht_node *nptr;
193 struct ust_registry_event *event = NULL;
45893984 194 struct ust_registry_channel *chan;
d0b96690
DG
195
196 assert(session);
d0b96690
DG
197 assert(name);
198 assert(sig);
7972aab2 199 assert(event_id_p);
d0b96690 200
d5d629b5
DG
201 rcu_read_lock();
202
d0b96690
DG
203 /*
204 * This should not happen but since it comes from the UST tracer, an
205 * external party, don't assert and simply validate values.
206 */
207 if (session_objd < 0 || channel_objd < 0) {
208 ret = -EINVAL;
d5d629b5 209 goto error_free;
d0b96690
DG
210 }
211
45893984
DG
212 chan = ust_registry_channel_find(session, chan_key);
213 if (!chan) {
214 ret = -EINVAL;
d5d629b5 215 goto error_free;
45893984
DG
216 }
217
d0b96690
DG
218 /* Check if we've reached the maximum possible id. */
219 if (ust_registry_is_max_id(chan->used_event_id)) {
220 ret = -ENOENT;
d5d629b5 221 goto error_free;
d0b96690
DG
222 }
223
224 event = alloc_event(session_objd, channel_objd, name, sig, nr_fields,
225 fields, loglevel, model_emf_uri);
226 if (!event) {
227 ret = -ENOMEM;
d5d629b5 228 goto error_free;
d0b96690
DG
229 }
230
d0b96690 231 DBG3("UST registry creating event with event: %s, sig: %s, id: %u, "
7972aab2
DG
232 "chan_objd: %u, sess_objd: %u, chan_id: %u", event->name,
233 event->signature, event->id, event->channel_objd,
234 event->session_objd, chan->chan_id);
d0b96690 235
d0b96690
DG
236 /*
237 * This is an add unique with a custom match function for event. The node
238 * are matched using the event name and signature.
239 */
7972aab2 240 nptr = cds_lfht_add_unique(chan->ht->ht, chan->ht->hash_fct(event,
d0b96690
DG
241 lttng_ht_seed), chan->ht->match_fct, event, &event->node.node);
242 if (nptr != &event->node.node) {
7972aab2
DG
243 if (buffer_type == LTTNG_BUFFER_PER_UID) {
244 /*
245 * This is normal, we just have to send the event id of the
246 * returned node and make sure we destroy the previously allocated
247 * event object.
248 */
249 destroy_event(event);
250 event = caa_container_of(nptr, struct ust_registry_event,
251 node.node);
252 assert(event);
253 event_id = event->id;
254 } else {
255 ERR("UST registry create event add unique failed for event: %s, "
256 "sig: %s, id: %u, chan_objd: %u, sess_objd: %u",
257 event->name, event->signature, event->id,
258 event->channel_objd, event->session_objd);
259 ret = -EINVAL;
260 goto error_unlock;
261 }
262 } else {
263 /* Request next event id if the node was successfully added. */
264 event_id = event->id = ust_registry_get_next_event_id(chan);
d0b96690
DG
265 }
266
7972aab2 267 *event_id_p = event_id;
d0b96690 268
7972aab2
DG
269 if (!event->metadata_dumped) {
270 /* Append to metadata */
271 ret = ust_metadata_event_statedump(session, chan, event);
272 if (ret) {
273 ERR("Error appending event metadata (errno = %d)", ret);
274 rcu_read_unlock();
275 return ret;
276 }
d0b96690
DG
277 }
278
45893984 279 rcu_read_unlock();
d0b96690
DG
280 return 0;
281
d5d629b5
DG
282error_free:
283 free(sig);
284 free(fields);
285 free(model_emf_uri);
d0b96690
DG
286error_unlock:
287 rcu_read_unlock();
d0b96690
DG
288 destroy_event(event);
289 return ret;
290}
291
292/*
293 * For a given event in a registry, delete the entry and destroy the event.
294 * This MUST be called within a RCU read side lock section.
295 */
296void ust_registry_destroy_event(struct ust_registry_channel *chan,
297 struct ust_registry_event *event)
298{
299 int ret;
300 struct lttng_ht_iter iter;
301
302 assert(chan);
303 assert(event);
304
305 /* Delete the node first. */
306 iter.iter.node = &event->node.node;
307 ret = lttng_ht_del(chan->ht, &iter);
308 assert(!ret);
309
310 call_rcu(&event->node.head, destroy_event_rcu);
311
312 return;
313}
314
36b588ed
MD
315/*
316 * We need to execute ht_destroy outside of RCU read-side critical
0b2dc8df
MD
317 * section and outside of call_rcu thread, so we postpone its execution
318 * using ht_cleanup_push. It is simpler than to change the semantic of
319 * the many callers of delete_ust_app_session().
36b588ed
MD
320 */
321static
322void destroy_channel_rcu(struct rcu_head *head)
323{
324 struct ust_registry_channel *chan =
325 caa_container_of(head, struct ust_registry_channel, rcu_head);
326
9dbcf332 327 if (chan->ht) {
0b2dc8df 328 ht_cleanup_push(chan->ht);
9dbcf332 329 }
3295105b 330 free(chan->ctx_fields);
36b588ed
MD
331 free(chan);
332}
333
d0b96690
DG
334/*
335 * Destroy every element of the registry and free the memory. This does NOT
336 * free the registry pointer since it might not have been allocated before so
337 * it's the caller responsability.
d0b96690 338 */
45893984 339static void destroy_channel(struct ust_registry_channel *chan)
d0b96690
DG
340{
341 struct lttng_ht_iter iter;
342 struct ust_registry_event *event;
343
344 assert(chan);
345
9209cee7 346 rcu_read_lock();
d0b96690
DG
347 /* Destroy all event associated with this registry. */
348 cds_lfht_for_each_entry(chan->ht->ht, &iter.iter, event, node.node) {
349 /* Delete the node from the ht and free it. */
350 ust_registry_destroy_event(chan, event);
351 }
9209cee7 352 rcu_read_unlock();
36b588ed 353 call_rcu(&chan->rcu_head, destroy_channel_rcu);
d0b96690
DG
354}
355
356/*
357 * Initialize registry with default values.
358 */
45893984
DG
359int ust_registry_channel_add(struct ust_registry_session *session,
360 uint64_t key)
361{
362 int ret = 0;
363 struct ust_registry_channel *chan;
364
365 assert(session);
366
367 chan = zmalloc(sizeof(*chan));
368 if (!chan) {
369 PERROR("zmalloc ust registry channel");
370 ret = -ENOMEM;
9dbcf332 371 goto error_alloc;
45893984
DG
372 }
373
374 chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
375 if (!chan->ht) {
376 ret = -ENOMEM;
377 goto error;
378 }
379
380 /* Set custom match function. */
381 chan->ht->match_fct = ht_match_event;
7972aab2
DG
382 chan->ht->hash_fct = ht_hash_event;
383
384 /*
385 * Assign a channel ID right now since the event notification comes
386 * *before* the channel notify so the ID needs to be set at this point so
387 * the metadata can be dumped for that event.
388 */
389 if (ust_registry_is_max_id(session->used_channel_id)) {
390 ret = -1;
391 goto error;
392 }
393 chan->chan_id = ust_registry_get_next_chan_id(session);
45893984
DG
394
395 rcu_read_lock();
396 lttng_ht_node_init_u64(&chan->node, key);
397 lttng_ht_add_unique_u64(session->channels, &chan->node);
398 rcu_read_unlock();
399
9dbcf332
DG
400 return 0;
401
45893984 402error:
9dbcf332
DG
403 destroy_channel(chan);
404error_alloc:
45893984
DG
405 return ret;
406}
407
408/*
409 * Find a channel in the given registry. RCU read side lock MUST be acquired
410 * before calling this function and as long as the event reference is kept by
411 * the caller.
412 *
413 * On success, the pointer is returned else NULL.
414 */
415struct ust_registry_channel *ust_registry_channel_find(
416 struct ust_registry_session *session, uint64_t key)
417{
418 struct lttng_ht_node_u64 *node;
419 struct lttng_ht_iter iter;
420 struct ust_registry_channel *chan = NULL;
421
422 assert(session);
423 assert(session->channels);
424
7972aab2
DG
425 DBG3("UST registry channel finding key %" PRIu64, key);
426
45893984
DG
427 lttng_ht_lookup(session->channels, &key, &iter);
428 node = lttng_ht_iter_get_node_u64(&iter);
429 if (!node) {
430 goto end;
431 }
432 chan = caa_container_of(node, struct ust_registry_channel, node);
433
434end:
435 return chan;
436}
437
438/*
439 * Remove channel using key from registry and free memory.
440 */
441void ust_registry_channel_del_free(struct ust_registry_session *session,
442 uint64_t key)
443{
444 struct lttng_ht_iter iter;
445 struct ust_registry_channel *chan;
9209cee7 446 int ret;
45893984
DG
447
448 assert(session);
449
450 rcu_read_lock();
451 chan = ust_registry_channel_find(session, key);
452 if (!chan) {
9209cee7 453 rcu_read_unlock();
45893984
DG
454 goto end;
455 }
456
457 iter.iter.node = &chan->node.node;
9209cee7
MD
458 ret = lttng_ht_del(session->channels, &iter);
459 assert(!ret);
460 rcu_read_unlock();
45893984
DG
461 destroy_channel(chan);
462
463end:
45893984
DG
464 return;
465}
466
467/*
468 * Initialize registry with default values and set the newly allocated session
469 * pointer to sessionp.
470 *
471 * Return 0 on success and sessionp is set or else return -1 and sessionp is
472 * kept untouched.
473 */
474int ust_registry_session_init(struct ust_registry_session **sessionp,
d0b96690
DG
475 struct ust_app *app,
476 uint32_t bits_per_long,
477 uint32_t uint8_t_alignment,
478 uint32_t uint16_t_alignment,
479 uint32_t uint32_t_alignment,
480 uint32_t uint64_t_alignment,
481 uint32_t long_alignment,
af6142cf
MD
482 int byte_order,
483 uint32_t major,
484 uint32_t minor)
d0b96690
DG
485{
486 int ret;
45893984 487 struct ust_registry_session *session;
d0b96690 488
45893984 489 assert(sessionp);
d0b96690 490
45893984
DG
491 session = zmalloc(sizeof(*session));
492 if (!session) {
493 PERROR("zmalloc ust registry session");
9dbcf332 494 goto error_alloc;
45893984 495 }
d0b96690
DG
496
497 pthread_mutex_init(&session->lock, NULL);
498 session->bits_per_long = bits_per_long;
499 session->uint8_t_alignment = uint8_t_alignment;
500 session->uint16_t_alignment = uint16_t_alignment;
501 session->uint32_t_alignment = uint32_t_alignment;
502 session->uint64_t_alignment = uint64_t_alignment;
503 session->long_alignment = long_alignment;
504 session->byte_order = byte_order;
505
45893984
DG
506 session->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
507 if (!session->channels) {
508 goto error;
509 }
510
d0b96690
DG
511 ret = lttng_uuid_generate(session->uuid);
512 if (ret) {
513 ERR("Failed to generate UST uuid (errno = %d)", ret);
514 goto error;
515 }
516
517 pthread_mutex_lock(&session->lock);
af6142cf 518 ret = ust_metadata_session_statedump(session, app, major, minor);
d0b96690
DG
519 pthread_mutex_unlock(&session->lock);
520 if (ret) {
521 ERR("Failed to generate session metadata (errno = %d)", ret);
522 goto error;
523 }
524
45893984
DG
525 *sessionp = session;
526
d0b96690
DG
527 return 0;
528
529error:
9dbcf332
DG
530 ust_registry_session_destroy(session);
531error_alloc:
d0b96690
DG
532 return -1;
533}
534
535/*
536 * Destroy session registry. This does NOT free the given pointer since it
537 * might get passed as a reference. The registry lock should NOT be acquired.
538 */
539void ust_registry_session_destroy(struct ust_registry_session *reg)
540{
541 int ret;
45893984
DG
542 struct lttng_ht_iter iter;
543 struct ust_registry_channel *chan;
d0b96690
DG
544
545 /* On error, EBUSY can be returned if lock. Code flow error. */
546 ret = pthread_mutex_destroy(&reg->lock);
547 assert(!ret);
548
45893984
DG
549 rcu_read_lock();
550 /* Destroy all event associated with this registry. */
551 cds_lfht_for_each_entry(reg->channels->ht, &iter.iter, chan, node.node) {
552 /* Delete the node from the ht and free it. */
553 ret = lttng_ht_del(reg->channels, &iter);
554 assert(!ret);
555 destroy_channel(chan);
556 }
45893984
DG
557 rcu_read_unlock();
558
52d8ccce 559 ht_cleanup_push(reg->channels);
d0b96690
DG
560 free(reg->metadata);
561}
This page took 0.076357 seconds and 4 git commands to generate.