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>
13 #include <common/macros.h>
19 void init_notification_thread_command(struct notification_thread_command
*cmd
)
21 CDS_INIT_LIST_HEAD(&cmd
->cmd_list_node
);
22 lttng_waiter_init(&cmd
->reply_waiter
);
26 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
,
35 &handle
->cmd_queue
.list
);
37 ret
= lttng_write(lttng_pipe_get_writefd(handle
->cmd_queue
.event_pipe
),
38 ¬ification_counter
, sizeof(notification_counter
));
39 if (ret
!= sizeof(notification_counter
)) {
40 PERROR("write to notification thread's queue event fd");
42 * Remove the command from the list so the notification
43 * thread does not process it.
45 cds_list_del(&cmd
->cmd_list_node
);
46 goto error_unlock_queue
;
48 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
50 lttng_waiter_wait(&cmd
->reply_waiter
);
53 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
58 struct notification_thread_command
*notification_thread_command_copy(
59 const struct notification_thread_command
*original_cmd
)
61 struct notification_thread_command
*new_cmd
;
63 new_cmd
= zmalloc(sizeof(*new_cmd
));
68 *new_cmd
= *original_cmd
;
69 init_notification_thread_command(new_cmd
);
75 int run_command_no_wait(struct notification_thread_handle
*handle
,
76 const struct notification_thread_command
*in_cmd
)
79 uint64_t notification_counter
= 1;
80 struct notification_thread_command
*new_cmd
=
81 notification_thread_command_copy(in_cmd
);
86 new_cmd
->is_async
= true;
88 pthread_mutex_lock(&handle
->cmd_queue
.lock
);
90 cds_list_add_tail(&new_cmd
->cmd_list_node
,
91 &handle
->cmd_queue
.list
);
93 ret
= lttng_write(lttng_pipe_get_writefd(handle
->cmd_queue
.event_pipe
),
94 ¬ification_counter
, sizeof(notification_counter
));
95 if (ret
!= sizeof(notification_counter
)) {
96 PERROR("write to notification thread's queue event fd");
98 * Remove the command from the list so the notification
99 * thread does not process it.
101 cds_list_del(&new_cmd
->cmd_list_node
);
102 goto error_unlock_queue
;
104 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
108 pthread_mutex_unlock(&handle
->cmd_queue
.lock
);
113 enum lttng_error_code
notification_thread_command_register_trigger(
114 struct notification_thread_handle
*handle
,
115 struct lttng_trigger
*trigger
)
118 enum lttng_error_code ret_code
;
119 struct notification_thread_command cmd
= {};
121 init_notification_thread_command(&cmd
);
123 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER
;
124 cmd
.parameters
.trigger
= trigger
;
126 ret
= run_command_wait(handle
, &cmd
);
128 ret_code
= LTTNG_ERR_UNK
;
131 ret_code
= cmd
.reply_code
;
136 enum lttng_error_code
notification_thread_command_unregister_trigger(
137 struct notification_thread_handle
*handle
,
138 struct lttng_trigger
*trigger
)
141 enum lttng_error_code ret_code
;
142 struct notification_thread_command cmd
= {};
144 init_notification_thread_command(&cmd
);
146 cmd
.type
= NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER
;
147 cmd
.parameters
.trigger
= trigger
;
149 ret
= run_command_wait(handle
, &cmd
);
151 ret_code
= LTTNG_ERR_UNK
;
154 ret_code
= cmd
.reply_code
;
159 enum lttng_error_code
notification_thread_command_add_channel(
160 struct notification_thread_handle
*handle
,
161 char *session_name
, uid_t uid
, gid_t gid
,
162 char *channel_name
, uint64_t key
,
163 enum lttng_domain_type domain
, uint64_t capacity
)
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_CHANNEL
;
172 cmd
.parameters
.add_channel
.session
.name
= session_name
;
173 cmd
.parameters
.add_channel
.session
.uid
= uid
;
174 cmd
.parameters
.add_channel
.session
.gid
= gid
;
175 cmd
.parameters
.add_channel
.channel
.name
= channel_name
;
176 cmd
.parameters
.add_channel
.channel
.key
= key
;
177 cmd
.parameters
.add_channel
.channel
.domain
= domain
;
178 cmd
.parameters
.add_channel
.channel
.capacity
= capacity
;
180 ret
= run_command_wait(handle
, &cmd
);
182 ret_code
= LTTNG_ERR_UNK
;
185 ret_code
= cmd
.reply_code
;
190 enum lttng_error_code
notification_thread_command_remove_channel(
191 struct notification_thread_handle
*handle
,
192 uint64_t key
, enum lttng_domain_type domain
)
195 enum lttng_error_code ret_code
;
196 struct notification_thread_command cmd
= {};
198 init_notification_thread_command(&cmd
);
200 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL
;
201 cmd
.parameters
.remove_channel
.key
= key
;
202 cmd
.parameters
.remove_channel
.domain
= domain
;
204 ret
= run_command_wait(handle
, &cmd
);
206 ret_code
= LTTNG_ERR_UNK
;
209 ret_code
= cmd
.reply_code
;
214 enum lttng_error_code
notification_thread_command_session_rotation_ongoing(
215 struct notification_thread_handle
*handle
,
216 const char *session_name
, uid_t uid
, gid_t gid
,
217 uint64_t trace_archive_chunk_id
)
220 enum lttng_error_code ret_code
;
221 struct notification_thread_command cmd
= {};
223 init_notification_thread_command(&cmd
);
225 cmd
.type
= NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING
;
226 cmd
.parameters
.session_rotation
.session_name
= session_name
;
227 cmd
.parameters
.session_rotation
.uid
= uid
;
228 cmd
.parameters
.session_rotation
.gid
= gid
;
229 cmd
.parameters
.session_rotation
.trace_archive_chunk_id
=
230 trace_archive_chunk_id
;
232 ret
= run_command_wait(handle
, &cmd
);
234 ret_code
= LTTNG_ERR_UNK
;
237 ret_code
= cmd
.reply_code
;
242 enum lttng_error_code
notification_thread_command_session_rotation_completed(
243 struct notification_thread_handle
*handle
,
244 const char *session_name
, uid_t uid
, gid_t gid
,
245 uint64_t trace_archive_chunk_id
,
246 struct lttng_trace_archive_location
*location
)
249 enum lttng_error_code ret_code
;
250 struct notification_thread_command cmd
= {};
252 init_notification_thread_command(&cmd
);
254 cmd
.type
= NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED
;
255 cmd
.parameters
.session_rotation
.session_name
= session_name
;
256 cmd
.parameters
.session_rotation
.uid
= uid
;
257 cmd
.parameters
.session_rotation
.gid
= gid
;
258 cmd
.parameters
.session_rotation
.trace_archive_chunk_id
=
259 trace_archive_chunk_id
;
260 cmd
.parameters
.session_rotation
.location
= location
;
262 ret
= run_command_wait(handle
, &cmd
);
264 ret_code
= LTTNG_ERR_UNK
;
267 ret_code
= cmd
.reply_code
;
272 enum lttng_error_code
notification_thread_command_add_application(
273 struct notification_thread_handle
*handle
,
274 struct lttng_pipe
*pipe
)
277 enum lttng_error_code ret_code
;
278 struct notification_thread_command cmd
= {};
280 init_notification_thread_command(&cmd
);
282 cmd
.type
= NOTIFICATION_COMMAND_TYPE_ADD_APPLICATION
;
283 cmd
.parameters
.application
.read_side_trigger_event_application_pipe
= lttng_pipe_get_readfd(pipe
);
285 ret
= run_command_wait(handle
, &cmd
);
287 ret_code
= LTTNG_ERR_UNK
;
290 ret_code
= cmd
.reply_code
;
295 enum lttng_error_code
notification_thread_command_remove_application(
296 struct notification_thread_handle
*handle
,
297 struct lttng_pipe
*pipe
)
300 enum lttng_error_code ret_code
;
301 struct notification_thread_command cmd
= {};
303 init_notification_thread_command(&cmd
);
305 cmd
.type
= NOTIFICATION_COMMAND_TYPE_REMOVE_APPLICATION
;
306 cmd
.parameters
.application
.read_side_trigger_event_application_pipe
= lttng_pipe_get_readfd(pipe
);
308 ret
= run_command_wait(handle
, &cmd
);
310 ret_code
= LTTNG_ERR_UNK
;
313 ret_code
= cmd
.reply_code
;
318 enum lttng_error_code
notification_thread_command_get_tokens(
319 struct notification_thread_handle
*handle
,
320 struct lttng_triggers
**tokens_triggers
)
323 enum lttng_error_code ret_code
;
324 struct notification_thread_command cmd
= {};
327 assert(tokens_triggers
);
329 init_notification_thread_command(&cmd
);
331 cmd
.type
= NOTIFICATION_COMMAND_TYPE_GET_TOKENS
;
333 ret
= run_command_wait(handle
, &cmd
);
335 ret_code
= LTTNG_ERR_UNK
;
338 ret_code
= cmd
.reply_code
;
339 *tokens_triggers
= cmd
.reply
.get_tokens
.triggers
;
345 enum lttng_error_code
notification_thread_command_list_triggers(
346 struct notification_thread_handle
*handle
,
349 struct lttng_triggers
**triggers
)
352 enum lttng_error_code ret_code
;
353 struct notification_thread_command cmd
= {};
358 init_notification_thread_command(&cmd
);
360 cmd
.type
= NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS
;
361 cmd
.parameters
.list_triggers
.uid
= uid
;
362 cmd
.parameters
.list_triggers
.gid
= gid
;
364 ret
= run_command_wait(handle
, &cmd
);
366 ret_code
= LTTNG_ERR_UNK
;
369 ret_code
= cmd
.reply_code
;
370 *triggers
= cmd
.reply
.list_triggers
.triggers
;
376 void notification_thread_command_quit(
377 struct notification_thread_handle
*handle
)
380 struct notification_thread_command cmd
= {};
382 init_notification_thread_command(&cmd
);
384 cmd
.type
= NOTIFICATION_COMMAND_TYPE_QUIT
;
385 ret
= run_command_wait(handle
, &cmd
);
386 assert(!ret
&& cmd
.reply_code
== LTTNG_OK
);
389 int notification_thread_client_communication_update(
390 struct notification_thread_handle
*handle
,
391 notification_client_id id
,
392 enum client_transmission_status transmission_status
)
394 struct notification_thread_command cmd
= {};
396 init_notification_thread_command(&cmd
);
398 cmd
.type
= NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE
;
399 cmd
.parameters
.client_communication_update
.id
= id
;
400 cmd
.parameters
.client_communication_update
.status
= transmission_status
;
401 return run_command_no_wait(handle
, &cmd
);
405 * Takes ownership of the payload if present.
408 struct lttng_trigger_notification
*lttng_trigger_notification_create(
410 enum lttng_domain_type domain
,
414 struct lttng_trigger_notification
*notification
= NULL
;
416 assert(domain
!= LTTNG_DOMAIN_NONE
);
419 assert(payload_size
> 0);
421 assert(payload_size
== 0);
424 notification
= zmalloc(sizeof(struct lttng_trigger_notification
));
425 if (notification
== NULL
) {
426 ERR("[notification-thread] Error allocating notification ");
430 notification
->id
= id
;
431 notification
->type
= domain
;
432 notification
->capture_buffer
= payload
;
433 notification
->capture_buf_size
= payload_size
;
440 void lttng_trigger_notification_destroy(
441 struct lttng_trigger_notification
*notification
)
447 if(notification
->capture_buffer
) {
448 free(notification
->capture_buffer
);