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.h"
11 #include "notification-thread-commands.h"
12 #include <common/error.h>
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(lttng_pipe_get_writefd(handle
->cmd_queue
.event_pipe
),
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(sizeof(*new_cmd
));
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(lttng_pipe_get_writefd(handle
->cmd_queue
.event_pipe
),
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
)
117 enum lttng_error_code ret_code
;
118 struct notification_thread_command cmd
= {};
120 init_notification_thread_command(&cmd
);
122 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER
;
123 cmd
.parameters
.trigger
= trigger
;
125 ret
= run_command_wait(handle
, &cmd
);
127 ret_code
= LTTNG_ERR_UNK
;
130 ret_code
= cmd
.reply_code
;
135 enum lttng_error_code
notification_thread_command_unregister_trigger(
136 struct notification_thread_handle
*handle
,
137 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
.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
notification_thread_command_add_channel(
159 struct notification_thread_handle
*handle
,
160 char *session_name
, uid_t uid
, gid_t gid
,
161 char *channel_name
, uint64_t key
,
162 enum lttng_domain_type domain
, uint64_t capacity
)
165 enum lttng_error_code ret_code
;
166 struct notification_thread_command cmd
= {};
168 init_notification_thread_command(&cmd
);
170 cmd
.type
= NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL
;
171 cmd
.parameters
.add_channel
.session
.name
= session_name
;
172 cmd
.parameters
.add_channel
.session
.uid
= uid
;
173 cmd
.parameters
.add_channel
.session
.gid
= gid
;
174 cmd
.parameters
.add_channel
.channel
.name
= channel_name
;
175 cmd
.parameters
.add_channel
.channel
.key
= key
;
176 cmd
.parameters
.add_channel
.channel
.domain
= domain
;
177 cmd
.parameters
.add_channel
.channel
.capacity
= capacity
;
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_channel(
190 struct notification_thread_handle
*handle
,
191 uint64_t key
, enum lttng_domain_type domain
)
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_CHANNEL
;
200 cmd
.parameters
.remove_channel
.key
= key
;
201 cmd
.parameters
.remove_channel
.domain
= domain
;
203 ret
= run_command_wait(handle
, &cmd
);
205 ret_code
= LTTNG_ERR_UNK
;
208 ret_code
= cmd
.reply_code
;
213 enum lttng_error_code
notification_thread_command_session_rotation_ongoing(
214 struct notification_thread_handle
*handle
,
215 const char *session_name
, uid_t uid
, gid_t gid
,
216 uint64_t trace_archive_chunk_id
)
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_SESSION_ROTATION_ONGOING
;
225 cmd
.parameters
.session_rotation
.session_name
= session_name
;
226 cmd
.parameters
.session_rotation
.uid
= uid
;
227 cmd
.parameters
.session_rotation
.gid
= gid
;
228 cmd
.parameters
.session_rotation
.trace_archive_chunk_id
=
229 trace_archive_chunk_id
;
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_session_rotation_completed(
242 struct notification_thread_handle
*handle
,
243 const char *session_name
, uid_t uid
, gid_t gid
,
244 uint64_t trace_archive_chunk_id
,
245 struct lttng_trace_archive_location
*location
)
248 enum lttng_error_code ret_code
;
249 struct notification_thread_command cmd
= {};
251 init_notification_thread_command(&cmd
);
253 cmd
.type
= NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED
;
254 cmd
.parameters
.session_rotation
.session_name
= session_name
;
255 cmd
.parameters
.session_rotation
.uid
= uid
;
256 cmd
.parameters
.session_rotation
.gid
= gid
;
257 cmd
.parameters
.session_rotation
.trace_archive_chunk_id
=
258 trace_archive_chunk_id
;
259 cmd
.parameters
.session_rotation
.location
= location
;
261 ret
= run_command_wait(handle
, &cmd
);
263 ret_code
= LTTNG_ERR_UNK
;
266 ret_code
= cmd
.reply_code
;
271 enum lttng_error_code
notification_thread_command_add_application(
272 struct notification_thread_handle
*handle
,
274 enum lttng_domain_type domain
)
277 enum lttng_error_code ret_code
;
278 struct notification_thread_command cmd
= {};
282 init_notification_thread_command(&cmd
);
284 cmd
.type
= NOTIFICATION_COMMAND_TYPE_ADD_APPLICATION
;
285 cmd
.parameters
.application
.read_side_trigger_event_application_pipe
= fd
;
286 cmd
.parameters
.application
.domain
= domain
;
288 ret
= run_command_wait(handle
, &cmd
);
290 ret_code
= LTTNG_ERR_UNK
;
293 ret_code
= cmd
.reply_code
;
298 enum lttng_error_code
notification_thread_command_remove_application(
299 struct notification_thread_handle
*handle
,
303 enum lttng_error_code ret_code
;
304 struct notification_thread_command cmd
= {};
306 init_notification_thread_command(&cmd
);
308 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_APPLICATION
;
309 cmd
.parameters
.application
.read_side_trigger_event_application_pipe
= fd
;
311 ret
= run_command_wait(handle
, &cmd
);
313 ret_code
= LTTNG_ERR_UNK
;
316 ret_code
= cmd
.reply_code
;
321 enum lttng_error_code
notification_thread_command_get_tokens(
322 struct notification_thread_handle
*handle
,
323 struct lttng_triggers
**tokens_triggers
)
326 enum lttng_error_code ret_code
;
327 struct notification_thread_command cmd
= {};
330 assert(tokens_triggers
);
332 init_notification_thread_command(&cmd
);
334 cmd
.type
= NOTIFICATION_COMMAND_TYPE_GET_TOKENS
;
336 ret
= run_command_wait(handle
, &cmd
);
338 ret_code
= LTTNG_ERR_UNK
;
341 ret_code
= cmd
.reply_code
;
342 *tokens_triggers
= cmd
.reply
.get_tokens
.triggers
;
348 enum lttng_error_code
notification_thread_command_list_triggers(
349 struct notification_thread_handle
*handle
,
351 struct lttng_triggers
**triggers
)
354 enum lttng_error_code ret_code
;
355 struct notification_thread_command cmd
= {};
360 init_notification_thread_command(&cmd
);
362 cmd
.type
= NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS
;
363 cmd
.parameters
.list_triggers
.uid
= uid
;
365 ret
= run_command_wait(handle
, &cmd
);
367 ret_code
= LTTNG_ERR_UNK
;
370 ret_code
= cmd
.reply_code
;
371 *triggers
= cmd
.reply
.list_triggers
.triggers
;
377 void notification_thread_command_quit(
378 struct notification_thread_handle
*handle
)
381 struct notification_thread_command cmd
= {};
383 init_notification_thread_command(&cmd
);
385 cmd
.type
= NOTIFICATION_COMMAND_TYPE_QUIT
;
386 ret
= run_command_wait(handle
, &cmd
);
387 assert(!ret
&& cmd
.reply_code
== LTTNG_OK
);
390 int notification_thread_client_communication_update(
391 struct notification_thread_handle
*handle
,
392 notification_client_id id
,
393 enum client_transmission_status transmission_status
)
395 struct notification_thread_command cmd
= {};
397 init_notification_thread_command(&cmd
);
399 cmd
.type
= NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE
;
400 cmd
.parameters
.client_communication_update
.id
= id
;
401 cmd
.parameters
.client_communication_update
.status
= transmission_status
;
402 return run_command_no_wait(handle
, &cmd
);
406 * Takes ownership of the payload if present.
409 struct lttng_trigger_notification
*lttng_trigger_notification_create(
411 enum lttng_domain_type domain
,
415 struct lttng_trigger_notification
*notification
= NULL
;
417 assert(domain
!= LTTNG_DOMAIN_NONE
);
420 assert(payload_size
> 0);
422 assert(payload_size
== 0);
425 notification
= zmalloc(sizeof(struct lttng_trigger_notification
));
426 if (notification
== NULL
) {
427 ERR("[notification-thread] Error allocating notification ");
431 notification
->id
= id
;
432 notification
->type
= domain
;
433 notification
->capture_buffer
= payload
;
434 notification
->capture_buf_size
= payload_size
;
441 void lttng_trigger_notification_destroy(
442 struct lttng_trigger_notification
*notification
)
448 if(notification
->capture_buffer
) {
449 free(notification
->capture_buffer
);