Implement firing policy for the rotate session action
[lttng-tools.git] / src / common / actions / rotate-session.c
1 /*
2 * Copyright (C) 2019 Simon Marchi <simon.marchi@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 <common/macros.h>
11 #include <lttng/action/action-internal.h>
12 #include <lttng/action/firing-policy-internal.h>
13 #include <lttng/action/firing-policy.h>
14 #include <lttng/action/rotate-session-internal.h>
15 #include <lttng/action/rotate-session.h>
16
17 #define IS_ROTATE_SESSION_ACTION(action) \
18 (lttng_action_get_type(action) == LTTNG_ACTION_TYPE_ROTATE_SESSION)
19
20 struct lttng_action_rotate_session {
21 struct lttng_action parent;
22
23 /* Owned by this. */
24 char *session_name;
25 struct lttng_firing_policy *policy;
26 };
27
28 struct lttng_action_rotate_session_comm {
29 /* Includes the trailing \0. */
30 uint32_t session_name_len;
31
32 /*
33 * Variable data:
34 *
35 * - session name (null terminated)
36 * - policy
37 */
38 char data[];
39 } LTTNG_PACKED;
40
41 static struct lttng_action_rotate_session *action_rotate_session_from_action(
42 struct lttng_action *action)
43 {
44 assert(action);
45
46 return container_of(action, struct lttng_action_rotate_session, parent);
47 }
48
49 static const struct lttng_action_rotate_session *
50 action_rotate_session_from_action_const(const struct lttng_action *action)
51 {
52 assert(action);
53
54 return container_of(action, struct lttng_action_rotate_session, parent);
55 }
56
57 static bool lttng_action_rotate_session_validate(struct lttng_action *action)
58 {
59 bool valid;
60 struct lttng_action_rotate_session *action_rotate_session;
61
62 if (!action) {
63 valid = false;
64 goto end;
65 }
66
67 action_rotate_session = action_rotate_session_from_action(action);
68
69 /* A non-empty session name is mandatory. */
70 if (!action_rotate_session->session_name ||
71 strlen(action_rotate_session->session_name) == 0) {
72 valid = false;
73 goto end;
74 }
75
76 valid = true;
77 end:
78 return valid;
79 }
80
81 static bool lttng_action_rotate_session_is_equal(
82 const struct lttng_action *_a, const struct lttng_action *_b)
83 {
84 bool is_equal = false;
85 const struct lttng_action_rotate_session *a, *b;
86
87 a = action_rotate_session_from_action_const(_a);
88 b = action_rotate_session_from_action_const(_b);
89
90 /* Action is not valid if this is not true. */
91 assert(a->session_name);
92 assert(b->session_name);
93 if (strcmp(a->session_name, b->session_name)) {
94 goto end;
95 }
96
97 is_equal = lttng_firing_policy_is_equal(a->policy, b->policy);
98 end:
99 return is_equal;
100 }
101 static int lttng_action_rotate_session_serialize(
102 struct lttng_action *action, struct lttng_payload *payload)
103 {
104 struct lttng_action_rotate_session *action_rotate_session;
105 struct lttng_action_rotate_session_comm comm;
106 size_t session_name_len;
107 int ret;
108
109 assert(action);
110 assert(payload);
111
112 action_rotate_session = action_rotate_session_from_action(action);
113
114 assert(action_rotate_session->session_name);
115
116 DBG("Serializing rotate session action: session-name: %s",
117 action_rotate_session->session_name);
118
119 session_name_len = strlen(action_rotate_session->session_name) + 1;
120 comm.session_name_len = session_name_len;
121
122 ret = lttng_dynamic_buffer_append(
123 &payload->buffer, &comm, sizeof(comm));
124 if (ret) {
125 ret = -1;
126 goto end;
127 }
128
129 ret = lttng_dynamic_buffer_append(&payload->buffer,
130 action_rotate_session->session_name, session_name_len);
131 if (ret) {
132 ret = -1;
133 goto end;
134 }
135
136 ret = lttng_firing_policy_serialize(
137 action_rotate_session->policy, payload);
138 if (ret) {
139 ret = -1;
140 goto end;
141 }
142 end:
143 return ret;
144 }
145
146 static void lttng_action_rotate_session_destroy(struct lttng_action *action)
147 {
148 struct lttng_action_rotate_session *action_rotate_session;
149
150 if (!action) {
151 goto end;
152 }
153
154 action_rotate_session = action_rotate_session_from_action(action);
155
156 lttng_firing_policy_destroy(action_rotate_session->policy);
157 free(action_rotate_session->session_name);
158 free(action_rotate_session);
159
160 end:
161 return;
162 }
163
164 ssize_t lttng_action_rotate_session_create_from_payload(
165 struct lttng_payload_view *view,
166 struct lttng_action **p_action)
167 {
168 ssize_t consumed_len, ret;
169 const struct lttng_action_rotate_session_comm *comm;
170 const char *session_name;
171 struct lttng_action *action;
172 enum lttng_action_status status;
173 struct lttng_firing_policy *policy = NULL;
174
175 action = lttng_action_rotate_session_create();
176 if (!action) {
177 consumed_len = -1;
178 goto end;
179 }
180
181 comm = (typeof(comm)) view->buffer.data;
182 session_name = (const char *) &comm->data;
183
184 if (!lttng_buffer_view_contains_string(
185 &view->buffer, session_name, comm->session_name_len)) {
186 consumed_len = -1;
187 goto end;
188 }
189 consumed_len = sizeof(*comm) + comm->session_name_len;
190
191 /* Firing policy. */
192 {
193 struct lttng_payload_view policy_view =
194 lttng_payload_view_from_view(
195 view, consumed_len, -1);
196 ret = lttng_firing_policy_create_from_payload(
197 &policy_view, &policy);
198 if (ret < 0) {
199 consumed_len = -1;
200 goto end;
201 }
202 consumed_len += ret;
203 }
204
205 status = lttng_action_rotate_session_set_session_name(
206 action, session_name);
207 if (status != LTTNG_ACTION_STATUS_OK) {
208 consumed_len = -1;
209 goto end;
210 }
211
212 assert(policy);
213 status = lttng_action_rotate_session_set_firing_policy(action, policy);
214 if (status != LTTNG_ACTION_STATUS_OK) {
215 consumed_len = -1;
216 goto end;
217 }
218
219 *p_action = action;
220 action = NULL;
221
222 end:
223 lttng_firing_policy_destroy(policy);
224 lttng_action_rotate_session_destroy(action);
225
226 return consumed_len;
227 }
228
229 struct lttng_action *lttng_action_rotate_session_create(void)
230 {
231 struct lttng_action *action = NULL;
232 struct lttng_firing_policy *policy = NULL;
233 enum lttng_action_status status;
234
235 /* Create a every N = 1 firing policy. */
236 policy = lttng_firing_policy_every_n_create(1);
237 if (!policy) {
238 goto end;
239 }
240
241 action = zmalloc(sizeof(struct lttng_action_rotate_session));
242 if (!action) {
243 goto end;
244 }
245
246 lttng_action_init(action, LTTNG_ACTION_TYPE_ROTATE_SESSION,
247 lttng_action_rotate_session_validate,
248 lttng_action_rotate_session_serialize,
249 lttng_action_rotate_session_is_equal,
250 lttng_action_rotate_session_destroy);
251
252 status = lttng_action_rotate_session_set_firing_policy(action, policy);
253 if (status != LTTNG_ACTION_STATUS_OK) {
254 free(action);
255 action = NULL;
256 goto end;
257 }
258
259 end:
260 lttng_firing_policy_destroy(policy);
261 return action;
262 }
263
264 enum lttng_action_status lttng_action_rotate_session_set_session_name(
265 struct lttng_action *action, const char *session_name)
266 {
267 struct lttng_action_rotate_session *action_rotate_session;
268 enum lttng_action_status status;
269
270 if (!action || !IS_ROTATE_SESSION_ACTION(action) || !session_name ||
271 strlen(session_name) == 0) {
272 status = LTTNG_ACTION_STATUS_INVALID;
273 goto end;
274 }
275
276 action_rotate_session = action_rotate_session_from_action(action);
277
278 free(action_rotate_session->session_name);
279
280 action_rotate_session->session_name = strdup(session_name);
281 if (!action_rotate_session->session_name) {
282 status = LTTNG_ACTION_STATUS_ERROR;
283 goto end;
284 }
285
286 status = LTTNG_ACTION_STATUS_OK;
287 end:
288 return status;
289 }
290
291 enum lttng_action_status lttng_action_rotate_session_get_session_name(
292 const struct lttng_action *action, const char **session_name)
293 {
294 const struct lttng_action_rotate_session *action_rotate_session;
295 enum lttng_action_status status;
296
297 if (!action || !IS_ROTATE_SESSION_ACTION(action) || !session_name) {
298 status = LTTNG_ACTION_STATUS_INVALID;
299 goto end;
300 }
301
302 action_rotate_session = action_rotate_session_from_action_const(action);
303
304 *session_name = action_rotate_session->session_name;
305
306 status = LTTNG_ACTION_STATUS_OK;
307 end:
308 return status;
309 }
310
311 enum lttng_action_status lttng_action_rotate_session_set_firing_policy(
312 struct lttng_action *action,
313 const struct lttng_firing_policy *policy)
314 {
315 enum lttng_action_status status;
316 struct lttng_action_rotate_session *rotate_session_action;
317 struct lttng_firing_policy *copy = NULL;
318
319 if (!action || !policy || !IS_ROTATE_SESSION_ACTION(action)) {
320 status = LTTNG_ACTION_STATUS_INVALID;
321 goto end;
322 }
323
324 copy = lttng_firing_policy_copy(policy);
325 if (!copy) {
326 status = LTTNG_ACTION_STATUS_ERROR;
327 goto end;
328 }
329
330 rotate_session_action = action_rotate_session_from_action(action);
331
332 /* Free the previous firing policy .*/
333 lttng_firing_policy_destroy(rotate_session_action->policy);
334
335 /* Assign the policy. */
336 rotate_session_action->policy = copy;
337 status = LTTNG_ACTION_STATUS_OK;
338 copy = NULL;
339
340 end:
341 lttng_firing_policy_destroy(copy);
342 return status;
343 }
344
345 enum lttng_action_status lttng_action_rotate_session_get_firing_policy(
346 const struct lttng_action *action,
347 const struct lttng_firing_policy **policy)
348 {
349 enum lttng_action_status status;
350 const struct lttng_action_rotate_session *rotate_session_action;
351
352 if (!action || !policy || !IS_ROTATE_SESSION_ACTION(action)) {
353 status = LTTNG_ACTION_STATUS_INVALID;
354 goto end;
355 }
356
357 rotate_session_action = action_rotate_session_from_action_const(action);
358
359 *policy = rotate_session_action->policy;
360 status = LTTNG_ACTION_STATUS_OK;
361 end:
362 return status;
363 }
This page took 0.062044 seconds and 4 git commands to generate.