Force usage of assert() condition when NDEBUG is defined
[lttng-tools.git] / src / common / conditions / condition.c
1 /*
2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/buffer-view.h>
9 #include <common/dynamic-buffer.h>
10 #include <common/error.h>
11 #include <common/macros.h>
12 #include <common/mi-lttng.h>
13 #include <lttng/condition/buffer-usage-internal.h>
14 #include <lttng/condition/condition-internal.h>
15 #include <lttng/condition/event-rule-matches-internal.h>
16 #include <lttng/condition/session-consumed-size-internal.h>
17 #include <lttng/condition/session-rotation-internal.h>
18 #include <lttng/error-query-internal.h>
19 #include <stdbool.h>
20
21 enum lttng_condition_type lttng_condition_get_type(
22 const struct lttng_condition *condition)
23 {
24 return condition ? condition->type : LTTNG_CONDITION_TYPE_UNKNOWN;
25 }
26
27 void lttng_condition_destroy(struct lttng_condition *condition)
28 {
29 lttng_condition_put(condition);
30 }
31
32 static void condition_destroy_ref(struct urcu_ref *ref)
33 {
34 struct lttng_condition *condition =
35 container_of(ref, struct lttng_condition, ref);
36
37 condition->destroy(condition);
38 }
39
40 LTTNG_HIDDEN
41 void lttng_condition_get(struct lttng_condition *condition)
42 {
43 urcu_ref_get(&condition->ref);
44 }
45
46 LTTNG_HIDDEN
47 void lttng_condition_put(struct lttng_condition *condition)
48 {
49 if (!condition) {
50 return;
51 }
52
53 LTTNG_ASSERT(condition->destroy);
54 urcu_ref_put(&condition->ref, condition_destroy_ref);
55 }
56
57
58 LTTNG_HIDDEN
59 bool lttng_condition_validate(const struct lttng_condition *condition)
60 {
61 bool valid;
62
63 if (!condition) {
64 valid = false;
65 goto end;
66 }
67
68 if (!condition->validate) {
69 /* Sub-class guarantees that it can never be invalid. */
70 valid = true;
71 goto end;
72 }
73
74 valid = condition->validate(condition);
75 end:
76 return valid;
77 }
78
79 LTTNG_HIDDEN
80 int lttng_condition_serialize(const struct lttng_condition *condition,
81 struct lttng_payload *payload)
82 {
83 int ret;
84 struct lttng_condition_comm condition_comm = {};
85
86 if (!condition) {
87 ret = -1;
88 goto end;
89 }
90
91 condition_comm.condition_type = (int8_t) condition->type;
92
93 ret = lttng_dynamic_buffer_append(&payload->buffer, &condition_comm,
94 sizeof(condition_comm));
95 if (ret) {
96 goto end;
97 }
98
99 ret = condition->serialize(condition, payload);
100 if (ret) {
101 goto end;
102 }
103 end:
104 return ret;
105 }
106
107 LTTNG_HIDDEN
108 bool lttng_condition_is_equal(const struct lttng_condition *a,
109 const struct lttng_condition *b)
110 {
111 bool is_equal = false;
112
113 if (!a || !b) {
114 goto end;
115 }
116
117 if (a->type != b->type) {
118 goto end;
119 }
120
121 if (a == b) {
122 is_equal = true;
123 goto end;
124 }
125
126 is_equal = a->equal ? a->equal(a, b) : true;
127 end:
128 return is_equal;
129 }
130
131 LTTNG_HIDDEN
132 ssize_t lttng_condition_create_from_payload(
133 struct lttng_payload_view *view,
134 struct lttng_condition **condition)
135 {
136 ssize_t ret, condition_size = 0;
137 condition_create_from_payload_cb create_from_payload = NULL;
138 const struct lttng_condition_comm *condition_comm;
139 const struct lttng_payload_view condition_comm_view =
140 lttng_payload_view_from_view(
141 view, 0, sizeof(*condition_comm));
142
143 if (!view || !condition) {
144 ret = -1;
145 goto end;
146 }
147
148 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
149 /* Payload not large enough to contain the header. */
150 ret = -1;
151 goto end;
152 }
153
154 DBG("Deserializing condition from buffer");
155 condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data;
156 condition_size += sizeof(*condition_comm);
157
158 switch ((enum lttng_condition_type) condition_comm->condition_type) {
159 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
160 create_from_payload = lttng_condition_buffer_usage_low_create_from_payload;
161 break;
162 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
163 create_from_payload = lttng_condition_buffer_usage_high_create_from_payload;
164 break;
165 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
166 create_from_payload = lttng_condition_session_consumed_size_create_from_payload;
167 break;
168 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
169 create_from_payload = lttng_condition_session_rotation_ongoing_create_from_payload;
170 break;
171 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
172 create_from_payload = lttng_condition_session_rotation_completed_create_from_payload;
173 break;
174 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
175 create_from_payload =
176 lttng_condition_event_rule_matches_create_from_payload;
177 break;
178 default:
179 ERR("Attempted to create condition of unknown type (%i)",
180 (int) condition_comm->condition_type);
181 ret = -1;
182 goto end;
183 }
184
185 if (create_from_payload) {
186 struct lttng_payload_view condition_view =
187 lttng_payload_view_from_view(view,
188 sizeof(*condition_comm), -1);
189
190 ret = create_from_payload(&condition_view, condition);
191 if (ret < 0) {
192 goto end;
193 }
194 condition_size += ret;
195
196 } else {
197 abort();
198 }
199
200 ret = condition_size;
201 end:
202 return ret;
203 }
204
205 LTTNG_HIDDEN
206 void lttng_condition_init(struct lttng_condition *condition,
207 enum lttng_condition_type type)
208 {
209 condition->type = type;
210 urcu_ref_init(&condition->ref);
211 }
212
213 LTTNG_HIDDEN
214 const char *lttng_condition_type_str(enum lttng_condition_type type)
215 {
216 switch (type) {
217 case LTTNG_CONDITION_TYPE_UNKNOWN:
218 return "unknown";
219
220 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
221 return "session consumed size";
222
223 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
224 return "buffer usage high";
225
226 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
227 return "buffer usage low";
228
229 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
230 return "session rotation ongoing";
231
232 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
233 return "session rotation completed";
234
235 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
236 return "event rule matches";
237
238 default:
239 return "???";
240 }
241 }
242
243 LTTNG_HIDDEN
244 enum lttng_error_code lttng_condition_mi_serialize(
245 const struct lttng_trigger *trigger,
246 const struct lttng_condition *condition,
247 struct mi_writer *writer,
248 const struct mi_lttng_error_query_callbacks *error_query_callbacks)
249 {
250 int ret;
251 enum lttng_error_code ret_code;
252 struct lttng_error_query_results *error_query_results = NULL;
253
254 LTTNG_ASSERT(condition);
255 LTTNG_ASSERT(writer);
256 LTTNG_ASSERT(condition->mi_serialize);
257
258 /* Open condition element. */
259 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_condition);
260 if (ret) {
261 goto mi_error;
262 }
263
264 /* Serialize underlying condition. */
265 ret_code = condition->mi_serialize(condition, writer);
266 if (ret_code != LTTNG_OK) {
267 goto end;
268 }
269
270 /* Serialize error query results for the action. */
271 if (error_query_callbacks && error_query_callbacks->action_cb) {
272 ret_code = error_query_callbacks->condition_cb(
273 trigger, &error_query_results);
274 if (ret_code != LTTNG_OK) {
275 goto end;
276 }
277
278 ret_code = lttng_error_query_results_mi_serialize(
279 error_query_results, writer);
280 if (ret_code != LTTNG_OK) {
281 goto end;
282 }
283 }
284
285 /* Close condition element. */
286 ret = mi_lttng_writer_close_element(writer);
287 if (ret) {
288 goto mi_error;
289 }
290
291 ret_code = LTTNG_OK;
292 goto end;
293
294 mi_error:
295 ret_code = LTTNG_ERR_MI_IO_FAIL;
296 end:
297 lttng_error_query_results_destroy(error_query_results);
298 return ret_code;
299 }
This page took 0.03448 seconds and 4 git commands to generate.