2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
8 #include "notification-thread-commands.hpp"
9 #include "notification-thread.hpp"
11 #include <common/error.hpp>
13 #include <lttng/lttng-error.h>
14 #include <lttng/trigger/trigger.h>
20 static void init_notification_thread_command(struct notification_thread_command
*cmd
)
22 CDS_INIT_LIST_HEAD(&cmd
->cmd_list_node
);
23 lttng_waiter_init(&cmd
->reply_waiter
);
26 static int run_command_wait(struct notification_thread_handle
*handle
,
27 struct notification_thread_command
*cmd
)
30 uint64_t notification_counter
= 1;
32 pthread_mutex_lock(&handle
->cmd_queue
.lock
);
34 cds_list_add_tail(&cmd
->cmd_list_node
, &handle
->cmd_queue
.list
);
37 handle
->cmd_queue
.event_fd
, ¬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
);
56 static struct notification_thread_command
*
57 notification_thread_command_copy(const struct notification_thread_command
*original_cmd
)
59 struct notification_thread_command
*new_cmd
;
61 new_cmd
= zmalloc
<notification_thread_command
>();
66 *new_cmd
= *original_cmd
;
67 init_notification_thread_command(new_cmd
);
72 static int run_command_no_wait(struct notification_thread_handle
*handle
,
73 const struct notification_thread_command
*in_cmd
)
76 uint64_t notification_counter
= 1;
77 struct notification_thread_command
*new_cmd
= notification_thread_command_copy(in_cmd
);
82 new_cmd
->is_async
= true;
84 pthread_mutex_lock(&handle
->cmd_queue
.lock
);
86 cds_list_add_tail(&new_cmd
->cmd_list_node
, &handle
->cmd_queue
.list
);
89 handle
->cmd_queue
.event_fd
, ¬ification_counter
, sizeof(notification_counter
));
90 if (ret
!= sizeof(notification_counter
)) {
91 PERROR("write to notification thread's queue event fd");
93 * Remove the command from the list so the notification
94 * thread does not process it.
96 cds_list_del(&new_cmd
->cmd_list_node
);
97 goto error_unlock_queue
;
99 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
103 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
108 enum lttng_error_code
109 notification_thread_command_register_trigger(struct notification_thread_handle
*handle
,
110 struct lttng_trigger
*trigger
,
111 bool is_trigger_anonymous
)
114 enum lttng_error_code ret_code
;
115 struct notification_thread_command cmd
= {};
117 LTTNG_ASSERT(trigger
);
118 init_notification_thread_command(&cmd
);
120 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER
;
121 lttng_trigger_get(trigger
);
122 cmd
.parameters
.register_trigger
.trigger
= trigger
;
123 cmd
.parameters
.register_trigger
.is_trigger_anonymous
= is_trigger_anonymous
;
125 ret
= run_command_wait(handle
, &cmd
);
127 ret_code
= LTTNG_ERR_UNK
;
130 ret_code
= cmd
.reply_code
;
135 enum lttng_error_code
136 notification_thread_command_unregister_trigger(struct notification_thread_handle
*handle
,
137 const struct lttng_trigger
*trigger
)
140 enum lttng_error_code ret_code
;
141 struct notification_thread_command cmd
= {};
143 init_notification_thread_command(&cmd
);
145 cmd
.type
= NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER
;
146 cmd
.parameters
.unregister_trigger
.trigger
= trigger
;
148 ret
= run_command_wait(handle
, &cmd
);
150 ret_code
= LTTNG_ERR_UNK
;
153 ret_code
= cmd
.reply_code
;
158 enum lttng_error_code
159 notification_thread_command_add_session(struct notification_thread_handle
*handle
,
161 const char *session_name
,
166 enum lttng_error_code ret_code
;
167 struct notification_thread_command cmd
= {};
169 init_notification_thread_command(&cmd
);
171 cmd
.type
= NOTIFICATION_COMMAND_TYPE_ADD_SESSION
;
172 cmd
.parameters
.add_session
.session_id
= session_id
;
173 cmd
.parameters
.add_session
.session_name
= session_name
;
174 cmd
.parameters
.add_session
.session_uid
= session_uid
;
175 cmd
.parameters
.add_session
.session_gid
= session_gid
;
177 ret
= run_command_wait(handle
, &cmd
);
179 ret_code
= LTTNG_ERR_UNK
;
182 ret_code
= cmd
.reply_code
;
187 enum lttng_error_code
188 notification_thread_command_remove_session(struct notification_thread_handle
*handle
,
192 enum lttng_error_code ret_code
;
193 struct notification_thread_command cmd
= {};
195 init_notification_thread_command(&cmd
);
197 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION
;
198 cmd
.parameters
.remove_session
.session_id
= session_id
;
200 ret
= run_command_wait(handle
, &cmd
);
202 ret_code
= LTTNG_ERR_UNK
;
205 ret_code
= cmd
.reply_code
;
210 enum lttng_error_code
211 notification_thread_command_add_channel(struct notification_thread_handle
*handle
,
215 enum lttng_domain_type domain
,
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
, uint64_t key
, enum lttng_domain_type domain
)
245 enum lttng_error_code ret_code
;
246 struct notification_thread_command cmd
= {};
248 init_notification_thread_command(&cmd
);
250 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL
;
251 cmd
.parameters
.remove_channel
.key
= key
;
252 cmd
.parameters
.remove_channel
.domain
= domain
;
254 ret
= run_command_wait(handle
, &cmd
);
256 ret_code
= LTTNG_ERR_UNK
;
259 ret_code
= cmd
.reply_code
;
264 enum lttng_error_code
265 notification_thread_command_session_rotation_ongoing(struct notification_thread_handle
*handle
,
267 uint64_t trace_archive_chunk_id
)
270 enum lttng_error_code ret_code
;
271 struct notification_thread_command cmd
= {};
273 init_notification_thread_command(&cmd
);
275 cmd
.type
= NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING
;
276 cmd
.parameters
.session_rotation
.session_id
= session_id
;
277 cmd
.parameters
.session_rotation
.trace_archive_chunk_id
= trace_archive_chunk_id
;
279 ret
= run_command_wait(handle
, &cmd
);
281 ret_code
= LTTNG_ERR_UNK
;
284 ret_code
= cmd
.reply_code
;
289 enum lttng_error_code
notification_thread_command_session_rotation_completed(
290 struct notification_thread_handle
*handle
,
292 uint64_t trace_archive_chunk_id
,
293 struct lttng_trace_archive_location
*location
)
296 enum lttng_error_code ret_code
;
297 struct notification_thread_command cmd
= {};
299 init_notification_thread_command(&cmd
);
301 cmd
.type
= NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED
;
302 cmd
.parameters
.session_rotation
.session_id
= session_id
;
303 cmd
.parameters
.session_rotation
.trace_archive_chunk_id
= trace_archive_chunk_id
;
304 cmd
.parameters
.session_rotation
.location
= location
;
306 ret
= run_command_wait(handle
, &cmd
);
308 ret_code
= LTTNG_ERR_UNK
;
311 ret_code
= cmd
.reply_code
;
316 enum lttng_error_code
317 notification_thread_command_add_tracer_event_source(struct notification_thread_handle
*handle
,
318 int tracer_event_source_fd
,
319 enum lttng_domain_type domain
)
322 enum lttng_error_code ret_code
;
323 struct notification_thread_command cmd
= {};
325 LTTNG_ASSERT(tracer_event_source_fd
>= 0);
327 init_notification_thread_command(&cmd
);
329 cmd
.type
= NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE
;
330 cmd
.parameters
.tracer_event_source
.tracer_event_source_fd
= tracer_event_source_fd
;
331 cmd
.parameters
.tracer_event_source
.domain
= domain
;
333 ret
= run_command_wait(handle
, &cmd
);
335 ret_code
= LTTNG_ERR_UNK
;
339 ret_code
= cmd
.reply_code
;
344 enum lttng_error_code
345 notification_thread_command_remove_tracer_event_source(struct notification_thread_handle
*handle
,
346 int tracer_event_source_fd
)
349 enum lttng_error_code ret_code
;
350 struct notification_thread_command cmd
= {};
352 init_notification_thread_command(&cmd
);
354 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE
;
355 cmd
.parameters
.tracer_event_source
.tracer_event_source_fd
= tracer_event_source_fd
;
357 ret
= run_command_wait(handle
, &cmd
);
359 ret_code
= LTTNG_ERR_UNK
;
363 ret_code
= cmd
.reply_code
;
368 enum lttng_error_code
notification_thread_command_list_triggers(
369 struct notification_thread_handle
*handle
, uid_t uid
, struct lttng_triggers
**triggers
)
372 enum lttng_error_code ret_code
;
373 struct notification_thread_command cmd
= {};
375 LTTNG_ASSERT(handle
);
376 LTTNG_ASSERT(triggers
);
378 init_notification_thread_command(&cmd
);
380 cmd
.type
= NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS
;
381 cmd
.parameters
.list_triggers
.uid
= uid
;
383 ret
= run_command_wait(handle
, &cmd
);
385 ret_code
= LTTNG_ERR_UNK
;
389 ret_code
= cmd
.reply_code
;
390 *triggers
= cmd
.reply
.list_triggers
.triggers
;
396 void notification_thread_command_quit(struct notification_thread_handle
*handle
)
399 struct notification_thread_command cmd
= {};
401 init_notification_thread_command(&cmd
);
403 cmd
.type
= NOTIFICATION_COMMAND_TYPE_QUIT
;
404 ret
= run_command_wait(handle
, &cmd
);
405 LTTNG_ASSERT(!ret
&& cmd
.reply_code
== LTTNG_OK
);
408 int notification_thread_client_communication_update(
409 struct notification_thread_handle
*handle
,
410 notification_client_id id
,
411 enum client_transmission_status transmission_status
)
413 struct notification_thread_command cmd
= {};
415 init_notification_thread_command(&cmd
);
417 cmd
.type
= NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE
;
418 cmd
.parameters
.client_communication_update
.id
= id
;
419 cmd
.parameters
.client_communication_update
.status
= transmission_status
;
420 return run_command_no_wait(handle
, &cmd
);
423 enum lttng_error_code
424 notification_thread_command_get_trigger(struct notification_thread_handle
*handle
,
425 const struct lttng_trigger
*trigger
,
426 struct lttng_trigger
**real_trigger
)
429 enum lttng_error_code ret_code
;
430 struct notification_thread_command cmd
= {};
432 init_notification_thread_command(&cmd
);
434 cmd
.type
= NOTIFICATION_COMMAND_TYPE_GET_TRIGGER
;
435 cmd
.parameters
.get_trigger
.trigger
= trigger
;
436 ret
= run_command_wait(handle
, &cmd
);
438 ret_code
= LTTNG_ERR_UNK
;
442 ret_code
= cmd
.reply_code
;
443 *real_trigger
= cmd
.reply
.get_trigger
.trigger
;
450 * Takes ownership of the payload if present.
452 struct lttng_event_notifier_notification
*lttng_event_notifier_notification_create(
453 uint64_t tracer_token
, enum lttng_domain_type domain
, char *payload
, size_t payload_size
)
455 struct lttng_event_notifier_notification
*notification
= NULL
;
457 LTTNG_ASSERT(domain
!= LTTNG_DOMAIN_NONE
);
458 LTTNG_ASSERT((payload
&& payload_size
) || (!payload
&& !payload_size
));
460 notification
= zmalloc
<lttng_event_notifier_notification
>();
461 if (notification
== NULL
) {
462 ERR("Error allocating notification");
466 notification
->tracer_token
= tracer_token
;
467 notification
->type
= domain
;
468 notification
->capture_buffer
= payload
;
469 notification
->capture_buf_size
= payload_size
;
475 void lttng_event_notifier_notification_destroy(
476 struct lttng_event_notifier_notification
*notification
)
482 free(notification
->capture_buffer
);