2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/error.h>
10 #include <common/macros.h>
11 #include <lttng/condition/condition-internal.h>
12 #include <lttng/condition/event-rule-internal.h>
13 #include <lttng/condition/event-rule.h>
14 #include <lttng/event-rule/event-rule-internal.h>
17 #define IS_EVENT_RULE_CONDITION(condition) \
18 (lttng_condition_get_type(condition) == \
19 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT)
21 static bool is_event_rule_evaluation(const struct lttng_evaluation
*evaluation
)
23 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
25 return type
== LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
28 static bool lttng_condition_event_rule_validate(
29 const struct lttng_condition
*condition
);
30 static int lttng_condition_event_rule_serialize(
31 const struct lttng_condition
*condition
,
32 struct lttng_payload
*payload
);
33 static bool lttng_condition_event_rule_is_equal(
34 const struct lttng_condition
*_a
,
35 const struct lttng_condition
*_b
);
36 static void lttng_condition_event_rule_destroy(
37 struct lttng_condition
*condition
);
39 static bool lttng_condition_event_rule_validate(
40 const struct lttng_condition
*condition
)
43 struct lttng_condition_event_rule
*event_rule
;
49 event_rule
= container_of(
50 condition
, struct lttng_condition_event_rule
, parent
);
51 if (!event_rule
->rule
) {
52 ERR("Invalid event rule condition: a rule must be set.");
56 valid
= lttng_event_rule_validate(event_rule
->rule
);
61 static int lttng_condition_event_rule_serialize(
62 const struct lttng_condition
*condition
,
63 struct lttng_payload
*payload
)
66 size_t header_offset
, size_before_payload
;
67 struct lttng_condition_event_rule
*event_rule
;
68 struct lttng_condition_event_rule_comm event_rule_comm
= {};
69 struct lttng_condition_event_rule_comm
*header
= NULL
;
71 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
76 DBG("Serializing event rule condition");
77 event_rule
= container_of(
78 condition
, struct lttng_condition_event_rule
, parent
);
80 header_offset
= payload
->buffer
.size
;
81 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &event_rule_comm
,
82 sizeof(event_rule_comm
));
87 size_before_payload
= payload
->buffer
.size
;
88 ret
= lttng_event_rule_serialize(event_rule
->rule
, payload
);
93 /* Update payload size. */
94 header
= (struct lttng_condition_event_rule_comm
*)
95 ((char *) payload
->buffer
.data
+ header_offset
);
96 header
->event_rule_length
= payload
->buffer
.size
- size_before_payload
;
102 static bool lttng_condition_event_rule_is_equal(
103 const struct lttng_condition
*_a
,
104 const struct lttng_condition
*_b
)
106 bool is_equal
= false;
107 struct lttng_condition_event_rule
*a
, *b
;
109 a
= container_of(_a
, struct lttng_condition_event_rule
, parent
);
110 b
= container_of(_b
, struct lttng_condition_event_rule
, parent
);
112 /* Both event rules must be set or both must be unset. */
113 if ((a
->rule
&& !b
->rule
) || (!a
->rule
&& b
->rule
)) {
114 WARN("Comparing event_rule conditions with uninitialized rule");
118 is_equal
= lttng_event_rule_is_equal(a
->rule
, b
->rule
);
123 static void lttng_condition_event_rule_destroy(
124 struct lttng_condition
*condition
)
126 struct lttng_condition_event_rule
*event_rule
;
128 event_rule
= container_of(
129 condition
, struct lttng_condition_event_rule
, parent
);
131 lttng_event_rule_put(event_rule
->rule
);
135 struct lttng_condition
*lttng_condition_event_rule_create(
136 struct lttng_event_rule
*rule
)
138 struct lttng_condition
*parent
= NULL
;
139 struct lttng_condition_event_rule
*condition
= NULL
;
145 condition
= zmalloc(sizeof(struct lttng_condition_event_rule
));
150 lttng_condition_init(&condition
->parent
,
151 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
);
152 condition
->parent
.validate
= lttng_condition_event_rule_validate
,
153 condition
->parent
.serialize
= lttng_condition_event_rule_serialize
,
154 condition
->parent
.equal
= lttng_condition_event_rule_is_equal
,
155 condition
->parent
.destroy
= lttng_condition_event_rule_destroy
,
157 lttng_event_rule_get(rule
);
158 condition
->rule
= rule
;
161 parent
= &condition
->parent
;
167 ssize_t
lttng_condition_event_rule_create_from_payload(
168 struct lttng_payload_view
*view
,
169 struct lttng_condition
**_condition
)
171 ssize_t offset
, event_rule_length
;
172 struct lttng_condition
*condition
= NULL
;
173 struct lttng_event_rule
*event_rule
= NULL
;
174 const struct lttng_condition_event_rule_comm
*header
;
175 const struct lttng_payload_view header_view
=
176 lttng_payload_view_from_view(
177 view
, 0, sizeof(*header
));
179 if (!view
|| !_condition
) {
183 if (!lttng_payload_view_is_valid(&header_view
)) {
184 ERR("Failed to initialize from malformed event rule condition: buffer too short to contain header");
188 header
= (const struct lttng_condition_event_rule_comm
*)
189 header_view
.buffer
.data
;
190 offset
= sizeof(*header
);
192 /* lttng_event_rule payload. */
194 struct lttng_payload_view event_rule_view
=
195 lttng_payload_view_from_view(view
, offset
, -1);
197 event_rule_length
= lttng_event_rule_create_from_payload(
198 &event_rule_view
, &event_rule
);
201 if (event_rule_length
< 0 || !event_rule
) {
205 if ((size_t) header
->event_rule_length
!= event_rule_length
) {
209 /* Move to the end of the payload. */
210 offset
+= header
->event_rule_length
;
212 /* Acquires a reference to the event rule. */
213 condition
= lttng_condition_event_rule_create(event_rule
);
218 *_condition
= condition
;
226 lttng_event_rule_put(event_rule
);
227 lttng_condition_put(condition
);
232 enum lttng_condition_status
lttng_condition_event_rule_borrow_rule_mutable(
233 const struct lttng_condition
*condition
,
234 struct lttng_event_rule
**rule
)
236 struct lttng_condition_event_rule
*event_rule
;
237 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
239 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !rule
) {
240 status
= LTTNG_CONDITION_STATUS_INVALID
;
244 event_rule
= container_of(
245 condition
, struct lttng_condition_event_rule
, parent
);
246 if (!event_rule
->rule
) {
247 status
= LTTNG_CONDITION_STATUS_UNSET
;
251 *rule
= event_rule
->rule
;
256 enum lttng_condition_status
lttng_condition_event_rule_get_rule(
257 const struct lttng_condition
*condition
,
258 const struct lttng_event_rule
**rule
)
260 struct lttng_event_rule
*mutable_rule
= NULL
;
261 const enum lttng_condition_status status
=
262 lttng_condition_event_rule_borrow_rule_mutable(
263 condition
, &mutable_rule
);
265 *rule
= mutable_rule
;
270 ssize_t
lttng_evaluation_event_rule_create_from_payload(
271 struct lttng_payload_view
*view
,
272 struct lttng_evaluation
**_evaluation
)
274 ssize_t ret
, offset
= 0;
275 const char *trigger_name
;
276 struct lttng_evaluation
*evaluation
= NULL
;
277 const struct lttng_evaluation_event_rule_comm
*header
;
278 const struct lttng_payload_view header_view
=
279 lttng_payload_view_from_view(
280 view
, 0, sizeof(*header
));
287 if (!lttng_payload_view_is_valid(&header_view
)) {
288 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header");
293 header
= (typeof(header
)) header_view
.buffer
.data
;
295 /* Map the originating trigger's name. */
296 offset
+= sizeof(*header
);
298 struct lttng_payload_view current_view
=
299 lttng_payload_view_from_view(view
, offset
,
300 header
->trigger_name_length
);
302 if (!lttng_payload_view_is_valid(¤t_view
)) {
303 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name");
308 trigger_name
= current_view
.buffer
.data
;
309 if (!lttng_buffer_view_contains_string(¤t_view
.buffer
,
310 trigger_name
, header
->trigger_name_length
)) {
311 ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name");
317 offset
+= header
->trigger_name_length
;
319 evaluation
= lttng_evaluation_event_rule_create(trigger_name
);
325 *_evaluation
= evaluation
;
330 lttng_evaluation_destroy(evaluation
);
334 static int lttng_evaluation_event_rule_serialize(
335 const struct lttng_evaluation
*evaluation
,
336 struct lttng_payload
*payload
)
339 struct lttng_evaluation_event_rule
*hit
;
340 struct lttng_evaluation_event_rule_comm comm
;
343 evaluation
, struct lttng_evaluation_event_rule
, parent
);
346 comm
.trigger_name_length
= strlen(hit
->name
) + 1;
348 ret
= lttng_dynamic_buffer_append(
349 &payload
->buffer
, &comm
, sizeof(comm
));
354 ret
= lttng_dynamic_buffer_append(
355 &payload
->buffer
, hit
->name
, comm
.trigger_name_length
);
360 static void lttng_evaluation_event_rule_destroy(
361 struct lttng_evaluation
*evaluation
)
363 struct lttng_evaluation_event_rule
*hit
;
366 evaluation
, struct lttng_evaluation_event_rule
, parent
);
372 struct lttng_evaluation
*lttng_evaluation_event_rule_create(
373 const char *trigger_name
)
375 struct lttng_evaluation_event_rule
*hit
;
376 struct lttng_evaluation
*evaluation
= NULL
;
378 hit
= zmalloc(sizeof(struct lttng_evaluation_event_rule
));
383 hit
->name
= strdup(trigger_name
);
388 hit
->parent
.type
= LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
389 hit
->parent
.serialize
= lttng_evaluation_event_rule_serialize
;
390 hit
->parent
.destroy
= lttng_evaluation_event_rule_destroy
;
392 evaluation
= &hit
->parent
;
397 lttng_evaluation_event_rule_destroy(&hit
->parent
);
403 enum lttng_evaluation_status
lttng_evaluation_event_rule_get_trigger_name(
404 const struct lttng_evaluation
*evaluation
, const char **name
)
406 struct lttng_evaluation_event_rule
*hit
;
407 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
409 if (!evaluation
|| !is_event_rule_evaluation(evaluation
) || !name
) {
410 status
= LTTNG_EVALUATION_STATUS_INVALID
;
415 evaluation
, struct lttng_evaluation_event_rule
, parent
);