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