Fix: consumerd: consumed size miscomputed during statistics sampling
[lttng-tools.git] / src / common / actions / action.cpp
CommitLineData
a58c490f 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
a58c490f 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
a58c490f 5 *
a58c490f
JG
6 */
7
c9e313bc
SM
8#include <common/error.hpp>
9#include <common/mi-lttng.hpp>
28ab034a 10
c9e313bc
SM
11#include <lttng/action/action-internal.hpp>
12#include <lttng/action/list-internal.hpp>
13#include <lttng/action/notify-internal.hpp>
14#include <lttng/action/rate-policy-internal.hpp>
15#include <lttng/action/rotate-session-internal.hpp>
16#include <lttng/action/snapshot-session-internal.hpp>
17#include <lttng/action/start-session-internal.hpp>
18#include <lttng/action/stop-session-internal.hpp>
19#include <lttng/error-query-internal.hpp>
a58c490f 20
10615eee 21const char *lttng_action_type_string(enum lttng_action_type action_type)
2666d352
SM
22{
23 switch (action_type) {
24 case LTTNG_ACTION_TYPE_UNKNOWN:
25 return "UNKNOWN";
7c2fae7c
JG
26 case LTTNG_ACTION_TYPE_LIST:
27 return "LIST";
2666d352
SM
28 case LTTNG_ACTION_TYPE_NOTIFY:
29 return "NOTIFY";
bfb2ec6a
SM
30 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
31 return "ROTATE_SESSION";
757c48a2
SM
32 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
33 return "SNAPSHOT_SESSION";
58397d0d
SM
34 case LTTNG_ACTION_TYPE_START_SESSION:
35 return "START_SESSION";
931bdbaa
SM
36 case LTTNG_ACTION_TYPE_STOP_SESSION:
37 return "STOP_SESSION";
2666d352
SM
38 default:
39 return "???";
40 }
41}
42
17182cfd 43enum lttng_action_type lttng_action_get_type(const struct lttng_action *action)
a58c490f
JG
44{
45 return action ? action->type : LTTNG_ACTION_TYPE_UNKNOWN;
46}
47
2d57482c 48void lttng_action_init(struct lttng_action *action,
28ab034a
JG
49 enum lttng_action_type type,
50 action_validate_cb validate,
51 action_serialize_cb serialize,
52 action_equal_cb equal,
53 action_destroy_cb destroy,
54 action_get_rate_policy_cb get_rate_policy,
55 action_add_error_query_results_cb add_error_query_results,
56 action_mi_serialize_cb mi)
6acb3f46 57{
c852ce4e 58 urcu_ref_init(&action->ref);
6acb3f46
SM
59 action->type = type;
60 action->validate = validate;
61 action->serialize = serialize;
3dd04a6a 62 action->equal = equal;
6acb3f46 63 action->destroy = destroy;
7f4d5b07 64 action->get_rate_policy = get_rate_policy;
588c4b0d 65 action->add_error_query_results = add_error_query_results;
6a751b95 66 action->mi_serialize = mi;
2d57482c
JR
67
68 action->execution_request_counter = 0;
69 action->execution_counter = 0;
70 action->execution_failure_counter = 0;
6acb3f46
SM
71}
72
28ab034a 73static void action_destroy_ref(struct urcu_ref *ref)
c852ce4e 74{
28ab034a 75 struct lttng_action *action = lttng::utils::container_of(ref, &lttng_action::ref);
c852ce4e
JG
76
77 action->destroy(action);
78}
79
c852ce4e
JG
80void lttng_action_get(struct lttng_action *action)
81{
82 urcu_ref_get(&action->ref);
83}
84
c852ce4e 85void lttng_action_put(struct lttng_action *action)
a58c490f
JG
86{
87 if (!action) {
88 return;
89 }
90
a0377dfe 91 LTTNG_ASSERT(action->destroy);
c852ce4e
JG
92 urcu_ref_put(&action->ref, action_destroy_ref);
93}
94
95void lttng_action_destroy(struct lttng_action *action)
96{
97 lttng_action_put(action);
a58c490f
JG
98}
99
a58c490f
JG
100bool lttng_action_validate(struct lttng_action *action)
101{
102 bool valid;
103
104 if (!action) {
105 valid = false;
106 goto end;
107 }
108
109 if (!action->validate) {
110 /* Sub-class guarantees that it can never be invalid. */
111 valid = true;
112 goto end;
113 }
114
115 valid = action->validate(action);
116end:
117 return valid;
118}
119
28ab034a 120int lttng_action_serialize(struct lttng_action *action, struct lttng_payload *payload)
a58c490f 121{
3647288f
JG
122 int ret;
123 struct lttng_action_comm action_comm = {
124 .action_type = (int8_t) action->type,
125 };
126
28ab034a 127 ret = lttng_dynamic_buffer_append(&payload->buffer, &action_comm, sizeof(action_comm));
3647288f 128 if (ret) {
a58c490f
JG
129 goto end;
130 }
131
c0a66c84 132 ret = action->serialize(action, payload);
3647288f 133 if (ret) {
a58c490f
JG
134 goto end;
135 }
a58c490f
JG
136end:
137 return ret;
138}
139
c0a66c84 140ssize_t lttng_action_create_from_payload(struct lttng_payload_view *view,
28ab034a 141 struct lttng_action **action)
a58c490f 142{
869a3c2d 143 ssize_t consumed_len, specific_action_consumed_len;
c0a66c84 144 action_create_from_payload_cb create_from_payload_cb;
3e6e0df2
JG
145 const struct lttng_action_comm *action_comm;
146 const struct lttng_payload_view action_comm_view =
28ab034a 147 lttng_payload_view_from_view(view, 0, sizeof(*action_comm));
a58c490f 148
869a3c2d
SM
149 if (!view || !action) {
150 consumed_len = -1;
a58c490f
JG
151 goto end;
152 }
153
3e6e0df2
JG
154 if (!lttng_payload_view_is_valid(&action_comm_view)) {
155 /* Payload not large enough to contain the header. */
156 consumed_len = -1;
157 goto end;
158 }
159
160 action_comm = (const struct lttng_action_comm *) action_comm_view.buffer.data;
869a3c2d 161
c0a66c84 162 DBG("Create action from payload: action-type=%s",
28ab034a 163 lttng_action_type_string((lttng_action_type) action_comm->action_type));
2666d352 164
a58c490f
JG
165 switch (action_comm->action_type) {
166 case LTTNG_ACTION_TYPE_NOTIFY:
c0a66c84 167 create_from_payload_cb = lttng_action_notify_create_from_payload;
a58c490f 168 break;
bfb2ec6a 169 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
28ab034a 170 create_from_payload_cb = lttng_action_rotate_session_create_from_payload;
bfb2ec6a 171 break;
757c48a2 172 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
28ab034a 173 create_from_payload_cb = lttng_action_snapshot_session_create_from_payload;
757c48a2 174 break;
58397d0d 175 case LTTNG_ACTION_TYPE_START_SESSION:
28ab034a 176 create_from_payload_cb = lttng_action_start_session_create_from_payload;
58397d0d 177 break;
931bdbaa 178 case LTTNG_ACTION_TYPE_STOP_SESSION:
28ab034a 179 create_from_payload_cb = lttng_action_stop_session_create_from_payload;
931bdbaa 180 break;
7c2fae7c 181 case LTTNG_ACTION_TYPE_LIST:
702f26c8 182 create_from_payload_cb = lttng_action_list_create_from_payload;
0c51e8f3 183 break;
a58c490f 184 default:
c0a66c84 185 ERR("Failed to create action from payload, unhandled action type: action-type=%u (%s)",
28ab034a
JG
186 action_comm->action_type,
187 lttng_action_type_string((lttng_action_type) action_comm->action_type));
869a3c2d 188 consumed_len = -1;
a58c490f
JG
189 goto end;
190 }
191
c0a66c84
JG
192 {
193 /* Create buffer view for the action-type-specific data. */
194 struct lttng_payload_view specific_action_view =
28ab034a 195 lttng_payload_view_from_view(view, sizeof(struct lttng_action_comm), -1);
869a3c2d 196
28ab034a
JG
197 specific_action_consumed_len =
198 create_from_payload_cb(&specific_action_view, action);
c0a66c84 199 }
869a3c2d
SM
200 if (specific_action_consumed_len < 0) {
201 ERR("Failed to create specific action from buffer.");
202 consumed_len = -1;
a58c490f
JG
203 goto end;
204 }
869a3c2d 205
a0377dfe 206 LTTNG_ASSERT(*action);
869a3c2d 207
28ab034a 208 consumed_len = sizeof(struct lttng_action_comm) + specific_action_consumed_len;
869a3c2d 209
a58c490f 210end:
869a3c2d 211 return consumed_len;
a58c490f 212}
3dd04a6a 213
28ab034a 214bool lttng_action_is_equal(const struct lttng_action *a, const struct lttng_action *b)
3dd04a6a
JR
215{
216 bool is_equal = false;
217
218 if (!a || !b) {
219 goto end;
220 }
221
222 if (a->type != b->type) {
223 goto end;
224 }
225
226 if (a == b) {
227 is_equal = true;
228 goto end;
229 }
230
a0377dfe 231 LTTNG_ASSERT(a->equal);
3dd04a6a
JR
232 is_equal = a->equal(a, b);
233end:
234 return is_equal;
235}
2d57482c 236
2d57482c
JR
237void lttng_action_increase_execution_request_count(struct lttng_action *action)
238{
239 action->execution_request_counter++;
240}
241
2d57482c
JR
242void lttng_action_increase_execution_count(struct lttng_action *action)
243{
244 action->execution_counter++;
245}
246
2d57482c
JR
247void lttng_action_increase_execution_failure_count(struct lttng_action *action)
248{
588c4b0d 249 uatomic_inc(&action->execution_failure_counter);
2d57482c
JR
250}
251
2d57482c
JR
252bool lttng_action_should_execute(const struct lttng_action *action)
253{
cd9adb8b 254 const struct lttng_rate_policy *policy = nullptr;
2d57482c
JR
255 bool execute = false;
256
cd9adb8b 257 if (action->get_rate_policy == nullptr) {
2d57482c
JR
258 execute = true;
259 goto end;
260 }
261
7f4d5b07 262 policy = action->get_rate_policy(action);
cd9adb8b 263 if (policy == nullptr) {
2d57482c
JR
264 execute = true;
265 goto end;
266 }
267
28ab034a 268 execute = lttng_rate_policy_should_execute(policy, action->execution_request_counter);
2d57482c
JR
269end:
270 return execute;
271}
588c4b0d 272
28ab034a
JG
273enum lttng_action_status
274lttng_action_add_error_query_results(const struct lttng_action *action,
275 struct lttng_error_query_results *results)
588c4b0d
JG
276{
277 return action->add_error_query_results(action, results);
278}
279
28ab034a
JG
280enum lttng_action_status
281lttng_action_generic_add_error_query_results(const struct lttng_action *action,
282 struct lttng_error_query_results *results)
588c4b0d
JG
283{
284 enum lttng_action_status action_status;
cd9adb8b 285 struct lttng_error_query_result *error_counter = nullptr;
28ab034a 286 const uint64_t execution_failure_counter = uatomic_read(&action->execution_failure_counter);
588c4b0d
JG
287
288 error_counter = lttng_error_query_result_counter_create(
28ab034a
JG
289 "total execution failures",
290 "Aggregated count of errors encountered when executing the action",
291 execution_failure_counter);
588c4b0d
JG
292 if (!error_counter) {
293 action_status = LTTNG_ACTION_STATUS_ERROR;
294 goto end;
295 }
296
28ab034a 297 if (lttng_error_query_results_add_result(results, error_counter)) {
588c4b0d
JG
298 action_status = LTTNG_ACTION_STATUS_ERROR;
299 goto end;
300 }
301
302 /* Ownership transferred to the results. */
cd9adb8b 303 error_counter = nullptr;
588c4b0d
JG
304 action_status = LTTNG_ACTION_STATUS_OK;
305end:
306 lttng_error_query_result_destroy(error_counter);
307 return action_status;
308}
6a751b95 309
28ab034a
JG
310enum lttng_error_code
311lttng_action_mi_serialize(const struct lttng_trigger *trigger,
312 const struct lttng_action *action,
313 struct mi_writer *writer,
314 const struct mi_lttng_error_query_callbacks *error_query_callbacks,
315 struct lttng_dynamic_array *action_path_indexes)
6a751b95
JR
316{
317 int ret;
318 enum lttng_error_code ret_code;
cd9adb8b
JG
319 struct lttng_action_path *action_path = nullptr;
320 struct lttng_error_query_results *error_query_results = nullptr;
6a751b95 321
a0377dfe
FD
322 LTTNG_ASSERT(action);
323 LTTNG_ASSERT(writer);
6a751b95
JR
324
325 /* Open action. */
326 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_action);
327 if (ret) {
328 goto mi_error;
329 }
330
331 if (action->type == LTTNG_ACTION_TYPE_LIST) {
332 /*
333 * Recursion is safe since action lists can't be nested for
334 * the moment.
335 */
28ab034a
JG
336 ret_code = lttng_action_list_mi_serialize(
337 trigger, action, writer, error_query_callbacks, action_path_indexes);
6a751b95
JR
338 if (ret_code != LTTNG_OK) {
339 goto end;
340 }
341
342 /* Nothing else to do. */
343 goto close_action_element;
344 }
345
a0377dfe 346 LTTNG_ASSERT(action->mi_serialize);
6a751b95
JR
347 ret_code = action->mi_serialize(action, writer);
348 if (ret_code != LTTNG_OK) {
349 goto end;
350 }
351
352 /* Error query for the action. */
353 if (error_query_callbacks && error_query_callbacks->action_cb) {
cd9adb8b 354 const uint64_t *action_path_indexes_raw_pointer = nullptr;
6a751b95 355 const size_t action_path_indexes_size =
28ab034a 356 lttng_dynamic_array_get_count(action_path_indexes);
6a751b95
JR
357
358 if (action_path_indexes_size != 0) {
359 action_path_indexes_raw_pointer =
28ab034a 360 (const uint64_t *) action_path_indexes->buffer.data;
6a751b95
JR
361 }
362
28ab034a
JG
363 action_path = lttng_action_path_create(action_path_indexes_raw_pointer,
364 action_path_indexes_size);
a0377dfe 365 LTTNG_ASSERT(action_path);
6a751b95
JR
366
367 ret_code = error_query_callbacks->action_cb(
28ab034a 368 trigger, action_path, &error_query_results);
6a751b95
JR
369 if (ret_code != LTTNG_OK) {
370 goto end;
371 }
372
373 /* Serialize the error query results. */
28ab034a 374 ret_code = lttng_error_query_results_mi_serialize(error_query_results, writer);
6a751b95
JR
375 if (ret_code != LTTNG_OK) {
376 goto end;
377 }
378 }
379
380close_action_element:
381 /* Close action. */
382 ret = mi_lttng_writer_close_element(writer);
383 if (ret) {
384 goto mi_error;
385 }
386
387 ret_code = LTTNG_OK;
388 goto end;
389
390mi_error:
391 ret_code = LTTNG_ERR_MI_IO_FAIL;
392end:
393 lttng_action_path_destroy(action_path);
394 lttng_error_query_results_destroy(error_query_results);
395 return ret_code;
396}
This page took 0.10141 seconds and 4 git commands to generate.