Fix: pthread::mutex unlock must not throw
[lttng-tools.git] / src / common / log-level-rule.cpp
1 /*
2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/dynamic-buffer.hpp>
9 #include <common/error.hpp>
10 #include <common/hashtable/hashtable.hpp>
11 #include <common/hashtable/utils.hpp>
12 #include <common/macros.hpp>
13 #include <common/mi-lttng.hpp>
14 #include <lttng/log-level-rule-internal.hpp>
15 #include <lttng/log-level-rule.h>
16 #include <stdbool.h>
17 #include <stdlib.h>
18
19 static bool is_log_level_rule_exactly_type(const struct lttng_log_level_rule *rule)
20 {
21 enum lttng_log_level_rule_type type =
22 lttng_log_level_rule_get_type(rule);
23
24 return type == LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY;
25 }
26
27 static bool is_log_level_rule_at_least_as_severe_type(const struct lttng_log_level_rule *rule)
28 {
29
30 enum lttng_log_level_rule_type type =
31 lttng_log_level_rule_get_type(rule);
32
33 return type == LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS;
34 }
35
36 enum lttng_log_level_rule_type lttng_log_level_rule_get_type(
37 const struct lttng_log_level_rule *rule)
38 {
39 return rule ? rule->type : LTTNG_LOG_LEVEL_RULE_TYPE_UNKNOWN;
40 }
41
42 struct lttng_log_level_rule *lttng_log_level_rule_exactly_create(
43 int level)
44 {
45 struct lttng_log_level_rule *rule = NULL;
46
47 rule = zmalloc<lttng_log_level_rule>();
48 if (!rule) {
49 goto end;
50 }
51
52 rule->type = LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY;
53 rule->level = level;
54
55 end:
56 return rule;
57 }
58
59 enum lttng_log_level_rule_status lttng_log_level_rule_exactly_get_level(
60 const struct lttng_log_level_rule *rule, int *level)
61 {
62 enum lttng_log_level_rule_status status =
63 LTTNG_LOG_LEVEL_RULE_STATUS_OK;
64
65 if (!rule || !level || !is_log_level_rule_exactly_type(rule)) {
66 status = LTTNG_LOG_LEVEL_RULE_STATUS_INVALID;
67 goto end;
68 }
69
70 *level = rule->level;
71 end:
72 return status;
73 }
74
75 struct lttng_log_level_rule *
76 lttng_log_level_rule_at_least_as_severe_as_create(int level)
77 {
78 struct lttng_log_level_rule *rule = NULL;
79
80 rule = zmalloc<lttng_log_level_rule>();
81 if (!rule) {
82 goto end;
83 }
84
85 rule->type = LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS;
86 rule->level = level;
87
88 end:
89 return rule;
90 }
91
92 enum lttng_log_level_rule_status
93 lttng_log_level_rule_at_least_as_severe_as_get_level(
94 const struct lttng_log_level_rule *rule, int *level)
95 {
96 enum lttng_log_level_rule_status status = LTTNG_LOG_LEVEL_RULE_STATUS_OK;
97
98 if (!rule || !level ||
99 !is_log_level_rule_at_least_as_severe_type(rule)) {
100 status = LTTNG_LOG_LEVEL_RULE_STATUS_INVALID;
101 goto end;
102 }
103
104 *level = rule->level;
105 end:
106 return status;
107 }
108
109 void lttng_log_level_rule_destroy(struct lttng_log_level_rule *log_level_rule)
110 {
111 free(log_level_rule);
112 }
113
114 ssize_t lttng_log_level_rule_create_from_payload(
115 struct lttng_payload_view *view,
116 struct lttng_log_level_rule **_rule)
117 {
118 ssize_t ret;
119 size_t offset = 0;
120 struct lttng_log_level_rule *rule = NULL;
121 const struct lttng_log_level_rule_comm *comm =
122 (const struct lttng_log_level_rule_comm *)
123 view->buffer.data;
124
125 offset += sizeof(*comm);
126
127 if (!_rule) {
128 ret = -1;
129 goto end;
130 }
131
132 if (view->buffer.size < sizeof(*comm)) {
133 ret = -1;
134 goto end;
135 }
136
137 switch (comm->type) {
138 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
139 rule = lttng_log_level_rule_exactly_create((int) comm->level);
140 break;
141 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
142 rule = lttng_log_level_rule_at_least_as_severe_as_create(
143 (int) comm->level);
144 break;
145 default:
146 abort();
147 }
148
149 if (!rule) {
150 ret = -1;
151 goto end;
152 }
153
154 *_rule = rule;
155 ret = offset;
156
157 end:
158 return ret;
159 }
160
161 int lttng_log_level_rule_serialize(const struct lttng_log_level_rule *rule,
162 struct lttng_payload *payload)
163 {
164 int ret;
165 struct lttng_log_level_rule_comm comm;
166
167
168 if (!rule) {
169 ret = 0;
170 goto end;
171 }
172
173 comm.type = (int8_t) rule->type;
174 comm.level = (int32_t) rule->level;
175
176 DBG("Serializing log level rule of type %d", rule->type);
177 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm,
178 sizeof(comm));
179 if (ret) {
180 goto end;
181 }
182
183 end:
184 return ret;
185 }
186
187 bool lttng_log_level_rule_is_equal(const struct lttng_log_level_rule *a,
188 const struct lttng_log_level_rule *b)
189 {
190 bool is_equal = false;
191
192 if (a == NULL && b == NULL) {
193 /* Both are null. */
194 is_equal = true;
195 goto end;
196 }
197
198 if (a == NULL || b == NULL) {
199 /* One is NULL.*/
200 goto end;
201 }
202
203 if (a == b) {
204 /* Same object.*/
205 is_equal = true;
206 goto end;
207 }
208
209 if (a->type != b->type) {
210 goto end;
211 }
212
213 if (a->level != b->level) {
214 goto end;
215 }
216
217 is_equal = true;
218
219 end:
220 return is_equal;
221 }
222
223 struct lttng_log_level_rule *lttng_log_level_rule_copy(
224 const struct lttng_log_level_rule *source)
225 {
226 struct lttng_log_level_rule *copy = NULL;
227
228 LTTNG_ASSERT(source);
229
230 copy = zmalloc<lttng_log_level_rule>();
231 if (!copy) {
232 goto end;
233 }
234
235 copy->type = source->type;
236 copy->level = source->level;
237 end:
238 return copy;
239 }
240
241 void lttng_log_level_rule_to_loglevel(
242 const struct lttng_log_level_rule *log_level_rule,
243 enum lttng_loglevel_type *loglevel_type,
244 int *loglevel_value)
245 {
246 LTTNG_ASSERT(log_level_rule);
247
248 switch (log_level_rule->type) {
249 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
250 *loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
251 break;
252 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
253 *loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
254 break;
255 default:
256 abort();
257 }
258
259 *loglevel_value = log_level_rule->level;
260 }
261
262 unsigned long lttng_log_level_rule_hash(
263 const struct lttng_log_level_rule *log_level_rule)
264 {
265 unsigned long hash;
266 enum lttng_log_level_rule_status llr_status;
267 int log_level_value;
268 enum lttng_log_level_rule_type type;
269
270 LTTNG_ASSERT(log_level_rule);
271
272 type = lttng_log_level_rule_get_type(log_level_rule);
273
274 switch (type) {
275 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
276 llr_status = lttng_log_level_rule_exactly_get_level(
277 log_level_rule, &log_level_value);
278 break;
279 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
280 llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
281 log_level_rule, &log_level_value);
282 break;
283 default:
284 abort();
285 break;
286 }
287
288 LTTNG_ASSERT(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
289
290 hash = hash_key_ulong((void *) (unsigned long) type, lttng_ht_seed);
291
292 hash ^= hash_key_ulong((void *) (unsigned long) log_level_value,
293 lttng_ht_seed);
294
295 return hash;
296 }
297
298 enum lttng_error_code lttng_log_level_rule_mi_serialize(
299 const struct lttng_log_level_rule *rule,
300 struct mi_writer *writer)
301 {
302 int ret;
303 enum lttng_error_code ret_code;
304 enum lttng_log_level_rule_status status;
305 const char *element_str = NULL;
306 int level;
307
308 LTTNG_ASSERT(rule);
309 LTTNG_ASSERT(writer);
310
311 switch (lttng_log_level_rule_get_type(rule)) {
312 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
313 status = lttng_log_level_rule_exactly_get_level(rule, &level);
314 element_str = mi_lttng_element_log_level_rule_exactly;
315 break;
316 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
317 element_str = mi_lttng_element_log_level_rule_at_least_as_severe_as;
318 status = lttng_log_level_rule_at_least_as_severe_as_get_level(
319 rule, &level);
320 break;
321 default:
322 abort();
323 break;
324 }
325
326 LTTNG_ASSERT(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
327
328 /* Open log level rule element. */
329 ret = mi_lttng_writer_open_element(
330 writer, mi_lttng_element_log_level_rule);
331 if (ret) {
332 goto mi_error;
333 }
334
335 /* Log level rule type element. */
336 ret = mi_lttng_writer_open_element(writer, element_str);
337 if (ret) {
338 goto mi_error;
339 }
340
341 /* Level. */
342 ret = mi_lttng_writer_write_element_signed_int(
343 writer, mi_lttng_element_log_level_rule_level, level);
344 if (ret) {
345 goto mi_error;
346 }
347
348 /* Close log level rule type element. */
349 ret = mi_lttng_writer_close_element(writer);
350 if (ret) {
351 goto mi_error;
352 }
353
354 /* Close log level rule element. */
355 ret = mi_lttng_writer_close_element(writer);
356 if (ret) {
357 goto mi_error;
358 }
359
360 ret_code = LTTNG_OK;
361 goto end;
362
363 mi_error:
364 ret_code = LTTNG_ERR_MI_IO_FAIL;
365 end:
366 return ret_code;
367 }
This page took 0.0377690000000001 seconds and 4 git commands to generate.