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