Commit | Line | Data |
---|---|---|
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 | ||
c9e313bc | 8 | #include "notification-thread-commands.hpp" |
28ab034a JG |
9 | #include "notification-thread.hpp" |
10 | ||
c9e313bc | 11 | #include <common/error.hpp> |
28ab034a JG |
12 | |
13 | #include <lttng/lttng-error.h> | |
14 | #include <lttng/trigger/trigger.h> | |
15 | ||
ab0ee2ca | 16 | #include <inttypes.h> |
28ab034a JG |
17 | #include <stdint.h> |
18 | #include <unistd.h> | |
ab0ee2ca | 19 | |
28ab034a | 20 | static void init_notification_thread_command(struct notification_thread_command *cmd) |
ab0ee2ca | 21 | { |
ab0ee2ca JG |
22 | CDS_INIT_LIST_HEAD(&cmd->cmd_list_node); |
23 | } | |
24 | ||
28ab034a JG |
25 | static int run_command_wait(struct notification_thread_handle *handle, |
26 | struct notification_thread_command *cmd) | |
ab0ee2ca JG |
27 | { |
28 | int ret; | |
29 | uint64_t notification_counter = 1; | |
30 | ||
32670d71 JG |
31 | lttng::synchro::waiter command_completion_waiter; |
32 | cmd->command_completed_waker.emplace(command_completion_waiter.get_waker()); | |
33 | ||
ab0ee2ca JG |
34 | pthread_mutex_lock(&handle->cmd_queue.lock); |
35 | /* Add to queue. */ | |
28ab034a | 36 | cds_list_add_tail(&cmd->cmd_list_node, &handle->cmd_queue.list); |
ab0ee2ca | 37 | /* Wake-up thread. */ |
28ab034a JG |
38 | ret = lttng_write( |
39 | handle->cmd_queue.event_fd, ¬ification_counter, sizeof(notification_counter)); | |
58d3fed5 | 40 | if (ret != sizeof(notification_counter)) { |
ab0ee2ca JG |
41 | PERROR("write to notification thread's queue event fd"); |
42 | /* | |
43 | * Remove the command from the list so the notification | |
44 | * thread does not process it. | |
45 | */ | |
46 | cds_list_del(&cmd->cmd_list_node); | |
47 | goto error_unlock_queue; | |
48 | } | |
49 | pthread_mutex_unlock(&handle->cmd_queue.lock); | |
50 | ||
32670d71 | 51 | command_completion_waiter.wait();; |
ab0ee2ca JG |
52 | return 0; |
53 | error_unlock_queue: | |
54 | pthread_mutex_unlock(&handle->cmd_queue.lock); | |
55 | return -1; | |
56 | } | |
57 | ||
28ab034a JG |
58 | static struct notification_thread_command * |
59 | notification_thread_command_copy(const struct notification_thread_command *original_cmd) | |
0ab399e0 JG |
60 | { |
61 | struct notification_thread_command *new_cmd; | |
62 | ||
32670d71 JG |
63 | try { |
64 | new_cmd = new notification_thread_command; | |
65 | } catch (const std::bad_alloc &e) { | |
66 | ERR("Failed to allocate notification_thread_command: %s", e.what()); | |
67 | return nullptr; | |
0ab399e0 JG |
68 | } |
69 | ||
70 | *new_cmd = *original_cmd; | |
71 | init_notification_thread_command(new_cmd); | |
0ab399e0 JG |
72 | return new_cmd; |
73 | } | |
74 | ||
28ab034a JG |
75 | static int run_command_no_wait(struct notification_thread_handle *handle, |
76 | const struct notification_thread_command *in_cmd) | |
0ab399e0 JG |
77 | { |
78 | int ret; | |
79 | uint64_t notification_counter = 1; | |
28ab034a | 80 | struct notification_thread_command *new_cmd = notification_thread_command_copy(in_cmd); |
0ab399e0 JG |
81 | |
82 | if (!new_cmd) { | |
83 | goto error; | |
84 | } | |
85 | new_cmd->is_async = true; | |
86 | ||
87 | pthread_mutex_lock(&handle->cmd_queue.lock); | |
88 | /* Add to queue. */ | |
28ab034a | 89 | cds_list_add_tail(&new_cmd->cmd_list_node, &handle->cmd_queue.list); |
0ab399e0 | 90 | /* Wake-up thread. */ |
28ab034a JG |
91 | ret = lttng_write( |
92 | handle->cmd_queue.event_fd, ¬ification_counter, sizeof(notification_counter)); | |
0ab399e0 JG |
93 | if (ret != sizeof(notification_counter)) { |
94 | PERROR("write to notification thread's queue event fd"); | |
95 | /* | |
96 | * Remove the command from the list so the notification | |
97 | * thread does not process it. | |
98 | */ | |
99 | cds_list_del(&new_cmd->cmd_list_node); | |
100 | goto error_unlock_queue; | |
101 | } | |
32670d71 | 102 | |
0ab399e0 JG |
103 | pthread_mutex_unlock(&handle->cmd_queue.lock); |
104 | return 0; | |
105 | error_unlock_queue: | |
32670d71 JG |
106 | |
107 | delete new_cmd; | |
0ab399e0 JG |
108 | pthread_mutex_unlock(&handle->cmd_queue.lock); |
109 | error: | |
110 | return -1; | |
111 | } | |
112 | ||
28ab034a JG |
113 | enum lttng_error_code |
114 | notification_thread_command_register_trigger(struct notification_thread_handle *handle, | |
115 | struct lttng_trigger *trigger, | |
116 | bool is_trigger_anonymous) | |
ab0ee2ca JG |
117 | { |
118 | int ret; | |
119 | enum lttng_error_code ret_code; | |
32670d71 | 120 | notification_thread_command cmd; |
ab0ee2ca | 121 | |
a0377dfe | 122 | LTTNG_ASSERT(trigger); |
ab0ee2ca JG |
123 | init_notification_thread_command(&cmd); |
124 | ||
125 | cmd.type = NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER; | |
242388e4 | 126 | lttng_trigger_get(trigger); |
ac16173e | 127 | cmd.parameters.register_trigger.trigger = trigger; |
28ab034a | 128 | cmd.parameters.register_trigger.is_trigger_anonymous = is_trigger_anonymous; |
ab0ee2ca JG |
129 | |
130 | ret = run_command_wait(handle, &cmd); | |
131 | if (ret) { | |
132 | ret_code = LTTNG_ERR_UNK; | |
133 | goto end; | |
134 | } | |
135 | ret_code = cmd.reply_code; | |
136 | end: | |
137 | return ret_code; | |
138 | } | |
139 | ||
28ab034a JG |
140 | enum lttng_error_code |
141 | notification_thread_command_unregister_trigger(struct notification_thread_handle *handle, | |
142 | const struct lttng_trigger *trigger) | |
ab0ee2ca JG |
143 | { |
144 | int ret; | |
145 | enum lttng_error_code ret_code; | |
32670d71 | 146 | notification_thread_command cmd; |
ab0ee2ca JG |
147 | |
148 | init_notification_thread_command(&cmd); | |
149 | ||
150 | cmd.type = NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER; | |
ac16173e | 151 | cmd.parameters.unregister_trigger.trigger = trigger; |
ab0ee2ca JG |
152 | |
153 | ret = run_command_wait(handle, &cmd); | |
154 | if (ret) { | |
155 | ret_code = LTTNG_ERR_UNK; | |
156 | goto end; | |
157 | } | |
158 | ret_code = cmd.reply_code; | |
159 | end: | |
160 | return ret_code; | |
161 | } | |
162 | ||
28ab034a JG |
163 | enum lttng_error_code |
164 | notification_thread_command_add_session(struct notification_thread_handle *handle, | |
165 | uint64_t session_id, | |
166 | const char *session_name, | |
167 | uid_t session_uid, | |
168 | gid_t session_gid) | |
139a8d25 JG |
169 | { |
170 | int ret; | |
171 | enum lttng_error_code ret_code; | |
32670d71 | 172 | notification_thread_command cmd; |
139a8d25 JG |
173 | |
174 | init_notification_thread_command(&cmd); | |
175 | ||
176 | cmd.type = NOTIFICATION_COMMAND_TYPE_ADD_SESSION; | |
177 | cmd.parameters.add_session.session_id = session_id; | |
178 | cmd.parameters.add_session.session_name = session_name; | |
179 | cmd.parameters.add_session.session_uid = session_uid; | |
180 | cmd.parameters.add_session.session_gid = session_gid; | |
181 | ||
182 | ret = run_command_wait(handle, &cmd); | |
183 | if (ret) { | |
184 | ret_code = LTTNG_ERR_UNK; | |
185 | goto end; | |
186 | } | |
187 | ret_code = cmd.reply_code; | |
188 | end: | |
189 | return ret_code; | |
190 | } | |
191 | ||
28ab034a JG |
192 | enum lttng_error_code |
193 | notification_thread_command_remove_session(struct notification_thread_handle *handle, | |
194 | uint64_t session_id) | |
139a8d25 JG |
195 | { |
196 | int ret; | |
197 | enum lttng_error_code ret_code; | |
32670d71 | 198 | notification_thread_command cmd; |
139a8d25 JG |
199 | |
200 | init_notification_thread_command(&cmd); | |
201 | ||
202 | cmd.type = NOTIFICATION_COMMAND_TYPE_REMOVE_SESSION; | |
203 | cmd.parameters.remove_session.session_id = session_id; | |
204 | ||
205 | ret = run_command_wait(handle, &cmd); | |
206 | if (ret) { | |
207 | ret_code = LTTNG_ERR_UNK; | |
208 | goto end; | |
209 | } | |
210 | ret_code = cmd.reply_code; | |
211 | end: | |
212 | return ret_code; | |
213 | } | |
214 | ||
28ab034a JG |
215 | enum lttng_error_code |
216 | notification_thread_command_add_channel(struct notification_thread_handle *handle, | |
217 | uint64_t session_id, | |
218 | char *channel_name, | |
219 | uint64_t key, | |
220 | enum lttng_domain_type domain, | |
221 | uint64_t capacity) | |
ab0ee2ca JG |
222 | { |
223 | int ret; | |
224 | enum lttng_error_code ret_code; | |
32670d71 | 225 | notification_thread_command cmd; |
ab0ee2ca JG |
226 | |
227 | init_notification_thread_command(&cmd); | |
228 | ||
229 | cmd.type = NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL; | |
139a8d25 | 230 | cmd.parameters.add_channel.session.id = session_id; |
8abe313a JG |
231 | cmd.parameters.add_channel.channel.name = channel_name; |
232 | cmd.parameters.add_channel.channel.key = key; | |
233 | cmd.parameters.add_channel.channel.domain = domain; | |
234 | cmd.parameters.add_channel.channel.capacity = capacity; | |
ab0ee2ca JG |
235 | |
236 | ret = run_command_wait(handle, &cmd); | |
237 | if (ret) { | |
238 | ret_code = LTTNG_ERR_UNK; | |
239 | goto end; | |
240 | } | |
241 | ret_code = cmd.reply_code; | |
242 | end: | |
243 | return ret_code; | |
244 | } | |
245 | ||
246 | enum lttng_error_code notification_thread_command_remove_channel( | |
28ab034a | 247 | struct notification_thread_handle *handle, uint64_t key, enum lttng_domain_type domain) |
ab0ee2ca JG |
248 | { |
249 | int ret; | |
250 | enum lttng_error_code ret_code; | |
32670d71 | 251 | notification_thread_command cmd; |
ab0ee2ca JG |
252 | |
253 | init_notification_thread_command(&cmd); | |
254 | ||
255 | cmd.type = NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL; | |
256 | cmd.parameters.remove_channel.key = key; | |
257 | cmd.parameters.remove_channel.domain = domain; | |
258 | ||
259 | ret = run_command_wait(handle, &cmd); | |
260 | if (ret) { | |
261 | ret_code = LTTNG_ERR_UNK; | |
262 | goto end; | |
263 | } | |
264 | ret_code = cmd.reply_code; | |
265 | end: | |
266 | return ret_code; | |
267 | } | |
268 | ||
28ab034a JG |
269 | enum lttng_error_code |
270 | notification_thread_command_session_rotation_ongoing(struct notification_thread_handle *handle, | |
271 | uint64_t session_id, | |
272 | uint64_t trace_archive_chunk_id) | |
731c1b12 JG |
273 | { |
274 | int ret; | |
275 | enum lttng_error_code ret_code; | |
32670d71 | 276 | notification_thread_command cmd; |
731c1b12 JG |
277 | |
278 | init_notification_thread_command(&cmd); | |
279 | ||
280 | cmd.type = NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING; | |
139a8d25 | 281 | cmd.parameters.session_rotation.session_id = session_id; |
28ab034a | 282 | cmd.parameters.session_rotation.trace_archive_chunk_id = trace_archive_chunk_id; |
731c1b12 JG |
283 | |
284 | ret = run_command_wait(handle, &cmd); | |
285 | if (ret) { | |
286 | ret_code = LTTNG_ERR_UNK; | |
287 | goto end; | |
288 | } | |
289 | ret_code = cmd.reply_code; | |
290 | end: | |
291 | return ret_code; | |
292 | } | |
293 | ||
294 | enum lttng_error_code notification_thread_command_session_rotation_completed( | |
28ab034a JG |
295 | struct notification_thread_handle *handle, |
296 | uint64_t session_id, | |
297 | uint64_t trace_archive_chunk_id, | |
298 | struct lttng_trace_archive_location *location) | |
731c1b12 JG |
299 | { |
300 | int ret; | |
301 | enum lttng_error_code ret_code; | |
32670d71 | 302 | notification_thread_command cmd; |
731c1b12 JG |
303 | |
304 | init_notification_thread_command(&cmd); | |
305 | ||
306 | cmd.type = NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED; | |
139a8d25 | 307 | cmd.parameters.session_rotation.session_id = session_id; |
28ab034a | 308 | cmd.parameters.session_rotation.trace_archive_chunk_id = trace_archive_chunk_id; |
731c1b12 JG |
309 | cmd.parameters.session_rotation.location = location; |
310 | ||
311 | ret = run_command_wait(handle, &cmd); | |
312 | if (ret) { | |
313 | ret_code = LTTNG_ERR_UNK; | |
314 | goto end; | |
315 | } | |
316 | ret_code = cmd.reply_code; | |
317 | end: | |
318 | return ret_code; | |
319 | } | |
320 | ||
28ab034a JG |
321 | enum lttng_error_code |
322 | notification_thread_command_add_tracer_event_source(struct notification_thread_handle *handle, | |
323 | int tracer_event_source_fd, | |
324 | enum lttng_domain_type domain) | |
d02d7404 JR |
325 | { |
326 | int ret; | |
327 | enum lttng_error_code ret_code; | |
32670d71 | 328 | notification_thread_command cmd; |
d02d7404 | 329 | |
a0377dfe | 330 | LTTNG_ASSERT(tracer_event_source_fd >= 0); |
d02d7404 JR |
331 | |
332 | init_notification_thread_command(&cmd); | |
333 | ||
334 | cmd.type = NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE; | |
28ab034a | 335 | cmd.parameters.tracer_event_source.tracer_event_source_fd = tracer_event_source_fd; |
d02d7404 JR |
336 | cmd.parameters.tracer_event_source.domain = domain; |
337 | ||
338 | ret = run_command_wait(handle, &cmd); | |
339 | if (ret) { | |
340 | ret_code = LTTNG_ERR_UNK; | |
341 | goto end; | |
342 | } | |
343 | ||
344 | ret_code = cmd.reply_code; | |
345 | end: | |
346 | return ret_code; | |
347 | } | |
348 | ||
28ab034a JG |
349 | enum lttng_error_code |
350 | notification_thread_command_remove_tracer_event_source(struct notification_thread_handle *handle, | |
351 | int tracer_event_source_fd) | |
d02d7404 JR |
352 | { |
353 | int ret; | |
354 | enum lttng_error_code ret_code; | |
32670d71 | 355 | notification_thread_command cmd; |
d02d7404 JR |
356 | |
357 | init_notification_thread_command(&cmd); | |
358 | ||
359 | cmd.type = NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE; | |
28ab034a | 360 | cmd.parameters.tracer_event_source.tracer_event_source_fd = tracer_event_source_fd; |
d02d7404 JR |
361 | |
362 | ret = run_command_wait(handle, &cmd); | |
363 | if (ret) { | |
364 | ret_code = LTTNG_ERR_UNK; | |
365 | goto end; | |
366 | } | |
367 | ||
368 | ret_code = cmd.reply_code; | |
369 | end: | |
370 | return ret_code; | |
371 | } | |
372 | ||
fbc9f37d | 373 | enum lttng_error_code notification_thread_command_list_triggers( |
28ab034a | 374 | struct notification_thread_handle *handle, uid_t uid, struct lttng_triggers **triggers) |
fbc9f37d JR |
375 | { |
376 | int ret; | |
377 | enum lttng_error_code ret_code; | |
32670d71 | 378 | notification_thread_command cmd; |
fbc9f37d | 379 | |
a0377dfe FD |
380 | LTTNG_ASSERT(handle); |
381 | LTTNG_ASSERT(triggers); | |
fbc9f37d JR |
382 | |
383 | init_notification_thread_command(&cmd); | |
384 | ||
385 | cmd.type = NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS; | |
386 | cmd.parameters.list_triggers.uid = uid; | |
387 | ||
388 | ret = run_command_wait(handle, &cmd); | |
389 | if (ret) { | |
390 | ret_code = LTTNG_ERR_UNK; | |
391 | goto end; | |
392 | } | |
393 | ||
394 | ret_code = cmd.reply_code; | |
395 | *triggers = cmd.reply.list_triggers.triggers; | |
396 | ||
397 | end: | |
398 | return ret_code; | |
399 | } | |
400 | ||
28ab034a | 401 | void notification_thread_command_quit(struct notification_thread_handle *handle) |
ab0ee2ca JG |
402 | { |
403 | int ret; | |
32670d71 | 404 | notification_thread_command cmd; |
ab0ee2ca JG |
405 | |
406 | init_notification_thread_command(&cmd); | |
407 | ||
408 | cmd.type = NOTIFICATION_COMMAND_TYPE_QUIT; | |
409 | ret = run_command_wait(handle, &cmd); | |
a0377dfe | 410 | LTTNG_ASSERT(!ret && cmd.reply_code == LTTNG_OK); |
ab0ee2ca | 411 | } |
f2b3ef9f JG |
412 | |
413 | int notification_thread_client_communication_update( | |
28ab034a JG |
414 | struct notification_thread_handle *handle, |
415 | notification_client_id id, | |
416 | enum client_transmission_status transmission_status) | |
f2b3ef9f | 417 | { |
32670d71 | 418 | notification_thread_command cmd; |
f2b3ef9f JG |
419 | |
420 | init_notification_thread_command(&cmd); | |
421 | ||
422 | cmd.type = NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE; | |
423 | cmd.parameters.client_communication_update.id = id; | |
424 | cmd.parameters.client_communication_update.status = transmission_status; | |
425 | return run_command_no_wait(handle, &cmd); | |
426 | } | |
b9a8d78f | 427 | |
28ab034a JG |
428 | enum lttng_error_code |
429 | notification_thread_command_get_trigger(struct notification_thread_handle *handle, | |
430 | const struct lttng_trigger *trigger, | |
431 | struct lttng_trigger **real_trigger) | |
8790759c FD |
432 | { |
433 | int ret; | |
434 | enum lttng_error_code ret_code; | |
32670d71 | 435 | notification_thread_command cmd; |
8790759c FD |
436 | |
437 | init_notification_thread_command(&cmd); | |
438 | ||
439 | cmd.type = NOTIFICATION_COMMAND_TYPE_GET_TRIGGER; | |
440 | cmd.parameters.get_trigger.trigger = trigger; | |
441 | ret = run_command_wait(handle, &cmd); | |
442 | if (ret) { | |
443 | ret_code = LTTNG_ERR_UNK; | |
444 | goto end; | |
445 | } | |
446 | ||
447 | ret_code = cmd.reply_code; | |
448 | *real_trigger = cmd.reply.get_trigger.trigger; | |
449 | ||
450 | end: | |
451 | return ret_code; | |
452 | } | |
453 | ||
82b3cbf4 JR |
454 | /* |
455 | * Takes ownership of the payload if present. | |
456 | */ | |
82b3cbf4 | 457 | struct lttng_event_notifier_notification *lttng_event_notifier_notification_create( |
28ab034a | 458 | uint64_t tracer_token, enum lttng_domain_type domain, char *payload, size_t payload_size) |
b9a8d78f | 459 | { |
cd9adb8b | 460 | struct lttng_event_notifier_notification *notification = nullptr; |
b9a8d78f | 461 | |
a0377dfe FD |
462 | LTTNG_ASSERT(domain != LTTNG_DOMAIN_NONE); |
463 | LTTNG_ASSERT((payload && payload_size) || (!payload && !payload_size)); | |
b9a8d78f | 464 | |
64803277 | 465 | notification = zmalloc<lttng_event_notifier_notification>(); |
cd9adb8b | 466 | if (notification == nullptr) { |
bd0514a5 | 467 | ERR("Error allocating notification"); |
b9a8d78f FD |
468 | goto end; |
469 | } | |
470 | ||
471 | notification->tracer_token = tracer_token; | |
472 | notification->type = domain; | |
82b3cbf4 JR |
473 | notification->capture_buffer = payload; |
474 | notification->capture_buf_size = payload_size; | |
b9a8d78f FD |
475 | |
476 | end: | |
477 | return notification; | |
478 | } | |
479 | ||
b9a8d78f | 480 | void lttng_event_notifier_notification_destroy( |
28ab034a | 481 | struct lttng_event_notifier_notification *notification) |
b9a8d78f FD |
482 | { |
483 | if (!notification) { | |
484 | return; | |
485 | } | |
486 | ||
82b3cbf4 | 487 | free(notification->capture_buffer); |
b9a8d78f FD |
488 | free(notification); |
489 | } |