clang-tidy: add Chrome-inspired checks
[lttng-tools.git] / src / bin / lttng-sessiond / notification-thread-events.cpp
CommitLineData
ab0ee2ca 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
ab0ee2ca 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
ab0ee2ca 5 *
ab0ee2ca
JG
6 */
7
f2b3ef9f 8#include "lttng/action/action.h"
c9e313bc 9#include "lttng/trigger/trigger-internal.hpp"
ab0ee2ca 10#define _LGPL_SOURCE
28ab034a
JG
11#include "condition-internal.hpp"
12#include "event-notifier-error-accounting.hpp"
13#include "kernel.hpp"
14#include "lttng-sessiond.hpp"
15#include "notification-thread-commands.hpp"
16#include "notification-thread-events.hpp"
17#include "notification-thread.hpp"
ab0ee2ca 18
c9e313bc 19#include <common/defaults.hpp>
28ab034a 20#include <common/dynamic-buffer.hpp>
c9e313bc
SM
21#include <common/error.hpp>
22#include <common/futex.hpp>
c9e313bc 23#include <common/hashtable/utils.hpp>
c9e313bc 24#include <common/macros.hpp>
28ab034a
JG
25#include <common/sessiond-comm/sessiond-comm.hpp>
26#include <common/unix.hpp>
27
c9e313bc
SM
28#include <lttng/action/action-internal.hpp>
29#include <lttng/action/list-internal.hpp>
c9e313bc 30#include <lttng/condition/buffer-usage-internal.hpp>
28ab034a
JG
31#include <lttng/condition/condition-internal.hpp>
32#include <lttng/condition/condition.h>
33#include <lttng/condition/event-rule-matches-internal.hpp>
c9e313bc
SM
34#include <lttng/condition/session-consumed-size-internal.hpp>
35#include <lttng/condition/session-rotation-internal.hpp>
c9e313bc 36#include <lttng/domain-internal.hpp>
c9e313bc 37#include <lttng/event-rule/event-rule-internal.hpp>
319dcddc 38#include <lttng/location-internal.hpp>
28ab034a
JG
39#include <lttng/notification/channel-internal.hpp>
40#include <lttng/notification/notification-internal.hpp>
41#include <lttng/trigger/trigger-internal.hpp>
1da26331 42
28ab034a
JG
43#include <fcntl.h>
44#include <inttypes.h>
ab0ee2ca
JG
45#include <time.h>
46#include <unistd.h>
28ab034a
JG
47#include <urcu.h>
48#include <urcu/rculfhash.h>
1da26331 49
28ab034a 50#define CLIENT_POLL_EVENTS_IN (LPOLLIN | LPOLLRDHUP)
9016dbfc 51#define CLIENT_POLL_EVENTS_IN_OUT (CLIENT_POLL_EVENTS_IN | LPOLLOUT)
ab0ee2ca 52
82b3cbf4
JR
53/* The tracers currently limit the capture size to PIPE_BUF (4kb on linux). */
54#define MAX_CAPTURE_SIZE (PIPE_BUF)
55
51eab943
JG
56enum lttng_object_type {
57 LTTNG_OBJECT_TYPE_UNKNOWN,
58 LTTNG_OBJECT_TYPE_NONE,
59 LTTNG_OBJECT_TYPE_CHANNEL,
60 LTTNG_OBJECT_TYPE_SESSION,
61};
62
ab0ee2ca
JG
63struct lttng_channel_trigger_list {
64 struct channel_key channel_key;
ea9a44f0 65 /* List of struct lttng_trigger_list_element. */
ab0ee2ca 66 struct cds_list_head list;
ea9a44f0 67 /* Node in the channel_triggers_ht */
ab0ee2ca 68 struct cds_lfht_node channel_triggers_ht_node;
83b934ad
MD
69 /* call_rcu delayed reclaim. */
70 struct rcu_head rcu_node;
ab0ee2ca
JG
71};
72
ea9a44f0
JG
73/*
74 * List of triggers applying to a given session.
75 *
76 * See:
77 * - lttng_session_trigger_list_create()
78 * - lttng_session_trigger_list_build()
79 * - lttng_session_trigger_list_destroy()
80 * - lttng_session_trigger_list_add()
81 */
82struct lttng_session_trigger_list {
319dcddc 83 char *session_name;
ea9a44f0
JG
84 /* List of struct lttng_trigger_list_element. */
85 struct cds_list_head list;
86 /* Node in the session_triggers_ht */
87 struct cds_lfht_node session_triggers_ht_node;
88 /*
89 * Weak reference to the notification system's session triggers
90 * hashtable.
91 *
92 * The session trigger list structure structure is owned by
93 * the session's session_info.
94 *
95 * The session_info is kept alive the the channel_infos holding a
96 * reference to it (reference counting). When those channels are
97 * destroyed (at runtime or on teardown), the reference they hold
98 * to the session_info are released. On destruction of session_info,
99 * session_info_destroy() will remove the list of triggers applying
100 * to this session from the notification system's state.
101 *
102 * This implies that the session_triggers_ht must be destroyed
103 * after the channels.
104 */
105 struct cds_lfht *session_triggers_ht;
106 /* Used for delayed RCU reclaim. */
107 struct rcu_head rcu_node;
108};
109
f1494934
JG
110namespace {
111struct lttng_trigger_list_element {
112 /* No ownership of the trigger object is assumed. */
113 struct lttng_trigger *trigger;
114 struct cds_list_head node;
115};
116
ab0ee2ca
JG
117struct lttng_trigger_ht_element {
118 struct lttng_trigger *trigger;
119 struct cds_lfht_node node;
242388e4 120 struct cds_lfht_node node_by_name_uid;
091fa780 121 struct cds_list_head client_list_trigger_node;
83b934ad
MD
122 /* call_rcu delayed reclaim. */
123 struct rcu_head rcu_node;
ab0ee2ca
JG
124};
125
126struct lttng_condition_list_element {
127 struct lttng_condition *condition;
128 struct cds_list_head node;
129};
130
ab0ee2ca
JG
131struct channel_state_sample {
132 struct channel_key key;
133 struct cds_lfht_node channel_state_ht_node;
134 uint64_t highest_usage;
135 uint64_t lowest_usage;
83b934ad
MD
136 /* call_rcu delayed reclaim. */
137 struct rcu_head rcu_node;
ab0ee2ca 138};
f1494934 139} /* namespace */
ab0ee2ca 140
e4db5ace 141static unsigned long hash_channel_key(struct channel_key *key);
ed327204 142static int evaluate_buffer_condition(const struct lttng_condition *condition,
28ab034a
JG
143 struct lttng_evaluation **evaluation,
144 const struct notification_thread_state *state,
145 const struct channel_state_sample *previous_sample,
146 const struct channel_state_sample *latest_sample,
147 struct channel_info *channel_info);
148static int send_evaluation_to_clients(const struct lttng_trigger *trigger,
149 const struct lttng_evaluation *evaluation,
150 struct notification_client_list *client_list,
151 struct notification_thread_state *state,
152 uid_t channel_uid,
153 gid_t channel_gid);
8abe313a 154
ea9a44f0 155/* session_info API */
28ab034a
JG
156static void session_info_destroy(void *_data);
157static void session_info_get(struct session_info *session_info);
158static void session_info_put(struct session_info *session_info);
159static struct session_info *session_info_create(uint64_t id,
160 const char *name,
161 uid_t uid,
162 gid_t gid,
163 struct lttng_session_trigger_list *trigger_list,
164 struct cds_lfht *sessions_ht);
165static void session_info_add_channel(struct session_info *session_info,
166 struct channel_info *channel_info);
167static void session_info_remove_channel(struct session_info *session_info,
168 struct channel_info *channel_info);
8abe313a 169
ea9a44f0 170/* lttng_session_trigger_list API */
28ab034a
JG
171static struct lttng_session_trigger_list *
172lttng_session_trigger_list_create(const char *session_name, struct cds_lfht *session_triggers_ht);
173static struct lttng_session_trigger_list *
174lttng_session_trigger_list_build(const struct notification_thread_state *state,
175 const char *session_name);
176static void lttng_session_trigger_list_destroy(struct lttng_session_trigger_list *list);
177static int lttng_session_trigger_list_add(struct lttng_session_trigger_list *list,
178 struct lttng_trigger *trigger);
179
180static int client_handle_transmission_status(struct notification_client *client,
181 enum client_transmission_status transmission_status,
182 struct notification_thread_state *state);
183
184static int handle_one_event_notifier_notification(struct notification_thread_state *state,
185 int pipe,
186 enum lttng_domain_type domain);
187
188static void free_lttng_trigger_ht_element_rcu(struct rcu_head *node);
189
190static int match_client_socket(struct cds_lfht_node *node, const void *key)
ab0ee2ca
JG
191{
192 /* This double-cast is intended to supress pointer-to-cast warning. */
ac1889bf 193 const int socket = (int) (intptr_t) key;
28ab034a
JG
194 const struct notification_client *client =
195 caa_container_of(node, struct notification_client, client_socket_ht_node);
ab0ee2ca 196
ac1889bf
JG
197 return client->socket == socket;
198}
199
28ab034a 200static int match_client_id(struct cds_lfht_node *node, const void *key)
ac1889bf
JG
201{
202 /* This double-cast is intended to supress pointer-to-cast warning. */
203 const notification_client_id id = *((notification_client_id *) key);
28ab034a
JG
204 const struct notification_client *client =
205 lttng::utils::container_of(node, &notification_client::client_id_ht_node);
ab0ee2ca 206
ac1889bf 207 return client->id == id;
ab0ee2ca
JG
208}
209
28ab034a 210static int match_channel_trigger_list(struct cds_lfht_node *node, const void *key)
ab0ee2ca
JG
211{
212 struct channel_key *channel_key = (struct channel_key *) key;
213 struct lttng_channel_trigger_list *trigger_list;
214
28ab034a
JG
215 trigger_list =
216 caa_container_of(node, struct lttng_channel_trigger_list, channel_triggers_ht_node);
ab0ee2ca
JG
217
218 return !!((channel_key->key == trigger_list->channel_key.key) &&
28ab034a 219 (channel_key->domain == trigger_list->channel_key.domain));
ab0ee2ca
JG
220}
221
28ab034a 222static int match_session_trigger_list(struct cds_lfht_node *node, const void *key)
51eab943
JG
223{
224 const char *session_name = (const char *) key;
225 struct lttng_session_trigger_list *trigger_list;
226
28ab034a
JG
227 trigger_list =
228 caa_container_of(node, struct lttng_session_trigger_list, session_triggers_ht_node);
51eab943
JG
229
230 return !!(strcmp(trigger_list->session_name, session_name) == 0);
231}
232
28ab034a 233static int match_channel_state_sample(struct cds_lfht_node *node, const void *key)
ab0ee2ca
JG
234{
235 struct channel_key *channel_key = (struct channel_key *) key;
236 struct channel_state_sample *sample;
237
28ab034a 238 sample = caa_container_of(node, struct channel_state_sample, channel_state_ht_node);
ab0ee2ca
JG
239
240 return !!((channel_key->key == sample->key.key) &&
28ab034a 241 (channel_key->domain == sample->key.domain));
ab0ee2ca
JG
242}
243
28ab034a 244static int match_channel_info(struct cds_lfht_node *node, const void *key)
ab0ee2ca
JG
245{
246 struct channel_key *channel_key = (struct channel_key *) key;
247 struct channel_info *channel_info;
248
28ab034a 249 channel_info = caa_container_of(node, struct channel_info, channels_ht_node);
ab0ee2ca
JG
250
251 return !!((channel_key->key == channel_info->key.key) &&
28ab034a 252 (channel_key->domain == channel_info->key.domain));
ab0ee2ca
JG
253}
254
28ab034a 255static int match_trigger(struct cds_lfht_node *node, const void *key)
ab0ee2ca 256{
242388e4
JR
257 struct lttng_trigger *trigger_key = (struct lttng_trigger *) key;
258 struct lttng_trigger_ht_element *trigger_ht_element;
ab0ee2ca 259
28ab034a 260 trigger_ht_element = caa_container_of(node, struct lttng_trigger_ht_element, node);
ab0ee2ca 261
242388e4 262 return !!lttng_trigger_is_equal(trigger_key, trigger_ht_element->trigger);
ab0ee2ca
JG
263}
264
28ab034a 265static int match_trigger_token(struct cds_lfht_node *node, const void *key)
e7c93cf9 266{
7966af57 267 const uint64_t *_key = (uint64_t *) key;
e7c93cf9
JR
268 struct notification_trigger_tokens_ht_element *element;
269
28ab034a 270 element = caa_container_of(node, struct notification_trigger_tokens_ht_element, node);
e7c93cf9
JR
271 return *_key == element->token;
272}
273
28ab034a 274static int match_client_list_condition(struct cds_lfht_node *node, const void *key)
ab0ee2ca
JG
275{
276 struct lttng_condition *condition_key = (struct lttng_condition *) key;
277 struct notification_client_list *client_list;
f82f93a1 278 const struct lttng_condition *condition;
ab0ee2ca 279
a0377dfe 280 LTTNG_ASSERT(condition_key);
ab0ee2ca 281
28ab034a
JG
282 client_list = caa_container_of(
283 node, struct notification_client_list, notification_trigger_clients_ht_node);
091fa780 284 condition = client_list->condition;
ab0ee2ca
JG
285
286 return !!lttng_condition_is_equal(condition_key, condition);
287}
288
28ab034a 289static int match_session_info(struct cds_lfht_node *node, const void *key)
f82f93a1 290{
139a8d25 291 const auto session_id = *((uint64_t *) key);
28ab034a
JG
292 const auto *session_info =
293 lttng::utils::container_of(node, &session_info::sessions_ht_node);
f82f93a1 294
139a8d25
JG
295 return session_id == session_info->id;
296}
297
28ab034a 298static unsigned long hash_session_info_id(uint64_t id)
139a8d25
JG
299{
300 return hash_key_u64(&id, lttng_ht_seed);
301}
302
28ab034a 303static unsigned long hash_session_info(const struct session_info *session_info)
139a8d25
JG
304{
305 return hash_session_info_id(session_info->id);
306}
307
28ab034a
JG
308static struct session_info *get_session_info_by_id(const struct notification_thread_state *state,
309 uint64_t id)
139a8d25
JG
310{
311 struct cds_lfht_iter iter;
312 struct cds_lfht_node *node;
313 lttng::urcu::read_lock_guard read_lock_guard;
314
28ab034a
JG
315 cds_lfht_lookup(
316 state->sessions_ht, hash_session_info_id(id), match_session_info, &id, &iter);
139a8d25
JG
317 node = cds_lfht_iter_get_node(&iter);
318
319 if (node) {
28ab034a
JG
320 auto session_info =
321 lttng::utils::container_of(node, &session_info::sessions_ht_node);
139a8d25
JG
322
323 session_info_get(session_info);
324 return session_info;
325 }
326
cd9adb8b 327 return nullptr;
139a8d25
JG
328}
329
28ab034a
JG
330static struct session_info *get_session_info_by_name(const struct notification_thread_state *state,
331 const char *name)
139a8d25
JG
332{
333 uint64_t session_id;
334 const auto found = sample_session_id_by_name(name, &session_id);
335
cd9adb8b 336 return found ? get_session_info_by_id(state, session_id) : nullptr;
f82f93a1
JG
337}
338
28ab034a 339static const char *notification_command_type_str(enum notification_thread_command_type type)
6900ae81
FD
340{
341 switch (type) {
342 case NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER:
343 return "REGISTER_TRIGGER";
344 case NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER:
345 return "UNREGISTER_TRIGGER";
346 case NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL:
347 return "ADD_CHANNEL";
348 case NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL:
349 return "REMOVE_CHANNEL";
139a8d25
JG
350 case NOTIFICATION_COMMAND_TYPE_ADD_SESSION:
351 return "ADD_SESSION";
352 case NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION:
353 return "REMOVE_SESSION";
6900ae81
FD
354 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING:
355 return "SESSION_ROTATION_ONGOING";
356 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED:
357 return "SESSION_ROTATION_COMPLETED";
358 case NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE:
359 return "ADD_TRACER_EVENT_SOURCE";
360 case NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE:
361 return "REMOVE_TRACER_EVENT_SOURCE";
362 case NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS:
363 return "LIST_TRIGGERS";
8790759c
FD
364 case NOTIFICATION_COMMAND_TYPE_GET_TRIGGER:
365 return "GET_TRIGGER";
6900ae81
FD
366 case NOTIFICATION_COMMAND_TYPE_QUIT:
367 return "QUIT";
368 case NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE:
369 return "CLIENT_COMMUNICATION_UPDATE";
370 default:
371 abort();
372 }
373}
374
242388e4
JR
375/*
376 * Match trigger based on name and credentials only.
377 * Name duplication is NOT allowed for the same uid.
378 */
28ab034a 379static int match_trigger_by_name_uid(struct cds_lfht_node *node, const void *key)
242388e4
JR
380{
381 bool match = false;
0efb2ad7 382 const char *element_trigger_name;
242388e4
JR
383 const char *key_name;
384 enum lttng_trigger_status status;
385 const struct lttng_credentials *key_creds;
386 const struct lttng_credentials *node_creds;
28ab034a 387 const struct lttng_trigger *trigger_key = (const struct lttng_trigger *) key;
242388e4 388 const struct lttng_trigger_ht_element *trigger_ht_element =
28ab034a 389 caa_container_of(node, struct lttng_trigger_ht_element, node_by_name_uid);
242388e4 390
28ab034a 391 status = lttng_trigger_get_name(trigger_ht_element->trigger, &element_trigger_name);
cd9adb8b 392 element_trigger_name = status == LTTNG_TRIGGER_STATUS_OK ? element_trigger_name : nullptr;
242388e4
JR
393
394 status = lttng_trigger_get_name(trigger_key, &key_name);
cd9adb8b 395 key_name = status == LTTNG_TRIGGER_STATUS_OK ? key_name : nullptr;
242388e4 396
0efb2ad7
JG
397 /*
398 * Compare the names.
399 * Consider null names as not equal. This is to maintain backwards
400 * compatibility with pre-2.13 anonymous triggers. Multiples anonymous
401 * triggers are allowed for a given user.
402 */
403 if (!element_trigger_name || !key_name) {
404 goto end;
405 }
406
407 if (strcmp(element_trigger_name, key_name) != 0) {
242388e4
JR
408 goto end;
409 }
410
411 /* Compare the owners' UIDs. */
412 key_creds = lttng_trigger_get_credentials(trigger_key);
413 node_creds = lttng_trigger_get_credentials(trigger_ht_element->trigger);
414
415 match = lttng_credentials_is_equal_uid(key_creds, node_creds);
416
417end:
418 return match;
419}
420
421/*
422 * Hash trigger based on name and credentials only.
423 */
28ab034a 424static unsigned long hash_trigger_by_name_uid(const struct lttng_trigger *trigger)
242388e4
JR
425{
426 unsigned long hash = 0;
427 const struct lttng_credentials *trigger_creds;
428 const char *trigger_name;
429 enum lttng_trigger_status status;
430
431 status = lttng_trigger_get_name(trigger, &trigger_name);
432 if (status == LTTNG_TRIGGER_STATUS_OK) {
433 hash = hash_key_str(trigger_name, lttng_ht_seed);
434 }
435
436 trigger_creds = lttng_trigger_get_credentials(trigger);
437 hash ^= hash_key_ulong((void *) (unsigned long) LTTNG_OPTIONAL_GET(trigger_creds->uid),
28ab034a 438 lttng_ht_seed);
242388e4
JR
439
440 return hash;
441}
442
28ab034a 443static unsigned long hash_channel_key(struct channel_key *key)
e4db5ace
JR
444{
445 unsigned long key_hash = hash_key_u64(&key->key, lttng_ht_seed);
28ab034a
JG
446 unsigned long domain_hash =
447 hash_key_ulong((void *) (unsigned long) key->domain, lttng_ht_seed);
e4db5ace
JR
448
449 return key_hash ^ domain_hash;
450}
451
28ab034a 452static unsigned long hash_client_socket(int socket)
ac1889bf
JG
453{
454 return hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed);
455}
456
28ab034a 457static unsigned long hash_client_id(notification_client_id id)
ac1889bf
JG
458{
459 return hash_key_u64(&id, lttng_ht_seed);
460}
461
f82f93a1
JG
462/*
463 * Get the type of object to which a given condition applies. Bindings let
464 * the notification system evaluate a trigger's condition when a given
465 * object's state is updated.
466 *
467 * For instance, a condition bound to a channel will be evaluated everytime
468 * the channel's state is changed by a channel monitoring sample.
469 */
28ab034a 470static enum lttng_object_type get_condition_binding_object(const struct lttng_condition *condition)
f82f93a1
JG
471{
472 switch (lttng_condition_get_type(condition)) {
473 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
474 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
e742b055 475 return LTTNG_OBJECT_TYPE_CHANNEL;
f82f93a1
JG
476 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
477 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
319dcddc 478 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
f82f93a1 479 return LTTNG_OBJECT_TYPE_SESSION;
8dbb86b8 480 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
959e3c66 481 return LTTNG_OBJECT_TYPE_NONE;
f82f93a1
JG
482 default:
483 return LTTNG_OBJECT_TYPE_UNKNOWN;
484 }
485}
486
28ab034a 487static void free_channel_info_rcu(struct rcu_head *node)
83b934ad 488{
0114db0e 489 free(lttng::utils::container_of(node, &channel_info::rcu_node));
83b934ad
MD
490}
491
28ab034a 492static void channel_info_destroy(struct channel_info *channel_info)
ab0ee2ca
JG
493{
494 if (!channel_info) {
495 return;
496 }
497
8abe313a 498 if (channel_info->session_info) {
28ab034a 499 session_info_remove_channel(channel_info->session_info, channel_info);
8abe313a 500 session_info_put(channel_info->session_info);
ab0ee2ca 501 }
8abe313a
JG
502 if (channel_info->name) {
503 free(channel_info->name);
ab0ee2ca 504 }
83b934ad
MD
505 call_rcu(&channel_info->rcu_node, free_channel_info_rcu);
506}
507
28ab034a 508static void free_session_info_rcu(struct rcu_head *node)
83b934ad 509{
0114db0e 510 free(lttng::utils::container_of(node, &session_info::rcu_node));
ab0ee2ca
JG
511}
512
8abe313a 513/* Don't call directly, use the ref-counting mechanism. */
28ab034a 514static void session_info_destroy(void *_data)
ab0ee2ca 515{
7966af57 516 struct session_info *session_info = (struct session_info *) _data;
3b68d0a3 517 int ret;
ab0ee2ca 518
a0377dfe 519 LTTNG_ASSERT(session_info);
8abe313a 520 if (session_info->channel_infos_ht) {
cd9adb8b 521 ret = cds_lfht_destroy(session_info->channel_infos_ht, nullptr);
3b68d0a3 522 if (ret) {
bd0514a5 523 ERR("Failed to destroy channel information hash table");
3b68d0a3 524 }
8abe313a 525 }
ea9a44f0 526 lttng_session_trigger_list_destroy(session_info->trigger_list);
1eee26c5
JG
527
528 rcu_read_lock();
28ab034a 529 cds_lfht_del(session_info->sessions_ht, &session_info->sessions_ht_node);
1eee26c5 530 rcu_read_unlock();
8abe313a 531 free(session_info->name);
319dcddc 532 lttng_trace_archive_location_put(session_info->last_state_sample.rotation.location);
83b934ad 533 call_rcu(&session_info->rcu_node, free_session_info_rcu);
8abe313a 534}
ab0ee2ca 535
28ab034a 536static void session_info_get(struct session_info *session_info)
8abe313a
JG
537{
538 if (!session_info) {
539 return;
540 }
541 lttng_ref_get(&session_info->ref);
542}
543
28ab034a 544static void session_info_put(struct session_info *session_info)
8abe313a
JG
545{
546 if (!session_info) {
547 return;
ab0ee2ca 548 }
8abe313a
JG
549 lttng_ref_put(&session_info->ref);
550}
551
28ab034a
JG
552static struct session_info *session_info_create(uint64_t id,
553 const char *name,
554 uid_t uid,
555 gid_t gid,
556 struct lttng_session_trigger_list *trigger_list,
557 struct cds_lfht *sessions_ht)
8abe313a
JG
558{
559 struct session_info *session_info;
ab0ee2ca 560
a0377dfe 561 LTTNG_ASSERT(name);
ab0ee2ca 562
64803277 563 session_info = zmalloc<struct session_info>();
8abe313a
JG
564 if (!session_info) {
565 goto end;
566 }
139a8d25 567
8abe313a
JG
568 lttng_ref_init(&session_info->ref, session_info_destroy);
569
28ab034a 570 session_info->channel_infos_ht = cds_lfht_new(
cd9adb8b 571 DEFAULT_HT_SIZE, 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, nullptr);
8abe313a 572 if (!session_info->channel_infos_ht) {
ab0ee2ca
JG
573 goto error;
574 }
8abe313a
JG
575
576 cds_lfht_node_init(&session_info->sessions_ht_node);
139a8d25 577 session_info->id = id;
8abe313a
JG
578 session_info->name = strdup(name);
579 if (!session_info->name) {
ab0ee2ca
JG
580 goto error;
581 }
139a8d25 582
8abe313a
JG
583 session_info->uid = uid;
584 session_info->gid = gid;
ea9a44f0 585 session_info->trigger_list = trigger_list;
1eee26c5 586 session_info->sessions_ht = sessions_ht;
8abe313a
JG
587end:
588 return session_info;
589error:
590 session_info_put(session_info);
cd9adb8b 591 return nullptr;
8abe313a
JG
592}
593
28ab034a
JG
594static void session_info_add_channel(struct session_info *session_info,
595 struct channel_info *channel_info)
8abe313a
JG
596{
597 rcu_read_lock();
598 cds_lfht_add(session_info->channel_infos_ht,
28ab034a
JG
599 hash_channel_key(&channel_info->key),
600 &channel_info->session_info_channels_ht_node);
8abe313a
JG
601 rcu_read_unlock();
602}
603
28ab034a
JG
604static void session_info_remove_channel(struct session_info *session_info,
605 struct channel_info *channel_info)
8abe313a
JG
606{
607 rcu_read_lock();
28ab034a 608 cds_lfht_del(session_info->channel_infos_ht, &channel_info->session_info_channels_ht_node);
8abe313a
JG
609 rcu_read_unlock();
610}
611
28ab034a
JG
612static struct channel_info *channel_info_create(const char *channel_name,
613 struct channel_key *channel_key,
614 uint64_t channel_capacity,
615 struct session_info *session_info)
8abe313a 616{
64803277 617 struct channel_info *channel_info = zmalloc<struct channel_info>();
8abe313a
JG
618
619 if (!channel_info) {
620 goto end;
621 }
622
ab0ee2ca 623 cds_lfht_node_init(&channel_info->channels_ht_node);
8abe313a
JG
624 cds_lfht_node_init(&channel_info->session_info_channels_ht_node);
625 memcpy(&channel_info->key, channel_key, sizeof(*channel_key));
626 channel_info->capacity = channel_capacity;
627
628 channel_info->name = strdup(channel_name);
629 if (!channel_info->name) {
630 goto error;
631 }
632
633 /*
634 * Set the references between session and channel infos:
635 * - channel_info holds a strong reference to session_info
636 * - session_info holds a weak reference to channel_info
637 */
638 session_info_get(session_info);
639 session_info_add_channel(session_info, channel_info);
640 channel_info->session_info = session_info;
ab0ee2ca 641end:
8abe313a 642 return channel_info;
ab0ee2ca 643error:
8abe313a 644 channel_info_destroy(channel_info);
cd9adb8b 645 return nullptr;
ab0ee2ca
JG
646}
647
505b2d90
JG
648bool notification_client_list_get(struct notification_client_list *list)
649{
650 return urcu_ref_get_unless_zero(&list->ref);
651}
652
28ab034a 653static void free_notification_client_list_rcu(struct rcu_head *node)
505b2d90 654{
28ab034a 655 free(caa_container_of(node, struct notification_client_list, rcu_node));
505b2d90
JG
656}
657
28ab034a 658static void notification_client_list_release(struct urcu_ref *list_ref)
505b2d90
JG
659{
660 struct notification_client_list *list =
28ab034a 661 lttng::utils::container_of(list_ref, &notification_client_list::ref);
505b2d90
JG
662 struct notification_client_list_element *client_list_element, *tmp;
663
091fa780
FD
664 lttng_condition_put(list->condition);
665
505b2d90
JG
666 if (list->notification_trigger_clients_ht) {
667 rcu_read_lock();
091fa780 668
505b2d90 669 cds_lfht_del(list->notification_trigger_clients_ht,
28ab034a 670 &list->notification_trigger_clients_ht_node);
505b2d90 671 rcu_read_unlock();
cd9adb8b 672 list->notification_trigger_clients_ht = nullptr;
505b2d90 673 }
28ab034a 674 cds_list_for_each_entry_safe (client_list_element, tmp, &list->clients_list, node) {
505b2d90
JG
675 free(client_list_element);
676 }
091fa780 677
a0377dfe 678 LTTNG_ASSERT(cds_list_empty(&list->triggers_list));
091fa780 679
505b2d90
JG
680 pthread_mutex_destroy(&list->lock);
681 call_rcu(&list->rcu_node, free_notification_client_list_rcu);
682}
683
28ab034a
JG
684static bool condition_applies_to_client(const struct lttng_condition *condition,
685 struct notification_client *client)
091fa780
FD
686{
687 bool applies = false;
688 struct lttng_condition_list_element *condition_list_element;
689
28ab034a
JG
690 cds_list_for_each_entry (condition_list_element, &client->condition_list, node) {
691 applies = lttng_condition_is_equal(condition_list_element->condition, condition);
091fa780
FD
692 if (applies) {
693 break;
694 }
695 }
696
697 return applies;
698}
699
28ab034a
JG
700static struct notification_client_list *
701notification_client_list_create(struct notification_thread_state *state,
702 const struct lttng_condition *condition)
505b2d90 703{
091fa780
FD
704 struct notification_client *client;
705 struct cds_lfht_iter iter;
706 struct notification_client_list *client_list;
505b2d90 707
64803277 708 client_list = zmalloc<notification_client_list>();
505b2d90 709 if (!client_list) {
091fa780
FD
710 PERROR("Failed to allocate notification client list");
711 goto end;
505b2d90 712 }
091fa780 713
cd9adb8b 714 pthread_mutex_init(&client_list->lock, nullptr);
091fa780
FD
715 /*
716 * The trigger that owns the condition has the first reference to this
717 * client list.
718 */
505b2d90
JG
719 urcu_ref_init(&client_list->ref);
720 cds_lfht_node_init(&client_list->notification_trigger_clients_ht_node);
091fa780
FD
721 CDS_INIT_LIST_HEAD(&client_list->clients_list);
722 CDS_INIT_LIST_HEAD(&client_list->triggers_list);
505b2d90 723
091fa780
FD
724 /*
725 * Create a copy of the condition so that it's independent of any
726 * trigger. The client list may outlive the trigger object (which owns
727 * the condition) that is used to create it.
728 */
729 client_list->condition = lttng_condition_copy(condition);
730
731 /* Build a list of clients to which this new condition applies. */
28ab034a 732 cds_lfht_for_each_entry (state->client_socket_ht, &iter, client, client_socket_ht_node) {
091fa780 733 struct notification_client_list_element *client_list_element;
505b2d90 734
091fa780
FD
735 if (!condition_applies_to_client(condition, client)) {
736 continue;
737 }
738
64803277 739 client_list_element = zmalloc<notification_client_list_element>();
091fa780
FD
740 if (!client_list_element) {
741 goto error_put_client_list;
742 }
505b2d90 743
091fa780
FD
744 CDS_INIT_LIST_HEAD(&client_list_element->node);
745 client_list_element->client = client;
746 cds_list_add(&client_list_element->node, &client_list->clients_list);
747 }
748
28ab034a 749 client_list->notification_trigger_clients_ht = state->notification_trigger_clients_ht;
505b2d90
JG
750
751 rcu_read_lock();
091fa780
FD
752 /*
753 * Add the client list to the global list of client list.
754 */
755 cds_lfht_add_unique(state->notification_trigger_clients_ht,
28ab034a
JG
756 lttng_condition_hash(client_list->condition),
757 match_client_list_condition,
758 client_list->condition,
759 &client_list->notification_trigger_clients_ht_node);
505b2d90 760 rcu_read_unlock();
091fa780
FD
761 goto end;
762
763error_put_client_list:
764 notification_client_list_put(client_list);
cd9adb8b 765 client_list = nullptr;
091fa780
FD
766
767end:
768 return client_list;
505b2d90
JG
769}
770
505b2d90
JG
771void notification_client_list_put(struct notification_client_list *list)
772{
773 if (!list) {
774 return;
775 }
776 return urcu_ref_put(&list->ref, notification_client_list_release);
777}
778
779/* Provides a reference to the returned list. */
28ab034a
JG
780static struct notification_client_list *
781get_client_list_from_condition(struct notification_thread_state *state,
782 const struct lttng_condition *condition)
ed327204
JG
783{
784 struct cds_lfht_node *node;
785 struct cds_lfht_iter iter;
cd9adb8b 786 struct notification_client_list *list = nullptr;
ed327204 787
505b2d90 788 rcu_read_lock();
ed327204
JG
789 cds_lfht_lookup(state->notification_trigger_clients_ht,
790 lttng_condition_hash(condition),
791 match_client_list_condition,
792 condition,
793 &iter);
794 node = cds_lfht_iter_get_node(&iter);
505b2d90 795 if (node) {
28ab034a
JG
796 list = lttng::utils::container_of(
797 node, &notification_client_list::notification_trigger_clients_ht_node);
cd9adb8b 798 list = notification_client_list_get(list) ? list : nullptr;
505b2d90 799 }
ed327204 800
505b2d90
JG
801 rcu_read_unlock();
802 return list;
ed327204
JG
803}
804
28ab034a
JG
805static int evaluate_channel_condition_for_client(const struct lttng_condition *condition,
806 struct notification_thread_state *state,
807 struct lttng_evaluation **evaluation,
808 uid_t *session_uid,
809 gid_t *session_gid)
e4db5ace
JR
810{
811 int ret;
812 struct cds_lfht_iter iter;
813 struct cds_lfht_node *node;
cd9adb8b
JG
814 struct channel_info *channel_info = nullptr;
815 struct channel_key *channel_key = nullptr;
816 struct channel_state_sample *last_sample = nullptr;
817 struct lttng_channel_trigger_list *channel_trigger_list = nullptr;
e4db5ace 818
505b2d90
JG
819 rcu_read_lock();
820
f82f93a1 821 /* Find the channel associated with the condition. */
28ab034a
JG
822 cds_lfht_for_each_entry (
823 state->channel_triggers_ht, &iter, channel_trigger_list, channel_triggers_ht_node) {
e4db5ace
JR
824 struct lttng_trigger_list_element *element;
825
28ab034a 826 cds_list_for_each_entry (element, &channel_trigger_list->list, node) {
9b63a4aa 827 const struct lttng_condition *current_condition =
28ab034a 828 lttng_trigger_get_const_condition(element->trigger);
e4db5ace 829
a0377dfe 830 LTTNG_ASSERT(current_condition);
28ab034a 831 if (!lttng_condition_is_equal(condition, current_condition)) {
e4db5ace
JR
832 continue;
833 }
834
835 /* Found the trigger, save the channel key. */
836 channel_key = &channel_trigger_list->channel_key;
837 break;
838 }
839 if (channel_key) {
840 /* The channel key was found stop iteration. */
841 break;
842 }
843 }
844
28ab034a 845 if (!channel_key) {
e4db5ace 846 /* No channel found; normal exit. */
bd0514a5 847 DBG("No known channel associated with newly subscribed-to condition");
e4db5ace
JR
848 ret = 0;
849 goto end;
850 }
851
852 /* Fetch channel info for the matching channel. */
853 cds_lfht_lookup(state->channels_ht,
854 hash_channel_key(channel_key),
855 match_channel_info,
856 channel_key,
857 &iter);
858 node = cds_lfht_iter_get_node(&iter);
a0377dfe 859 LTTNG_ASSERT(node);
28ab034a 860 channel_info = caa_container_of(node, struct channel_info, channels_ht_node);
e4db5ace
JR
861
862 /* Retrieve the channel's last sample, if it exists. */
863 cds_lfht_lookup(state->channel_state_ht,
864 hash_channel_key(channel_key),
865 match_channel_state_sample,
866 channel_key,
867 &iter);
868 node = cds_lfht_iter_get_node(&iter);
869 if (node) {
28ab034a
JG
870 last_sample =
871 caa_container_of(node, struct channel_state_sample, channel_state_ht_node);
e4db5ace
JR
872 } else {
873 /* Nothing to evaluate, no sample was ever taken. Normal exit */
bd0514a5 874 DBG("No channel sample associated with newly subscribed-to condition");
e4db5ace
JR
875 ret = 0;
876 goto end;
877 }
878
28ab034a 879 ret = evaluate_buffer_condition(
cd9adb8b 880 condition, evaluation, state, nullptr, last_sample, channel_info);
e4db5ace 881 if (ret) {
bd0514a5 882 WARN("Fatal error occurred while evaluating a newly subscribed-to condition");
e4db5ace
JR
883 goto end;
884 }
885
f82f93a1
JG
886 *session_uid = channel_info->session_info->uid;
887 *session_gid = channel_info->session_info->gid;
888end:
505b2d90 889 rcu_read_unlock();
f82f93a1
JG
890 return ret;
891}
892
28ab034a 893static const char *get_condition_session_name(const struct lttng_condition *condition)
f82f93a1 894{
cd9adb8b 895 const char *session_name = nullptr;
f82f93a1
JG
896 enum lttng_condition_status status;
897
898 switch (lttng_condition_get_type(condition)) {
899 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
900 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
28ab034a 901 status = lttng_condition_buffer_usage_get_session_name(condition, &session_name);
f82f93a1
JG
902 break;
903 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
28ab034a
JG
904 status = lttng_condition_session_consumed_size_get_session_name(condition,
905 &session_name);
f82f93a1
JG
906 break;
907 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
908 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
28ab034a
JG
909 status =
910 lttng_condition_session_rotation_get_session_name(condition, &session_name);
f82f93a1
JG
911 break;
912 default:
913 abort();
914 }
915 if (status != LTTNG_CONDITION_STATUS_OK) {
bd0514a5 916 ERR("Failed to retrieve session rotation condition's session name");
f82f93a1
JG
917 goto end;
918 }
919end:
920 return session_name;
921}
922
28ab034a
JG
923static bool evaluate_session_rotation_ongoing_condition(const struct lttng_condition *condition
924 __attribute__((unused)),
925 const struct session_state_sample *sample)
319dcddc
JG
926{
927 return sample->rotation.ongoing;
928}
929
28ab034a
JG
930static bool evaluate_session_consumed_size_condition(const struct lttng_condition *condition,
931 const struct session_state_sample *sample)
319dcddc
JG
932{
933 uint64_t threshold;
934 const struct lttng_condition_session_consumed_size *size_condition =
28ab034a
JG
935 lttng::utils::container_of(condition,
936 &lttng_condition_session_consumed_size::parent);
319dcddc
JG
937
938 threshold = size_condition->consumed_threshold_bytes.value;
28ab034a
JG
939 DBG("Session consumed size condition being evaluated: threshold = %" PRIu64
940 ", current size = %" PRIu64,
941 threshold,
942 sample->consumed_data_size);
319dcddc
JG
943 return sample->consumed_data_size >= threshold;
944}
945
946/*
947 * `new_state` can be NULL to indicate that we are not evaluating a
948 * state transition. A client subscribed or a trigger was registered and
949 * we wish to perform an initial evaluation.
950 */
28ab034a
JG
951static int evaluate_session_condition(const struct lttng_condition *condition,
952 const struct session_info *session_info,
953 const struct session_state_sample *new_state,
954 struct lttng_evaluation **evaluation)
f82f93a1
JG
955{
956 int ret;
319dcddc 957 bool previous_result, newest_result;
f82f93a1 958
319dcddc
JG
959 switch (lttng_condition_get_type(condition)) {
960 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
961 if (new_state) {
962 previous_result = evaluate_session_rotation_ongoing_condition(
28ab034a
JG
963 condition, &session_info->last_state_sample);
964 newest_result =
965 evaluate_session_rotation_ongoing_condition(condition, new_state);
319dcddc
JG
966 } else {
967 previous_result = false;
968 newest_result = evaluate_session_rotation_ongoing_condition(
28ab034a 969 condition, &session_info->last_state_sample);
319dcddc
JG
970 }
971 break;
972 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
973 if (new_state) {
974 previous_result = evaluate_session_consumed_size_condition(
28ab034a
JG
975 condition, &session_info->last_state_sample);
976 newest_result =
977 evaluate_session_consumed_size_condition(condition, new_state);
319dcddc
JG
978 } else {
979 previous_result = false;
980 newest_result = evaluate_session_consumed_size_condition(
28ab034a 981 condition, &session_info->last_state_sample);
319dcddc
JG
982 }
983 break;
984 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
985 /*
986 * Note that LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED is
987 * evaluated differently to only consider state transitions without regard for the
988 * initial state. This is a deliberate choice as it is unlikely that a user would
989 * expect an action to occur for a rotation that occurred long before the trigger or
990 * subscription occurred.
991 */
992 if (!new_state) {
993 ret = 0;
994 goto end;
995 }
f82f93a1 996
319dcddc
JG
997 previous_result = !session_info->last_state_sample.rotation.ongoing;
998 newest_result = !new_state->rotation.ongoing;
999 break;
1000 default:
1001 ret = 0;
1002 goto end;
1003 }
1004
1005 if (!newest_result || (previous_result == newest_result)) {
1006 /* Not a state transition, evaluate to false. */
f82f93a1
JG
1007 ret = 0;
1008 goto end;
1009 }
1010
f82f93a1
JG
1011 switch (lttng_condition_get_type(condition)) {
1012 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
319dcddc 1013 {
28ab034a
JG
1014 const auto rotation_id = new_state ? new_state->rotation.id :
1015 session_info->last_state_sample.rotation.id;
f82f93a1 1016
319dcddc
JG
1017 *evaluation = lttng_evaluation_session_rotation_ongoing_create(rotation_id);
1018 break;
1019 }
1020 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
1021 {
d5ea8944
JG
1022 const auto& sample = new_state ? *new_state : session_info->last_state_sample;
1023 const auto rotation_id = sample.rotation.id;
319dcddc
JG
1024
1025 /* Callee acquires a reference to location. */
1026 *evaluation = lttng_evaluation_session_rotation_completed_create(
28ab034a 1027 rotation_id, sample.rotation.location);
319dcddc
JG
1028 break;
1029 }
1030 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
1031 {
1032 const auto latest_session_consumed_total = new_state ?
28ab034a
JG
1033 new_state->consumed_data_size :
1034 session_info->last_state_sample.consumed_data_size;
319dcddc
JG
1035
1036 *evaluation = lttng_evaluation_session_consumed_size_create(
28ab034a 1037 latest_session_consumed_total);
f82f93a1 1038 break;
319dcddc 1039 }
f82f93a1 1040 default:
319dcddc 1041 abort();
f82f93a1
JG
1042 }
1043
319dcddc
JG
1044 if (!*evaluation) {
1045 /* Fatal error. */
1046 ERR("Failed to create session condition evaluation: session name = `%s`",
28ab034a 1047 session_info->name);
319dcddc
JG
1048 ret = -1;
1049 goto end;
1050 }
f82f93a1 1051
319dcddc 1052 ret = 0;
f82f93a1
JG
1053end:
1054 return ret;
1055}
1056
28ab034a
JG
1057static int evaluate_condition_for_client(const struct lttng_trigger *trigger,
1058 const struct lttng_condition *condition,
1059 struct notification_client *client,
1060 struct notification_thread_state *state)
f82f93a1
JG
1061{
1062 int ret;
cd9adb8b 1063 struct lttng_evaluation *evaluation = nullptr;
505b2d90
JG
1064 struct notification_client_list client_list = {
1065 .lock = PTHREAD_MUTEX_INITIALIZER,
1c9a0b0e 1066 .ref = {},
cd9adb8b 1067 .condition = nullptr,
1c9a0b0e
MJ
1068 .triggers_list = {},
1069 .clients_list = {},
cd9adb8b 1070 .notification_trigger_clients_ht = nullptr,
1c9a0b0e
MJ
1071 .notification_trigger_clients_ht_node = {},
1072 .rcu_node = {},
505b2d90 1073 };
1c9a0b0e 1074 struct notification_client_list_element client_list_element = {};
f82f93a1
JG
1075 uid_t object_uid = 0;
1076 gid_t object_gid = 0;
1077
a0377dfe
FD
1078 LTTNG_ASSERT(trigger);
1079 LTTNG_ASSERT(condition);
1080 LTTNG_ASSERT(client);
1081 LTTNG_ASSERT(state);
f82f93a1
JG
1082
1083 switch (get_condition_binding_object(condition)) {
1084 case LTTNG_OBJECT_TYPE_SESSION:
319dcddc
JG
1085 {
1086 /* Find the session associated with the condition. */
1087 const auto *session_name = get_condition_session_name(condition);
1088 auto session_info = get_session_info_by_name(state, session_name);
1089 if (!session_info) {
1090 /* Not an error, the session doesn't exist yet. */
1091 DBG("Session not found while evaluating session condition for client: session name = `%s`",
28ab034a 1092 session_name);
319dcddc
JG
1093 ret = 0;
1094 goto end;
1095 }
1096
1097 object_uid = session_info->uid;
1098 object_gid = session_info->gid;
1099
cd9adb8b 1100 ret = evaluate_session_condition(condition, session_info, nullptr, &evaluation);
319dcddc 1101 session_info_put(session_info);
f82f93a1 1102 break;
319dcddc 1103 }
f82f93a1 1104 case LTTNG_OBJECT_TYPE_CHANNEL:
28ab034a
JG
1105 ret = evaluate_channel_condition_for_client(
1106 condition, state, &evaluation, &object_uid, &object_gid);
f82f93a1
JG
1107 break;
1108 case LTTNG_OBJECT_TYPE_NONE:
bd0514a5 1109 DBG("Newly subscribed-to condition not bound to object, nothing to evaluate");
f82f93a1
JG
1110 ret = 0;
1111 goto end;
1112 case LTTNG_OBJECT_TYPE_UNKNOWN:
1113 default:
1114 ret = -1;
1115 goto end;
1116 }
af0c318d
JG
1117 if (ret) {
1118 /* Fatal error. */
1119 goto end;
1120 }
e4db5ace
JR
1121 if (!evaluation) {
1122 /* Evaluation yielded nothing. Normal exit. */
bd0514a5 1123 DBG("Newly subscribed-to condition evaluated to false, nothing to report to client");
e4db5ace
JR
1124 ret = 0;
1125 goto end;
1126 }
1127
1128 /*
1129 * Create a temporary client list with the client currently
1130 * subscribing.
1131 */
505b2d90 1132 cds_lfht_node_init(&client_list.notification_trigger_clients_ht_node);
091fa780 1133 CDS_INIT_LIST_HEAD(&client_list.clients_list);
e4db5ace
JR
1134
1135 CDS_INIT_LIST_HEAD(&client_list_element.node);
1136 client_list_element.client = client;
091fa780 1137 cds_list_add(&client_list_element.node, &client_list.clients_list);
e4db5ace
JR
1138
1139 /* Send evaluation result to the newly-subscribed client. */
bd0514a5 1140 DBG("Newly subscribed-to condition evaluated to true, notifying client");
28ab034a
JG
1141 ret = send_evaluation_to_clients(
1142 trigger, evaluation, &client_list, state, object_uid, object_gid);
e4db5ace
JR
1143
1144end:
1145 return ret;
1146}
1147
28ab034a
JG
1148static int notification_thread_client_subscribe(struct notification_client *client,
1149 struct lttng_condition *condition,
1150 struct notification_thread_state *state,
1151 enum lttng_notification_channel_status *_status)
ab0ee2ca
JG
1152{
1153 int ret = 0;
cd9adb8b
JG
1154 struct notification_client_list *client_list = nullptr;
1155 struct lttng_condition_list_element *condition_list_element = nullptr;
1156 struct notification_client_list_element *client_list_element = nullptr;
a3ed2a4e 1157 struct lttng_trigger_ht_element *trigger_ht_element;
28ab034a 1158 enum lttng_notification_channel_status status = LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
ab0ee2ca
JG
1159
1160 /*
1161 * Ensure that the client has not already subscribed to this condition
1162 * before.
1163 */
28ab034a
JG
1164 cds_list_for_each_entry (condition_list_element, &client->condition_list, node) {
1165 if (lttng_condition_is_equal(condition_list_element->condition, condition)) {
ab0ee2ca
JG
1166 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED;
1167 goto end;
1168 }
1169 }
1170
64803277 1171 condition_list_element = zmalloc<lttng_condition_list_element>();
ab0ee2ca
JG
1172 if (!condition_list_element) {
1173 ret = -1;
1174 goto error;
1175 }
64803277 1176 client_list_element = zmalloc<notification_client_list_element>();
ab0ee2ca
JG
1177 if (!client_list_element) {
1178 ret = -1;
1179 goto error;
1180 }
1181
ab0ee2ca
JG
1182 /*
1183 * Add the newly-subscribed condition to the client's subscription list.
1184 */
1185 CDS_INIT_LIST_HEAD(&condition_list_element->node);
1186 condition_list_element->condition = condition;
cd9adb8b 1187 condition = nullptr;
ab0ee2ca
JG
1188 cds_list_add(&condition_list_element->node, &client->condition_list);
1189
28ab034a 1190 client_list = get_client_list_from_condition(state, condition_list_element->condition);
ed327204 1191 if (!client_list) {
2ae99f0b
JG
1192 /*
1193 * No notification-emiting trigger registered with this
1194 * condition. We don't evaluate the condition right away
1195 * since this trigger is not registered yet.
1196 */
4fb43b68 1197 free(client_list_element);
505b2d90 1198 goto end;
ab0ee2ca
JG
1199 }
1200
2ae99f0b
JG
1201 /*
1202 * The condition to which the client just subscribed is evaluated
1203 * at this point so that conditions that are already TRUE result
1204 * in a notification being sent out.
505b2d90 1205 *
57644a7f
JG
1206 * Note the iteration on all triggers which share an identical
1207 * `condition` than the one to which the client is registering. This is
1208 * done to ensure that the client receives a distinct notification for
1209 * all triggers that have a `notify` action that have this condition.
2ae99f0b 1210 */
091fa780 1211 pthread_mutex_lock(&client_list->lock);
28ab034a
JG
1212 cds_list_for_each_entry (
1213 trigger_ht_element, &client_list->triggers_list, client_list_trigger_node) {
1214 if (evaluate_condition_for_client(trigger_ht_element->trigger,
1215 condition_list_element->condition,
1216 client,
1217 state)) {
bd0514a5 1218 WARN("Evaluation of a condition on client subscription failed, aborting.");
091fa780
FD
1219 ret = -1;
1220 free(client_list_element);
ecc7ed07 1221 pthread_mutex_unlock(&client_list->lock);
091fa780
FD
1222 goto end;
1223 }
e4db5ace 1224 }
091fa780 1225 pthread_mutex_unlock(&client_list->lock);
e4db5ace
JR
1226
1227 /*
1228 * Add the client to the list of clients interested in a given trigger
1229 * if a "notification" trigger with a corresponding condition was
1230 * added prior.
1231 */
ab0ee2ca
JG
1232 client_list_element->client = client;
1233 CDS_INIT_LIST_HEAD(&client_list_element->node);
505b2d90
JG
1234
1235 pthread_mutex_lock(&client_list->lock);
091fa780 1236 cds_list_add(&client_list_element->node, &client_list->clients_list);
505b2d90 1237 pthread_mutex_unlock(&client_list->lock);
ab0ee2ca
JG
1238end:
1239 if (_status) {
1240 *_status = status;
1241 }
505b2d90
JG
1242 if (client_list) {
1243 notification_client_list_put(client_list);
1244 }
5a6306f7 1245 lttng_condition_destroy(condition);
ab0ee2ca
JG
1246 return ret;
1247error:
1248 free(condition_list_element);
1249 free(client_list_element);
5a6306f7 1250 lttng_condition_destroy(condition);
ab0ee2ca
JG
1251 return ret;
1252}
1253
28ab034a
JG
1254static int notification_thread_client_unsubscribe(struct notification_client *client,
1255 struct lttng_condition *condition,
1256 struct notification_thread_state *state,
1257 enum lttng_notification_channel_status *_status)
ab0ee2ca 1258{
ab0ee2ca 1259 struct notification_client_list *client_list;
28ab034a
JG
1260 struct lttng_condition_list_element *condition_list_element, *condition_tmp;
1261 struct notification_client_list_element *client_list_element, *client_tmp;
ab0ee2ca 1262 bool condition_found = false;
28ab034a 1263 enum lttng_notification_channel_status status = LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
ab0ee2ca
JG
1264
1265 /* Remove the condition from the client's condition list. */
28ab034a
JG
1266 cds_list_for_each_entry_safe (
1267 condition_list_element, condition_tmp, &client->condition_list, node) {
1268 if (!lttng_condition_is_equal(condition_list_element->condition, condition)) {
ab0ee2ca
JG
1269 continue;
1270 }
1271
1272 cds_list_del(&condition_list_element->node);
1273 /*
1274 * The caller may be iterating on the client's conditions to
1275 * tear down a client's connection. In this case, the condition
1276 * will be destroyed at the end.
1277 */
1278 if (condition != condition_list_element->condition) {
28ab034a 1279 lttng_condition_destroy(condition_list_element->condition);
ab0ee2ca
JG
1280 }
1281 free(condition_list_element);
1282 condition_found = true;
1283 break;
1284 }
1285
1286 if (!condition_found) {
1287 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION;
1288 goto end;
1289 }
1290
1291 /*
1292 * Remove the client from the list of clients interested the trigger
1293 * matching the condition.
1294 */
ed327204
JG
1295 client_list = get_client_list_from_condition(state, condition);
1296 if (!client_list) {
505b2d90 1297 goto end;
ab0ee2ca
JG
1298 }
1299
505b2d90 1300 pthread_mutex_lock(&client_list->lock);
28ab034a
JG
1301 cds_list_for_each_entry_safe (
1302 client_list_element, client_tmp, &client_list->clients_list, node) {
505b2d90 1303 if (client_list_element->client->id != client->id) {
ab0ee2ca
JG
1304 continue;
1305 }
1306 cds_list_del(&client_list_element->node);
1307 free(client_list_element);
1308 break;
1309 }
505b2d90
JG
1310 pthread_mutex_unlock(&client_list->lock);
1311 notification_client_list_put(client_list);
cd9adb8b 1312 client_list = nullptr;
ab0ee2ca
JG
1313end:
1314 lttng_condition_destroy(condition);
1315 if (_status) {
1316 *_status = status;
1317 }
1318 return 0;
1319}
1320
28ab034a 1321static void free_notification_client_rcu(struct rcu_head *node)
83b934ad 1322{
0114db0e 1323 free(lttng::utils::container_of(node, &notification_client::rcu_node));
83b934ad
MD
1324}
1325
28ab034a 1326static void notification_client_destroy(struct notification_client *client)
ab0ee2ca 1327{
ab0ee2ca
JG
1328 if (!client) {
1329 return;
1330 }
1331
505b2d90
JG
1332 /*
1333 * The client object is not reachable by other threads, no need to lock
1334 * the client here.
1335 */
ab0ee2ca
JG
1336 if (client->socket >= 0) {
1337 (void) lttcomm_close_unix_sock(client->socket);
ac1889bf 1338 client->socket = -1;
ab0ee2ca 1339 }
505b2d90 1340 client->communication.active = false;
882093ee
JR
1341 lttng_payload_reset(&client->communication.inbound.payload);
1342 lttng_payload_reset(&client->communication.outbound.payload);
505b2d90 1343 pthread_mutex_destroy(&client->lock);
83b934ad 1344 call_rcu(&client->rcu_node, free_notification_client_rcu);
ab0ee2ca
JG
1345}
1346
1347/*
1348 * Call with rcu_read_lock held (and hold for the lifetime of the returned
1349 * client pointer).
1350 */
28ab034a
JG
1351static struct notification_client *get_client_from_socket(int socket,
1352 struct notification_thread_state *state)
ab0ee2ca
JG
1353{
1354 struct cds_lfht_iter iter;
1355 struct cds_lfht_node *node;
cd9adb8b 1356 struct notification_client *client = nullptr;
ab0ee2ca 1357
48b7cdc2
FD
1358 ASSERT_RCU_READ_LOCKED();
1359
ab0ee2ca 1360 cds_lfht_lookup(state->client_socket_ht,
ac1889bf
JG
1361 hash_client_socket(socket),
1362 match_client_socket,
ab0ee2ca
JG
1363 (void *) (unsigned long) socket,
1364 &iter);
1365 node = cds_lfht_iter_get_node(&iter);
1366 if (!node) {
1367 goto end;
1368 }
1369
28ab034a 1370 client = caa_container_of(node, struct notification_client, client_socket_ht_node);
ab0ee2ca
JG
1371end:
1372 return client;
1373}
1374
f2b3ef9f
JG
1375/*
1376 * Call with rcu_read_lock held (and hold for the lifetime of the returned
1377 * client pointer).
1378 */
28ab034a
JG
1379static struct notification_client *get_client_from_id(notification_client_id id,
1380 struct notification_thread_state *state)
f2b3ef9f
JG
1381{
1382 struct cds_lfht_iter iter;
1383 struct cds_lfht_node *node;
cd9adb8b 1384 struct notification_client *client = nullptr;
f2b3ef9f 1385
48b7cdc2
FD
1386 ASSERT_RCU_READ_LOCKED();
1387
28ab034a 1388 cds_lfht_lookup(state->client_id_ht, hash_client_id(id), match_client_id, &id, &iter);
f2b3ef9f
JG
1389 node = cds_lfht_iter_get_node(&iter);
1390 if (!node) {
1391 goto end;
1392 }
1393
28ab034a 1394 client = caa_container_of(node, struct notification_client, client_id_ht_node);
f2b3ef9f
JG
1395end:
1396 return client;
1397}
1398
28ab034a
JG
1399static bool buffer_usage_condition_applies_to_channel(const struct lttng_condition *condition,
1400 const struct channel_info *channel_info)
ab0ee2ca
JG
1401{
1402 enum lttng_condition_status status;
e8360425 1403 enum lttng_domain_type condition_domain;
cd9adb8b
JG
1404 const char *condition_session_name = nullptr;
1405 const char *condition_channel_name = nullptr;
ab0ee2ca 1406
28ab034a 1407 status = lttng_condition_buffer_usage_get_domain_type(condition, &condition_domain);
a0377dfe 1408 LTTNG_ASSERT(status == LTTNG_CONDITION_STATUS_OK);
e8360425 1409 if (channel_info->key.domain != condition_domain) {
ab0ee2ca
JG
1410 goto fail;
1411 }
1412
28ab034a 1413 status = lttng_condition_buffer_usage_get_session_name(condition, &condition_session_name);
a0377dfe 1414 LTTNG_ASSERT((status == LTTNG_CONDITION_STATUS_OK) && condition_session_name);
e8360425 1415
28ab034a 1416 status = lttng_condition_buffer_usage_get_channel_name(condition, &condition_channel_name);
a0377dfe 1417 LTTNG_ASSERT((status == LTTNG_CONDITION_STATUS_OK) && condition_channel_name);
e8360425
JD
1418
1419 if (strcmp(channel_info->session_info->name, condition_session_name)) {
1420 goto fail;
1421 }
1422 if (strcmp(channel_info->name, condition_channel_name)) {
ab0ee2ca
JG
1423 goto fail;
1424 }
1425
e8360425
JD
1426 return true;
1427fail:
1428 return false;
1429}
1430
28ab034a
JG
1431static bool trigger_applies_to_channel(const struct lttng_trigger *trigger,
1432 const struct channel_info *channel_info)
51eab943
JG
1433{
1434 const struct lttng_condition *condition;
e8360425 1435 bool trigger_applies;
ab0ee2ca 1436
51eab943 1437 condition = lttng_trigger_get_const_condition(trigger);
e8360425 1438 if (!condition) {
ab0ee2ca
JG
1439 goto fail;
1440 }
e8360425
JD
1441
1442 switch (lttng_condition_get_type(condition)) {
1443 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
1444 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
28ab034a
JG
1445 trigger_applies =
1446 buffer_usage_condition_applies_to_channel(condition, channel_info);
e8360425 1447 break;
e8360425 1448 default:
ab0ee2ca
JG
1449 goto fail;
1450 }
1451
e8360425 1452 return trigger_applies;
ab0ee2ca
JG
1453fail:
1454 return false;
1455}
1456
ed327204 1457/* Must be called with RCU read lock held. */
28ab034a
JG
1458static struct lttng_session_trigger_list *
1459get_session_trigger_list(struct notification_thread_state *state, const char *session_name)
ed327204 1460{
cd9adb8b 1461 struct lttng_session_trigger_list *list = nullptr;
ed327204
JG
1462 struct cds_lfht_node *node;
1463 struct cds_lfht_iter iter;
1464
48b7cdc2
FD
1465 ASSERT_RCU_READ_LOCKED();
1466
ed327204
JG
1467 cds_lfht_lookup(state->session_triggers_ht,
1468 hash_key_str(session_name, lttng_ht_seed),
1469 match_session_trigger_list,
1470 session_name,
1471 &iter);
1472 node = cds_lfht_iter_get_node(&iter);
1473 if (!node) {
1474 /*
1475 * Not an error, the list of triggers applying to that session
1476 * will be initialized when the session is created.
1477 */
bd0514a5 1478 DBG("No trigger list found for session \"%s\" as it is not yet known to the notification system",
28ab034a 1479 session_name);
ed327204
JG
1480 goto end;
1481 }
1482
28ab034a 1483 list = caa_container_of(node, struct lttng_session_trigger_list, session_triggers_ht_node);
ed327204
JG
1484end:
1485 return list;
1486}
1487
ea9a44f0
JG
1488/*
1489 * Allocate an empty lttng_session_trigger_list for the session named
1490 * 'session_name'.
ea9a44f0 1491 */
28ab034a
JG
1492static struct lttng_session_trigger_list *
1493lttng_session_trigger_list_create(const char *session_name, struct cds_lfht *session_triggers_ht)
ea9a44f0 1494{
cd9adb8b 1495 struct lttng_session_trigger_list *list = nullptr;
319dcddc
JG
1496 char *session_name_copy = strdup(session_name);
1497
1498 if (!session_name_copy) {
1499 PERROR("Failed to allocate session name while building trigger list");
1500 goto end;
1501 }
ea9a44f0 1502
64803277 1503 list = zmalloc<lttng_session_trigger_list>();
ea9a44f0 1504 if (!list) {
319dcddc 1505 PERROR("Failed to allocate session trigger list while building trigger list");
ea9a44f0
JG
1506 goto end;
1507 }
319dcddc
JG
1508
1509 list->session_name = session_name_copy;
ea9a44f0
JG
1510 CDS_INIT_LIST_HEAD(&list->list);
1511 cds_lfht_node_init(&list->session_triggers_ht_node);
1512 list->session_triggers_ht = session_triggers_ht;
1513
1514 rcu_read_lock();
1515 /* Publish the list through the session_triggers_ht. */
1516 cds_lfht_add(session_triggers_ht,
28ab034a
JG
1517 hash_key_str(session_name, lttng_ht_seed),
1518 &list->session_triggers_ht_node);
ea9a44f0
JG
1519 rcu_read_unlock();
1520end:
1521 return list;
1522}
1523
28ab034a 1524static void free_session_trigger_list_rcu(struct rcu_head *node)
ea9a44f0 1525{
319dcddc 1526 struct lttng_session_trigger_list *list =
28ab034a 1527 caa_container_of(node, struct lttng_session_trigger_list, rcu_node);
319dcddc
JG
1528
1529 free(list->session_name);
1530 free(list);
ea9a44f0
JG
1531}
1532
28ab034a 1533static void lttng_session_trigger_list_destroy(struct lttng_session_trigger_list *list)
ea9a44f0
JG
1534{
1535 struct lttng_trigger_list_element *trigger_list_element, *tmp;
1536
1537 /* Empty the list element by element, and then free the list itself. */
28ab034a 1538 cds_list_for_each_entry_safe (trigger_list_element, tmp, &list->list, node) {
ea9a44f0
JG
1539 cds_list_del(&trigger_list_element->node);
1540 free(trigger_list_element);
1541 }
1542 rcu_read_lock();
1543 /* Unpublish the list from the session_triggers_ht. */
28ab034a 1544 cds_lfht_del(list->session_triggers_ht, &list->session_triggers_ht_node);
ea9a44f0
JG
1545 rcu_read_unlock();
1546 call_rcu(&list->rcu_node, free_session_trigger_list_rcu);
1547}
1548
28ab034a
JG
1549static int lttng_session_trigger_list_add(struct lttng_session_trigger_list *list,
1550 struct lttng_trigger *trigger)
ea9a44f0
JG
1551{
1552 int ret = 0;
28ab034a 1553 struct lttng_trigger_list_element *new_element = zmalloc<lttng_trigger_list_element>();
ea9a44f0
JG
1554
1555 if (!new_element) {
1556 ret = -1;
1557 goto end;
1558 }
1559 CDS_INIT_LIST_HEAD(&new_element->node);
1560 new_element->trigger = trigger;
1561 cds_list_add(&new_element->node, &list->list);
1562end:
1563 return ret;
1564}
1565
28ab034a
JG
1566static bool trigger_applies_to_session(const struct lttng_trigger *trigger,
1567 const char *session_name)
ea9a44f0
JG
1568{
1569 bool applies = false;
1570 const struct lttng_condition *condition;
1571
1572 condition = lttng_trigger_get_const_condition(trigger);
1573 switch (lttng_condition_get_type(condition)) {
1574 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
1575 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
319dcddc 1576 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
ea9a44f0 1577 {
ea9a44f0
JG
1578 const char *condition_session_name;
1579
319dcddc 1580 condition_session_name = get_condition_session_name(condition);
a0377dfe 1581 LTTNG_ASSERT(condition_session_name);
ea9a44f0
JG
1582 applies = !strcmp(condition_session_name, session_name);
1583 break;
1584 }
1585 default:
1586 goto end;
1587 }
1588end:
1589 return applies;
1590}
1591
1592/*
1593 * Allocate and initialize an lttng_session_trigger_list which contains
1594 * all triggers that apply to the session named 'session_name'.
ea9a44f0 1595 */
28ab034a
JG
1596static struct lttng_session_trigger_list *
1597lttng_session_trigger_list_build(const struct notification_thread_state *state,
1598 const char *session_name)
ea9a44f0
JG
1599{
1600 int trigger_count = 0;
cd9adb8b
JG
1601 struct lttng_session_trigger_list *session_trigger_list = nullptr;
1602 struct lttng_trigger_ht_element *trigger_ht_element = nullptr;
ea9a44f0
JG
1603 struct cds_lfht_iter iter;
1604
28ab034a
JG
1605 session_trigger_list =
1606 lttng_session_trigger_list_create(session_name, state->session_triggers_ht);
ea9a44f0
JG
1607
1608 /* Add all triggers applying to the session named 'session_name'. */
28ab034a 1609 cds_lfht_for_each_entry (state->triggers_ht, &iter, trigger_ht_element, node) {
ea9a44f0
JG
1610 int ret;
1611
28ab034a 1612 if (!trigger_applies_to_session(trigger_ht_element->trigger, session_name)) {
ea9a44f0
JG
1613 continue;
1614 }
1615
1616 ret = lttng_session_trigger_list_add(session_trigger_list,
28ab034a 1617 trigger_ht_element->trigger);
ea9a44f0
JG
1618 if (ret) {
1619 goto error;
1620 }
1621
1622 trigger_count++;
1623 }
1624
28ab034a 1625 DBG("Found %i triggers that apply to newly created session", trigger_count);
ea9a44f0
JG
1626 return session_trigger_list;
1627error:
1628 lttng_session_trigger_list_destroy(session_trigger_list);
cd9adb8b 1629 return nullptr;
ea9a44f0
JG
1630}
1631
28ab034a
JG
1632static struct session_info *create_and_publish_session_info(struct notification_thread_state *state,
1633 uint64_t id,
1634 const char *name,
1635 uid_t uid,
1636 gid_t gid)
8abe313a 1637{
cd9adb8b 1638 struct session_info *session = nullptr;
ea9a44f0 1639 struct lttng_session_trigger_list *trigger_list;
8abe313a
JG
1640
1641 rcu_read_lock();
ea9a44f0
JG
1642 trigger_list = lttng_session_trigger_list_build(state, name);
1643 if (!trigger_list) {
1644 goto error;
8abe313a
JG
1645 }
1646
28ab034a 1647 session = session_info_create(id, name, uid, gid, trigger_list, state->sessions_ht);
8abe313a 1648 if (!session) {
bd0514a5 1649 ERR("Failed to allocation session info for session \"%s\" (uid = %i, gid = %i)",
28ab034a
JG
1650 name,
1651 uid,
1652 gid);
b248644d 1653 lttng_session_trigger_list_destroy(trigger_list);
ea9a44f0 1654 goto error;
8abe313a 1655 }
139a8d25
JG
1656
1657 /* Transferred ownership to the new session. */
cd9adb8b 1658 trigger_list = nullptr;
577983cb 1659
28ab034a
JG
1660 if (cds_lfht_add_unique(state->sessions_ht,
1661 hash_session_info(session),
1662 match_session_info,
1663 &id,
1664 &session->sessions_ht_node) != &session->sessions_ht_node) {
139a8d25
JG
1665 ERR("Duplicate session found: name = `%s`, id = %" PRIu64, name, id);
1666 goto error;
1667 }
1668
8abe313a
JG
1669 rcu_read_unlock();
1670 return session;
ea9a44f0
JG
1671error:
1672 rcu_read_unlock();
1673 session_info_put(session);
cd9adb8b 1674 return nullptr;
8abe313a
JG
1675}
1676
28ab034a
JG
1677static int handle_notification_thread_command_add_channel(struct notification_thread_state *state,
1678 uint64_t session_id,
1679 const char *channel_name,
1680 enum lttng_domain_type channel_domain,
1681 uint64_t channel_key_int,
1682 uint64_t channel_capacity,
1683 enum lttng_error_code *cmd_result)
ab0ee2ca
JG
1684{
1685 struct cds_list_head trigger_list;
cd9adb8b 1686 struct channel_info *new_channel_info = nullptr;
8abe313a
JG
1687 struct channel_key channel_key = {
1688 .key = channel_key_int,
1689 .domain = channel_domain,
1690 };
cd9adb8b
JG
1691 struct lttng_channel_trigger_list *channel_trigger_list = nullptr;
1692 struct lttng_trigger_ht_element *trigger_ht_element = nullptr;
ab0ee2ca
JG
1693 int trigger_count = 0;
1694 struct cds_lfht_iter iter;
cd9adb8b 1695 struct session_info *session_info = nullptr;
ab0ee2ca 1696
28ab034a
JG
1697 DBG("Adding channel: channel name = `%s`, session id = %" PRIu64 ", channel key = %" PRIu64
1698 ", domain = %s",
1699 channel_name,
1700 session_id,
1701 channel_key_int,
1702 lttng_domain_type_str(channel_domain));
ab0ee2ca
JG
1703
1704 CDS_INIT_LIST_HEAD(&trigger_list);
1705
139a8d25 1706 session_info = get_session_info_by_id(state, session_id);
8abe313a 1707 if (!session_info) {
139a8d25
JG
1708 /* Fatal logic error. */
1709 ERR("Failed to find session while adding channel: session id = %" PRIu64,
28ab034a 1710 session_id);
ab0ee2ca
JG
1711 goto error;
1712 }
1713
28ab034a
JG
1714 new_channel_info =
1715 channel_info_create(channel_name, &channel_key, channel_capacity, session_info);
8abe313a
JG
1716 if (!new_channel_info) {
1717 goto error;
1718 }
ab0ee2ca 1719
83b934ad 1720 rcu_read_lock();
ab0ee2ca 1721 /* Build a list of all triggers applying to the new channel. */
28ab034a 1722 cds_lfht_for_each_entry (state->triggers_ht, &iter, trigger_ht_element, node) {
ab0ee2ca
JG
1723 struct lttng_trigger_list_element *new_element;
1724
28ab034a 1725 if (!trigger_applies_to_channel(trigger_ht_element->trigger, new_channel_info)) {
ab0ee2ca
JG
1726 continue;
1727 }
1728
64803277 1729 new_element = zmalloc<lttng_trigger_list_element>();
ab0ee2ca 1730 if (!new_element) {
83b934ad 1731 rcu_read_unlock();
ab0ee2ca
JG
1732 goto error;
1733 }
1734 CDS_INIT_LIST_HEAD(&new_element->node);
1735 new_element->trigger = trigger_ht_element->trigger;
1736 cds_list_add(&new_element->node, &trigger_list);
1737 trigger_count++;
1738 }
83b934ad 1739 rcu_read_unlock();
ab0ee2ca 1740
28ab034a 1741 DBG("Found %i triggers that apply to newly added channel", trigger_count);
64803277 1742 channel_trigger_list = zmalloc<lttng_channel_trigger_list>();
ab0ee2ca
JG
1743 if (!channel_trigger_list) {
1744 goto error;
1745 }
8abe313a 1746 channel_trigger_list->channel_key = new_channel_info->key;
ab0ee2ca
JG
1747 CDS_INIT_LIST_HEAD(&channel_trigger_list->list);
1748 cds_lfht_node_init(&channel_trigger_list->channel_triggers_ht_node);
1749 cds_list_splice(&trigger_list, &channel_trigger_list->list);
1750
1751 rcu_read_lock();
1752 /* Add channel to the channel_ht which owns the channel_infos. */
1753 cds_lfht_add(state->channels_ht,
28ab034a
JG
1754 hash_channel_key(&new_channel_info->key),
1755 &new_channel_info->channels_ht_node);
ab0ee2ca
JG
1756 /*
1757 * Add the list of triggers associated with this channel to the
1758 * channel_triggers_ht.
1759 */
1760 cds_lfht_add(state->channel_triggers_ht,
28ab034a
JG
1761 hash_channel_key(&new_channel_info->key),
1762 &channel_trigger_list->channel_triggers_ht_node);
ab0ee2ca 1763 rcu_read_unlock();
1eee26c5 1764 session_info_put(session_info);
ab0ee2ca
JG
1765 *cmd_result = LTTNG_OK;
1766 return 0;
1767error:
ab0ee2ca 1768 channel_info_destroy(new_channel_info);
8abe313a 1769 session_info_put(session_info);
ab0ee2ca
JG
1770 return 1;
1771}
1772
28ab034a
JG
1773static int handle_notification_thread_command_add_session(struct notification_thread_state *state,
1774 uint64_t session_id,
1775 const char *session_name,
1776 uid_t session_uid,
1777 gid_t session_gid,
1778 enum lttng_error_code *cmd_result)
139a8d25
JG
1779{
1780 int ret;
1781
28ab034a
JG
1782 DBG("Adding session: session name = `%s`, session id = %" PRIu64
1783 ", session uid = %d, session gid = %d",
1784 session_name,
1785 session_id,
1786 session_uid,
1787 session_gid);
139a8d25 1788
28ab034a
JG
1789 auto session = create_and_publish_session_info(
1790 state, session_id, session_name, session_uid, session_gid);
139a8d25 1791 if (!session) {
28ab034a
JG
1792 PERROR("Failed to add session: session name = `%s`, session id = %" PRIu64
1793 ", session uid = %d, session gid = %d",
1794 session_name,
1795 session_id,
1796 session_uid,
1797 session_gid);
139a8d25
JG
1798 ret = -1;
1799 *cmd_result = LTTNG_ERR_NOMEM;
1800 goto end;
1801 }
1802
1803 /*
1804 * Note that the reference to `session` is not released; this reference is
1805 * the "global" reference that is used to allow look-ups. This reference will
1806 * only be released when the session is removed. See
1807 * handle_notification_thread_command_remove_session.
1808 */
1809 ret = 0;
1810 *cmd_result = LTTNG_OK;
1811end:
1812 return ret;
1813}
1814
28ab034a
JG
1815static int
1816handle_notification_thread_command_remove_session(struct notification_thread_state *state,
1817 uint64_t session_id,
1818 enum lttng_error_code *cmd_result)
139a8d25
JG
1819{
1820 int ret;
1821
1822 DBG("Removing session: session id = %" PRIu64, session_id);
1823
1824 auto session = get_session_info_by_id(state, session_id);
1825 if (!session) {
1826 ERR("Failed to remove session: session id = %" PRIu64, session_id);
1827 ret = -1;
1828 *cmd_result = LTTNG_ERR_NO_SESSION;
1829 goto end;
1830 }
1831
1832 /* Release the reference returned by the look-up, and then release the global reference. */
1833 session_info_put(session);
1834 session_info_put(session);
1835 ret = 0;
1836 *cmd_result = LTTNG_OK;
1837end:
1838 return ret;
1839}
1840
28ab034a 1841static void free_channel_trigger_list_rcu(struct rcu_head *node)
83b934ad 1842{
28ab034a 1843 free(caa_container_of(node, struct lttng_channel_trigger_list, rcu_node));
83b934ad
MD
1844}
1845
28ab034a 1846static void free_channel_state_sample_rcu(struct rcu_head *node)
83b934ad 1847{
28ab034a 1848 free(caa_container_of(node, struct channel_state_sample, rcu_node));
83b934ad
MD
1849}
1850
28ab034a
JG
1851static int
1852handle_notification_thread_command_remove_channel(struct notification_thread_state *state,
1853 uint64_t channel_key,
1854 enum lttng_domain_type domain,
1855 enum lttng_error_code *cmd_result)
ab0ee2ca
JG
1856{
1857 struct cds_lfht_node *node;
1858 struct cds_lfht_iter iter;
1859 struct lttng_channel_trigger_list *trigger_list;
1860 struct lttng_trigger_list_element *trigger_list_element, *tmp;
1861 struct channel_key key = { .key = channel_key, .domain = domain };
1862 struct channel_info *channel_info;
1863
bd0514a5 1864 DBG("Removing channel key = %" PRIu64 " in %s domain",
28ab034a
JG
1865 channel_key,
1866 lttng_domain_type_str(domain));
ab0ee2ca
JG
1867
1868 rcu_read_lock();
1869
1870 cds_lfht_lookup(state->channel_triggers_ht,
1871 hash_channel_key(&key),
1872 match_channel_trigger_list,
1873 &key,
1874 &iter);
1875 node = cds_lfht_iter_get_node(&iter);
1876 /*
1877 * There is a severe internal error if we are being asked to remove a
1878 * channel that doesn't exist.
1879 */
1880 if (!node) {
bd0514a5 1881 ERR("Channel being removed is unknown to the notification thread");
ab0ee2ca
JG
1882 goto end;
1883 }
1884
1885 /* Free the list of triggers associated with this channel. */
28ab034a
JG
1886 trigger_list =
1887 caa_container_of(node, struct lttng_channel_trigger_list, channel_triggers_ht_node);
1888 cds_list_for_each_entry_safe (trigger_list_element, tmp, &trigger_list->list, node) {
ab0ee2ca
JG
1889 cds_list_del(&trigger_list_element->node);
1890 free(trigger_list_element);
1891 }
1892 cds_lfht_del(state->channel_triggers_ht, node);
83b934ad 1893 call_rcu(&trigger_list->rcu_node, free_channel_trigger_list_rcu);
ab0ee2ca
JG
1894
1895 /* Free sampled channel state. */
1896 cds_lfht_lookup(state->channel_state_ht,
1897 hash_channel_key(&key),
1898 match_channel_state_sample,
1899 &key,
1900 &iter);
1901 node = cds_lfht_iter_get_node(&iter);
1902 /*
1903 * This is expected to be NULL if the channel is destroyed before we
1904 * received a sample.
1905 */
1906 if (node) {
28ab034a
JG
1907 struct channel_state_sample *sample =
1908 caa_container_of(node, struct channel_state_sample, channel_state_ht_node);
ab0ee2ca
JG
1909
1910 cds_lfht_del(state->channel_state_ht, node);
83b934ad 1911 call_rcu(&sample->rcu_node, free_channel_state_sample_rcu);
ab0ee2ca
JG
1912 }
1913
1914 /* Remove the channel from the channels_ht and free it. */
28ab034a
JG
1915 cds_lfht_lookup(
1916 state->channels_ht, hash_channel_key(&key), match_channel_info, &key, &iter);
ab0ee2ca 1917 node = cds_lfht_iter_get_node(&iter);
a0377dfe 1918 LTTNG_ASSERT(node);
28ab034a 1919 channel_info = caa_container_of(node, struct channel_info, channels_ht_node);
ab0ee2ca
JG
1920 cds_lfht_del(state->channels_ht, node);
1921 channel_info_destroy(channel_info);
1922end:
1923 rcu_read_unlock();
1924 *cmd_result = LTTNG_OK;
1925 return 0;
1926}
1927
28ab034a
JG
1928static int
1929handle_notification_thread_command_session_rotation(struct notification_thread_state *state,
1930 enum notification_thread_command_type cmd_type,
1931 uint64_t session_id,
1932 uint64_t trace_archive_chunk_id,
1933 struct lttng_trace_archive_location *location,
1934 enum lttng_error_code *_cmd_result)
0ca52944 1935{
ed327204
JG
1936 int ret = 0;
1937 enum lttng_error_code cmd_result = LTTNG_OK;
1938 struct lttng_session_trigger_list *trigger_list;
1939 struct lttng_trigger_list_element *trigger_list_element;
1940 struct session_info *session_info;
139a8d25 1941 struct lttng_credentials session_creds;
319dcddc 1942 struct session_state_sample new_session_state;
0ca52944 1943
ed327204
JG
1944 rcu_read_lock();
1945
139a8d25 1946 session_info = get_session_info_by_id(state, session_id);
ed327204 1947 if (!session_info) {
139a8d25
JG
1948 /* Fatal logic error. */
1949 ERR("Failed to find session while handling rotation state change: session id = %" PRIu64,
28ab034a 1950 session_id);
ed327204 1951 ret = -1;
139a8d25 1952 cmd_result = LTTNG_ERR_FATAL;
ed327204
JG
1953 goto end;
1954 }
1955
319dcddc
JG
1956 new_session_state = session_info->last_state_sample;
1957 if (location) {
1958 lttng_trace_archive_location_get(location);
1959 new_session_state.rotation.location = location;
1960 } else {
cd9adb8b 1961 new_session_state.rotation.location = nullptr;
319dcddc
JG
1962 }
1963
139a8d25
JG
1964 session_creds = {
1965 .uid = LTTNG_OPTIONAL_INIT_VALUE(session_info->uid),
1966 .gid = LTTNG_OPTIONAL_INIT_VALUE(session_info->gid),
1967 };
1968
319dcddc 1969 new_session_state.rotation.ongoing = cmd_type ==
28ab034a 1970 NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING;
319dcddc
JG
1971 new_session_state.rotation.id = trace_archive_chunk_id;
1972
139a8d25 1973 trigger_list = get_session_trigger_list(state, session_info->name);
319dcddc 1974 LTTNG_ASSERT(trigger_list);
ed327204 1975
28ab034a 1976 cds_list_for_each_entry (trigger_list_element, &trigger_list->list, node) {
ed327204 1977 const struct lttng_condition *condition;
f2b3ef9f 1978 struct lttng_trigger *trigger;
ed327204 1979 struct notification_client_list *client_list;
cd9adb8b 1980 struct lttng_evaluation *evaluation = nullptr;
f2b3ef9f 1981 enum action_executor_status executor_status;
ed327204
JG
1982
1983 trigger = trigger_list_element->trigger;
1984 condition = lttng_trigger_get_const_condition(trigger);
a0377dfe 1985 LTTNG_ASSERT(condition);
ed327204 1986
319dcddc 1987 ret = evaluate_session_condition(
28ab034a 1988 condition, session_info, &new_session_state, &evaluation);
319dcddc
JG
1989 if (ret) {
1990 ret = -1;
1991 cmd_result = LTTNG_ERR_NOMEM;
1992 goto end;
ed327204
JG
1993 }
1994
1995 if (!evaluation) {
319dcddc 1996 continue;
ed327204
JG
1997 }
1998
f2b3ef9f
JG
1999 /*
2000 * Ownership of `evaluation` transferred to the action executor
319dcddc
JG
2001 * no matter the result. The callee acquires a reference to the
2002 * client list: we can release our own.
f2b3ef9f 2003 */
319dcddc 2004 client_list = get_client_list_from_condition(state, condition);
72365501 2005 executor_status = action_executor_enqueue_trigger(
28ab034a 2006 state->executor, trigger, evaluation, &session_creds, client_list);
319dcddc 2007 notification_client_list_put(client_list);
cd9adb8b 2008 evaluation = nullptr;
f2b3ef9f
JG
2009 switch (executor_status) {
2010 case ACTION_EXECUTOR_STATUS_OK:
2011 break;
2012 case ACTION_EXECUTOR_STATUS_ERROR:
2013 case ACTION_EXECUTOR_STATUS_INVALID:
2014 /*
2015 * TODO Add trigger identification (name/id) when
2016 * it is added to the API.
2017 */
2018 ERR("Fatal error occurred while enqueuing action associated with session rotation trigger");
2019 ret = -1;
319dcddc 2020 goto end;
f2b3ef9f
JG
2021 case ACTION_EXECUTOR_STATUS_OVERFLOW:
2022 /*
2023 * TODO Add trigger identification (name/id) when
2024 * it is added to the API.
2025 *
2026 * Not a fatal error.
2027 */
2028 WARN("No space left when enqueuing action associated with session rotation trigger");
2029 ret = 0;
319dcddc 2030 goto end;
f2b3ef9f
JG
2031 default:
2032 abort();
2033 }
ed327204 2034 }
319dcddc 2035
ed327204 2036end:
319dcddc
JG
2037 if (session_info) {
2038 /* Ownership of new_session_state::location is transferred. */
2039 lttng_trace_archive_location_put(session_info->last_state_sample.rotation.location);
2040 session_info->last_state_sample = new_session_state;
2041 }
2042
ed327204
JG
2043 session_info_put(session_info);
2044 *_cmd_result = cmd_result;
2045 rcu_read_unlock();
2046 return ret;
0ca52944
JG
2047}
2048
28ab034a
JG
2049static int
2050handle_notification_thread_command_add_tracer_event_source(struct notification_thread_state *state,
2051 int tracer_event_source_fd,
2052 enum lttng_domain_type domain_type,
2053 enum lttng_error_code *_cmd_result)
d02d7404
JR
2054{
2055 int ret = 0;
2056 enum lttng_error_code cmd_result = LTTNG_OK;
cd9adb8b 2057 struct notification_event_tracer_event_source_element *element = nullptr;
d02d7404 2058
64803277 2059 element = zmalloc<notification_event_tracer_event_source_element>();
d02d7404
JR
2060 if (!element) {
2061 cmd_result = LTTNG_ERR_NOMEM;
2062 ret = -1;
2063 goto end;
2064 }
2065
d02d7404
JR
2066 element->fd = tracer_event_source_fd;
2067 element->domain = domain_type;
2068
2069 cds_list_add(&element->node, &state->tracer_event_sources_list);
2070
bd0514a5 2071 DBG3("Adding tracer event source fd to poll set: tracer_event_source_fd = %d, domain = '%s'",
28ab034a
JG
2072 tracer_event_source_fd,
2073 lttng_domain_type_str(domain_type));
d02d7404
JR
2074
2075 /* Adding the read side pipe to the event poll. */
1524f98c 2076 ret = lttng_poll_add(&state->events, tracer_event_source_fd, LPOLLPRI | LPOLLIN);
d02d7404 2077 if (ret < 0) {
bd0514a5 2078 ERR("Failed to add tracer event source to poll set: tracer_event_source_fd = %d, domain = '%s'",
28ab034a
JG
2079 tracer_event_source_fd,
2080 lttng_domain_type_str(element->domain));
d02d7404
JR
2081 cds_list_del(&element->node);
2082 free(element);
2083 goto end;
2084 }
2085
2086 element->is_fd_in_poll_set = true;
2087
2088end:
2089 *_cmd_result = cmd_result;
2090 return ret;
2091}
2092
28ab034a
JG
2093static int drain_event_notifier_notification_pipe(struct notification_thread_state *state,
2094 int pipe,
2095 enum lttng_domain_type domain)
8b524060 2096{
1c9a0b0e 2097 struct lttng_poll_event events = {};
8b524060
FD
2098 int ret;
2099
2100 ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
2101 if (ret < 0) {
bd0514a5 2102 ERR("Error creating lttng_poll_event");
8b524060
FD
2103 goto end;
2104 }
2105
2106 ret = lttng_poll_add(&events, pipe, LPOLLIN);
2107 if (ret < 0) {
bd0514a5 2108 ERR("Error adding fd event notifier notification pipe to lttng_poll_event: fd = %d",
28ab034a 2109 pipe);
8b524060
FD
2110 goto end;
2111 }
2112
2113 while (true) {
2114 /*
2115 * Continue to consume notifications as long as there are new
2116 * ones coming in. The tracer has been asked to stop producing
2117 * them.
2118 *
2119 * LPOLLIN is explicitly checked since LPOLLHUP is implicitly
2120 * monitored (on Linux, at least) and will be returned when
2121 * the pipe is closed but empty.
2122 */
2123 ret = lttng_poll_wait_interruptible(&events, 0);
a17b133b 2124 if (ret == 0 || (LTTNG_POLL_GETEV(&events, 0) & LPOLLIN) == 0) {
8b524060
FD
2125 /* No more notification to be read on this pipe. */
2126 ret = 0;
2127 goto end;
2128 } else if (ret < 0) {
2129 PERROR("Failed on lttng_poll_wait_interruptible() call");
2130 ret = -1;
2131 goto end;
2132 }
2133
2134 ret = handle_one_event_notifier_notification(state, pipe, domain);
2135 if (ret) {
bd0514a5 2136 ERR("Error consuming an event notifier notification from pipe: fd = %d",
28ab034a 2137 pipe);
8b524060
FD
2138 }
2139 }
2140end:
2141 lttng_poll_clean(&events);
2142 return ret;
2143}
2144
28ab034a 2145static struct notification_event_tracer_event_source_element *
34bf4f69 2146find_tracer_event_source_element(struct notification_thread_state *state,
28ab034a 2147 int tracer_event_source_fd)
d02d7404 2148{
34bf4f69 2149 struct notification_event_tracer_event_source_element *source_element;
d02d7404 2150
28ab034a 2151 cds_list_for_each_entry (source_element, &state->tracer_event_sources_list, node) {
34bf4f69
FD
2152 if (source_element->fd == tracer_event_source_fd) {
2153 goto end;
d02d7404 2154 }
d02d7404
JR
2155 }
2156
cd9adb8b 2157 source_element = nullptr;
34bf4f69 2158end:
97cf926d 2159 return source_element;
34bf4f69 2160}
d02d7404 2161
28ab034a
JG
2162static int remove_tracer_event_source_from_pollset(
2163 struct notification_thread_state *state,
2164 struct notification_event_tracer_event_source_element *source_element)
34bf4f69
FD
2165{
2166 int ret = 0;
2167
a0377dfe 2168 LTTNG_ASSERT(source_element->is_fd_in_poll_set);
d02d7404 2169
bd0514a5 2170 DBG3("Removing tracer event source from poll set: tracer_event_source_fd = %d, domain = '%s'",
28ab034a
JG
2171 source_element->fd,
2172 lttng_domain_type_str(source_element->domain));
d02d7404
JR
2173
2174 /* Removing the fd from the event poll set. */
34bf4f69 2175 ret = lttng_poll_del(&state->events, source_element->fd);
d02d7404 2176 if (ret < 0) {
bd0514a5 2177 ERR("Failed to remove tracer event source from poll set: tracer_event_source_fd = %d, domain = '%s'",
28ab034a
JG
2178 source_element->fd,
2179 lttng_domain_type_str(source_element->domain));
34bf4f69 2180 ret = -1;
d02d7404
JR
2181 goto end;
2182 }
2183
173900f6
JG
2184 source_element->is_fd_in_poll_set = false;
2185
2ddbdc7a
FD
2186 /*
2187 * Force the notification thread to restart the poll() loop to ensure
2188 * that any events from the removed fd are removed.
2189 */
2190 state->restart_poll = true;
2191
28ab034a
JG
2192 ret = drain_event_notifier_notification_pipe(
2193 state, source_element->fd, source_element->domain);
8b524060 2194 if (ret) {
bd0514a5 2195 ERR("Error draining event notifier notification: tracer_event_source_fd = %d, domain = %s",
28ab034a
JG
2196 source_element->fd,
2197 lttng_domain_type_str(source_element->domain));
34bf4f69 2198 ret = -1;
8b524060
FD
2199 goto end;
2200 }
2201
d02d7404 2202end:
d02d7404
JR
2203 return ret;
2204}
2205
28ab034a
JG
2206int handle_notification_thread_tracer_event_source_died(struct notification_thread_state *state,
2207 int tracer_event_source_fd)
d02d7404 2208{
34bf4f69
FD
2209 int ret = 0;
2210 struct notification_event_tracer_event_source_element *source_element;
2211
28ab034a 2212 source_element = find_tracer_event_source_element(state, tracer_event_source_fd);
34bf4f69 2213
a0377dfe 2214 LTTNG_ASSERT(source_element);
34bf4f69
FD
2215
2216 ret = remove_tracer_event_source_from_pollset(state, source_element);
2217 if (ret) {
2218 ERR("Failed to remove dead tracer event source from poll set");
2219 }
d02d7404 2220
34bf4f69
FD
2221 return ret;
2222}
2223
28ab034a
JG
2224static int handle_notification_thread_command_remove_tracer_event_source(
2225 struct notification_thread_state *state,
2226 int tracer_event_source_fd,
2227 enum lttng_error_code *_cmd_result)
34bf4f69
FD
2228{
2229 int ret = 0;
2230 enum lttng_error_code cmd_result = LTTNG_OK;
cd9adb8b 2231 struct notification_event_tracer_event_source_element *source_element = nullptr;
34bf4f69 2232
28ab034a 2233 source_element = find_tracer_event_source_element(state, tracer_event_source_fd);
34bf4f69 2234
a0377dfe 2235 LTTNG_ASSERT(source_element);
34bf4f69
FD
2236
2237 /* Remove the tracer source from the list. */
2238 cds_list_del(&source_element->node);
2239
2240 if (!source_element->is_fd_in_poll_set) {
2241 /* Skip the poll set removal. */
2242 goto end;
2243 }
2244
2245 ret = remove_tracer_event_source_from_pollset(state, source_element);
2246 if (ret) {
2247 ERR("Failed to remove tracer event source from poll set");
2248 cmd_result = LTTNG_ERR_FATAL;
2249 }
2250
2251end:
2252 free(source_element);
2253 *_cmd_result = cmd_result;
d02d7404
JR
2254 return ret;
2255}
2256
28ab034a
JG
2257static int
2258handle_notification_thread_command_list_triggers(struct notification_thread_handle *handle
2259 __attribute__((unused)),
2260 struct notification_thread_state *state,
2261 uid_t client_uid,
2262 struct lttng_triggers **triggers,
2263 enum lttng_error_code *_cmd_result)
fbc9f37d
JR
2264{
2265 int ret = 0;
2266 enum lttng_error_code cmd_result = LTTNG_OK;
2267 struct cds_lfht_iter iter;
2268 struct lttng_trigger_ht_element *trigger_ht_element;
cd9adb8b 2269 struct lttng_triggers *local_triggers = nullptr;
fbc9f37d
JR
2270 const struct lttng_credentials *creds;
2271
2272 rcu_read_lock();
2273
2274 local_triggers = lttng_triggers_create();
2275 if (!local_triggers) {
2276 /* Not a fatal error. */
2277 cmd_result = LTTNG_ERR_NOMEM;
2278 goto end;
2279 }
2280
28ab034a 2281 cds_lfht_for_each_entry (state->triggers_ht, &iter, trigger_ht_element, node) {
fbc9f37d
JR
2282 /*
2283 * Only return the triggers to which the client has access.
2284 * The root user has visibility over all triggers.
2285 */
2286 creds = lttng_trigger_get_credentials(trigger_ht_element->trigger);
2287 if (client_uid != lttng_credentials_get_uid(creds) && client_uid != 0) {
2288 continue;
2289 }
2290
28ab034a 2291 ret = lttng_triggers_add(local_triggers, trigger_ht_element->trigger);
fbc9f37d
JR
2292 if (ret < 0) {
2293 /* Not a fatal error. */
2294 ret = 0;
2295 cmd_result = LTTNG_ERR_NOMEM;
2296 goto end;
2297 }
2298 }
2299
2300 /* Transferring ownership to the caller. */
2301 *triggers = local_triggers;
cd9adb8b 2302 local_triggers = nullptr;
fbc9f37d
JR
2303
2304end:
2305 rcu_read_unlock();
2306 lttng_triggers_destroy(local_triggers);
2307 *_cmd_result = cmd_result;
2308 return ret;
2309}
2310
8790759c 2311static inline void get_trigger_info_for_log(const struct lttng_trigger *trigger,
28ab034a
JG
2312 const char **trigger_name,
2313 uid_t *trigger_owner_uid)
8790759c
FD
2314{
2315 enum lttng_trigger_status trigger_status;
2316
2317 trigger_status = lttng_trigger_get_name(trigger, trigger_name);
2318 switch (trigger_status) {
2319 case LTTNG_TRIGGER_STATUS_OK:
2320 break;
2321 case LTTNG_TRIGGER_STATUS_UNSET:
0efb2ad7 2322 *trigger_name = "(anonymous)";
8790759c
FD
2323 break;
2324 default:
2325 abort();
2326 }
2327
28ab034a 2328 trigger_status = lttng_trigger_get_owner_uid(trigger, trigger_owner_uid);
a0377dfe 2329 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
8790759c
FD
2330}
2331
28ab034a
JG
2332static int handle_notification_thread_command_get_trigger(struct notification_thread_state *state,
2333 const struct lttng_trigger *trigger,
2334 struct lttng_trigger **registered_trigger,
2335 enum lttng_error_code *_cmd_result)
8790759c
FD
2336{
2337 int ret = -1;
2338 struct cds_lfht_iter iter;
2339 struct lttng_trigger_ht_element *trigger_ht_element;
2340 enum lttng_error_code cmd_result = LTTNG_ERR_TRIGGER_NOT_FOUND;
2341 const char *trigger_name;
2342 uid_t trigger_owner_uid;
2343
2344 rcu_read_lock();
2345
28ab034a
JG
2346 cds_lfht_for_each_entry (state->triggers_ht, &iter, trigger_ht_element, node) {
2347 if (lttng_trigger_is_equal(trigger, trigger_ht_element->trigger)) {
8790759c
FD
2348 /* Take one reference on the return trigger. */
2349 *registered_trigger = trigger_ht_element->trigger;
2350 lttng_trigger_get(*registered_trigger);
2351 ret = 0;
2352 cmd_result = LTTNG_OK;
2353 goto end;
2354 }
2355 }
2356
2357 /* Not a fatal error if the trigger is not found. */
2358 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
87661585 2359 DBG("Failed to retrieve registered version of trigger: trigger name = '%s', trigger owner uid = %d",
28ab034a
JG
2360 trigger_name,
2361 (int) trigger_owner_uid);
8790759c
FD
2362
2363 ret = 0;
2364
2365end:
2366 rcu_read_unlock();
2367 *_cmd_result = cmd_result;
2368 return ret;
2369}
2370
28ab034a 2371static bool condition_is_supported(struct lttng_condition *condition)
1da26331 2372{
959e3c66 2373 bool is_supported;
1da26331
JG
2374
2375 switch (lttng_condition_get_type(condition)) {
2376 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
2377 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
2378 {
959e3c66 2379 int ret;
1da26331
JG
2380 enum lttng_domain_type domain;
2381
28ab034a 2382 ret = lttng_condition_buffer_usage_get_domain_type(condition, &domain);
a0377dfe 2383 LTTNG_ASSERT(ret == 0);
1da26331
JG
2384
2385 if (domain != LTTNG_DOMAIN_KERNEL) {
959e3c66 2386 is_supported = true;
1da26331
JG
2387 goto end;
2388 }
2389
2390 /*
2391 * Older kernel tracers don't expose the API to monitor their
2392 * buffers. Therefore, we reject triggers that require that
2393 * mechanism to be available to be evaluated.
959e3c66
JR
2394 *
2395 * Assume unsupported on error.
1da26331 2396 */
959e3c66
JR
2397 is_supported = kernel_supports_ring_buffer_snapshot_sample_positions() == 1;
2398 break;
2399 }
8dbb86b8 2400 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
959e3c66
JR
2401 {
2402 const struct lttng_event_rule *event_rule;
2403 enum lttng_domain_type domain;
2404 const enum lttng_condition_status status =
28ab034a 2405 lttng_condition_event_rule_matches_get_rule(condition, &event_rule);
959e3c66 2406
a0377dfe 2407 LTTNG_ASSERT(status == LTTNG_CONDITION_STATUS_OK);
959e3c66
JR
2408
2409 domain = lttng_event_rule_get_domain_type(event_rule);
2410 if (domain != LTTNG_DOMAIN_KERNEL) {
2411 is_supported = true;
2412 goto end;
2413 }
2414
2415 /*
2416 * Older kernel tracers can't emit notification. Therefore, we
2417 * reject triggers that require that mechanism to be available
2418 * to be evaluated.
2419 *
2420 * Assume unsupported on error.
2421 */
2422 is_supported = kernel_supports_event_notifiers() == 1;
1da26331
JG
2423 break;
2424 }
2425 default:
959e3c66 2426 is_supported = true;
1da26331
JG
2427 }
2428end:
959e3c66 2429 return is_supported;
1da26331
JG
2430}
2431
51eab943 2432/* Must be called with RCU read lock held. */
28ab034a
JG
2433static int bind_trigger_to_matching_session(struct lttng_trigger *trigger,
2434 struct notification_thread_state *state)
51eab943
JG
2435{
2436 int ret = 0;
51eab943
JG
2437 const struct lttng_condition *condition;
2438 const char *session_name;
2439 struct lttng_session_trigger_list *trigger_list;
2440
48b7cdc2
FD
2441 ASSERT_RCU_READ_LOCKED();
2442
51eab943 2443 condition = lttng_trigger_get_const_condition(trigger);
319dcddc 2444 session_name = get_condition_session_name(condition);
51eab943 2445
ed327204
JG
2446 trigger_list = get_session_trigger_list(state, session_name);
2447 if (!trigger_list) {
bd0514a5 2448 DBG("Unable to bind trigger applying to session \"%s\" as it is not yet known to the notification system",
28ab034a 2449 session_name);
51eab943 2450 goto end;
ed327204 2451 }
51eab943 2452
28ab034a 2453 DBG("Newly registered trigger bound to session \"%s\"", session_name);
51eab943
JG
2454 ret = lttng_session_trigger_list_add(trigger_list, trigger);
2455end:
2456 return ret;
2457}
2458
2459/* Must be called with RCU read lock held. */
28ab034a
JG
2460static int bind_trigger_to_matching_channels(struct lttng_trigger *trigger,
2461 struct notification_thread_state *state)
51eab943
JG
2462{
2463 int ret = 0;
2464 struct cds_lfht_node *node;
2465 struct cds_lfht_iter iter;
2466 struct channel_info *channel;
2467
48b7cdc2
FD
2468 ASSERT_RCU_READ_LOCKED();
2469
28ab034a 2470 cds_lfht_for_each_entry (state->channels_ht, &iter, channel, channels_ht_node) {
51eab943
JG
2471 struct lttng_trigger_list_element *trigger_list_element;
2472 struct lttng_channel_trigger_list *trigger_list;
a5d64ae7 2473 struct cds_lfht_iter lookup_iter;
51eab943
JG
2474
2475 if (!trigger_applies_to_channel(trigger, channel)) {
2476 continue;
2477 }
2478
2479 cds_lfht_lookup(state->channel_triggers_ht,
2480 hash_channel_key(&channel->key),
2481 match_channel_trigger_list,
2482 &channel->key,
a5d64ae7
MD
2483 &lookup_iter);
2484 node = cds_lfht_iter_get_node(&lookup_iter);
a0377dfe 2485 LTTNG_ASSERT(node);
28ab034a
JG
2486 trigger_list = caa_container_of(
2487 node, struct lttng_channel_trigger_list, channel_triggers_ht_node);
51eab943 2488
64803277 2489 trigger_list_element = zmalloc<lttng_trigger_list_element>();
51eab943
JG
2490 if (!trigger_list_element) {
2491 ret = -1;
2492 goto end;
2493 }
2494 CDS_INIT_LIST_HEAD(&trigger_list_element->node);
2495 trigger_list_element->trigger = trigger;
2496 cds_list_add(&trigger_list_element->node, &trigger_list->list);
28ab034a 2497 DBG("Newly registered trigger bound to channel \"%s\"", channel->name);
51eab943
JG
2498 }
2499end:
2500 return ret;
2501}
2502
28ab034a 2503static bool is_trigger_action_notify(const struct lttng_trigger *trigger)
f2b3ef9f
JG
2504{
2505 bool is_notify = false;
2506 unsigned int i, count;
2507 enum lttng_action_status action_status;
28ab034a 2508 const struct lttng_action *action = lttng_trigger_get_const_action(trigger);
f2b3ef9f
JG
2509 enum lttng_action_type action_type;
2510
a0377dfe 2511 LTTNG_ASSERT(action);
17182cfd 2512 action_type = lttng_action_get_type(action);
f2b3ef9f
JG
2513 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
2514 is_notify = true;
2515 goto end;
7c2fae7c 2516 } else if (action_type != LTTNG_ACTION_TYPE_LIST) {
f2b3ef9f
JG
2517 goto end;
2518 }
2519
702f26c8 2520 action_status = lttng_action_list_get_count(action, &count);
a0377dfe 2521 LTTNG_ASSERT(action_status == LTTNG_ACTION_STATUS_OK);
f2b3ef9f
JG
2522
2523 for (i = 0; i < count; i++) {
28ab034a 2524 const struct lttng_action *inner_action = lttng_action_list_get_at_index(action, i);
f2b3ef9f 2525
17182cfd 2526 action_type = lttng_action_get_type(inner_action);
f2b3ef9f
JG
2527 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
2528 is_notify = true;
2529 goto end;
2530 }
2531 }
2532
2533end:
2534 return is_notify;
2535}
2536
242388e4 2537static bool trigger_name_taken(struct notification_thread_state *state,
28ab034a 2538 const struct lttng_trigger *trigger)
242388e4
JR
2539{
2540 struct cds_lfht_iter iter;
2541
2542 /*
2543 * No duplicata is allowed in the triggers_by_name_uid_ht.
2544 * The match is done against the trigger name and uid.
2545 */
2546 cds_lfht_lookup(state->triggers_by_name_uid_ht,
2547 hash_trigger_by_name_uid(trigger),
2548 match_trigger_by_name_uid,
2549 trigger,
2550 &iter);
2551 return !!cds_lfht_iter_get_node(&iter);
2552}
2553
28ab034a
JG
2554static enum lttng_error_code generate_trigger_name(struct notification_thread_state *state,
2555 struct lttng_trigger *trigger,
2556 const char **name)
242388e4
JR
2557{
2558 enum lttng_error_code ret_code = LTTNG_OK;
2559 bool taken = false;
2560 enum lttng_trigger_status status;
2561
2562 do {
28ab034a
JG
2563 const int ret =
2564 lttng_trigger_generate_name(trigger, state->trigger_id.name_offset++);
242388e4
JR
2565 if (ret) {
2566 /* The only reason this can fail right now. */
2567 ret_code = LTTNG_ERR_NOMEM;
2568 break;
2569 }
2570
2571 status = lttng_trigger_get_name(trigger, name);
a0377dfe 2572 LTTNG_ASSERT(status == LTTNG_TRIGGER_STATUS_OK);
242388e4
JR
2573
2574 taken = trigger_name_taken(state, trigger);
2575 } while (taken || state->trigger_id.name_offset == UINT64_MAX);
2576
2577 return ret_code;
2578}
2579
28ab034a
JG
2580static inline void
2581notif_thread_state_remove_trigger_ht_elem(struct notification_thread_state *state,
2582 struct lttng_trigger_ht_element *trigger_ht_element)
2758e38b 2583{
a0377dfe
FD
2584 LTTNG_ASSERT(state);
2585 LTTNG_ASSERT(trigger_ht_element);
2758e38b
FD
2586
2587 cds_lfht_del(state->triggers_ht, &trigger_ht_element->node);
2588 cds_lfht_del(state->triggers_by_name_uid_ht, &trigger_ht_element->node_by_name_uid);
2589}
2590
28ab034a
JG
2591static enum lttng_error_code setup_tracer_notifier(struct notification_thread_state *state,
2592 struct lttng_trigger *trigger)
6487ad53
FD
2593{
2594 enum lttng_error_code ret;
2595 enum event_notifier_error_accounting_status error_accounting_status;
2596 struct cds_lfht_node *node;
2597 uint64_t error_counter_index = 0;
2598 struct lttng_condition *condition = lttng_trigger_get_condition(trigger);
cd9adb8b 2599 struct notification_trigger_tokens_ht_element *trigger_tokens_ht_element = nullptr;
6487ad53 2600
64803277 2601 trigger_tokens_ht_element = zmalloc<notification_trigger_tokens_ht_element>();
6487ad53
FD
2602 if (!trigger_tokens_ht_element) {
2603 ret = LTTNG_ERR_NOMEM;
2604 goto end;
2605 }
2606
2607 /* Add trigger token to the trigger_tokens_ht. */
2608 cds_lfht_node_init(&trigger_tokens_ht_element->node);
2609 trigger_tokens_ht_element->token = LTTNG_OPTIONAL_GET(trigger->tracer_token);
2610 trigger_tokens_ht_element->trigger = trigger;
2611
2612 node = cds_lfht_add_unique(state->trigger_tokens_ht,
28ab034a
JG
2613 hash_key_u64(&trigger_tokens_ht_element->token, lttng_ht_seed),
2614 match_trigger_token,
2615 &trigger_tokens_ht_element->token,
2616 &trigger_tokens_ht_element->node);
6487ad53
FD
2617 if (node != &trigger_tokens_ht_element->node) {
2618 ret = LTTNG_ERR_TRIGGER_EXISTS;
2619 goto error_free_ht_element;
2620 }
2621
2622 error_accounting_status = event_notifier_error_accounting_register_event_notifier(
28ab034a 2623 trigger, &error_counter_index);
6487ad53 2624 if (error_accounting_status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
28ab034a
JG
2625 if (error_accounting_status ==
2626 EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE) {
7c2fae7c 2627 DBG("Trigger list error accounting counter full.");
6487ad53
FD
2628 ret = LTTNG_ERR_EVENT_NOTIFIER_ERROR_ACCOUNTING_FULL;
2629 } else {
2630 ERR("Error registering trigger for error accounting");
2631 ret = LTTNG_ERR_EVENT_NOTIFIER_REGISTRATION;
2632 }
2633
2634 goto error_remove_ht_element;
2635 }
2636
28ab034a 2637 lttng_condition_event_rule_matches_set_error_counter_index(condition, error_counter_index);
6487ad53
FD
2638
2639 ret = LTTNG_OK;
2640 goto end;
2641
2642error_remove_ht_element:
2643 cds_lfht_del(state->trigger_tokens_ht, &trigger_tokens_ht_element->node);
2644error_free_ht_element:
2645 free(trigger_tokens_ht_element);
2646end:
2647 return ret;
2648}
2649
ab0ee2ca 2650/*
f2b3ef9f 2651 * FIXME A client's credentials are not checked when registering a trigger.
ab0ee2ca 2652 *
1da26331 2653 * The effects of this are benign since:
ab0ee2ca 2654 * - The client will succeed in registering the trigger, as it is valid,
51eab943 2655 * - The trigger will, internally, be bound to the channel/session,
ab0ee2ca
JG
2656 * - The notifications will not be sent since the client's credentials
2657 * are checked against the channel at that moment.
1da26331
JG
2658 *
2659 * If this function returns a non-zero value, it means something is
50ca7858 2660 * fundamentally broken and the whole subsystem/thread will be torn down.
1da26331
JG
2661 *
2662 * If a non-fatal error occurs, just set the cmd_result to the appropriate
2663 * error code.
ab0ee2ca 2664 */
28ab034a
JG
2665static int
2666handle_notification_thread_command_register_trigger(struct notification_thread_state *state,
2667 struct lttng_trigger *trigger,
2668 bool is_trigger_anonymous,
2669 enum lttng_error_code *cmd_result)
ab0ee2ca
JG
2670{
2671 int ret = 0;
2672 struct lttng_condition *condition;
cd9adb8b
JG
2673 struct notification_client_list *client_list = nullptr;
2674 struct lttng_trigger_ht_element *trigger_ht_element = nullptr;
ab0ee2ca 2675 struct cds_lfht_node *node;
28ab034a 2676 const char *trigger_name;
ab0ee2ca 2677 bool free_trigger = true;
cd9adb8b 2678 struct lttng_evaluation *evaluation = nullptr;
f2b3ef9f 2679 struct lttng_credentials object_creds;
ff588497
JR
2680 uid_t object_uid;
2681 gid_t object_gid;
f2b3ef9f 2682 enum action_executor_status executor_status;
28ab034a 2683 const uint64_t trigger_tracer_token = state->trigger_id.next_tracer_token++;
ab0ee2ca
JG
2684
2685 rcu_read_lock();
2686
e6887944
JR
2687 /* Set the trigger's tracer token. */
2688 lttng_trigger_set_tracer_token(trigger, trigger_tracer_token);
2689
0efb2ad7 2690 if (!is_trigger_anonymous) {
28ab034a 2691 if (lttng_trigger_get_name(trigger, &trigger_name) == LTTNG_TRIGGER_STATUS_UNSET) {
0efb2ad7 2692 const enum lttng_error_code ret_code =
28ab034a 2693 generate_trigger_name(state, trigger, &trigger_name);
242388e4 2694
0efb2ad7
JG
2695 if (ret_code != LTTNG_OK) {
2696 /* Fatal error. */
2697 ret = -1;
2698 *cmd_result = ret_code;
2699 goto error;
2700 }
2701 } else if (trigger_name_taken(state, trigger)) {
2702 /* Not a fatal error. */
2703 *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
2704 ret = 0;
242388e4
JR
2705 goto error;
2706 }
0efb2ad7
JG
2707 } else {
2708 trigger_name = "(anonymous)";
242388e4
JR
2709 }
2710
ab0ee2ca 2711 condition = lttng_trigger_get_condition(trigger);
a0377dfe 2712 LTTNG_ASSERT(condition);
1da26331 2713
959e3c66
JR
2714 /* Some conditions require tracers to implement a minimal ABI version. */
2715 if (!condition_is_supported(condition)) {
1da26331
JG
2716 *cmd_result = LTTNG_ERR_NOT_SUPPORTED;
2717 goto error;
1da26331
JG
2718 }
2719
64803277 2720 trigger_ht_element = zmalloc<lttng_trigger_ht_element>();
ab0ee2ca
JG
2721 if (!trigger_ht_element) {
2722 ret = -1;
2723 goto error;
2724 }
2725
2726 /* Add trigger to the trigger_ht. */
2727 cds_lfht_node_init(&trigger_ht_element->node);
242388e4 2728 cds_lfht_node_init(&trigger_ht_element->node_by_name_uid);
ab0ee2ca
JG
2729 trigger_ht_element->trigger = trigger;
2730
2731 node = cds_lfht_add_unique(state->triggers_ht,
28ab034a
JG
2732 lttng_condition_hash(condition),
2733 match_trigger,
2734 trigger,
2735 &trigger_ht_element->node);
ab0ee2ca
JG
2736 if (node != &trigger_ht_element->node) {
2737 /* Not a fatal error, simply report it to the client. */
2738 *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
2739 goto error_free_ht_element;
2740 }
2741
242388e4 2742 node = cds_lfht_add_unique(state->triggers_by_name_uid_ht,
28ab034a
JG
2743 hash_trigger_by_name_uid(trigger),
2744 match_trigger_by_name_uid,
2745 trigger,
2746 &trigger_ht_element->node_by_name_uid);
242388e4 2747 if (node != &trigger_ht_element->node_by_name_uid) {
75e540c6
JG
2748 /* Internal error: add to triggers_ht should have failed. */
2749 ret = -1;
242388e4
JR
2750 goto error_free_ht_element;
2751 }
2752
9c374932
JR
2753 /* From this point consider the trigger registered. */
2754 lttng_trigger_set_as_registered(trigger);
2755
6487ad53
FD
2756 /*
2757 * Some triggers might need a tracer notifier depending on its
2758 * condition and actions.
2759 */
2760 if (lttng_trigger_needs_tracer_notifier(trigger)) {
2761 enum lttng_error_code error_code;
e7c93cf9 2762
6487ad53
FD
2763 error_code = setup_tracer_notifier(state, trigger);
2764 if (error_code != LTTNG_OK) {
28ab034a 2765 notif_thread_state_remove_trigger_ht_elem(state, trigger_ht_element);
6487ad53
FD
2766 if (error_code == LTTNG_ERR_NOMEM) {
2767 ret = -1;
2768 } else {
2769 *cmd_result = error_code;
2770 ret = 0;
90aa04a1
FD
2771 }
2772
6487ad53 2773 goto error_free_ht_element;
90aa04a1 2774 }
e7c93cf9
JR
2775 }
2776
ab0ee2ca
JG
2777 /*
2778 * The rest only applies to triggers that have a "notify" action.
2779 * It is not skipped as this is the only action type currently
2780 * supported.
2781 */
f2b3ef9f 2782 if (is_trigger_action_notify(trigger)) {
091fa780
FD
2783 /*
2784 * Find or create the client list of this condition. It may
2785 * already be present if another trigger is already registered
2786 * with the same condition.
2787 */
2788 client_list = get_client_list_from_condition(state, condition);
f2b3ef9f 2789 if (!client_list) {
091fa780
FD
2790 /*
2791 * No client list for this condition yet. We create new
2792 * one and build it up.
2793 */
2794 client_list = notification_client_list_create(state, condition);
2795 if (!client_list) {
28ab034a
JG
2796 ERR("Error creating notification client list for trigger %s",
2797 trigger->name);
a3c9aa3c 2798 ret = -1;
091fa780 2799 goto error_free_ht_element;
f2b3ef9f 2800 }
ab0ee2ca 2801 }
f2b3ef9f 2802
091fa780
FD
2803 CDS_INIT_LIST_HEAD(&trigger_ht_element->client_list_trigger_node);
2804
2805 pthread_mutex_lock(&client_list->lock);
28ab034a
JG
2806 cds_list_add(&trigger_ht_element->client_list_trigger_node,
2807 &client_list->triggers_list);
091fa780 2808 pthread_mutex_unlock(&client_list->lock);
ab0ee2ca
JG
2809 }
2810
091fa780
FD
2811 /*
2812 * Ownership of the trigger and of its wrapper was transfered to
2813 * the triggers_ht. Same for token ht element if necessary.
2814 */
cd9adb8b 2815 trigger_ht_element = nullptr;
091fa780
FD
2816 free_trigger = false;
2817
f82f93a1 2818 switch (get_condition_binding_object(condition)) {
51eab943
JG
2819 case LTTNG_OBJECT_TYPE_SESSION:
2820 /* Add the trigger to the list if it matches a known session. */
2821 ret = bind_trigger_to_matching_session(trigger, state);
2822 if (ret) {
091fa780 2823 goto error_free_ht_element;
ab0ee2ca 2824 }
f82f93a1 2825 break;
51eab943
JG
2826 case LTTNG_OBJECT_TYPE_CHANNEL:
2827 /*
2828 * Add the trigger to list of triggers bound to the channels
2829 * currently known.
2830 */
2831 ret = bind_trigger_to_matching_channels(trigger, state);
2832 if (ret) {
091fa780 2833 goto error_free_ht_element;
ab0ee2ca 2834 }
51eab943
JG
2835 break;
2836 case LTTNG_OBJECT_TYPE_NONE:
2837 break;
2838 default:
f2b3ef9f 2839 ERR("Unknown object type on which to bind a newly registered trigger was encountered");
51eab943 2840 ret = -1;
091fa780 2841 goto error_free_ht_element;
ab0ee2ca
JG
2842 }
2843
2ae99f0b 2844 /*
f2b3ef9f
JG
2845 * The new trigger's condition must be evaluated against the current
2846 * state.
2847 *
2848 * In the case of `notify` action, nothing preventing clients from
2849 * subscribing to a condition before the corresponding trigger is
2850 * registered, we have to evaluate this new condition right away.
2ae99f0b
JG
2851 *
2852 * At some point, we were waiting for the next "evaluation" (e.g. on
2853 * reception of a channel sample) to evaluate this new condition, but
2854 * that was broken.
2855 *
2856 * The reason it was broken is that waiting for the next sample
2857 * does not allow us to properly handle transitions for edge-triggered
2858 * conditions.
2859 *
2860 * Consider this example: when we handle a new channel sample, we
2861 * evaluate each conditions twice: once with the previous state, and
2862 * again with the newest state. We then use those two results to
2863 * determine whether a state change happened: a condition was false and
2864 * became true. If a state change happened, we have to notify clients.
2865 *
2866 * Now, if a client subscribes to a given notification and registers
2867 * a trigger *after* that subscription, we have to make sure the
2868 * condition is evaluated at this point while considering only the
2869 * current state. Otherwise, the next evaluation cycle may only see
2870 * that the evaluations remain the same (true for samples n-1 and n) and
2871 * the client will never know that the condition has been met.
2872 */
f2b3ef9f
JG
2873 switch (get_condition_binding_object(condition)) {
2874 case LTTNG_OBJECT_TYPE_SESSION:
319dcddc
JG
2875 {
2876 /* Find the session associated with the condition. */
2877 const auto *session_name = get_condition_session_name(condition);
2878 auto session_info = get_session_info_by_name(state, session_name);
2879 if (!session_info) {
2880 /* Not an error, the session doesn't exist yet. */
2881 DBG("Session not found while evaluating session condition during registration of trigger: session name = `%s`",
28ab034a 2882 session_name);
319dcddc
JG
2883 ret = 0;
2884 goto success;
2885 }
2886
2887 LTTNG_OPTIONAL_SET(&object_creds.uid, session_info->uid);
2888 LTTNG_OPTIONAL_SET(&object_creds.gid, session_info->gid);
2889
cd9adb8b 2890 ret = evaluate_session_condition(condition, session_info, nullptr, &evaluation);
319dcddc 2891 session_info_put(session_info);
b42ada90 2892 break;
319dcddc 2893 }
f2b3ef9f 2894 case LTTNG_OBJECT_TYPE_CHANNEL:
28ab034a
JG
2895 ret = evaluate_channel_condition_for_client(
2896 condition, state, &evaluation, &object_uid, &object_gid);
bc8daafb
JG
2897 LTTNG_OPTIONAL_SET(&object_creds.uid, object_uid);
2898 LTTNG_OPTIONAL_SET(&object_creds.gid, object_gid);
f2b3ef9f
JG
2899 break;
2900 case LTTNG_OBJECT_TYPE_NONE:
2901 ret = 0;
242388e4 2902 break;
f2b3ef9f
JG
2903 case LTTNG_OBJECT_TYPE_UNKNOWN:
2904 default:
2905 ret = -1;
242388e4 2906 break;
f2b3ef9f
JG
2907 }
2908
2909 if (ret) {
2910 /* Fatal error. */
091fa780 2911 goto error_free_ht_element;
f2b3ef9f
JG
2912 }
2913
28ab034a 2914 DBG("Newly registered trigger's condition evaluated to %s", evaluation ? "true" : "false");
f2b3ef9f
JG
2915 if (!evaluation) {
2916 /* Evaluation yielded nothing. Normal exit. */
2917 ret = 0;
091fa780 2918 goto success;
2ae99f0b
JG
2919 }
2920
2921 /*
f2b3ef9f
JG
2922 * Ownership of `evaluation` transferred to the action executor
2923 * no matter the result.
2ae99f0b 2924 */
28ab034a
JG
2925 executor_status = action_executor_enqueue_trigger(
2926 state->executor, trigger, evaluation, &object_creds, client_list);
cd9adb8b 2927 evaluation = nullptr;
f2b3ef9f
JG
2928 switch (executor_status) {
2929 case ACTION_EXECUTOR_STATUS_OK:
2930 break;
2931 case ACTION_EXECUTOR_STATUS_ERROR:
2932 case ACTION_EXECUTOR_STATUS_INVALID:
2933 /*
2934 * TODO Add trigger identification (name/id) when
2935 * it is added to the API.
2936 */
2937 ERR("Fatal error occurred while enqueuing action associated to newly registered trigger");
2938 ret = -1;
091fa780 2939 goto error_free_ht_element;
f2b3ef9f
JG
2940 case ACTION_EXECUTOR_STATUS_OVERFLOW:
2941 /*
2942 * TODO Add trigger identification (name/id) when
2943 * it is added to the API.
2944 *
2945 * Not a fatal error.
2946 */
2947 WARN("No space left when enqueuing action associated to newly registered trigger");
2948 ret = 0;
091fa780 2949 goto success;
f2b3ef9f
JG
2950 default:
2951 abort();
2952 }
2ae99f0b 2953
091fa780 2954success:
ab0ee2ca 2955 *cmd_result = LTTNG_OK;
e6887944 2956 DBG("Registered trigger: name = `%s`, tracer token = %" PRIu64,
28ab034a
JG
2957 trigger_name,
2958 trigger_tracer_token);
091fa780 2959 goto end;
505b2d90 2960
ab0ee2ca 2961error_free_ht_element:
242388e4
JR
2962 if (trigger_ht_element) {
2963 /* Delayed removal due to RCU constraint on delete. */
28ab034a 2964 call_rcu(&trigger_ht_element->rcu_node, free_lttng_trigger_ht_element_rcu);
242388e4 2965 }
ab0ee2ca
JG
2966error:
2967 if (free_trigger) {
9c374932
JR
2968 /*
2969 * Other objects might have a reference to the trigger, mark it
2970 * as unregistered.
2971 */
2972 lttng_trigger_set_as_unregistered(trigger);
ab0ee2ca
JG
2973 lttng_trigger_destroy(trigger);
2974 }
091fa780 2975end:
ab0ee2ca
JG
2976 rcu_read_unlock();
2977 return ret;
2978}
2979
28ab034a 2980static void free_lttng_trigger_ht_element_rcu(struct rcu_head *node)
83b934ad 2981{
28ab034a 2982 free(caa_container_of(node, struct lttng_trigger_ht_element, rcu_node));
83b934ad
MD
2983}
2984
28ab034a 2985static void free_notification_trigger_tokens_ht_element_rcu(struct rcu_head *node)
e7c93cf9 2986{
28ab034a 2987 free(caa_container_of(node, struct notification_trigger_tokens_ht_element, rcu_node));
e7c93cf9
JR
2988}
2989
28ab034a
JG
2990static void teardown_tracer_notifier(struct notification_thread_state *state,
2991 const struct lttng_trigger *trigger)
6487ad53
FD
2992{
2993 struct cds_lfht_iter iter;
2994 struct notification_trigger_tokens_ht_element *trigger_tokens_ht_element;
2995
28ab034a
JG
2996 cds_lfht_for_each_entry (state->trigger_tokens_ht, &iter, trigger_tokens_ht_element, node) {
2997 if (!lttng_trigger_is_equal(trigger, trigger_tokens_ht_element->trigger)) {
6487ad53
FD
2998 continue;
2999 }
3000
3001 event_notifier_error_accounting_unregister_event_notifier(
28ab034a 3002 trigger_tokens_ht_element->trigger);
6487ad53
FD
3003
3004 /* TODO talk to all app and remove it */
bd0514a5 3005 DBG("Removed trigger from tokens_ht");
28ab034a 3006 cds_lfht_del(state->trigger_tokens_ht, &trigger_tokens_ht_element->node);
6487ad53
FD
3007
3008 call_rcu(&trigger_tokens_ht_element->rcu_node,
28ab034a 3009 free_notification_trigger_tokens_ht_element_rcu);
6487ad53
FD
3010
3011 break;
3012 }
3013}
3014
28ab034a
JG
3015static void
3016remove_trigger_from_session_trigger_list(struct lttng_session_trigger_list *trigger_list,
3017 const struct lttng_trigger *trigger)
319dcddc
JG
3018{
3019 bool found = false;
3020 struct lttng_trigger_list_element *trigger_element, *tmp;
3021
3022 cds_list_for_each_entry_safe (trigger_element, tmp, &trigger_list->list, node) {
3023 if (!lttng_trigger_is_equal(trigger, trigger_element->trigger)) {
3024 continue;
3025 }
3026
3027 DBG("Removed trigger from session_triggers_ht");
3028 cds_list_del(&trigger_element->node);
3029 free(trigger_element);
3030 /* A trigger can only appear once per session. */
3031 found = true;
3032 break;
3033 }
3034
3035 if (!found) {
3036 ERR("Failed to find trigger associated with session: session name = `%s`",
28ab034a 3037 trigger_list->session_name);
319dcddc
JG
3038 }
3039
3040 LTTNG_ASSERT(found);
3041}
3042
28ab034a
JG
3043static int
3044handle_notification_thread_command_unregister_trigger(struct notification_thread_state *state,
3045 const struct lttng_trigger *trigger,
3046 enum lttng_error_code *_cmd_reply)
ab0ee2ca
JG
3047{
3048 struct cds_lfht_iter iter;
ed327204 3049 struct cds_lfht_node *triggers_ht_node;
ab0ee2ca 3050 struct notification_client_list *client_list;
cd9adb8b 3051 struct lttng_trigger_ht_element *trigger_ht_element = nullptr;
28ab034a 3052 const struct lttng_condition *condition = lttng_trigger_get_const_condition(trigger);
ab0ee2ca
JG
3053 enum lttng_error_code cmd_reply;
3054
3055 rcu_read_lock();
3056
28ab034a
JG
3057 cds_lfht_lookup(
3058 state->triggers_ht, lttng_condition_hash(condition), match_trigger, trigger, &iter);
ab0ee2ca
JG
3059 triggers_ht_node = cds_lfht_iter_get_node(&iter);
3060 if (!triggers_ht_node) {
3061 cmd_reply = LTTNG_ERR_TRIGGER_NOT_FOUND;
3062 goto end;
3063 } else {
3064 cmd_reply = LTTNG_OK;
3065 }
3066
28ab034a
JG
3067 trigger_ht_element =
3068 caa_container_of(triggers_ht_node, struct lttng_trigger_ht_element, node);
9c374932 3069
319dcddc
JG
3070 switch (get_condition_binding_object(condition)) {
3071 case LTTNG_OBJECT_TYPE_CHANNEL:
3072 {
3073 struct lttng_channel_trigger_list *trigger_list;
ab0ee2ca 3074
319dcddc
JG
3075 /*
3076 * Remove trigger from channel_triggers_ht.
3077 *
3078 * Note that multiple channels may have matched the trigger's
3079 * condition (e.g. all instances of a given channel in per-pid buffering
3080 * mode).
3081 *
3082 * Iterate on all lists since we don't know the target channels' keys.
3083 */
28ab034a
JG
3084 cds_lfht_for_each_entry (
3085 state->channel_triggers_ht, &iter, trigger_list, channel_triggers_ht_node) {
319dcddc
JG
3086 struct lttng_trigger_list_element *trigger_element, *tmp;
3087
28ab034a
JG
3088 cds_list_for_each_entry_safe (
3089 trigger_element, tmp, &trigger_list->list, node) {
319dcddc
JG
3090 if (!lttng_trigger_is_equal(trigger, trigger_element->trigger)) {
3091 continue;
3092 }
3093
3094 DBG("Removed trigger from channel_triggers_ht");
3095 cds_list_del(&trigger_element->node);
6dcdb62c 3096 free(trigger_element);
319dcddc
JG
3097 /* A trigger can only appear once per channel */
3098 break;
ab0ee2ca 3099 }
319dcddc
JG
3100 }
3101 break;
3102 }
3103 case LTTNG_OBJECT_TYPE_SESSION:
3104 {
28ab034a
JG
3105 auto session =
3106 get_session_info_by_name(state, get_condition_session_name(condition));
ab0ee2ca 3107
319dcddc
JG
3108 /* Session doesn't exist, no trigger to remove. */
3109 if (!session) {
e4db5ace 3110 break;
ab0ee2ca 3111 }
319dcddc
JG
3112
3113 auto session_trigger_list = get_session_trigger_list(state, session->name);
3114 remove_trigger_from_session_trigger_list(session_trigger_list, trigger);
3115 session_info_put(session);
3116 }
3117 case LTTNG_OBJECT_TYPE_NONE:
3118 break;
3119 default:
3120 abort();
ab0ee2ca
JG
3121 }
3122
6487ad53
FD
3123 if (lttng_trigger_needs_tracer_notifier(trigger)) {
3124 teardown_tracer_notifier(state, trigger);
e7c93cf9
JR
3125 }
3126
51367634
JR
3127 if (is_trigger_action_notify(trigger)) {
3128 /*
3129 * Remove and release the client list from
3130 * notification_trigger_clients_ht.
3131 */
3132 client_list = get_client_list_from_condition(state, condition);
a0377dfe 3133 LTTNG_ASSERT(client_list);
ed327204 3134
091fa780
FD
3135 pthread_mutex_lock(&client_list->lock);
3136 cds_list_del(&trigger_ht_element->client_list_trigger_node);
3137 pthread_mutex_unlock(&client_list->lock);
3138
51367634
JR
3139 /* Put new reference and the hashtable's reference. */
3140 notification_client_list_put(client_list);
3141 notification_client_list_put(client_list);
cd9adb8b 3142 client_list = nullptr;
51367634 3143 }
ab0ee2ca 3144
2758e38b
FD
3145 /* Remove trigger from triggers_ht. */
3146 notif_thread_state_remove_trigger_ht_elem(state, trigger_ht_element);
ab0ee2ca 3147
7ca172c1 3148 /* Release the ownership of the trigger. */
ab0ee2ca 3149 lttng_trigger_destroy(trigger_ht_element->trigger);
83b934ad 3150 call_rcu(&trigger_ht_element->rcu_node, free_lttng_trigger_ht_element_rcu);
ab0ee2ca
JG
3151end:
3152 rcu_read_unlock();
3153 if (_cmd_reply) {
3154 *_cmd_reply = cmd_reply;
3155 }
3156 return 0;
3157}
3158
28ab034a
JG
3159static int pop_cmd_queue(struct notification_thread_handle *handle,
3160 struct notification_thread_command **cmd)
f370852f
JR
3161{
3162 int ret;
3163 uint64_t counter;
3164
3165 pthread_mutex_lock(&handle->cmd_queue.lock);
3166 ret = lttng_read(handle->cmd_queue.event_fd, &counter, sizeof(counter));
3167 if (ret != sizeof(counter)) {
3168 ret = -1;
3169 goto error_unlock;
3170 }
3171
28ab034a
JG
3172 *cmd = cds_list_first_entry(
3173 &handle->cmd_queue.list, struct notification_thread_command, cmd_list_node);
f370852f
JR
3174 cds_list_del(&((*cmd)->cmd_list_node));
3175 ret = 0;
3176
3177error_unlock:
3178 pthread_mutex_unlock(&handle->cmd_queue.lock);
3179 return ret;
3180}
3181
ab0ee2ca 3182/* Returns 0 on success, 1 on exit requested, negative value on error. */
28ab034a
JG
3183int handle_notification_thread_command(struct notification_thread_handle *handle,
3184 struct notification_thread_state *state)
ab0ee2ca
JG
3185{
3186 int ret;
ab0ee2ca
JG
3187 struct notification_thread_command *cmd;
3188
f370852f
JR
3189 ret = pop_cmd_queue(handle, &cmd);
3190 if (ret) {
ab0ee2ca
JG
3191 goto error;
3192 }
3193
28ab034a 3194 DBG("Received `%s` command", notification_command_type_str(cmd->type));
ab0ee2ca
JG
3195 switch (cmd->type) {
3196 case NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER:
28ab034a
JG
3197 ret = handle_notification_thread_command_register_trigger(
3198 state,
3199 cmd->parameters.register_trigger.trigger,
3200 cmd->parameters.register_trigger.is_trigger_anonymous,
3201 &cmd->reply_code);
ab0ee2ca
JG
3202 break;
3203 case NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER:
ab0ee2ca 3204 ret = handle_notification_thread_command_unregister_trigger(
28ab034a 3205 state, cmd->parameters.unregister_trigger.trigger, &cmd->reply_code);
ab0ee2ca
JG
3206 break;
3207 case NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL:
ab0ee2ca 3208 ret = handle_notification_thread_command_add_channel(
28ab034a
JG
3209 state,
3210 cmd->parameters.add_channel.session.id,
3211 cmd->parameters.add_channel.channel.name,
3212 cmd->parameters.add_channel.channel.domain,
3213 cmd->parameters.add_channel.channel.key,
3214 cmd->parameters.add_channel.channel.capacity,
3215 &cmd->reply_code);
ab0ee2ca
JG
3216 break;
3217 case NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL:
ab0ee2ca 3218 ret = handle_notification_thread_command_remove_channel(
28ab034a
JG
3219 state,
3220 cmd->parameters.remove_channel.key,
3221 cmd->parameters.remove_channel.domain,
3222 &cmd->reply_code);
ab0ee2ca 3223 break;
139a8d25 3224 case NOTIFICATION_COMMAND_TYPE_ADD_SESSION:
28ab034a
JG
3225 ret = handle_notification_thread_command_add_session(
3226 state,
3227 cmd->parameters.add_session.session_id,
3228 cmd->parameters.add_session.session_name,
3229 cmd->parameters.add_session.session_uid,
3230 cmd->parameters.add_session.session_gid,
3231 &cmd->reply_code);
139a8d25
JG
3232 break;
3233 case NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION:
3234 ret = handle_notification_thread_command_remove_session(
28ab034a 3235 state, cmd->parameters.remove_session.session_id, &cmd->reply_code);
139a8d25 3236 break;
0ca52944 3237 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING:
0ca52944 3238 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED:
ed327204 3239 ret = handle_notification_thread_command_session_rotation(
28ab034a
JG
3240 state,
3241 cmd->type,
3242 cmd->parameters.session_rotation.session_id,
3243 cmd->parameters.session_rotation.trace_archive_chunk_id,
3244 cmd->parameters.session_rotation.location,
3245 &cmd->reply_code);
0ca52944 3246 break;
d02d7404
JR
3247 case NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE:
3248 ret = handle_notification_thread_command_add_tracer_event_source(
28ab034a
JG
3249 state,
3250 cmd->parameters.tracer_event_source.tracer_event_source_fd,
3251 cmd->parameters.tracer_event_source.domain,
3252 &cmd->reply_code);
d02d7404
JR
3253 break;
3254 case NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE:
3255 ret = handle_notification_thread_command_remove_tracer_event_source(
28ab034a
JG
3256 state,
3257 cmd->parameters.tracer_event_source.tracer_event_source_fd,
3258 &cmd->reply_code);
d02d7404 3259 break;
fbc9f37d
JR
3260 case NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS:
3261 {
cd9adb8b 3262 struct lttng_triggers *triggers = nullptr;
fbc9f37d
JR
3263
3264 ret = handle_notification_thread_command_list_triggers(
28ab034a
JG
3265 handle,
3266 state,
3267 cmd->parameters.list_triggers.uid,
3268 &triggers,
3269 &cmd->reply_code);
fbc9f37d
JR
3270 cmd->reply.list_triggers.triggers = triggers;
3271 ret = 0;
3272 break;
3273 }
ab0ee2ca 3274 case NOTIFICATION_COMMAND_TYPE_QUIT:
ab0ee2ca
JG
3275 cmd->reply_code = LTTNG_OK;
3276 ret = 1;
3277 goto end;
8790759c
FD
3278 case NOTIFICATION_COMMAND_TYPE_GET_TRIGGER:
3279 {
cd9adb8b 3280 struct lttng_trigger *trigger = nullptr;
8790759c 3281
28ab034a
JG
3282 ret = handle_notification_thread_command_get_trigger(
3283 state, cmd->parameters.get_trigger.trigger, &trigger, &cmd->reply_code);
8790759c
FD
3284 cmd->reply.get_trigger.trigger = trigger;
3285 break;
3286 }
f2b3ef9f
JG
3287 case NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE:
3288 {
3289 const enum client_transmission_status client_status =
28ab034a 3290 cmd->parameters.client_communication_update.status;
f2b3ef9f 3291 const notification_client_id client_id =
28ab034a 3292 cmd->parameters.client_communication_update.id;
f2b3ef9f
JG
3293 struct notification_client *client;
3294
3295 rcu_read_lock();
3296 client = get_client_from_id(client_id, state);
3297
3298 if (!client) {
3299 /*
3300 * Client error was probably already picked-up by the
3301 * notification thread or it has disconnected
3302 * gracefully while this command was queued.
3303 */
3304 DBG("Failed to find notification client to update communication status, client id = %" PRIu64,
28ab034a 3305 client_id);
f2b3ef9f
JG
3306 ret = 0;
3307 } else {
28ab034a 3308 ret = client_handle_transmission_status(client, client_status, state);
f2b3ef9f
JG
3309 }
3310 rcu_read_unlock();
3311 break;
3312 }
ab0ee2ca 3313 default:
bd0514a5 3314 ERR("Unknown internal command received");
ab0ee2ca
JG
3315 goto error_unlock;
3316 }
3317
3318 if (ret) {
3319 goto error_unlock;
3320 }
3321end:
0ab399e0
JG
3322 if (cmd->is_async) {
3323 free(cmd);
cd9adb8b 3324 cmd = nullptr;
0ab399e0
JG
3325 } else {
3326 lttng_waiter_wake_up(&cmd->reply_waiter);
3327 }
ab0ee2ca
JG
3328 return ret;
3329error_unlock:
3330 /* Wake-up and return a fatal error to the calling thread. */
8ada111f 3331 lttng_waiter_wake_up(&cmd->reply_waiter);
ab0ee2ca
JG
3332 cmd->reply_code = LTTNG_ERR_FATAL;
3333error:
3334 /* Indicate a fatal error to the caller. */
3335 return -1;
3336}
3337
28ab034a 3338static int socket_set_non_blocking(int socket)
ab0ee2ca
JG
3339{
3340 int ret, flags;
3341
3342 /* Set the pipe as non-blocking. */
3343 ret = fcntl(socket, F_GETFL, 0);
3344 if (ret == -1) {
3345 PERROR("fcntl get socket flags");
3346 goto end;
3347 }
3348 flags = ret;
3349
3350 ret = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
3351 if (ret == -1) {
3352 PERROR("fcntl set O_NONBLOCK socket flag");
3353 goto end;
3354 }
3355 DBG("Client socket (fd = %i) set as non-blocking", socket);
3356end:
3357 return ret;
3358}
3359
28ab034a 3360static int client_reset_inbound_state(struct notification_client *client)
ab0ee2ca
JG
3361{
3362 int ret;
3363
882093ee 3364 lttng_payload_clear(&client->communication.inbound.payload);
ab0ee2ca
JG
3365
3366 client->communication.inbound.bytes_to_receive =
28ab034a
JG
3367 sizeof(struct lttng_notification_channel_message);
3368 client->communication.inbound.msg_type = LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN;
ab0ee2ca
JG
3369 LTTNG_SOCK_SET_UID_CRED(&client->communication.inbound.creds, -1);
3370 LTTNG_SOCK_SET_GID_CRED(&client->communication.inbound.creds, -1);
28ab034a
JG
3371 ret = lttng_dynamic_buffer_set_size(&client->communication.inbound.payload.buffer,
3372 client->communication.inbound.bytes_to_receive);
882093ee 3373
14fa22f8 3374 return ret;
ab0ee2ca
JG
3375}
3376
28ab034a 3377int handle_notification_thread_client_connect(struct notification_thread_state *state)
ab0ee2ca
JG
3378{
3379 int ret;
3380 struct notification_client *client;
3381
bd0514a5 3382 DBG("Handling new notification channel client connection");
ab0ee2ca 3383
64803277 3384 client = zmalloc<notification_client>();
ab0ee2ca
JG
3385 if (!client) {
3386 /* Fatal error. */
3387 ret = -1;
3388 goto error;
3389 }
6c24d3fd 3390
cd9adb8b 3391 pthread_mutex_init(&client->lock, nullptr);
ac1889bf 3392 client->id = state->next_notification_client_id++;
ab0ee2ca 3393 CDS_INIT_LIST_HEAD(&client->condition_list);
882093ee
JR
3394 lttng_payload_init(&client->communication.inbound.payload);
3395 lttng_payload_init(&client->communication.outbound.payload);
01ea340e 3396 client->communication.inbound.expect_creds = true;
505b2d90 3397
14fa22f8
JG
3398 ret = client_reset_inbound_state(client);
3399 if (ret) {
bd0514a5 3400 ERR("Failed to reset client communication's inbound state");
e742b055 3401 ret = 0;
14fa22f8
JG
3402 goto error;
3403 }
ab0ee2ca
JG
3404
3405 ret = lttcomm_accept_unix_sock(state->notification_channel_socket);
3406 if (ret < 0) {
bd0514a5 3407 ERR("Failed to accept new notification channel client connection");
ab0ee2ca
JG
3408 ret = 0;
3409 goto error;
3410 }
3411
3412 client->socket = ret;
3413
3414 ret = socket_set_non_blocking(client->socket);
3415 if (ret) {
bd0514a5 3416 ERR("Failed to set new notification channel client connection socket as non-blocking");
ab0ee2ca
JG
3417 goto error;
3418 }
3419
3420 ret = lttcomm_setsockopt_creds_unix_sock(client->socket);
3421 if (ret < 0) {
bd0514a5 3422 ERR("Failed to set socket options on new notification channel client socket");
ab0ee2ca
JG
3423 ret = 0;
3424 goto error;
3425 }
3426
9016dbfc 3427 client->communication.current_poll_events = CLIENT_POLL_EVENTS_IN;
28ab034a
JG
3428 ret = lttng_poll_add(
3429 &state->events, client->socket, client->communication.current_poll_events);
ab0ee2ca 3430 if (ret < 0) {
bd0514a5 3431 ERR("Failed to add notification channel client socket to poll set");
ab0ee2ca
JG
3432 ret = 0;
3433 goto error;
3434 }
28ab034a 3435 DBG("Added new notification channel client socket (%i) to poll set", client->socket);
ab0ee2ca 3436
ab0ee2ca
JG
3437 rcu_read_lock();
3438 cds_lfht_add(state->client_socket_ht,
28ab034a
JG
3439 hash_client_socket(client->socket),
3440 &client->client_socket_ht_node);
3441 cds_lfht_add(state->client_id_ht, hash_client_id(client->id), &client->client_id_ht_node);
ab0ee2ca
JG
3442 rcu_read_unlock();
3443
3444 return ret;
6c24d3fd 3445
ab0ee2ca 3446error:
f46376a1 3447 notification_client_destroy(client);
ab0ee2ca
JG
3448 return ret;
3449}
3450
6c24d3fd
JG
3451/*
3452 * RCU read-lock must be held by the caller.
3453 * Client lock must _not_ be held by the caller.
3454 */
28ab034a
JG
3455static int notification_thread_client_disconnect(struct notification_client *client,
3456 struct notification_thread_state *state)
505b2d90
JG
3457{
3458 int ret;
3459 struct lttng_condition_list_element *condition_list_element, *tmp;
3460
48b7cdc2
FD
3461 ASSERT_RCU_READ_LOCKED();
3462
505b2d90 3463 /* Acquire the client lock to disable its communication atomically. */
6c24d3fd 3464 pthread_mutex_lock(&client->lock);
505b2d90 3465 client->communication.active = false;
6c24d3fd
JG
3466 cds_lfht_del(state->client_socket_ht, &client->client_socket_ht_node);
3467 cds_lfht_del(state->client_id_ht, &client->client_id_ht_node);
3468 pthread_mutex_unlock(&client->lock);
3469
505b2d90
JG
3470 ret = lttng_poll_del(&state->events, client->socket);
3471 if (ret) {
28ab034a 3472 ERR("Failed to remove client socket %d from poll set", client->socket);
505b2d90
JG
3473 }
3474
505b2d90 3475 /* Release all conditions to which the client was subscribed. */
28ab034a
JG
3476 cds_list_for_each_entry_safe (condition_list_element, tmp, &client->condition_list, node) {
3477 (void) notification_thread_client_unsubscribe(
cd9adb8b 3478 client, condition_list_element->condition, state, nullptr);
505b2d90
JG
3479 }
3480
3481 /*
3482 * Client no longer accessible to other threads (through the
3483 * client lists).
3484 */
f46376a1 3485 notification_client_destroy(client);
505b2d90
JG
3486 return ret;
3487}
3488
28ab034a
JG
3489int handle_notification_thread_client_disconnect(int client_socket,
3490 struct notification_thread_state *state)
ab0ee2ca
JG
3491{
3492 int ret = 0;
3493 struct notification_client *client;
3494
3495 rcu_read_lock();
28ab034a 3496 DBG("Closing client connection (socket fd = %i)", client_socket);
ab0ee2ca
JG
3497 client = get_client_from_socket(client_socket, state);
3498 if (!client) {
3499 /* Internal state corruption, fatal error. */
28ab034a 3500 ERR("Unable to find client (socket fd = %i)", client_socket);
ab0ee2ca
JG
3501 ret = -1;
3502 goto end;
3503 }
3504
505b2d90 3505 ret = notification_thread_client_disconnect(client, state);
ab0ee2ca
JG
3506end:
3507 rcu_read_unlock();
3508 return ret;
3509}
3510
28ab034a 3511int handle_notification_thread_client_disconnect_all(struct notification_thread_state *state)
ab0ee2ca
JG
3512{
3513 struct cds_lfht_iter iter;
3514 struct notification_client *client;
3515 bool error_encoutered = false;
3516
3517 rcu_read_lock();
bd0514a5 3518 DBG("Closing all client connections");
28ab034a 3519 cds_lfht_for_each_entry (state->client_socket_ht, &iter, client, client_socket_ht_node) {
ab0ee2ca
JG
3520 int ret;
3521
28ab034a 3522 ret = notification_thread_client_disconnect(client, state);
ab0ee2ca
JG
3523 if (ret) {
3524 error_encoutered = true;
3525 }
3526 }
3527 rcu_read_unlock();
3528 return error_encoutered ? 1 : 0;
3529}
3530
28ab034a 3531int handle_notification_thread_trigger_unregister_all(struct notification_thread_state *state)
ab0ee2ca 3532{
4149ace8 3533 bool error_occurred = false;
ab0ee2ca
JG
3534 struct cds_lfht_iter iter;
3535 struct lttng_trigger_ht_element *trigger_ht_element;
3536
763de384 3537 rcu_read_lock();
28ab034a 3538 cds_lfht_for_each_entry (state->triggers_ht, &iter, trigger_ht_element, node) {
ab0ee2ca 3539 int ret = handle_notification_thread_command_unregister_trigger(
cd9adb8b 3540 state, trigger_ht_element->trigger, nullptr);
ab0ee2ca 3541 if (ret) {
4149ace8 3542 error_occurred = true;
ab0ee2ca
JG
3543 }
3544 }
763de384 3545 rcu_read_unlock();
4149ace8 3546 return error_occurred ? -1 : 0;
ab0ee2ca
JG
3547}
3548
28ab034a 3549static bool client_has_outbound_data_left(const struct notification_client *client)
9016dbfc 3550{
28ab034a
JG
3551 const struct lttng_payload_view pv =
3552 lttng_payload_view_from_payload(&client->communication.outbound.payload, 0, -1);
9016dbfc
JG
3553 const bool has_data = pv.buffer.size != 0;
3554 const bool has_fds = lttng_payload_view_get_fd_handle_count(&pv);
3555
3556 return has_data || has_fds;
3557}
3558
28ab034a
JG
3559static int client_handle_transmission_status(struct notification_client *client,
3560 enum client_transmission_status transmission_status,
3561 struct notification_thread_state *state)
dd877ea6
JG
3562{
3563 int ret = 0;
3564
3565 switch (transmission_status) {
3566 case CLIENT_TRANSMISSION_STATUS_COMPLETE:
dd877ea6 3567 case CLIENT_TRANSMISSION_STATUS_QUEUED:
9016dbfc
JG
3568 {
3569 int current_poll_events;
3570 int new_poll_events;
dd877ea6
JG
3571 /*
3572 * We want to be notified whenever there is buffer space
9016dbfc
JG
3573 * available to send the rest of the payload if we are
3574 * waiting to send data to the client.
3575 *
3576 * The state of the outbound queue being sampled here is
3577 * fine since:
3578 * - it is okay to wake-up "for nothing" in case we see
3579 * that data is left, but another thread succeeds in
3580 * flushing it before us when handling the client "out"
3581 * event. We will simply stop monitoring that event the next
3582 * time it wakes us up and we see no data left to be sent,
3583 * - if another thread fails to flush the entire client
3584 * outgoing queue, it will issue a "communication update"
3585 * command and cause the client's (e)poll mask to be
3586 * re-evaluated.
3587 *
3588 * The situation we seek to avoid would be to disable the
3589 * monitoring of "out" client events indefinitely when there is
3590 * data to be sent, which can't happen because of the
3591 * aforementioned "communication update" mechanism.
dd877ea6 3592 */
9016dbfc
JG
3593 pthread_mutex_lock(&client->lock);
3594 current_poll_events = client->communication.current_poll_events;
3595 new_poll_events = client_has_outbound_data_left(client) ?
28ab034a
JG
3596 CLIENT_POLL_EVENTS_IN_OUT :
3597 CLIENT_POLL_EVENTS_IN;
9016dbfc
JG
3598 client->communication.current_poll_events = new_poll_events;
3599 pthread_mutex_unlock(&client->lock);
3600
3601 /* Update the monitored event set only if it changed. */
3602 if (current_poll_events != new_poll_events) {
28ab034a 3603 ret = lttng_poll_mod(&state->events, client->socket, new_poll_events);
9016dbfc
JG
3604 if (ret) {
3605 goto end;
3606 }
dd877ea6 3607 }
9016dbfc 3608
dd877ea6 3609 break;
9016dbfc 3610 }
dd877ea6
JG
3611 case CLIENT_TRANSMISSION_STATUS_FAIL:
3612 ret = notification_thread_client_disconnect(client, state);
3613 if (ret) {
3614 goto end;
3615 }
3616 break;
3617 case CLIENT_TRANSMISSION_STATUS_ERROR:
3618 ret = -1;
3619 goto end;
3620 default:
3621 abort();
3622 }
3623end:
3624 return ret;
3625}
3626
505b2d90 3627/* Client lock must be acquired by caller. */
28ab034a
JG
3628static enum client_transmission_status
3629client_flush_outgoing_queue(struct notification_client *client)
ab0ee2ca
JG
3630{
3631 ssize_t ret;
3632 size_t to_send_count;
dd877ea6 3633 enum client_transmission_status status;
28ab034a
JG
3634 struct lttng_payload_view pv =
3635 lttng_payload_view_from_payload(&client->communication.outbound.payload, 0, -1);
3636 const int fds_to_send_count = lttng_payload_view_get_fd_handle_count(&pv);
ab0ee2ca 3637
505b2d90
JG
3638 ASSERT_LOCKED(client->lock);
3639
f2b3ef9f
JG
3640 if (!client->communication.active) {
3641 status = CLIENT_TRANSMISSION_STATUS_FAIL;
3642 goto end;
3643 }
3644
882093ee
JR
3645 if (pv.buffer.size == 0) {
3646 /*
3647 * If both data and fds are equal to zero, we are in an invalid
3648 * state.
3649 */
a0377dfe 3650 LTTNG_ASSERT(fds_to_send_count != 0);
882093ee
JR
3651 goto send_fds;
3652 }
3653
3654 /* Send data. */
3655 to_send_count = pv.buffer.size;
28ab034a 3656 DBG("Flushing client (socket fd = %i) outgoing queue", client->socket);
ab0ee2ca 3657
28ab034a 3658 ret = lttcomm_send_unix_sock_non_block(client->socket, pv.buffer.data, to_send_count);
44c180ca 3659 if ((ret >= 0 && ret < to_send_count)) {
bd0514a5 3660 DBG("Client (socket fd = %i) outgoing queue could not be completely flushed",
28ab034a 3661 client->socket);
7966af57 3662 to_send_count -= std::max(ret, (ssize_t) 0);
ab0ee2ca 3663
6f110534 3664 memmove(client->communication.outbound.payload.buffer.data,
28ab034a
JG
3665 pv.buffer.data + pv.buffer.size - to_send_count,
3666 to_send_count);
3667 ret = lttng_dynamic_buffer_set_size(&client->communication.outbound.payload.buffer,
3668 to_send_count);
ab0ee2ca
JG
3669 if (ret) {
3670 goto error;
3671 }
6c24d3fd 3672
dd877ea6 3673 status = CLIENT_TRANSMISSION_STATUS_QUEUED;
882093ee 3674 goto end;
ab0ee2ca 3675 } else if (ret < 0) {
6c24d3fd 3676 /* Generic error, disable the client's communication. */
bd0514a5 3677 ERR("Failed to flush outgoing queue, disconnecting client (socket fd = %i)",
28ab034a 3678 client->socket);
6c24d3fd 3679 client->communication.active = false;
dd877ea6 3680 status = CLIENT_TRANSMISSION_STATUS_FAIL;
882093ee 3681 goto end;
ab0ee2ca 3682 } else {
882093ee
JR
3683 /*
3684 * No error and flushed the queue completely.
3685 *
3686 * The payload buffer size is used later to
3687 * check if there is notifications queued. So albeit that the
3688 * direct caller knows that the transmission is complete, we
3689 * need to set the buffer size to zero.
3690 */
28ab034a
JG
3691 ret = lttng_dynamic_buffer_set_size(&client->communication.outbound.payload.buffer,
3692 0);
ab0ee2ca
JG
3693 if (ret) {
3694 goto error;
3695 }
882093ee 3696 }
6c24d3fd 3697
882093ee
JR
3698send_fds:
3699 /* No fds to send, transmission is complete. */
3700 if (fds_to_send_count == 0) {
dd877ea6 3701 status = CLIENT_TRANSMISSION_STATUS_COMPLETE;
882093ee 3702 goto end;
dd877ea6 3703 }
882093ee 3704
28ab034a 3705 ret = lttcomm_send_payload_view_fds_unix_sock_non_block(client->socket, &pv);
882093ee
JR
3706 if (ret < 0) {
3707 /* Generic error, disable the client's communication. */
bd0514a5 3708 ERR("Failed to flush outgoing fds queue, disconnecting client (socket fd = %i)",
28ab034a 3709 client->socket);
882093ee
JR
3710 client->communication.active = false;
3711 status = CLIENT_TRANSMISSION_STATUS_FAIL;
3712 goto end;
3713 } else if (ret == 0) {
3714 /* Nothing could be sent. */
3715 status = CLIENT_TRANSMISSION_STATUS_QUEUED;
3716 } else {
3717 /* Fd passing is an all or nothing kind of thing. */
3718 status = CLIENT_TRANSMISSION_STATUS_COMPLETE;
3719 /*
3720 * The payload _fd_array count is used later to
3721 * check if there is notifications queued. So although the
3722 * direct caller knows that the transmission is complete, we
3723 * need to clear the _fd_array for the queuing check.
3724 */
3725 lttng_dynamic_pointer_array_clear(
28ab034a 3726 &client->communication.outbound.payload._fd_handles);
882093ee
JR
3727 }
3728
f2b3ef9f 3729end:
882093ee
JR
3730 if (status == CLIENT_TRANSMISSION_STATUS_COMPLETE) {
3731 client->communication.outbound.queued_command_reply = false;
3732 client->communication.outbound.dropped_notification = false;
3733 lttng_payload_clear(&client->communication.outbound.payload);
3734 }
3735
f2b3ef9f 3736 return status;
ab0ee2ca 3737error:
f2b3ef9f 3738 return CLIENT_TRANSMISSION_STATUS_ERROR;
ab0ee2ca
JG
3739}
3740
6c24d3fd 3741/* Client lock must _not_ be held by the caller. */
28ab034a
JG
3742static int client_send_command_reply(struct notification_client *client,
3743 struct notification_thread_state *state,
3744 enum lttng_notification_channel_status status)
ab0ee2ca
JG
3745{
3746 int ret;
3747 struct lttng_notification_channel_command_reply reply = {
3748 .status = (int8_t) status,
3749 };
6bd79809 3750 struct lttng_notification_channel_message msg;
ab0ee2ca 3751 char buffer[sizeof(msg) + sizeof(reply)];
f2b3ef9f 3752 enum client_transmission_status transmission_status;
ab0ee2ca 3753
6bd79809
JG
3754 msg.type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY;
3755 msg.size = sizeof(reply);
3756 msg.fds = 0;
3757
6c24d3fd
JG
3758 memcpy(buffer, &msg, sizeof(msg));
3759 memcpy(buffer + sizeof(msg), &reply, sizeof(reply));
bd0514a5 3760 DBG("Send command reply (%i)", (int) status);
505b2d90 3761
6c24d3fd 3762 pthread_mutex_lock(&client->lock);
ab0ee2ca
JG
3763 if (client->communication.outbound.queued_command_reply) {
3764 /* Protocol error. */
6c24d3fd 3765 goto error_unlock;
ab0ee2ca
JG
3766 }
3767
ab0ee2ca
JG
3768 /* Enqueue buffer to outgoing queue and flush it. */
3769 ret = lttng_dynamic_buffer_append(
28ab034a 3770 &client->communication.outbound.payload.buffer, buffer, sizeof(buffer));
ab0ee2ca 3771 if (ret) {
6c24d3fd 3772 goto error_unlock;
ab0ee2ca
JG
3773 }
3774
f2b3ef9f 3775 transmission_status = client_flush_outgoing_queue(client);
882093ee
JR
3776
3777 if (client_has_outbound_data_left(client)) {
6c24d3fd
JG
3778 /* Queue could not be emptied. */
3779 client->communication.outbound.queued_command_reply = true;
3780 }
3781
3782 pthread_mutex_unlock(&client->lock);
28ab034a 3783 ret = client_handle_transmission_status(client, transmission_status, state);
ab0ee2ca
JG
3784 if (ret) {
3785 goto error;
3786 }
3787
ab0ee2ca 3788 return 0;
6c24d3fd
JG
3789error_unlock:
3790 pthread_mutex_unlock(&client->lock);
ab0ee2ca
JG
3791error:
3792 return -1;
3793}
3794
28ab034a
JG
3795static int client_handle_message_unknown(struct notification_client *client,
3796 struct notification_thread_state *state
3797 __attribute__((unused)))
505b2d90
JG
3798{
3799 int ret;
505b2d90
JG
3800 /*
3801 * Receiving message header. The function will be called again
3802 * once the rest of the message as been received and can be
3803 * interpreted.
3804 */
3805 const struct lttng_notification_channel_message *msg;
3806
a0377dfe 3807 LTTNG_ASSERT(sizeof(*msg) == client->communication.inbound.payload.buffer.size);
505b2d90 3808 msg = (const struct lttng_notification_channel_message *)
28ab034a 3809 client->communication.inbound.payload.buffer.data;
505b2d90 3810
28ab034a
JG
3811 if (msg->size == 0 || msg->size > DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE) {
3812 ERR("Invalid notification channel message: length = %u", msg->size);
505b2d90
JG
3813 ret = -1;
3814 goto end;
3815 }
3816
3817 switch (msg->type) {
3818 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE:
3819 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE:
3820 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE:
3821 break;
3822 default:
3823 ret = -1;
bd0514a5 3824 ERR("Invalid notification channel message: unexpected message type");
505b2d90
JG
3825 goto end;
3826 }
3827
3828 client->communication.inbound.bytes_to_receive = msg->size;
882093ee 3829 client->communication.inbound.fds_to_receive = msg->fds;
505b2d90 3830 client->communication.inbound.msg_type =
28ab034a
JG
3831 (enum lttng_notification_channel_message_type) msg->type;
3832 ret = lttng_dynamic_buffer_set_size(&client->communication.inbound.payload.buffer,
3833 msg->size);
882093ee
JR
3834
3835 /* msg is not valid anymore due to lttng_dynamic_buffer_set_size. */
cd9adb8b 3836 msg = nullptr;
505b2d90 3837end:
505b2d90
JG
3838 return ret;
3839}
3840
28ab034a
JG
3841static int client_handle_message_handshake(struct notification_client *client,
3842 struct notification_thread_state *state)
505b2d90
JG
3843{
3844 int ret;
3845 struct lttng_notification_channel_command_handshake *handshake_client;
3846 const struct lttng_notification_channel_command_handshake handshake_reply = {
28ab034a
JG
3847 .major = LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR,
3848 .minor = LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR,
505b2d90 3849 };
6bd79809 3850 struct lttng_notification_channel_message msg_header;
28ab034a 3851 enum lttng_notification_channel_status status = LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
505b2d90 3852 char send_buffer[sizeof(msg_header) + sizeof(handshake_reply)];
505b2d90 3853
6bd79809
JG
3854 msg_header.type = LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE;
3855 msg_header.size = sizeof(handshake_reply);
3856 msg_header.fds = 0;
3857
505b2d90 3858 memcpy(send_buffer, &msg_header, sizeof(msg_header));
28ab034a 3859 memcpy(send_buffer + sizeof(msg_header), &handshake_reply, sizeof(handshake_reply));
505b2d90 3860
28ab034a
JG
3861 handshake_client = (struct lttng_notification_channel_command_handshake *)
3862 client->communication.inbound.payload.buffer.data;
505b2d90
JG
3863 client->major = handshake_client->major;
3864 client->minor = handshake_client->minor;
3865 if (!client->communication.inbound.creds_received) {
bd0514a5 3866 ERR("No credentials received from client");
505b2d90
JG
3867 ret = -1;
3868 goto end;
3869 }
3870
28ab034a
JG
3871 client->uid = LTTNG_SOCK_GET_UID_CRED(&client->communication.inbound.creds);
3872 client->gid = LTTNG_SOCK_GET_GID_CRED(&client->communication.inbound.creds);
3873 client->is_sessiond = LTTNG_SOCK_GET_PID_CRED(&client->communication.inbound.creds) ==
3874 getpid();
f2bda80e 3875 DBG("Received handshake from client: uid = %u, gid = %u, protocol version = %i.%i, client is sessiond = %s",
28ab034a
JG
3876 client->uid,
3877 client->gid,
3878 (int) client->major,
3879 (int) client->minor,
3880 client->is_sessiond ? "true" : "false");
505b2d90 3881
28ab034a 3882 if (handshake_client->major != LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR) {
505b2d90
JG
3883 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_UNSUPPORTED_VERSION;
3884 }
3885
6c24d3fd
JG
3886 pthread_mutex_lock(&client->lock);
3887 /* Outgoing queue will be flushed when the command reply is sent. */
505b2d90 3888 ret = lttng_dynamic_buffer_append(
28ab034a 3889 &client->communication.outbound.payload.buffer, send_buffer, sizeof(send_buffer));
505b2d90 3890 if (ret) {
bd0514a5 3891 ERR("Failed to send protocol version to notification channel client");
6c24d3fd 3892 goto end_unlock;
505b2d90
JG
3893 }
3894
3895 client->validated = true;
3896 client->communication.active = true;
6c24d3fd 3897 pthread_mutex_unlock(&client->lock);
505b2d90 3898
6c24d3fd
JG
3899 /* Set reception state to receive the next message header. */
3900 ret = client_reset_inbound_state(client);
505b2d90 3901 if (ret) {
bd0514a5 3902 ERR("Failed to reset client communication's inbound state");
505b2d90
JG
3903 goto end;
3904 }
3905
6c24d3fd 3906 /* Flushes the outgoing queue. */
505b2d90
JG
3907 ret = client_send_command_reply(client, state, status);
3908 if (ret) {
bd0514a5 3909 ERR("Failed to send reply to notification channel client");
505b2d90
JG
3910 goto end;
3911 }
3912
6c24d3fd
JG
3913 goto end;
3914end_unlock:
505b2d90 3915 pthread_mutex_unlock(&client->lock);
6c24d3fd 3916end:
505b2d90
JG
3917 return ret;
3918}
3919
28ab034a
JG
3920static int client_handle_message_subscription(struct notification_client *client,
3921 enum lttng_notification_channel_message_type msg_type,
3922 struct notification_thread_state *state)
505b2d90
JG
3923{
3924 int ret;
3925 struct lttng_condition *condition;
28ab034a 3926 enum lttng_notification_channel_status status = LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
505b2d90 3927 struct lttng_payload_view condition_view =
28ab034a 3928 lttng_payload_view_from_payload(&client->communication.inbound.payload, 0, -1);
505b2d90
JG
3929 size_t expected_condition_size;
3930
6c24d3fd
JG
3931 /*
3932 * No need to lock client to sample the inbound state as the only
3933 * other thread accessing clients (action executor) only uses the
3934 * outbound state.
3935 */
882093ee 3936 expected_condition_size = client->communication.inbound.payload.buffer.size;
505b2d90
JG
3937 ret = lttng_condition_create_from_payload(&condition_view, &condition);
3938 if (ret != expected_condition_size) {
bd0514a5 3939 ERR("Malformed condition received from client");
505b2d90
JG
3940 goto end;
3941 }
3942
5a6306f7 3943 /* Ownership of condition is always transferred. */
505b2d90 3944 if (msg_type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE) {
28ab034a 3945 ret = notification_thread_client_subscribe(client, condition, state, &status);
505b2d90 3946 } else {
28ab034a 3947 ret = notification_thread_client_unsubscribe(client, condition, state, &status);
505b2d90 3948 }
505b2d90 3949
505b2d90 3950 if (ret) {
6c24d3fd 3951 goto end;
505b2d90
JG
3952 }
3953
3954 /* Set reception state to receive the next message header. */
3955 ret = client_reset_inbound_state(client);
3956 if (ret) {
bd0514a5 3957 ERR("Failed to reset client communication's inbound state");
6c24d3fd
JG
3958 goto end;
3959 }
3960
3961 ret = client_send_command_reply(client, state, status);
3962 if (ret) {
bd0514a5 3963 ERR("Failed to send reply to notification channel client");
6c24d3fd 3964 goto end;
505b2d90
JG
3965 }
3966
505b2d90
JG
3967end:
3968 return ret;
3969}
3970
28ab034a
JG
3971static int client_dispatch_message(struct notification_client *client,
3972 struct notification_thread_state *state)
ab0ee2ca
JG
3973{
3974 int ret = 0;
3975
3976 if (client->communication.inbound.msg_type !=
28ab034a
JG
3977 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE &&
3978 client->communication.inbound.msg_type !=
3979 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN &&
3980 !client->validated) {
bd0514a5 3981 WARN("client attempted a command before handshake");
ab0ee2ca
JG
3982 ret = -1;
3983 goto end;
3984 }
3985
3986 switch (client->communication.inbound.msg_type) {
3987 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN:
3988 {
505b2d90 3989 ret = client_handle_message_unknown(client, state);
ab0ee2ca
JG
3990 break;
3991 }
3992 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE:
3993 {
505b2d90 3994 ret = client_handle_message_handshake(client, state);
ab0ee2ca
JG
3995 break;
3996 }
3997 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE:
3998 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE:
3999 {
28ab034a
JG
4000 ret = client_handle_message_subscription(
4001 client, client->communication.inbound.msg_type, state);
ab0ee2ca
JG
4002 break;
4003 }
4004 default:
4005 abort();
4006 }
4007end:
4008 return ret;
4009}
4010
4011/* Incoming data from client. */
28ab034a 4012int handle_notification_thread_client_in(struct notification_thread_state *state, int socket)
ab0ee2ca 4013{
14fa22f8 4014 int ret = 0;
ab0ee2ca
JG
4015 struct notification_client *client;
4016 ssize_t recv_ret;
4017 size_t offset;
4018
98b5ff34 4019 rcu_read_lock();
ab0ee2ca
JG
4020 client = get_client_from_socket(socket, state);
4021 if (!client) {
4022 /* Internal error, abort. */
4023 ret = -1;
4024 goto end;
4025 }
4026
982583bd 4027 if (client->communication.inbound.bytes_to_receive == 0 &&
28ab034a 4028 client->communication.inbound.fds_to_receive != 0) {
982583bd
JR
4029 /* Only FDs left to receive. */
4030 goto receive_fds;
4031 }
4032
882093ee 4033 offset = client->communication.inbound.payload.buffer.size -
28ab034a 4034 client->communication.inbound.bytes_to_receive;
01ea340e 4035 if (client->communication.inbound.expect_creds) {
28ab034a
JG
4036 recv_ret = lttcomm_recv_creds_unix_sock(
4037 socket,
4038 client->communication.inbound.payload.buffer.data + offset,
4039 client->communication.inbound.bytes_to_receive,
4040 &client->communication.inbound.creds);
ab0ee2ca 4041 if (recv_ret > 0) {
01ea340e 4042 client->communication.inbound.expect_creds = false;
ab0ee2ca
JG
4043 client->communication.inbound.creds_received = true;
4044 }
4045 } else {
28ab034a
JG
4046 recv_ret = lttcomm_recv_unix_sock_non_block(
4047 socket,
4048 client->communication.inbound.payload.buffer.data + offset,
4049 client->communication.inbound.bytes_to_receive);
ab0ee2ca 4050 }
505b2d90
JG
4051 if (recv_ret >= 0) {
4052 client->communication.inbound.bytes_to_receive -= recv_ret;
882093ee
JR
4053 } else {
4054 goto error_disconnect_client;
505b2d90 4055 }
6c24d3fd 4056
882093ee
JR
4057 if (client->communication.inbound.bytes_to_receive != 0) {
4058 /* Message incomplete wait for more data. */
4059 ret = 0;
4060 goto end;
ab0ee2ca
JG
4061 }
4062
982583bd 4063receive_fds:
a0377dfe 4064 LTTNG_ASSERT(client->communication.inbound.bytes_to_receive == 0);
882093ee
JR
4065
4066 /* Receive fds. */
4067 if (client->communication.inbound.fds_to_receive != 0) {
4068 ret = lttcomm_recv_payload_fds_unix_sock_non_block(
28ab034a
JG
4069 client->socket,
4070 client->communication.inbound.fds_to_receive,
4071 &client->communication.inbound.payload);
882093ee 4072 if (ret > 0) {
ab0ee2ca 4073 /*
882093ee
JR
4074 * Fds received. non blocking fds passing is all
4075 * or nothing.
ab0ee2ca 4076 */
882093ee
JR
4077 ssize_t expected_size;
4078
28ab034a 4079 expected_size = sizeof(int) * client->communication.inbound.fds_to_receive;
a0377dfe 4080 LTTNG_ASSERT(ret == expected_size);
882093ee
JR
4081 client->communication.inbound.fds_to_receive = 0;
4082 } else if (ret == 0) {
4083 /* Received nothing. */
4084 ret = 0;
4085 goto end;
4086 } else {
ab0ee2ca
JG
4087 goto error_disconnect_client;
4088 }
ab0ee2ca 4089 }
882093ee
JR
4090
4091 /* At this point the message is complete.*/
a0377dfe 4092 LTTNG_ASSERT(client->communication.inbound.bytes_to_receive == 0 &&
28ab034a 4093 client->communication.inbound.fds_to_receive == 0);
882093ee
JR
4094 ret = client_dispatch_message(client, state);
4095 if (ret) {
4096 /*
4097 * Only returns an error if this client must be
4098 * disconnected.
4099 */
4100 goto error_disconnect_client;
4101 }
4102
ab0ee2ca 4103end:
98b5ff34 4104 rcu_read_unlock();
ab0ee2ca 4105 return ret;
882093ee 4106
ab0ee2ca 4107error_disconnect_client:
505b2d90 4108 ret = notification_thread_client_disconnect(client, state);
98b5ff34 4109 goto end;
ab0ee2ca
JG
4110}
4111
4112/* Client ready to receive outgoing data. */
28ab034a 4113int handle_notification_thread_client_out(struct notification_thread_state *state, int socket)
ab0ee2ca
JG
4114{
4115 int ret;
4116 struct notification_client *client;
f2b3ef9f 4117 enum client_transmission_status transmission_status;
ab0ee2ca 4118
98b5ff34 4119 rcu_read_lock();
ab0ee2ca
JG
4120 client = get_client_from_socket(socket, state);
4121 if (!client) {
4122 /* Internal error, abort. */
4123 ret = -1;
4124 goto end;
4125 }
4126
505b2d90 4127 pthread_mutex_lock(&client->lock);
9016dbfc
JG
4128 if (!client_has_outbound_data_left(client)) {
4129 /*
4130 * A client "out" event can be received when no payload is left
4131 * to send under some circumstances.
4132 *
4133 * Many threads can flush a client's outgoing queue and, if they
4134 * had to queue their message (socket was full), will use the
4135 * "communication update" command to signal the (e)poll thread
4136 * to monitor for space being made available in the socket.
4137 *
4138 * Commands are sent over an internal pipe serviced by the same
4139 * thread as the client sockets.
4140 *
4141 * When space is made available in the socket, there is a race
4142 * between the (e)poll thread and the other threads that may
4143 * wish to use the client's socket to flush its outgoing queue.
4144 *
4145 * A non-(e)poll thread may attempt (and succeed) in flushing
4146 * the queue before the (e)poll thread gets a chance to service
4147 * the client's "out" event.
4148 *
4149 * In this situation, the (e)poll thread processing the client
4150 * out event will see an empty payload: there is nothing to do
4151 * except unsubscribing (e)poll "out" events.
4152 *
4153 * Note that this thread is the (e)poll thread so it can modify
4154 * the (e)poll mask directly without using a communication
4155 * update command. Other threads that flush the outgoing queue
4156 * will use the "communication update" command to wake up this
4157 * thread and force it to monitor "out" events.
4158 *
4159 * When other threads succeed in emptying the outgoing queue,
4160 * they don't need to update the (e)poll mask: if the "out"
4161 * event is monitored, it will fire once and the (e)poll
4162 * thread will reach this condition, causing the event to
4163 * stop being monitored.
4164 */
4165 transmission_status = CLIENT_TRANSMISSION_STATUS_COMPLETE;
4166 } else {
4167 transmission_status = client_flush_outgoing_queue(client);
4168 }
6c24d3fd
JG
4169 pthread_mutex_unlock(&client->lock);
4170
28ab034a 4171 ret = client_handle_transmission_status(client, transmission_status, state);
ab0ee2ca
JG
4172 if (ret) {
4173 goto end;
4174 }
4175end:
98b5ff34 4176 rcu_read_unlock();
ab0ee2ca
JG
4177 return ret;
4178}
4179
28ab034a
JG
4180static bool evaluate_buffer_usage_condition(const struct lttng_condition *condition,
4181 const struct channel_state_sample *sample,
4182 uint64_t buffer_capacity)
ab0ee2ca
JG
4183{
4184 bool result = false;
4185 uint64_t threshold;
4186 enum lttng_condition_type condition_type;
28ab034a
JG
4187 const struct lttng_condition_buffer_usage *use_condition =
4188 lttng::utils::container_of(condition, &lttng_condition_buffer_usage::parent);
ab0ee2ca 4189
ab0ee2ca
JG
4190 if (use_condition->threshold_bytes.set) {
4191 threshold = use_condition->threshold_bytes.value;
4192 } else {
4193 /*
4194 * Threshold was expressed as a ratio.
4195 *
4196 * TODO the threshold (in bytes) of conditions expressed
4197 * as a ratio of total buffer size could be cached to
4198 * forego this double-multiplication or it could be performed
4199 * as fixed-point math.
4200 *
d49487dc 4201 * Note that caching should accommodates the case where the
ab0ee2ca
JG
4202 * condition applies to multiple channels (i.e. don't assume
4203 * that all channels matching my_chann* have the same size...)
4204 */
4205 threshold = (uint64_t) (use_condition->threshold_ratio.value *
28ab034a 4206 (double) buffer_capacity);
ab0ee2ca
JG
4207 }
4208
4209 condition_type = lttng_condition_get_type(condition);
4210 if (condition_type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW) {
28ab034a
JG
4211 DBG("Low buffer usage condition being evaluated: threshold = %" PRIu64
4212 ", highest usage = %" PRIu64,
4213 threshold,
4214 sample->highest_usage);
ab0ee2ca
JG
4215
4216 /*
4217 * The low condition should only be triggered once _all_ of the
4218 * streams in a channel have gone below the "low" threshold.
4219 */
4220 if (sample->highest_usage <= threshold) {
4221 result = true;
4222 }
4223 } else {
28ab034a
JG
4224 DBG("High buffer usage condition being evaluated: threshold = %" PRIu64
4225 ", highest usage = %" PRIu64,
4226 threshold,
4227 sample->highest_usage);
ab0ee2ca
JG
4228
4229 /*
4230 * For high buffer usage scenarios, we want to trigger whenever
4231 * _any_ of the streams has reached the "high" threshold.
4232 */
4233 if (sample->highest_usage >= threshold) {
4234 result = true;
4235 }
4236 }
e8360425 4237
ab0ee2ca
JG
4238 return result;
4239}
4240
28ab034a
JG
4241static int evaluate_buffer_condition(const struct lttng_condition *condition,
4242 struct lttng_evaluation **evaluation,
4243 const struct notification_thread_state *state
4244 __attribute__((unused)),
4245 const struct channel_state_sample *previous_sample,
4246 const struct channel_state_sample *latest_sample,
4247 struct channel_info *channel_info)
ab0ee2ca
JG
4248{
4249 int ret = 0;
4250 enum lttng_condition_type condition_type;
e8360425
JD
4251 const bool previous_sample_available = !!previous_sample;
4252 bool previous_sample_result = false;
ab0ee2ca
JG
4253 bool latest_sample_result;
4254
4255 condition_type = lttng_condition_get_type(condition);
ab0ee2ca 4256
e8360425
JD
4257 switch (condition_type) {
4258 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
4259 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
4260 if (caa_likely(previous_sample_available)) {
28ab034a
JG
4261 previous_sample_result = evaluate_buffer_usage_condition(
4262 condition, previous_sample, channel_info->capacity);
e8360425
JD
4263 }
4264 latest_sample_result = evaluate_buffer_usage_condition(
28ab034a 4265 condition, latest_sample, channel_info->capacity);
e8360425 4266 break;
e8360425
JD
4267 default:
4268 /* Unknown condition type; internal error. */
4269 abort();
4270 }
ab0ee2ca 4271
28ab034a 4272 if (!latest_sample_result || (previous_sample_result == latest_sample_result)) {
ab0ee2ca
JG
4273 /*
4274 * Only trigger on a condition evaluation transition.
4275 *
4276 * NOTE: This edge-triggered logic may not be appropriate for
4277 * future condition types.
4278 */
4279 goto end;
4280 }
4281
e8360425
JD
4282 if (!evaluation || !latest_sample_result) {
4283 goto end;
4284 }
4285
4286 switch (condition_type) {
4287 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
4288 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
ab0ee2ca 4289 *evaluation = lttng_evaluation_buffer_usage_create(
28ab034a 4290 condition_type, latest_sample->highest_usage, channel_info->capacity);
e8360425 4291 break;
e8360425
JD
4292 default:
4293 abort();
4294 }
4295
4296 if (!*evaluation) {
4297 ret = -1;
4298 goto end;
ab0ee2ca
JG
4299 }
4300end:
4301 return ret;
4302}
4303
28ab034a 4304static int client_notification_overflow(struct notification_client *client)
ab0ee2ca 4305{
f2b3ef9f 4306 int ret = 0;
6bd79809
JG
4307 struct lttng_notification_channel_message msg;
4308
4309 msg.type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED;
4310 msg.size = 0;
4311 msg.fds = 0;
ab0ee2ca 4312
505b2d90
JG
4313 ASSERT_LOCKED(client->lock);
4314
28ab034a 4315 DBG("Dropping notification addressed to client (socket fd = %i)", client->socket);
f2b3ef9f
JG
4316 if (client->communication.outbound.dropped_notification) {
4317 /*
4318 * The client already has a "notification dropped" message
4319 * in its outgoing queue. Nothing to do since all
4320 * of those messages are coalesced.
4321 */
4322 goto end;
4323 }
4324
4325 client->communication.outbound.dropped_notification = true;
ab0ee2ca 4326 ret = lttng_dynamic_buffer_append(
28ab034a 4327 &client->communication.outbound.payload.buffer, &msg, sizeof(msg));
f2b3ef9f
JG
4328 if (ret) {
4329 PERROR("Failed to enqueue \"dropped notification\" message in client's (socket fd = %i) outgoing queue",
28ab034a 4330 client->socket);
f2b3ef9f
JG
4331 }
4332end:
ab0ee2ca
JG
4333 return ret;
4334}
4335
28ab034a
JG
4336static int client_handle_transmission_status_wrapper(struct notification_client *client,
4337 enum client_transmission_status status,
4338 void *user_data)
f2b3ef9f 4339{
28ab034a
JG
4340 return client_handle_transmission_status(
4341 client, status, (struct notification_thread_state *) user_data);
f2b3ef9f
JG
4342}
4343
28ab034a
JG
4344static int send_evaluation_to_clients(const struct lttng_trigger *trigger,
4345 const struct lttng_evaluation *evaluation,
4346 struct notification_client_list *client_list,
4347 struct notification_thread_state *state,
4348 uid_t object_uid,
4349 gid_t object_gid)
f2b3ef9f 4350{
ff588497
JR
4351 const struct lttng_credentials creds = {
4352 .uid = LTTNG_OPTIONAL_INIT_VALUE(object_uid),
4353 .gid = LTTNG_OPTIONAL_INIT_VALUE(object_gid),
4354 };
4355
f2b3ef9f 4356 return notification_client_list_send_evaluation(client_list,
28ab034a
JG
4357 trigger,
4358 evaluation,
4359 &creds,
4360 client_handle_transmission_status_wrapper,
4361 state);
f2b3ef9f
JG
4362}
4363
f37d0f86
JG
4364/*
4365 * Permission checks relative to notification channel clients are performed
4366 * here. Notice how object, client, and trigger credentials are involved in
4367 * this check.
4368 *
4369 * The `object` credentials are the credentials associated with the "subject"
4370 * of a condition. For instance, a `rotation completed` condition applies
4371 * to a session. When that condition is met, it will produce an evaluation
4372 * against a session. Hence, in this case, the `object` credentials are the
4373 * credentials of the "subject" session.
4374 *
4375 * The `trigger` credentials are the credentials of the user that registered the
4376 * trigger.
4377 *
4378 * The `client` credentials are the credentials of the user that created a given
4379 * notification channel.
4380 *
4381 * In terms of visibility, it is expected that non-privilieged users can only
4382 * register triggers against "their" objects (their own sessions and
4383 * applications they are allowed to interact with). They can then open a
4384 * notification channel and subscribe to notifications associated with those
4385 * triggers.
4386 *
4387 * As for privilieged users, they can register triggers against the objects of
4388 * other users. They can then subscribe to the notifications associated to their
4389 * triggers. Privilieged users _can't_ subscribe to the notifications of
4390 * triggers owned by other users; they must create their own triggers.
4391 *
4392 * This is more a concern of usability than security. It would be difficult for
4393 * a root user reliably subscribe to a specific set of conditions without
4394 * interference from external users (those could, for instance, unregister
4395 * their triggers).
4396 */
28ab034a
JG
4397int notification_client_list_send_evaluation(struct notification_client_list *client_list,
4398 const struct lttng_trigger *trigger,
4399 const struct lttng_evaluation *evaluation,
4400 const struct lttng_credentials *source_object_creds,
4401 report_client_transmission_result_cb client_report,
4402 void *user_data)
ab0ee2ca
JG
4403{
4404 int ret = 0;
c0a66c84 4405 struct lttng_payload msg_payload;
ab0ee2ca 4406 struct notification_client_list_element *client_list_element, *tmp;
9b63a4aa 4407 const struct lttng_notification notification = {
52d55cf9 4408 .trigger = (struct lttng_trigger *) trigger,
9b63a4aa
JG
4409 .evaluation = (struct lttng_evaluation *) evaluation,
4410 };
6bd79809 4411 struct lttng_notification_channel_message msg_header;
28ab034a 4412 const struct lttng_credentials *trigger_creds = lttng_trigger_get_credentials(trigger);
ab0ee2ca 4413
c0a66c84 4414 lttng_payload_init(&msg_payload);
ab0ee2ca 4415
6bd79809
JG
4416 msg_header.type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION;
4417 msg_header.size = 0;
4418 msg_header.fds = 0;
4419
28ab034a 4420 ret = lttng_dynamic_buffer_append(&msg_payload.buffer, &msg_header, sizeof(msg_header));
ab0ee2ca
JG
4421 if (ret) {
4422 goto end;
4423 }
4424
c0a66c84 4425 ret = lttng_notification_serialize(&notification, &msg_payload);
ab0ee2ca 4426 if (ret) {
bd0514a5 4427 ERR("Failed to serialize notification");
ab0ee2ca
JG
4428 ret = -1;
4429 goto end;
4430 }
4431
3647288f 4432 /* Update payload size. */
28ab034a
JG
4433 ((struct lttng_notification_channel_message *) msg_payload.buffer.data)->size =
4434 (uint32_t) (msg_payload.buffer.size - sizeof(msg_header));
3647288f 4435
882093ee
JR
4436 /* Update the payload number of fds. */
4437 {
28ab034a
JG
4438 const struct lttng_payload_view pv =
4439 lttng_payload_view_from_payload(&msg_payload, 0, -1);
882093ee 4440
28ab034a
JG
4441 ((struct lttng_notification_channel_message *) msg_payload.buffer.data)->fds =
4442 (uint32_t) lttng_payload_view_get_fd_handle_count(&pv);
882093ee
JR
4443 }
4444
505b2d90 4445 pthread_mutex_lock(&client_list->lock);
28ab034a 4446 cds_list_for_each_entry_safe (client_list_element, tmp, &client_list->clients_list, node) {
f2b3ef9f 4447 enum client_transmission_status transmission_status;
28ab034a 4448 struct notification_client *client = client_list_element->client;
ab0ee2ca 4449
505b2d90
JG
4450 ret = 0;
4451 pthread_mutex_lock(&client->lock);
6c24d3fd
JG
4452 if (!client->communication.active) {
4453 /*
4454 * Skip inactive client (protocol error or
4455 * disconnecting).
4456 */
4457 DBG("Skipping client at it is marked as inactive");
4458 goto skip_client;
4459 }
4460
f2bda80e
JG
4461 if (lttng_trigger_is_hidden(trigger) && !client->is_sessiond) {
4462 /*
4463 * Notifications resulting from an hidden trigger are
4464 * only sent to the session daemon.
4465 */
70eb2f6f
JG
4466 DBG("Skipping client as the trigger is hidden and the client is not the session daemon");
4467 goto skip_client;
f2bda80e
JG
4468 }
4469
f2b3ef9f 4470 if (source_object_creds) {
ff588497 4471 if (client->uid != lttng_credentials_get_uid(source_object_creds) &&
28ab034a
JG
4472 client->gid != lttng_credentials_get_gid(source_object_creds) &&
4473 client->uid != 0) {
f2b3ef9f
JG
4474 /*
4475 * Client is not allowed to monitor this
4476 * object.
4477 */
bd0514a5 4478 DBG("Skipping client at it does not have the object permission to receive notification for this trigger");
6c24d3fd 4479 goto skip_client;
f2b3ef9f 4480 }
90843f49
JR
4481 }
4482
f712e5f6 4483 if (client->uid != lttng_credentials_get_uid(trigger_creds)) {
bd0514a5 4484 DBG("Skipping client at it does not have the permission to receive notification for this trigger");
6c24d3fd 4485 goto skip_client;
ab0ee2ca
JG
4486 }
4487
bd0514a5 4488 DBG("Sending notification to client (fd = %i, %zu bytes)",
28ab034a
JG
4489 client->socket,
4490 msg_payload.buffer.size);
882093ee
JR
4491
4492 if (client_has_outbound_data_left(client)) {
ab0ee2ca
JG
4493 /*
4494 * Outgoing data is already buffered for this client;
4495 * drop the notification and enqueue a "dropped
4496 * notification" message if this is the first dropped
4497 * notification since the socket spilled-over to the
4498 * queue.
4499 */
f2b3ef9f
JG
4500 ret = client_notification_overflow(client);
4501 if (ret) {
6c24d3fd
JG
4502 /* Fatal error. */
4503 goto skip_client;
ab0ee2ca 4504 }
ab0ee2ca
JG
4505 }
4506
882093ee 4507 ret = lttng_payload_copy(&msg_payload, &client->communication.outbound.payload);
ab0ee2ca 4508 if (ret) {
6c24d3fd
JG
4509 /* Fatal error. */
4510 goto skip_client;
ab0ee2ca
JG
4511 }
4512
f2b3ef9f 4513 transmission_status = client_flush_outgoing_queue(client);
6c24d3fd 4514 pthread_mutex_unlock(&client->lock);
f2b3ef9f 4515 ret = client_report(client, transmission_status, user_data);
ab0ee2ca 4516 if (ret) {
6c24d3fd
JG
4517 /* Fatal error. */
4518 goto end_unlock_list;
505b2d90 4519 }
6c24d3fd
JG
4520
4521 continue;
4522
28ab034a 4523 skip_client:
505b2d90
JG
4524 pthread_mutex_unlock(&client->lock);
4525 if (ret) {
6c24d3fd 4526 /* Fatal error. */
505b2d90 4527 goto end_unlock_list;
ab0ee2ca
JG
4528 }
4529 }
4530 ret = 0;
505b2d90
JG
4531
4532end_unlock_list:
4533 pthread_mutex_unlock(&client_list->lock);
ab0ee2ca 4534end:
c0a66c84 4535 lttng_payload_reset(&msg_payload);
ab0ee2ca
JG
4536 return ret;
4537}
4538
28ab034a
JG
4539static struct lttng_event_notifier_notification *
4540recv_one_event_notifier_notification(int notification_pipe_read_fd, enum lttng_domain_type domain)
94078603
JR
4541{
4542 int ret;
b9a8d78f 4543 uint64_t token;
cd9adb8b
JG
4544 struct lttng_event_notifier_notification *notification = nullptr;
4545 char *capture_buffer = nullptr;
82b3cbf4 4546 size_t capture_buffer_size;
94078603
JR
4547 void *reception_buffer;
4548 size_t reception_size;
4549
fc4b93fa 4550 struct lttng_ust_abi_event_notifier_notification ust_notification;
b8e2fb80 4551 struct lttng_kernel_abi_event_notifier_notification kernel_notification;
94078603 4552
b9a8d78f 4553 /* Init lttng_event_notifier_notification */
28ab034a 4554 switch (domain) {
94078603
JR
4555 case LTTNG_DOMAIN_UST:
4556 reception_buffer = (void *) &ust_notification;
4557 reception_size = sizeof(ust_notification);
94078603
JR
4558 break;
4559 case LTTNG_DOMAIN_KERNEL:
4560 reception_buffer = (void *) &kernel_notification;
4561 reception_size = sizeof(kernel_notification);
94078603
JR
4562 break;
4563 default:
4564 abort();
4565 }
4566
4567 /*
4568 * The monitoring pipe only holds messages smaller than PIPE_BUF,
4569 * ensuring that read/write of tracer notifications are atomic.
4570 */
28ab034a 4571 ret = lttng_read(notification_pipe_read_fd, reception_buffer, reception_size);
94078603
JR
4572 if (ret != reception_size) {
4573 PERROR("Failed to read from event source notification pipe: fd = %d, size to read = %zu, ret = %d",
28ab034a
JG
4574 notification_pipe_read_fd,
4575 reception_size,
4576 ret);
94078603
JR
4577 ret = -1;
4578 goto end;
4579 }
4580
28ab034a 4581 switch (domain) {
94078603 4582 case LTTNG_DOMAIN_UST:
b9a8d78f 4583 token = ust_notification.token;
82b3cbf4 4584 capture_buffer_size = ust_notification.capture_buf_size;
94078603
JR
4585 break;
4586 case LTTNG_DOMAIN_KERNEL:
b9a8d78f 4587 token = kernel_notification.token;
bbd6675c 4588 capture_buffer_size = kernel_notification.capture_buf_size;
94078603
JR
4589 break;
4590 default:
4591 abort();
4592 }
4593
82b3cbf4 4594 if (capture_buffer_size == 0) {
cd9adb8b 4595 capture_buffer = nullptr;
82b3cbf4
JR
4596 goto skip_capture;
4597 }
4598
4599 if (capture_buffer_size > MAX_CAPTURE_SIZE) {
bd0514a5 4600 ERR("Event notifier has a capture payload size which exceeds the maximum allowed size: capture_payload_size = %zu bytes, max allowed size = %d bytes",
28ab034a
JG
4601 capture_buffer_size,
4602 MAX_CAPTURE_SIZE);
82b3cbf4
JR
4603 goto end;
4604 }
4605
64803277 4606 capture_buffer = calloc<char>(capture_buffer_size);
82b3cbf4 4607 if (!capture_buffer) {
bd0514a5 4608 ERR("Failed to allocate capture buffer");
82b3cbf4
JR
4609 goto end;
4610 }
4611
4612 /* Fetch additional payload (capture). */
4613 ret = lttng_read(notification_pipe_read_fd, capture_buffer, capture_buffer_size);
4614 if (ret != capture_buffer_size) {
28ab034a 4615 ERR("Failed to read from event source pipe (fd = %i)", notification_pipe_read_fd);
82b3cbf4
JR
4616 goto end;
4617 }
4618
4619skip_capture:
28ab034a
JG
4620 notification = lttng_event_notifier_notification_create(
4621 token, domain, capture_buffer, capture_buffer_size);
cd9adb8b 4622 if (notification == nullptr) {
82b3cbf4
JR
4623 goto end;
4624 }
4625
4626 /*
4627 * Ownership transfered to the lttng_event_notifier_notification object.
4628 */
cd9adb8b 4629 capture_buffer = nullptr;
82b3cbf4 4630
b9a8d78f 4631end:
82b3cbf4 4632 free(capture_buffer);
b9a8d78f
FD
4633 return notification;
4634}
4635
28ab034a
JG
4636static int
4637dispatch_one_event_notifier_notification(struct notification_thread_state *state,
4638 struct lttng_event_notifier_notification *notification)
b9a8d78f 4639{
b9a8d78f
FD
4640 struct cds_lfht_node *node;
4641 struct cds_lfht_iter iter;
4642 struct notification_trigger_tokens_ht_element *element;
cd9adb8b 4643 struct lttng_evaluation *evaluation = nullptr;
b9a8d78f 4644 enum action_executor_status executor_status;
cd9adb8b 4645 struct notification_client_list *client_list = nullptr;
8b524060 4646 int ret;
7c920b63 4647 unsigned int capture_count = 0;
b9a8d78f 4648
94078603
JR
4649 /* Find triggers associated with this token. */
4650 rcu_read_lock();
4651 cds_lfht_lookup(state->trigger_tokens_ht,
b9a8d78f 4652 hash_key_u64(&notification->tracer_token, lttng_ht_seed),
28ab034a
JG
4653 match_trigger_token,
4654 &notification->tracer_token,
4655 &iter);
94078603 4656 node = cds_lfht_iter_get_node(&iter);
f1446131 4657 if (caa_unlikely(!node)) {
94078603 4658 /*
f1446131
JR
4659 * This is not an error, slow consumption of the tracer
4660 * notifications can lead to situations where a trigger is
4661 * removed but we still get tracer notifications matching a
4662 * trigger that no longer exists.
94078603
JR
4663 */
4664 ret = 0;
4665 goto end_unlock;
4666 }
4667
28ab034a 4668 element = caa_container_of(node, struct notification_trigger_tokens_ht_element, node);
94078603 4669
8dbb86b8 4670 if (lttng_condition_event_rule_matches_get_capture_descriptor_count(
28ab034a
JG
4671 lttng_trigger_get_const_condition(element->trigger), &capture_count) !=
4672 LTTNG_CONDITION_STATUS_OK) {
7c920b63
PP
4673 ERR("Failed to get capture count");
4674 ret = -1;
4675 goto end;
4676 }
4677
4678 if (!notification->capture_buffer && capture_count != 0) {
4679 ERR("Expected capture but capture buffer is null");
4680 ret = -1;
4681 goto end;
4682 }
4683
8dbb86b8 4684 evaluation = lttng_evaluation_event_rule_matches_create(
28ab034a
JG
4685 lttng::utils::container_of(lttng_trigger_get_const_condition(element->trigger),
4686 &lttng_condition_event_rule_matches::parent),
4687 notification->capture_buffer,
4688 notification->capture_buf_size,
4689 false);
7c920b63 4690
cd9adb8b 4691 if (evaluation == nullptr) {
8c1d25ff 4692 ERR("Failed to create event rule matches evaluation while creating and enqueuing action executor job");
f1446131
JR
4693 ret = -1;
4694 goto end_unlock;
4695 }
8c1d25ff 4696
28ab034a
JG
4697 client_list = get_client_list_from_condition(
4698 state, lttng_trigger_get_const_condition(element->trigger));
4699 executor_status = action_executor_enqueue_trigger(
cd9adb8b 4700 state->executor, element->trigger, evaluation, nullptr, client_list);
f1446131
JR
4701 switch (executor_status) {
4702 case ACTION_EXECUTOR_STATUS_OK:
4703 ret = 0;
4704 break;
4705 case ACTION_EXECUTOR_STATUS_OVERFLOW:
4706 {
28ab034a 4707 struct notification_client_list_element *client_list_element, *tmp;
f1446131
JR
4708
4709 /*
4710 * Not a fatal error; this is expected and simply means the
4711 * executor has too much work queued already.
4712 */
4713 ret = 0;
4714
4715 /* No clients subscribed to notifications for this trigger. */
4716 if (!client_list) {
4717 break;
4718 }
4719
4720 /* Warn clients that a notification (or more) was dropped. */
4721 pthread_mutex_lock(&client_list->lock);
28ab034a
JG
4722 cds_list_for_each_entry_safe (
4723 client_list_element, tmp, &client_list->clients_list, node) {
f1446131 4724 enum client_transmission_status transmission_status;
28ab034a 4725 struct notification_client *client = client_list_element->client;
f1446131
JR
4726
4727 pthread_mutex_lock(&client->lock);
4728 ret = client_notification_overflow(client);
4729 if (ret) {
4730 /* Fatal error. */
4731 goto next_client;
4732 }
4733
28ab034a
JG
4734 transmission_status = client_flush_outgoing_queue(client);
4735 ret = client_handle_transmission_status(client, transmission_status, state);
f1446131
JR
4736 if (ret) {
4737 /* Fatal error. */
4738 goto next_client;
4739 }
28ab034a 4740 next_client:
f1446131
JR
4741 pthread_mutex_unlock(&client->lock);
4742 if (ret) {
4743 break;
4744 }
4745 }
4746
4747 pthread_mutex_unlock(&client_list->lock);
4748 break;
4749 }
98dfca79 4750 case ACTION_EXECUTOR_STATUS_INVALID:
f1446131
JR
4751 case ACTION_EXECUTOR_STATUS_ERROR:
4752 /* Fatal error, shut down everything. */
4753 ERR("Fatal error encoutered while enqueuing action to the action executor");
4754 ret = -1;
4755 goto end_unlock;
4756 default:
4757 /* Unhandled error. */
4758 abort();
4759 }
94078603
JR
4760
4761end_unlock:
f1446131 4762 notification_client_list_put(client_list);
94078603 4763 rcu_read_unlock();
7c920b63 4764end:
8b524060
FD
4765 return ret;
4766}
4767
28ab034a
JG
4768static int handle_one_event_notifier_notification(struct notification_thread_state *state,
4769 int pipe,
4770 enum lttng_domain_type domain)
8b524060 4771{
82b3cbf4 4772 int ret = 0;
cd9adb8b 4773 struct lttng_event_notifier_notification *notification = nullptr;
8b524060
FD
4774
4775 notification = recv_one_event_notifier_notification(pipe, domain);
cd9adb8b 4776 if (notification == nullptr) {
82b3cbf4 4777 /* Reception failed, don't consider it fatal. */
bd0514a5 4778 ERR("Error receiving an event notifier notification from tracer: fd = %i, domain = %s",
28ab034a
JG
4779 pipe,
4780 lttng_domain_type_str(domain));
8b524060
FD
4781 goto end;
4782 }
4783
4784 ret = dispatch_one_event_notifier_notification(state, notification);
4785 if (ret) {
bd0514a5 4786 ERR("Error dispatching an event notifier notification from tracer: fd = %i, domain = %s",
28ab034a
JG
4787 pipe,
4788 lttng_domain_type_str(domain));
8b524060
FD
4789 goto end;
4790 }
4791
94078603 4792end:
8b524060 4793 lttng_event_notifier_notification_destroy(notification);
94078603
JR
4794 return ret;
4795}
4796
8b524060 4797int handle_notification_thread_event_notification(struct notification_thread_state *state,
28ab034a
JG
4798 int pipe,
4799 enum lttng_domain_type domain)
8b524060
FD
4800{
4801 return handle_one_event_notifier_notification(state, pipe, domain);
4802}
4803
28ab034a
JG
4804int handle_notification_thread_channel_sample(struct notification_thread_state *state,
4805 int pipe,
4806 enum lttng_domain_type domain)
ab0ee2ca
JG
4807{
4808 int ret = 0;
4809 struct lttcomm_consumer_channel_monitor_msg sample_msg;
cd9adb8b 4810 struct channel_info *channel_info = nullptr;
ab0ee2ca
JG
4811 struct cds_lfht_node *node;
4812 struct cds_lfht_iter iter;
319dcddc
JG
4813 struct lttng_channel_trigger_list *channel_trigger_list;
4814 struct lttng_session_trigger_list *session_trigger_list;
ab0ee2ca
JG
4815 struct lttng_trigger_list_element *trigger_list_element;
4816 bool previous_sample_available = false;
319dcddc
JG
4817 struct channel_state_sample channel_previous_sample, channel_new_sample;
4818 struct session_state_sample session_new_sample;
4819 struct lttng_credentials channel_creds = {};
4820 struct lttng_credentials session_creds = {};
4821 struct session_info *session;
ab0ee2ca
JG
4822
4823 /*
4824 * The monitoring pipe only holds messages smaller than PIPE_BUF,
4825 * ensuring that read/write of sampling messages are atomic.
4826 */
7c2551ef 4827 ret = lttng_read(pipe, &sample_msg, sizeof(sample_msg));
ab0ee2ca 4828 if (ret != sizeof(sample_msg)) {
28ab034a 4829 ERR("Failed to read from monitoring pipe (fd = %i)", pipe);
ab0ee2ca
JG
4830 ret = -1;
4831 goto end;
4832 }
4833
4834 ret = 0;
319dcddc
JG
4835 channel_new_sample.key.key = sample_msg.key;
4836 channel_new_sample.key.domain = domain;
4837 channel_new_sample.highest_usage = sample_msg.highest;
4838 channel_new_sample.lowest_usage = sample_msg.lowest;
ab0ee2ca
JG
4839
4840 rcu_read_lock();
4841
319dcddc
JG
4842 session = get_session_info_by_id(state, sample_msg.session_id);
4843 if (!session) {
4844 DBG("Received a sample for an unknown session from consumerd: session id = %" PRIu64,
28ab034a 4845 sample_msg.session_id);
319dcddc
JG
4846 goto end_unlock;
4847 }
4848
4849 session_new_sample = session->last_state_sample;
4850 session_new_sample.consumed_data_size += sample_msg.consumed_since_last_sample;
4851 session_creds = {
4852 .uid = LTTNG_OPTIONAL_INIT_VALUE(session->uid),
4853 .gid = LTTNG_OPTIONAL_INIT_VALUE(session->gid),
4854 };
4855
4856 session_trigger_list = get_session_trigger_list(state, session->name);
4857 LTTNG_ASSERT(session_trigger_list);
28ab034a 4858 cds_list_for_each_entry (trigger_list_element, &session_trigger_list->list, node) {
319dcddc
JG
4859 const struct lttng_condition *condition;
4860 struct lttng_trigger *trigger;
cd9adb8b
JG
4861 struct notification_client_list *client_list = nullptr;
4862 struct lttng_evaluation *evaluation = nullptr;
319dcddc
JG
4863 enum action_executor_status executor_status;
4864
4865 ret = 0;
4866 trigger = trigger_list_element->trigger;
4867 condition = lttng_trigger_get_const_condition(trigger);
4868 LTTNG_ASSERT(condition);
4869
4870 ret = evaluate_session_condition(
28ab034a 4871 condition, session, &session_new_sample, &evaluation);
319dcddc
JG
4872 if (caa_unlikely(ret)) {
4873 break;
4874 }
4875
4876 if (caa_likely(!evaluation)) {
4877 continue;
4878 }
4879
4880 /*
4881 * Ownership of `evaluation` transferred to the action executor
4882 * no matter the result. The callee acquires a reference to the
4883 * client list: we can release our own.
4884 */
4885 client_list = get_client_list_from_condition(state, condition);
4886 executor_status = action_executor_enqueue_trigger(
28ab034a 4887 state->executor, trigger, evaluation, &session_creds, client_list);
319dcddc 4888 notification_client_list_put(client_list);
cd9adb8b 4889 evaluation = nullptr;
319dcddc
JG
4890 switch (executor_status) {
4891 case ACTION_EXECUTOR_STATUS_OK:
4892 break;
4893 case ACTION_EXECUTOR_STATUS_ERROR:
4894 case ACTION_EXECUTOR_STATUS_INVALID:
4895 /*
4896 * TODO Add trigger identification (name/id) when
4897 * it is added to the API.
4898 */
4899 ERR("Fatal error occurred while enqueuing action associated with buffer-condition trigger");
4900 ret = -1;
4901 goto end_unlock;
4902 case ACTION_EXECUTOR_STATUS_OVERFLOW:
4903 /*
4904 * TODO Add trigger identification (name/id) when
4905 * it is added to the API.
4906 *
4907 * Not a fatal error.
4908 */
4909 WARN("No space left when enqueuing action associated with buffer-condition trigger");
4910 ret = 0;
4911 goto end_unlock;
4912 default:
4913 abort();
4914 }
4915 }
4916
ab0ee2ca
JG
4917 /* Retrieve the channel's informations */
4918 cds_lfht_lookup(state->channels_ht,
319dcddc 4919 hash_channel_key(&channel_new_sample.key),
ab0ee2ca 4920 match_channel_info,
319dcddc 4921 &channel_new_sample.key,
ab0ee2ca
JG
4922 &iter);
4923 node = cds_lfht_iter_get_node(&iter);
e0b5f87b 4924 if (caa_unlikely(!node)) {
ab0ee2ca
JG
4925 /*
4926 * Not an error since the consumer can push a sample to the pipe
4927 * and the rest of the session daemon could notify us of the
4928 * channel's destruction before we get a chance to process that
4929 * sample.
4930 */
28ab034a
JG
4931 DBG("Received a sample for an unknown channel from consumerd, key = %" PRIu64
4932 " in %s domain",
4933 channel_new_sample.key.key,
4934 lttng_domain_type_str(domain));
ab0ee2ca
JG
4935 goto end_unlock;
4936 }
319dcddc 4937
28ab034a
JG
4938 channel_info = caa_container_of(node, struct channel_info, channels_ht_node);
4939 DBG("Handling channel sample for channel %s (key = %" PRIu64
4940 ") in session %s (highest usage = %" PRIu64 ", lowest usage = %" PRIu64
4941 ", consumed since last sample = %" PRIu64 ")",
4942 channel_info->name,
4943 channel_new_sample.key.key,
4944 channel_info->session_info->name,
4945 channel_new_sample.highest_usage,
4946 channel_new_sample.lowest_usage,
4947 sample_msg.consumed_since_last_sample);
ab0ee2ca
JG
4948
4949 /* Retrieve the channel's last sample, if it exists, and update it. */
4950 cds_lfht_lookup(state->channel_state_ht,
319dcddc 4951 hash_channel_key(&channel_new_sample.key),
ab0ee2ca 4952 match_channel_state_sample,
319dcddc 4953 &channel_new_sample.key,
ab0ee2ca
JG
4954 &iter);
4955 node = cds_lfht_iter_get_node(&iter);
e0b5f87b 4956 if (caa_likely(node)) {
ab0ee2ca
JG
4957 struct channel_state_sample *stored_sample;
4958
4959 /* Update the sample stored. */
28ab034a
JG
4960 stored_sample =
4961 caa_container_of(node, struct channel_state_sample, channel_state_ht_node);
e8360425 4962
28ab034a 4963 memcpy(&channel_previous_sample, stored_sample, sizeof(channel_previous_sample));
319dcddc
JG
4964 stored_sample->highest_usage = channel_new_sample.highest_usage;
4965 stored_sample->lowest_usage = channel_new_sample.lowest_usage;
ab0ee2ca
JG
4966 previous_sample_available = true;
4967 } else {
4968 /*
4969 * This is the channel's first sample, allocate space for and
4970 * store the new sample.
4971 */
4972 struct channel_state_sample *stored_sample;
4973
64803277 4974 stored_sample = zmalloc<channel_state_sample>();
ab0ee2ca
JG
4975 if (!stored_sample) {
4976 ret = -1;
4977 goto end_unlock;
4978 }
4979
319dcddc 4980 memcpy(stored_sample, &channel_new_sample, sizeof(*stored_sample));
ab0ee2ca
JG
4981 cds_lfht_node_init(&stored_sample->channel_state_ht_node);
4982 cds_lfht_add(state->channel_state_ht,
28ab034a
JG
4983 hash_channel_key(&stored_sample->key),
4984 &stored_sample->channel_state_ht_node);
ab0ee2ca
JG
4985 }
4986
4987 /* Find triggers associated with this channel. */
4988 cds_lfht_lookup(state->channel_triggers_ht,
319dcddc 4989 hash_channel_key(&channel_new_sample.key),
ab0ee2ca 4990 match_channel_trigger_list,
319dcddc 4991 &channel_new_sample.key,
ab0ee2ca
JG
4992 &iter);
4993 node = cds_lfht_iter_get_node(&iter);
319dcddc 4994 LTTNG_ASSERT(node);
ab0ee2ca 4995
28ab034a 4996 channel_creds = (typeof(channel_creds)){
ff588497
JR
4997 .uid = LTTNG_OPTIONAL_INIT_VALUE(channel_info->session_info->uid),
4998 .gid = LTTNG_OPTIONAL_INIT_VALUE(channel_info->session_info->gid),
f2b3ef9f
JG
4999 };
5000
28ab034a
JG
5001 channel_trigger_list =
5002 caa_container_of(node, struct lttng_channel_trigger_list, channel_triggers_ht_node);
5003 cds_list_for_each_entry (trigger_list_element, &channel_trigger_list->list, node) {
9b63a4aa 5004 const struct lttng_condition *condition;
f2b3ef9f 5005 struct lttng_trigger *trigger;
cd9adb8b
JG
5006 struct notification_client_list *client_list = nullptr;
5007 struct lttng_evaluation *evaluation = nullptr;
f2b3ef9f 5008 enum action_executor_status executor_status;
ab0ee2ca 5009
505b2d90 5010 ret = 0;
ab0ee2ca 5011 trigger = trigger_list_element->trigger;
9b63a4aa 5012 condition = lttng_trigger_get_const_condition(trigger);
a0377dfe 5013 LTTNG_ASSERT(condition);
ab0ee2ca 5014
28ab034a
JG
5015 ret = evaluate_buffer_condition(
5016 condition,
5017 &evaluation,
5018 state,
cd9adb8b 5019 previous_sample_available ? &channel_previous_sample : nullptr,
28ab034a
JG
5020 &channel_new_sample,
5021 channel_info);
e8360425 5022 if (caa_unlikely(ret)) {
319dcddc 5023 break;
ab0ee2ca
JG
5024 }
5025
e8360425 5026 if (caa_likely(!evaluation)) {
319dcddc 5027 continue;
ab0ee2ca
JG
5028 }
5029
f2b3ef9f
JG
5030 /*
5031 * Ownership of `evaluation` transferred to the action executor
319dcddc
JG
5032 * no matter the result. The callee acquires a reference to the
5033 * client list: we can release our own.
f2b3ef9f 5034 */
319dcddc 5035 client_list = get_client_list_from_condition(state, condition);
72365501 5036 executor_status = action_executor_enqueue_trigger(
28ab034a 5037 state->executor, trigger, evaluation, &channel_creds, client_list);
319dcddc 5038 notification_client_list_put(client_list);
cd9adb8b 5039 evaluation = nullptr;
f2b3ef9f
JG
5040 switch (executor_status) {
5041 case ACTION_EXECUTOR_STATUS_OK:
5042 break;
5043 case ACTION_EXECUTOR_STATUS_ERROR:
5044 case ACTION_EXECUTOR_STATUS_INVALID:
5045 /*
5046 * TODO Add trigger identification (name/id) when
5047 * it is added to the API.
5048 */
5049 ERR("Fatal error occurred while enqueuing action associated with buffer-condition trigger");
5050 ret = -1;
319dcddc 5051 goto end_unlock;
f2b3ef9f
JG
5052 case ACTION_EXECUTOR_STATUS_OVERFLOW:
5053 /*
5054 * TODO Add trigger identification (name/id) when
5055 * it is added to the API.
5056 *
5057 * Not a fatal error.
5058 */
5059 WARN("No space left when enqueuing action associated with buffer-condition trigger");
5060 ret = 0;
319dcddc 5061 goto end_unlock;
f2b3ef9f
JG
5062 default:
5063 abort();
5064 }
ab0ee2ca
JG
5065 }
5066end_unlock:
319dcddc
JG
5067 if (session) {
5068 session->last_state_sample = session_new_sample;
5069 }
5070 session_info_put(session);
ab0ee2ca
JG
5071 rcu_read_unlock();
5072end:
5073 return ret;
5074}
This page took 0.365905 seconds and 4 git commands to generate.