sessiond: implement EXECUTE_ERROR_QUERY command
[lttng-tools.git] / src / common / actions / action.c
1 /*
2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <assert.h>
9 #include <common/error.h>
10 #include <lttng/action/action-internal.h>
11 #include <lttng/action/group-internal.h>
12 #include <lttng/action/notify-internal.h>
13 #include <lttng/action/rate-policy-internal.h>
14 #include <lttng/action/rotate-session-internal.h>
15 #include <lttng/action/snapshot-session-internal.h>
16 #include <lttng/action/start-session-internal.h>
17 #include <lttng/action/stop-session-internal.h>
18 #include <lttng/error-query-internal.h>
19
20 LTTNG_HIDDEN
21 const char *lttng_action_type_string(enum lttng_action_type action_type)
22 {
23 switch (action_type) {
24 case LTTNG_ACTION_TYPE_UNKNOWN:
25 return "UNKNOWN";
26 case LTTNG_ACTION_TYPE_GROUP:
27 return "GROUP";
28 case LTTNG_ACTION_TYPE_NOTIFY:
29 return "NOTIFY";
30 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
31 return "ROTATE_SESSION";
32 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
33 return "SNAPSHOT_SESSION";
34 case LTTNG_ACTION_TYPE_START_SESSION:
35 return "START_SESSION";
36 case LTTNG_ACTION_TYPE_STOP_SESSION:
37 return "STOP_SESSION";
38 default:
39 return "???";
40 }
41 }
42
43 enum lttng_action_type lttng_action_get_type(const struct lttng_action *action)
44 {
45 return action ? action->type : LTTNG_ACTION_TYPE_UNKNOWN;
46 }
47
48 LTTNG_HIDDEN
49 void lttng_action_init(struct lttng_action *action,
50 enum lttng_action_type type,
51 action_validate_cb validate,
52 action_serialize_cb serialize,
53 action_equal_cb equal,
54 action_destroy_cb destroy,
55 action_get_rate_policy_cb get_rate_policy,
56 action_add_error_query_results_cb add_error_query_results)
57 {
58 urcu_ref_init(&action->ref);
59 action->type = type;
60 action->validate = validate;
61 action->serialize = serialize;
62 action->equal = equal;
63 action->destroy = destroy;
64 action->get_rate_policy = get_rate_policy;
65 action->add_error_query_results = add_error_query_results;
66
67 action->execution_request_counter = 0;
68 action->execution_counter = 0;
69 action->execution_failure_counter = 0;
70 }
71
72 static
73 void action_destroy_ref(struct urcu_ref *ref)
74 {
75 struct lttng_action *action =
76 container_of(ref, struct lttng_action, ref);
77
78 action->destroy(action);
79 }
80
81 LTTNG_HIDDEN
82 void lttng_action_get(struct lttng_action *action)
83 {
84 urcu_ref_get(&action->ref);
85 }
86
87 LTTNG_HIDDEN
88 void lttng_action_put(struct lttng_action *action)
89 {
90 if (!action) {
91 return;
92 }
93
94 assert(action->destroy);
95 urcu_ref_put(&action->ref, action_destroy_ref);
96 }
97
98 void lttng_action_destroy(struct lttng_action *action)
99 {
100 lttng_action_put(action);
101 }
102
103 LTTNG_HIDDEN
104 bool lttng_action_validate(struct lttng_action *action)
105 {
106 bool valid;
107
108 if (!action) {
109 valid = false;
110 goto end;
111 }
112
113 if (!action->validate) {
114 /* Sub-class guarantees that it can never be invalid. */
115 valid = true;
116 goto end;
117 }
118
119 valid = action->validate(action);
120 end:
121 return valid;
122 }
123
124 LTTNG_HIDDEN
125 int lttng_action_serialize(struct lttng_action *action,
126 struct lttng_payload *payload)
127 {
128 int ret;
129 struct lttng_action_comm action_comm = {
130 .action_type = (int8_t) action->type,
131 };
132
133 ret = lttng_dynamic_buffer_append(&payload->buffer, &action_comm,
134 sizeof(action_comm));
135 if (ret) {
136 goto end;
137 }
138
139 ret = action->serialize(action, payload);
140 if (ret) {
141 goto end;
142 }
143 end:
144 return ret;
145 }
146
147 LTTNG_HIDDEN
148 ssize_t lttng_action_create_from_payload(struct lttng_payload_view *view,
149 struct lttng_action **action)
150 {
151 ssize_t consumed_len, specific_action_consumed_len;
152 action_create_from_payload_cb create_from_payload_cb;
153 const struct lttng_action_comm *action_comm;
154 const struct lttng_payload_view action_comm_view =
155 lttng_payload_view_from_view(
156 view, 0, sizeof(*action_comm));
157
158 if (!view || !action) {
159 consumed_len = -1;
160 goto end;
161 }
162
163 if (!lttng_payload_view_is_valid(&action_comm_view)) {
164 /* Payload not large enough to contain the header. */
165 consumed_len = -1;
166 goto end;
167 }
168
169 action_comm = (const struct lttng_action_comm *) action_comm_view.buffer.data;
170
171 DBG("Create action from payload: action-type=%s",
172 lttng_action_type_string(action_comm->action_type));
173
174 switch (action_comm->action_type) {
175 case LTTNG_ACTION_TYPE_NOTIFY:
176 create_from_payload_cb = lttng_action_notify_create_from_payload;
177 break;
178 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
179 create_from_payload_cb =
180 lttng_action_rotate_session_create_from_payload;
181 break;
182 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
183 create_from_payload_cb =
184 lttng_action_snapshot_session_create_from_payload;
185 break;
186 case LTTNG_ACTION_TYPE_START_SESSION:
187 create_from_payload_cb =
188 lttng_action_start_session_create_from_payload;
189 break;
190 case LTTNG_ACTION_TYPE_STOP_SESSION:
191 create_from_payload_cb =
192 lttng_action_stop_session_create_from_payload;
193 break;
194 case LTTNG_ACTION_TYPE_GROUP:
195 create_from_payload_cb = lttng_action_group_create_from_payload;
196 break;
197 default:
198 ERR("Failed to create action from payload, unhandled action type: action-type=%u (%s)",
199 action_comm->action_type,
200 lttng_action_type_string(
201 action_comm->action_type));
202 consumed_len = -1;
203 goto end;
204 }
205
206 {
207 /* Create buffer view for the action-type-specific data. */
208 struct lttng_payload_view specific_action_view =
209 lttng_payload_view_from_view(view,
210 sizeof(struct lttng_action_comm),
211 -1);
212
213 specific_action_consumed_len = create_from_payload_cb(
214 &specific_action_view, action);
215 }
216 if (specific_action_consumed_len < 0) {
217 ERR("Failed to create specific action from buffer.");
218 consumed_len = -1;
219 goto end;
220 }
221
222 assert(*action);
223
224 consumed_len = sizeof(struct lttng_action_comm) +
225 specific_action_consumed_len;
226
227 end:
228 return consumed_len;
229 }
230
231 LTTNG_HIDDEN
232 bool lttng_action_is_equal(const struct lttng_action *a,
233 const struct lttng_action *b)
234 {
235 bool is_equal = false;
236
237 if (!a || !b) {
238 goto end;
239 }
240
241 if (a->type != b->type) {
242 goto end;
243 }
244
245 if (a == b) {
246 is_equal = true;
247 goto end;
248 }
249
250 assert(a->equal);
251 is_equal = a->equal(a, b);
252 end:
253 return is_equal;
254 }
255
256 LTTNG_HIDDEN
257 void lttng_action_increase_execution_request_count(struct lttng_action *action)
258 {
259 action->execution_request_counter++;
260 }
261
262 LTTNG_HIDDEN
263 void lttng_action_increase_execution_count(struct lttng_action *action)
264 {
265 action->execution_counter++;
266 }
267
268 LTTNG_HIDDEN
269 void lttng_action_increase_execution_failure_count(struct lttng_action *action)
270 {
271 uatomic_inc(&action->execution_failure_counter);
272 }
273
274 LTTNG_HIDDEN
275 bool lttng_action_should_execute(const struct lttng_action *action)
276 {
277 const struct lttng_rate_policy *policy = NULL;
278 bool execute = false;
279
280 if (action->get_rate_policy == NULL) {
281 execute = true;
282 goto end;
283 }
284
285 policy = action->get_rate_policy(action);
286 if (policy == NULL) {
287 execute = true;
288 goto end;
289 }
290
291 execute = lttng_rate_policy_should_execute(
292 policy, action->execution_request_counter);
293 end:
294 return execute;
295 }
296
297 LTTNG_HIDDEN
298 enum lttng_action_status lttng_action_add_error_query_results(
299 const struct lttng_action *action,
300 struct lttng_error_query_results *results)
301 {
302 return action->add_error_query_results(action, results);
303 }
304
305 LTTNG_HIDDEN
306 enum lttng_action_status lttng_action_generic_add_error_query_results(
307 const struct lttng_action *action,
308 struct lttng_error_query_results *results)
309 {
310 enum lttng_action_status action_status;
311 struct lttng_error_query_result *error_counter = NULL;
312 const uint64_t execution_failure_counter =
313 uatomic_read(&action->execution_failure_counter);
314
315 error_counter = lttng_error_query_result_counter_create(
316 "total execution failures",
317 "Aggregated count of errors encountered when executing the action",
318 execution_failure_counter);
319 if (!error_counter) {
320 action_status = LTTNG_ACTION_STATUS_ERROR;
321 goto end;
322 }
323
324 if (lttng_error_query_results_add_result(
325 results, error_counter)) {
326 action_status = LTTNG_ACTION_STATUS_ERROR;
327 goto end;
328 }
329
330 /* Ownership transferred to the results. */
331 error_counter = NULL;
332 action_status = LTTNG_ACTION_STATUS_OK;
333 end:
334 lttng_error_query_result_destroy(error_counter);
335 return action_status;
336 }
This page took 0.03535 seconds and 4 git commands to generate.