SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / src / common / conditions / event-rule.c
1 /*
2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include <lttng/condition/condition-internal.h>
19 #include <lttng/condition/event-rule-internal.h>
20 #include <lttng/event-rule/event-rule-internal.h>
21 #include <common/macros.h>
22 #include <common/error.h>
23 #include <assert.h>
24 #include <stdbool.h>
25
26 #define IS_EVENT_RULE_CONDITION(condition) ( \
27 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT \
28 )
29
30 static
31 bool is_event_rule_evaluation(const struct lttng_evaluation *evaluation)
32 {
33 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
34
35 return type == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT;
36 }
37
38
39 static
40 bool lttng_condition_event_rule_validate(
41 const struct lttng_condition *condition);
42 static
43 int lttng_condition_event_rule_serialize(
44 const struct lttng_condition *condition,
45 struct lttng_dynamic_buffer *buf,
46 int *fd_to_send);
47 static
48 bool lttng_condition_event_rule_is_equal(const struct lttng_condition *_a,
49 const struct lttng_condition *_b);
50 static
51 void lttng_condition_event_rule_destroy(
52 struct lttng_condition *condition);
53
54
55 static
56 bool lttng_condition_event_rule_validate(
57 const struct lttng_condition *condition)
58 {
59 bool valid = false;
60 struct lttng_condition_event_rule *event_rule;
61
62 if (!condition) {
63 goto end;
64 }
65
66 event_rule = container_of(condition,
67 struct lttng_condition_event_rule, parent);
68 if (!event_rule->rule) {
69 ERR("Invalid session event_rule condition: a rule must be set.");
70 goto end;
71 }
72
73 valid = lttng_event_rule_validate(event_rule->rule);
74 end:
75 return valid;
76 }
77
78 static
79 int lttng_condition_event_rule_serialize(
80 const struct lttng_condition *condition,
81 struct lttng_dynamic_buffer *buf,
82 int *fd_to_send)
83 {
84 int ret;
85 size_t header_offset, size_before_payload;
86 struct lttng_condition_event_rule *event_rule;
87 struct lttng_condition_event_rule_comm event_rule_comm = { 0 };
88 struct lttng_condition_event_rule_comm *header;
89
90 if (!condition || !IS_EVENT_RULE_CONDITION(condition)) {
91 ret = -1;
92 goto end;
93 }
94
95 DBG("Serializing event rule condition");
96 event_rule = container_of(condition, struct lttng_condition_event_rule,
97 parent);
98
99 header_offset = buf->size;
100 ret = lttng_dynamic_buffer_append(buf, &event_rule_comm,
101 sizeof(event_rule_comm));
102 if (ret) {
103 goto end;
104 }
105
106 size_before_payload = buf->size;
107 ret = lttng_event_rule_serialize(event_rule->rule, buf, fd_to_send);
108 if (ret) {
109 goto end;
110 }
111
112 /* Update payload size */
113 header = (struct lttng_condition_event_rule_comm *) ((char *) buf->data + header_offset);
114 header->length = buf->size - size_before_payload;
115
116 end:
117 return ret;
118 }
119
120 static
121 bool lttng_condition_event_rule_is_equal(const struct lttng_condition *_a,
122 const struct lttng_condition *_b)
123 {
124 bool is_equal = false;
125 struct lttng_condition_event_rule *a, *b;
126
127 a = container_of(_a, struct lttng_condition_event_rule, parent);
128 b = container_of(_b, struct lttng_condition_event_rule, parent);
129
130 /* Both session names must be set or both must be unset. */
131 if ((a->rule && !b->rule) ||
132 (!a->rule && b->rule)) {
133 WARN("Comparing session event_rule conditions with uninitialized rule.");
134 goto end;
135 }
136
137 is_equal = lttng_event_rule_is_equal(a->rule, b->rule);
138 end:
139 return is_equal;
140 }
141
142 static
143 void lttng_condition_event_rule_destroy(
144 struct lttng_condition *condition)
145 {
146 struct lttng_condition_event_rule *event_rule;
147
148 event_rule = container_of(condition,
149 struct lttng_condition_event_rule, parent);
150
151
152 lttng_event_rule_destroy(event_rule->rule);
153 free(event_rule);
154 }
155
156 struct lttng_condition *lttng_condition_event_rule_create(
157 struct lttng_event_rule *rule)
158 {
159 struct lttng_condition *parent = NULL;
160 struct lttng_condition_event_rule *condition = NULL;
161
162 if (!rule) {
163 goto end;
164 }
165
166 condition = zmalloc(sizeof(struct lttng_condition_event_rule));
167 if (!condition) {
168 return NULL;
169 }
170
171 lttng_condition_init(&condition->parent, LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
172 condition->parent.validate = lttng_condition_event_rule_validate,
173 condition->parent.serialize = lttng_condition_event_rule_serialize,
174 condition->parent.equal = lttng_condition_event_rule_is_equal,
175 condition->parent.destroy = lttng_condition_event_rule_destroy,
176
177 condition->rule = rule;
178 parent = &condition->parent;
179 end:
180 return parent;
181 }
182
183 LTTNG_HIDDEN
184 ssize_t lttng_condition_event_rule_create_from_buffer(
185 const struct lttng_buffer_view *view,
186 struct lttng_condition **_condition)
187 {
188 ssize_t offset, event_rule_size;
189 const struct lttng_condition_event_rule_comm *comm;
190 struct lttng_condition *condition = NULL;
191 struct lttng_event_rule *event_rule = NULL;
192 struct lttng_buffer_view event_rule_view;
193
194 if (!view || !_condition) {
195 goto error;
196 }
197
198 if (view->size < sizeof(*comm)) {
199 ERR("Failed to initialize from malformed event rule condition: buffer too short to contain header");
200 goto error;
201 }
202
203 comm = (const struct lttng_condition_event_rule_comm *) view->data;
204 offset = sizeof(*comm);
205
206 /* Struct lttng_event_rule */
207 event_rule_view = lttng_buffer_view_from_view(view, offset, -1);
208 event_rule_size = lttng_event_rule_create_from_buffer(&event_rule_view, &event_rule);
209 if (event_rule_size < 0 || !event_rule) {
210 goto error;
211 }
212
213 if ((size_t) comm->length != event_rule_size) {
214 goto error;
215 }
216
217 /* Move to the end */
218 offset += comm->length;
219
220 condition = lttng_condition_event_rule_create(event_rule);
221 if (!condition) {
222 goto error;
223 }
224
225 /* Ownership passed on condition event rule create */
226 event_rule = NULL;
227
228 *_condition = condition;
229 condition = NULL;
230 goto end;
231
232 error:
233 offset = -1;
234
235 end:
236 lttng_event_rule_destroy(event_rule);
237 lttng_condition_destroy(condition);
238 return offset;
239 }
240
241 LTTNG_HIDDEN
242 enum lttng_condition_status
243 lttng_condition_event_rule_get_rule_no_const(
244 const struct lttng_condition *condition,
245 struct lttng_event_rule **rule)
246 {
247 struct lttng_condition_event_rule *event_rule;
248 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
249
250 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !rule) {
251 status = LTTNG_CONDITION_STATUS_INVALID;
252 goto end;
253 }
254
255 event_rule = container_of(condition, struct lttng_condition_event_rule,
256 parent);
257 if (!event_rule->rule) {
258 status = LTTNG_CONDITION_STATUS_UNSET;
259 goto end;
260 }
261 *rule = event_rule->rule;
262 end:
263 return status;
264 }
265
266 enum lttng_condition_status
267 lttng_condition_event_rule_get_rule(
268 const struct lttng_condition *condition,
269 const struct lttng_event_rule **rule)
270 {
271 struct lttng_event_rule *no_const_rule = NULL;
272 enum lttng_condition_status status;
273
274 status = lttng_condition_event_rule_get_rule_no_const(condition, &no_const_rule);
275 *rule = no_const_rule;
276 return status;
277 }
278
279 LTTNG_HIDDEN
280 ssize_t lttng_evaluation_event_rule_create_from_buffer(
281 const struct lttng_buffer_view *view,
282 struct lttng_evaluation **_evaluation)
283 {
284 ssize_t ret, offset = 0;
285 const char *name;
286 struct lttng_evaluation *evaluation = NULL;
287 const struct lttng_evaluation_event_rule_comm *comm =
288 (const struct lttng_evaluation_event_rule_comm *) view->data;
289 struct lttng_buffer_view current_view;
290
291 if (!_evaluation) {
292 ret = -1;
293 goto error;
294 }
295
296 if (view->size < sizeof(*comm)) {
297 ret = -1;
298 goto error;
299 }
300
301 /* Map the name, view of the payload */
302 offset += sizeof(*comm);
303 current_view = lttng_buffer_view_from_view(view, offset, comm->trigger_name_length);
304 name = current_view.data;
305 if (!name) {
306 ret = -1;
307 goto error;
308 }
309
310 if (comm->trigger_name_length == 1 ||
311 name[comm->trigger_name_length - 1] != '\0' ||
312 strlen(name) != comm->trigger_name_length - 1) {
313 /*
314 * Check that the name is not NULL, is NULL-terminated, and
315 * does not contain a NULL before the last byte.
316 */
317 ret = -1;
318 goto error;
319 }
320
321 offset += comm->trigger_name_length;
322
323 evaluation = lttng_evaluation_event_rule_create(name);
324 if (!evaluation) {
325 ret = -1;
326 goto error;
327 }
328
329 *_evaluation = evaluation;
330 evaluation = NULL;
331 ret = offset;
332
333 error:
334 lttng_evaluation_destroy(evaluation);
335 return ret;
336 }
337
338 static
339 int lttng_evaluation_event_rule_serialize(
340 const struct lttng_evaluation *evaluation,
341 struct lttng_dynamic_buffer *buf)
342 {
343 int ret = 0;
344 struct lttng_evaluation_event_rule *hit;
345 struct lttng_evaluation_event_rule_comm comm;
346
347 hit = container_of(evaluation, struct lttng_evaluation_event_rule,
348 parent);
349 comm.trigger_name_length = strlen(hit->name) + 1;
350 ret = lttng_dynamic_buffer_append(buf, &comm, sizeof(comm));
351 if (ret) {
352 goto end;
353 }
354 ret = lttng_dynamic_buffer_append(buf, hit->name, comm.trigger_name_length);
355 end:
356 return ret;
357 }
358
359 static
360 void lttng_evaluation_event_rule_destroy(
361 struct lttng_evaluation *evaluation)
362 {
363 struct lttng_evaluation_event_rule *hit;
364
365 hit = container_of(evaluation, struct lttng_evaluation_event_rule,
366 parent);
367 free(hit->name);
368 free(hit);
369 }
370
371 LTTNG_HIDDEN
372 struct lttng_evaluation *lttng_evaluation_event_rule_create(const char *trigger_name)
373 {
374 struct lttng_evaluation_event_rule *hit;
375
376 hit = zmalloc(sizeof(struct lttng_evaluation_event_rule));
377 if (!hit) {
378 goto end;
379 }
380
381 /* TODO errir handling */
382 hit->name = strdup(trigger_name);
383
384 hit->parent.type = LTTNG_CONDITION_TYPE_EVENT_RULE_HIT;
385 hit->parent.serialize = lttng_evaluation_event_rule_serialize;
386 hit->parent.destroy = lttng_evaluation_event_rule_destroy;
387 end:
388 return &hit->parent;
389 }
390
391 enum lttng_evaluation_status
392 lttng_evaluation_event_rule_get_trigger_name(
393 const struct lttng_evaluation *evaluation,
394 const char **name)
395 {
396 struct lttng_evaluation_event_rule *hit;
397 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
398
399 if (!evaluation || !is_event_rule_evaluation(evaluation) || !name) {
400 status = LTTNG_EVALUATION_STATUS_INVALID;
401 goto end;
402 }
403
404 hit = container_of(evaluation, struct lttng_evaluation_event_rule,
405 parent);
406 *name = hit->name;
407 end:
408 return status;
409 }
This page took 0.039427 seconds and 5 git commands to generate.