2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
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.
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
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
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>
26 #define IS_EVENT_RULE_CONDITION(condition) ( \
27 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT \
31 bool is_event_rule_evaluation(const struct lttng_evaluation
*evaluation
)
33 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
35 return type
== LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
40 bool lttng_condition_event_rule_validate(
41 const struct lttng_condition
*condition
);
43 int lttng_condition_event_rule_serialize(
44 const struct lttng_condition
*condition
,
45 struct lttng_dynamic_buffer
*buf
,
48 bool lttng_condition_event_rule_is_equal(const struct lttng_condition
*_a
,
49 const struct lttng_condition
*_b
);
51 void lttng_condition_event_rule_destroy(
52 struct lttng_condition
*condition
);
56 bool lttng_condition_event_rule_validate(
57 const struct lttng_condition
*condition
)
60 struct lttng_condition_event_rule
*event_rule
;
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.");
73 valid
= lttng_event_rule_validate(event_rule
->rule
);
79 int lttng_condition_event_rule_serialize(
80 const struct lttng_condition
*condition
,
81 struct lttng_dynamic_buffer
*buf
,
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
;
90 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
95 DBG("Serializing event rule condition");
96 event_rule
= container_of(condition
, struct lttng_condition_event_rule
,
99 header_offset
= buf
->size
;
100 ret
= lttng_dynamic_buffer_append(buf
, &event_rule_comm
,
101 sizeof(event_rule_comm
));
106 size_before_payload
= buf
->size
;
107 ret
= lttng_event_rule_serialize(event_rule
->rule
, buf
, fd_to_send
);
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
;
121 bool lttng_condition_event_rule_is_equal(const struct lttng_condition
*_a
,
122 const struct lttng_condition
*_b
)
124 bool is_equal
= false;
125 struct lttng_condition_event_rule
*a
, *b
;
127 a
= container_of(_a
, struct lttng_condition_event_rule
, parent
);
128 b
= container_of(_b
, struct lttng_condition_event_rule
, parent
);
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.");
137 is_equal
= lttng_event_rule_is_equal(a
->rule
, b
->rule
);
143 void lttng_condition_event_rule_destroy(
144 struct lttng_condition
*condition
)
146 struct lttng_condition_event_rule
*event_rule
;
148 event_rule
= container_of(condition
,
149 struct lttng_condition_event_rule
, parent
);
152 lttng_event_rule_destroy(event_rule
->rule
);
156 struct lttng_condition
*lttng_condition_event_rule_create(
157 struct lttng_event_rule
*rule
)
159 struct lttng_condition
*parent
= NULL
;
160 struct lttng_condition_event_rule
*condition
= NULL
;
166 condition
= zmalloc(sizeof(struct lttng_condition_event_rule
));
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
,
177 condition
->rule
= rule
;
178 parent
= &condition
->parent
;
184 ssize_t
lttng_condition_event_rule_create_from_buffer(
185 const struct lttng_buffer_view
*view
,
186 struct lttng_condition
**_condition
)
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
;
194 if (!view
|| !_condition
) {
198 if (view
->size
< sizeof(*comm
)) {
199 ERR("Failed to initialize from malformed event rule condition: buffer too short to contain header");
203 comm
= (const struct lttng_condition_event_rule_comm
*) view
->data
;
204 offset
= sizeof(*comm
);
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
) {
213 if ((size_t) comm
->length
!= event_rule_size
) {
217 /* Move to the end */
218 offset
+= comm
->length
;
220 condition
= lttng_condition_event_rule_create(event_rule
);
225 /* Ownership passed on condition event rule create */
228 *_condition
= condition
;
236 lttng_event_rule_destroy(event_rule
);
237 lttng_condition_destroy(condition
);
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
)
247 struct lttng_condition_event_rule
*event_rule
;
248 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
250 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !rule
) {
251 status
= LTTNG_CONDITION_STATUS_INVALID
;
255 event_rule
= container_of(condition
, struct lttng_condition_event_rule
,
257 if (!event_rule
->rule
) {
258 status
= LTTNG_CONDITION_STATUS_UNSET
;
261 *rule
= event_rule
->rule
;
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
)
271 struct lttng_event_rule
*no_const_rule
= NULL
;
272 enum lttng_condition_status status
;
274 status
= lttng_condition_event_rule_get_rule_no_const(condition
, &no_const_rule
);
275 *rule
= no_const_rule
;
280 ssize_t
lttng_evaluation_event_rule_create_from_buffer(
281 const struct lttng_buffer_view
*view
,
282 struct lttng_evaluation
**_evaluation
)
284 ssize_t ret
, offset
= 0;
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
;
296 if (view
->size
< sizeof(*comm
)) {
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
;
310 if (comm
->trigger_name_length
== 1 ||
311 name
[comm
->trigger_name_length
- 1] != '\0' ||
312 strlen(name
) != comm
->trigger_name_length
- 1) {
314 * Check that the name is not NULL, is NULL-terminated, and
315 * does not contain a NULL before the last byte.
321 offset
+= comm
->trigger_name_length
;
323 evaluation
= lttng_evaluation_event_rule_create(name
);
329 *_evaluation
= evaluation
;
334 lttng_evaluation_destroy(evaluation
);
339 int lttng_evaluation_event_rule_serialize(
340 const struct lttng_evaluation
*evaluation
,
341 struct lttng_dynamic_buffer
*buf
)
344 struct lttng_evaluation_event_rule
*hit
;
345 struct lttng_evaluation_event_rule_comm comm
;
347 hit
= container_of(evaluation
, struct lttng_evaluation_event_rule
,
349 comm
.trigger_name_length
= strlen(hit
->name
) + 1;
350 ret
= lttng_dynamic_buffer_append(buf
, &comm
, sizeof(comm
));
354 ret
= lttng_dynamic_buffer_append(buf
, hit
->name
, comm
.trigger_name_length
);
360 void lttng_evaluation_event_rule_destroy(
361 struct lttng_evaluation
*evaluation
)
363 struct lttng_evaluation_event_rule
*hit
;
365 hit
= container_of(evaluation
, struct lttng_evaluation_event_rule
,
372 struct lttng_evaluation
*lttng_evaluation_event_rule_create(const char *trigger_name
)
374 struct lttng_evaluation_event_rule
*hit
;
376 hit
= zmalloc(sizeof(struct lttng_evaluation_event_rule
));
381 /* TODO errir handling */
382 hit
->name
= strdup(trigger_name
);
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
;
391 enum lttng_evaluation_status
392 lttng_evaluation_event_rule_get_trigger_name(
393 const struct lttng_evaluation
*evaluation
,
396 struct lttng_evaluation_event_rule
*hit
;
397 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
399 if (!evaluation
|| !is_event_rule_evaluation(evaluation
) || !name
) {
400 status
= LTTNG_EVALUATION_STATUS_INVALID
;
404 hit
= container_of(evaluation
, struct lttng_evaluation_event_rule
,