2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
8 #include <lttng/trigger/trigger.h>
9 #include <lttng/lttng-error.h>
10 #include "notification-thread.hpp"
11 #include "notification-thread-commands.hpp"
12 #include <common/error.hpp>
18 void init_notification_thread_command(struct notification_thread_command
*cmd
)
20 CDS_INIT_LIST_HEAD(&cmd
->cmd_list_node
);
21 lttng_waiter_init(&cmd
->reply_waiter
);
25 int run_command_wait(struct notification_thread_handle
*handle
,
26 struct notification_thread_command
*cmd
)
29 uint64_t notification_counter
= 1;
31 pthread_mutex_lock(&handle
->cmd_queue
.lock
);
33 cds_list_add_tail(&cmd
->cmd_list_node
,
34 &handle
->cmd_queue
.list
);
36 ret
= lttng_write(handle
->cmd_queue
.event_fd
,
37 ¬ification_counter
, sizeof(notification_counter
));
38 if (ret
!= sizeof(notification_counter
)) {
39 PERROR("write to notification thread's queue event fd");
41 * Remove the command from the list so the notification
42 * thread does not process it.
44 cds_list_del(&cmd
->cmd_list_node
);
45 goto error_unlock_queue
;
47 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
49 lttng_waiter_wait(&cmd
->reply_waiter
);
52 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
57 struct notification_thread_command
*notification_thread_command_copy(
58 const struct notification_thread_command
*original_cmd
)
60 struct notification_thread_command
*new_cmd
;
62 new_cmd
= zmalloc
<notification_thread_command
>();
67 *new_cmd
= *original_cmd
;
68 init_notification_thread_command(new_cmd
);
74 int run_command_no_wait(struct notification_thread_handle
*handle
,
75 const struct notification_thread_command
*in_cmd
)
78 uint64_t notification_counter
= 1;
79 struct notification_thread_command
*new_cmd
=
80 notification_thread_command_copy(in_cmd
);
85 new_cmd
->is_async
= true;
87 pthread_mutex_lock(&handle
->cmd_queue
.lock
);
89 cds_list_add_tail(&new_cmd
->cmd_list_node
,
90 &handle
->cmd_queue
.list
);
92 ret
= lttng_write(handle
->cmd_queue
.event_fd
,
93 ¬ification_counter
, sizeof(notification_counter
));
94 if (ret
!= sizeof(notification_counter
)) {
95 PERROR("write to notification thread's queue event fd");
97 * Remove the command from the list so the notification
98 * thread does not process it.
100 cds_list_del(&new_cmd
->cmd_list_node
);
101 goto error_unlock_queue
;
103 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
107 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
112 enum lttng_error_code
notification_thread_command_register_trigger(
113 struct notification_thread_handle
*handle
,
114 struct lttng_trigger
*trigger
,
115 bool is_trigger_anonymous
)
118 enum lttng_error_code ret_code
;
119 struct notification_thread_command cmd
= {};
121 LTTNG_ASSERT(trigger
);
122 init_notification_thread_command(&cmd
);
124 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER
;
125 lttng_trigger_get(trigger
);
126 cmd
.parameters
.register_trigger
.trigger
= trigger
;
127 cmd
.parameters
.register_trigger
.is_trigger_anonymous
=
128 is_trigger_anonymous
;
130 ret
= run_command_wait(handle
, &cmd
);
132 ret_code
= LTTNG_ERR_UNK
;
135 ret_code
= cmd
.reply_code
;
140 enum lttng_error_code
notification_thread_command_unregister_trigger(
141 struct notification_thread_handle
*handle
,
142 const struct lttng_trigger
*trigger
)
145 enum lttng_error_code ret_code
;
146 struct notification_thread_command cmd
= {};
148 init_notification_thread_command(&cmd
);
150 cmd
.type
= NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER
;
151 cmd
.parameters
.unregister_trigger
.trigger
= trigger
;
153 ret
= run_command_wait(handle
, &cmd
);
155 ret_code
= LTTNG_ERR_UNK
;
158 ret_code
= cmd
.reply_code
;
163 enum lttng_error_code
notification_thread_command_add_session(
164 struct notification_thread_handle
*handle
,
165 uint64_t session_id
, const char *session_name
, uid_t session_uid
, gid_t session_gid
)
168 enum lttng_error_code ret_code
;
169 struct notification_thread_command cmd
= {};
171 init_notification_thread_command(&cmd
);
173 cmd
.type
= NOTIFICATION_COMMAND_TYPE_ADD_SESSION
;
174 cmd
.parameters
.add_session
.session_id
= session_id
;
175 cmd
.parameters
.add_session
.session_name
= session_name
;
176 cmd
.parameters
.add_session
.session_uid
= session_uid
;
177 cmd
.parameters
.add_session
.session_gid
= session_gid
;
179 ret
= run_command_wait(handle
, &cmd
);
181 ret_code
= LTTNG_ERR_UNK
;
184 ret_code
= cmd
.reply_code
;
189 enum lttng_error_code
notification_thread_command_remove_session(
190 struct notification_thread_handle
*handle
,
194 enum lttng_error_code ret_code
;
195 struct notification_thread_command cmd
= {};
197 init_notification_thread_command(&cmd
);
199 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION
;
200 cmd
.parameters
.remove_session
.session_id
= session_id
;
202 ret
= run_command_wait(handle
, &cmd
);
204 ret_code
= LTTNG_ERR_UNK
;
207 ret_code
= cmd
.reply_code
;
212 enum lttng_error_code
notification_thread_command_add_channel(
213 struct notification_thread_handle
*handle
,
215 char *channel_name
, uint64_t key
,
216 enum lttng_domain_type domain
, uint64_t capacity
)
219 enum lttng_error_code ret_code
;
220 struct notification_thread_command cmd
= {};
222 init_notification_thread_command(&cmd
);
224 cmd
.type
= NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL
;
225 cmd
.parameters
.add_channel
.session
.id
= session_id
;
226 cmd
.parameters
.add_channel
.channel
.name
= channel_name
;
227 cmd
.parameters
.add_channel
.channel
.key
= key
;
228 cmd
.parameters
.add_channel
.channel
.domain
= domain
;
229 cmd
.parameters
.add_channel
.channel
.capacity
= capacity
;
231 ret
= run_command_wait(handle
, &cmd
);
233 ret_code
= LTTNG_ERR_UNK
;
236 ret_code
= cmd
.reply_code
;
241 enum lttng_error_code
notification_thread_command_remove_channel(
242 struct notification_thread_handle
*handle
,
243 uint64_t key
, enum lttng_domain_type domain
)
246 enum lttng_error_code ret_code
;
247 struct notification_thread_command cmd
= {};
249 init_notification_thread_command(&cmd
);
251 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL
;
252 cmd
.parameters
.remove_channel
.key
= key
;
253 cmd
.parameters
.remove_channel
.domain
= domain
;
255 ret
= run_command_wait(handle
, &cmd
);
257 ret_code
= LTTNG_ERR_UNK
;
260 ret_code
= cmd
.reply_code
;
265 enum lttng_error_code
notification_thread_command_session_rotation_ongoing(
266 struct notification_thread_handle
*handle
,
268 uint64_t trace_archive_chunk_id
)
271 enum lttng_error_code ret_code
;
272 struct notification_thread_command cmd
= {};
274 init_notification_thread_command(&cmd
);
276 cmd
.type
= NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING
;
277 cmd
.parameters
.session_rotation
.session_id
= session_id
;
278 cmd
.parameters
.session_rotation
.trace_archive_chunk_id
=
279 trace_archive_chunk_id
;
281 ret
= run_command_wait(handle
, &cmd
);
283 ret_code
= LTTNG_ERR_UNK
;
286 ret_code
= cmd
.reply_code
;
291 enum lttng_error_code
notification_thread_command_session_rotation_completed(
292 struct notification_thread_handle
*handle
,
294 uint64_t trace_archive_chunk_id
,
295 struct lttng_trace_archive_location
*location
)
298 enum lttng_error_code ret_code
;
299 struct notification_thread_command cmd
= {};
301 init_notification_thread_command(&cmd
);
303 cmd
.type
= NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED
;
304 cmd
.parameters
.session_rotation
.session_id
= session_id
;
305 cmd
.parameters
.session_rotation
.trace_archive_chunk_id
=
306 trace_archive_chunk_id
;
307 cmd
.parameters
.session_rotation
.location
= location
;
309 ret
= run_command_wait(handle
, &cmd
);
311 ret_code
= LTTNG_ERR_UNK
;
314 ret_code
= cmd
.reply_code
;
319 enum lttng_error_code
notification_thread_command_add_tracer_event_source(
320 struct notification_thread_handle
*handle
,
321 int tracer_event_source_fd
,
322 enum lttng_domain_type domain
)
325 enum lttng_error_code ret_code
;
326 struct notification_thread_command cmd
= {};
328 LTTNG_ASSERT(tracer_event_source_fd
>= 0);
330 init_notification_thread_command(&cmd
);
332 cmd
.type
= NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE
;
333 cmd
.parameters
.tracer_event_source
.tracer_event_source_fd
=
334 tracer_event_source_fd
;
335 cmd
.parameters
.tracer_event_source
.domain
= domain
;
337 ret
= run_command_wait(handle
, &cmd
);
339 ret_code
= LTTNG_ERR_UNK
;
343 ret_code
= cmd
.reply_code
;
348 enum lttng_error_code
notification_thread_command_remove_tracer_event_source(
349 struct notification_thread_handle
*handle
,
350 int tracer_event_source_fd
)
353 enum lttng_error_code ret_code
;
354 struct notification_thread_command cmd
= {};
356 init_notification_thread_command(&cmd
);
358 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE
;
359 cmd
.parameters
.tracer_event_source
.tracer_event_source_fd
=
360 tracer_event_source_fd
;
362 ret
= run_command_wait(handle
, &cmd
);
364 ret_code
= LTTNG_ERR_UNK
;
368 ret_code
= cmd
.reply_code
;
373 enum lttng_error_code
notification_thread_command_list_triggers(
374 struct notification_thread_handle
*handle
,
376 struct lttng_triggers
**triggers
)
379 enum lttng_error_code ret_code
;
380 struct notification_thread_command cmd
= {};
382 LTTNG_ASSERT(handle
);
383 LTTNG_ASSERT(triggers
);
385 init_notification_thread_command(&cmd
);
387 cmd
.type
= NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS
;
388 cmd
.parameters
.list_triggers
.uid
= uid
;
390 ret
= run_command_wait(handle
, &cmd
);
392 ret_code
= LTTNG_ERR_UNK
;
396 ret_code
= cmd
.reply_code
;
397 *triggers
= cmd
.reply
.list_triggers
.triggers
;
403 void notification_thread_command_quit(
404 struct notification_thread_handle
*handle
)
407 struct notification_thread_command cmd
= {};
409 init_notification_thread_command(&cmd
);
411 cmd
.type
= NOTIFICATION_COMMAND_TYPE_QUIT
;
412 ret
= run_command_wait(handle
, &cmd
);
413 LTTNG_ASSERT(!ret
&& cmd
.reply_code
== LTTNG_OK
);
416 int notification_thread_client_communication_update(
417 struct notification_thread_handle
*handle
,
418 notification_client_id id
,
419 enum client_transmission_status transmission_status
)
421 struct notification_thread_command cmd
= {};
423 init_notification_thread_command(&cmd
);
425 cmd
.type
= NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE
;
426 cmd
.parameters
.client_communication_update
.id
= id
;
427 cmd
.parameters
.client_communication_update
.status
= transmission_status
;
428 return run_command_no_wait(handle
, &cmd
);
431 enum lttng_error_code
notification_thread_command_get_trigger(
432 struct notification_thread_handle
*handle
,
433 const struct lttng_trigger
*trigger
,
434 struct lttng_trigger
**real_trigger
)
437 enum lttng_error_code ret_code
;
438 struct notification_thread_command cmd
= {};
440 init_notification_thread_command(&cmd
);
442 cmd
.type
= NOTIFICATION_COMMAND_TYPE_GET_TRIGGER
;
443 cmd
.parameters
.get_trigger
.trigger
= trigger
;
444 ret
= run_command_wait(handle
, &cmd
);
446 ret_code
= LTTNG_ERR_UNK
;
450 ret_code
= cmd
.reply_code
;
451 *real_trigger
= cmd
.reply
.get_trigger
.trigger
;
458 * Takes ownership of the payload if present.
460 struct lttng_event_notifier_notification
*lttng_event_notifier_notification_create(
461 uint64_t tracer_token
,
462 enum lttng_domain_type domain
,
466 struct lttng_event_notifier_notification
*notification
= NULL
;
468 LTTNG_ASSERT(domain
!= LTTNG_DOMAIN_NONE
);
469 LTTNG_ASSERT((payload
&& payload_size
) || (!payload
&& !payload_size
));
471 notification
= zmalloc
<lttng_event_notifier_notification
>();
472 if (notification
== NULL
) {
473 ERR("Error allocating notification");
477 notification
->tracer_token
= tracer_token
;
478 notification
->type
= domain
;
479 notification
->capture_buffer
= payload
;
480 notification
->capture_buf_size
= payload_size
;
486 void lttng_event_notifier_notification_destroy(
487 struct lttng_event_notifier_notification
*notification
)
493 free(notification
->capture_buffer
);