wip: receive trigger registration in session daemon
[lttng-tools.git] / src / lib / lttng-ctl / buffer-usage.c
1 /*
2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
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.
7 *
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
11 * for more details.
12 *
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
16 */
17
18 #include <lttng/condition/condition-internal.h>
19 #include <lttng/condition/buffer-usage-internal.h>
20 #include <common/macros.h>
21 #include <assert.h>
22
23 static
24 bool is_usage_condition(struct lttng_condition *condition)
25 {
26 enum lttng_condition_type type = lttng_condition_get_type(condition);
27
28 return type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW ||
29 type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH;
30 }
31
32 static
33 bool is_usage_evaluation(struct lttng_evaluation *evaluation)
34 {
35 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
36
37 return type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW ||
38 type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH;
39 }
40
41 static
42 void lttng_condition_buffer_usage_destroy(struct lttng_condition *condition)
43 {
44 struct lttng_condition_buffer_usage *usage;
45
46 usage = container_of(condition, struct lttng_condition_buffer_usage,
47 parent);
48
49 free(usage->session_name);
50 free(usage->channel_name);
51 free(usage);
52 }
53
54 static
55 bool lttng_condition_buffer_usage_validate(struct lttng_condition *condition)
56 {
57 bool valid = false;
58 struct lttng_condition_buffer_usage *usage;
59
60 if (!condition) {
61 goto end;
62 }
63
64 usage = container_of(condition, struct lttng_condition_buffer_usage,
65 parent);
66 if (!usage->session_name) {
67 goto end;
68 }
69 if (!usage->channel_name) {
70 goto end;
71 }
72 if (!usage->threshold_percent.set && !usage->threshold_bytes.set) {
73 goto end;
74 }
75
76 valid = true;
77 end:
78 return valid;
79 }
80
81 static
82 ssize_t lttng_condition_buffer_usage_serialize(struct lttng_condition *condition,
83 char *buf)
84 {
85 struct lttng_condition_buffer_usage *usage;
86 ssize_t size;
87 size_t session_name_len, channel_name_len;
88
89 if (!condition || !is_usage_condition(condition)) {
90 size = -1;
91 goto end;
92 }
93
94 usage = container_of(condition, struct lttng_condition_buffer_usage,
95 parent);
96 size = sizeof(struct lttng_condition_buffer_usage_comm);
97 session_name_len = strlen(usage->session_name) + 1;
98 channel_name_len = strlen(usage->channel_name) + 1;
99 size += session_name_len + channel_name_len;
100 if (buf) {
101 struct lttng_condition_buffer_usage_comm usage_comm = {
102 .threshold_set_in_bytes = usage->threshold_bytes.set ? 1 : 0,
103 .session_name_len = session_name_len,
104 .channel_name_len = channel_name_len,
105 .domain_type = (int8_t) usage->domain.type,
106 };
107
108 if (usage->threshold_bytes.set) {
109 usage_comm.threshold.bytes =
110 usage->threshold_bytes.value;
111 } else {
112 usage_comm.threshold.percent =
113 usage->threshold_percent.value;
114 }
115
116 memcpy(buf, &usage_comm, sizeof(usage_comm));
117 buf += sizeof(usage_comm);
118 memcpy(buf, usage->session_name, session_name_len);
119 buf += session_name_len;
120 memcpy(buf, usage->channel_name, channel_name_len);
121 buf += channel_name_len;
122 }
123 end:
124 return size;
125 }
126
127 static
128 struct lttng_condition *lttng_condition_buffer_usage_create(
129 enum lttng_condition_type type)
130 {
131 struct lttng_condition_buffer_usage *condition;
132
133 condition = zmalloc(sizeof(struct lttng_condition_buffer_usage));
134 if (!condition) {
135 goto end;
136 }
137
138 condition->parent.type = type;
139 condition->parent.validate = lttng_condition_buffer_usage_validate;
140 condition->parent.serialize = lttng_condition_buffer_usage_serialize;
141 condition->parent.destroy = lttng_condition_buffer_usage_destroy;
142 end:
143 return &condition->parent;
144 }
145
146 struct lttng_condition *lttng_condition_buffer_usage_low_create(void)
147 {
148 return lttng_condition_buffer_usage_create(
149 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
150 }
151
152 struct lttng_condition *lttng_condition_buffer_usage_high_create(void)
153 {
154 return lttng_condition_buffer_usage_create(
155 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
156 }
157
158 static
159 ssize_t init_from_buffer(struct lttng_condition *condition, const char *buf)
160 {
161 ssize_t ret, condition_size;
162 enum lttng_condition_status status;
163 enum lttng_domain_type domain_type;
164 struct lttng_condition_buffer_usage_comm *condition_comm =
165 (struct lttng_condition_buffer_usage_comm *) buf;
166 const char *session_name, *channel_name;
167
168 if (condition_comm->threshold_set_in_bytes) {
169 status = lttng_condition_buffer_usage_set_threshold(condition,
170 condition_comm->threshold.bytes);
171 } else {
172 status = lttng_condition_buffer_usage_set_threshold_percentage(
173 condition, condition_comm->threshold.percent);
174 }
175 if (status != LTTNG_CONDITION_STATUS_OK) {
176 ret = -1;
177 goto end;
178 }
179
180 if (condition_comm->domain_type <= LTTNG_DOMAIN_NONE ||
181 condition_comm->domain_type > LTTNG_DOMAIN_PYTHON) {
182 /* Invalid domain value. */
183 ret = -1;
184 goto end;
185 }
186
187 domain_type = (enum lttng_domain_type) condition_comm->domain_type;
188 status = lttng_condition_buffer_usage_set_domain_type(condition,
189 domain_type);
190 if (status != LTTNG_CONDITION_STATUS_OK) {
191 ret = -1;
192 goto end;
193 }
194
195 session_name = buf + sizeof(struct lttng_condition_buffer_usage_comm);
196 channel_name = session_name + condition_comm->session_name_len;
197
198 status = lttng_condition_buffer_usage_set_session_name(condition,
199 session_name);
200 if (status != LTTNG_CONDITION_STATUS_OK) {
201 ret = -1;
202 goto end;
203 }
204
205 status = lttng_condition_buffer_usage_set_channel_name(condition,
206 channel_name);
207 if (status != LTTNG_CONDITION_STATUS_OK) {
208 ret = -1;
209 goto end;
210 }
211
212 if (!lttng_condition_validate(condition)) {
213 ret = -1;
214 goto end;
215 }
216
217 condition_size = sizeof(*condition_comm);
218 condition_size += (ssize_t) condition_comm->session_name_len;
219 condition_size += (ssize_t) condition_comm->channel_name_len;
220 ret = condition_size;
221 end:
222 return ret;
223 }
224
225 LTTNG_HIDDEN
226 ssize_t lttng_condition_buffer_usage_low_create_from_buffer(const char *buf,
227 struct lttng_condition **_condition)
228 {
229 ssize_t ret;
230 struct lttng_condition *condition =
231 lttng_condition_buffer_usage_low_create();
232
233 if (!_condition || !condition) {
234 ret = -1;
235 goto error;
236 }
237
238 ret = init_from_buffer(condition, buf);
239 if (ret < 0) {
240 goto error;
241 }
242
243 *_condition = condition;
244 return ret;
245 error:
246 lttng_condition_destroy(condition);
247 return ret;
248 }
249
250 LTTNG_HIDDEN
251 ssize_t lttng_condition_buffer_usage_high_create_from_buffer(const char *buf,
252 struct lttng_condition **_condition)
253 {
254 ssize_t ret;
255 struct lttng_condition *condition =
256 lttng_condition_buffer_usage_high_create();
257
258 if (!_condition || !condition) {
259 ret = -1;
260 goto error;
261 }
262
263 ret = init_from_buffer(condition, buf);
264 if (ret < 0) {
265 goto error;
266 }
267
268 *_condition = condition;
269 return ret;
270 error:
271 lttng_condition_destroy(condition);
272 return ret;
273 }
274
275 enum lttng_condition_status
276 lttng_condition_buffer_usage_get_threshold_percentage(
277 struct lttng_condition *condition, double *threshold_percent)
278 {
279 struct lttng_condition_buffer_usage *usage;
280 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
281
282 if (!condition || !is_usage_condition(condition) ||
283 !threshold_percent) {
284 status = LTTNG_CONDITION_STATUS_INVALID;
285 goto end;
286 }
287
288 usage = container_of(condition, struct lttng_condition_buffer_usage,
289 parent);
290 if (!usage->threshold_percent.set) {
291 status = LTTNG_CONDITION_STATUS_UNSET;
292 goto end;
293 }
294 *threshold_percent = usage->threshold_percent.value;
295 end:
296 return status;
297 }
298
299 /* threshold_percent expressed as [0.0, 1.0]. */
300 enum lttng_condition_status
301 lttng_condition_buffer_usage_set_threshold_percentage(
302 struct lttng_condition *condition, double threshold_percent)
303 {
304 struct lttng_condition_buffer_usage *usage;
305 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
306
307 if (!condition || !is_usage_condition(condition) ||
308 threshold_percent < 0.0 || threshold_percent > 1.0) {
309 status = LTTNG_CONDITION_STATUS_INVALID;
310 goto end;
311 }
312
313 usage = container_of(condition, struct lttng_condition_buffer_usage,
314 parent);
315 usage->threshold_percent.set = true;
316 usage->threshold_bytes.set = false;
317 usage->threshold_percent.value = threshold_percent;
318 end:
319 return status;
320 }
321
322 enum lttng_condition_status
323 lttng_condition_buffer_usage_get_threshold(
324 struct lttng_condition *condition, uint64_t *threshold_bytes)
325 {
326 struct lttng_condition_buffer_usage *usage;
327 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
328
329 if (!condition || !is_usage_condition(condition) || !threshold_bytes) {
330 status = LTTNG_CONDITION_STATUS_INVALID;
331 goto end;
332 }
333
334 usage = container_of(condition, struct lttng_condition_buffer_usage,
335 parent);
336 if (!usage->threshold_bytes.set) {
337 status = LTTNG_CONDITION_STATUS_UNSET;
338 goto end;
339 }
340 *threshold_bytes = usage->threshold_bytes.value;
341 end:
342 return status;
343 }
344
345 enum lttng_condition_status
346 lttng_condition_buffer_usage_set_threshold(
347 struct lttng_condition *condition, uint64_t threshold_bytes)
348 {
349 struct lttng_condition_buffer_usage *usage;
350 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
351
352 if (!condition || !is_usage_condition(condition)) {
353 status = LTTNG_CONDITION_STATUS_INVALID;
354 goto end;
355 }
356
357 usage = container_of(condition, struct lttng_condition_buffer_usage,
358 parent);
359 usage->threshold_percent.set = false;
360 usage->threshold_bytes.set = true;
361 usage->threshold_bytes.value = threshold_bytes;
362 end:
363 return status;
364 }
365
366 enum lttng_condition_status
367 lttng_condition_buffer_usage_get_session_name(
368 struct lttng_condition *condition, const char **session_name)
369 {
370 struct lttng_condition_buffer_usage *usage;
371 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
372
373 if (!condition || !is_usage_condition(condition) || !session_name) {
374 status = LTTNG_CONDITION_STATUS_INVALID;
375 goto end;
376 }
377
378 usage = container_of(condition, struct lttng_condition_buffer_usage,
379 parent);
380 if (!usage->session_name) {
381 status = LTTNG_CONDITION_STATUS_UNSET;
382 goto end;
383 }
384 *session_name = usage->session_name;
385 end:
386 return status;
387 }
388
389 extern enum lttng_condition_status
390 lttng_condition_buffer_usage_set_session_name(
391 struct lttng_condition *condition, const char *session_name)
392 {
393 struct lttng_condition_buffer_usage *usage;
394 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
395
396 if (!condition || !is_usage_condition(condition) || !session_name ||
397 strlen(session_name) == 0) {
398 status = LTTNG_CONDITION_STATUS_INVALID;
399 goto end;
400 }
401
402 usage = container_of(condition, struct lttng_condition_buffer_usage,
403 parent);
404 usage->session_name = strdup(session_name);
405 if (!usage->session_name) {
406 status = LTTNG_CONDITION_STATUS_ERROR;
407 goto end;
408 }
409 end:
410 return status;
411 }
412
413 enum lttng_condition_status
414 lttng_condition_buffer_usage_get_channel_name(
415 struct lttng_condition *condition, const char **channel_name)
416 {
417 struct lttng_condition_buffer_usage *usage;
418 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
419
420 if (!condition || !is_usage_condition(condition) || !channel_name) {
421 status = LTTNG_CONDITION_STATUS_INVALID;
422 goto end;
423 }
424
425 usage = container_of(condition, struct lttng_condition_buffer_usage,
426 parent);
427 if (!usage->channel_name) {
428 status = LTTNG_CONDITION_STATUS_UNSET;
429 goto end;
430 }
431 *channel_name = usage->channel_name;
432 end:
433 return status;
434 }
435
436 extern enum lttng_condition_status
437 lttng_condition_buffer_usage_set_channel_name(
438 struct lttng_condition *condition, const char *channel_name)
439 {
440 struct lttng_condition_buffer_usage *usage;
441 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
442
443 if (!condition || !is_usage_condition(condition) || !channel_name ||
444 strlen(channel_name) == 0) {
445 status = LTTNG_CONDITION_STATUS_INVALID;
446 goto end;
447 }
448
449 usage = container_of(condition, struct lttng_condition_buffer_usage,
450 parent);
451 usage->channel_name = strdup(channel_name);
452 if (!usage->channel_name) {
453 status = LTTNG_CONDITION_STATUS_ERROR;
454 goto end;
455 }
456 end:
457 return status;
458 }
459
460 extern enum lttng_condition_status
461 lttng_condition_buffer_usage_get_domain_type(
462 struct lttng_condition *condition, enum lttng_domain_type *type)
463 {
464 struct lttng_condition_buffer_usage *usage;
465 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
466
467 if (!condition || !is_usage_condition(condition) || !type) {
468 status = LTTNG_CONDITION_STATUS_INVALID;
469 goto end;
470 }
471
472 usage = container_of(condition, struct lttng_condition_buffer_usage,
473 parent);
474 if (!usage->domain.set) {
475 status = LTTNG_CONDITION_STATUS_UNSET;
476 goto end;
477 }
478 *type = usage->domain.type;
479 end:
480 return status;
481 }
482
483 extern enum lttng_condition_status
484 lttng_condition_buffer_usage_set_domain_type(
485 struct lttng_condition *condition, enum lttng_domain_type type)
486 {
487 struct lttng_condition_buffer_usage *usage;
488 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
489
490 if (!condition || !is_usage_condition(condition) ||
491 type == LTTNG_DOMAIN_NONE) {
492 status = LTTNG_CONDITION_STATUS_INVALID;
493 goto end;
494 }
495
496 usage = container_of(condition, struct lttng_condition_buffer_usage,
497 parent);
498 usage->domain.set = true;
499 usage->domain.type = type;
500 end:
501 return status;
502 }
503
504 static
505 void lttng_evaluation_buffer_usage_destroy(
506 struct lttng_evaluation *evaluation)
507 {
508 struct lttng_evaluation_buffer_usage *usage;
509
510 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
511 parent);
512 free(usage);
513 }
514
515 LTTNG_HIDDEN
516 struct lttng_evaluation *lttng_evaluation_buffer_usage_create(uint64_t use,
517 uint64_t capacity)
518 {
519 struct lttng_evaluation_buffer_usage *usage;
520
521 usage = zmalloc(sizeof(struct lttng_evaluation_buffer_usage));
522 if (!usage) {
523 goto end;
524 }
525
526 usage->buffer_use = use;
527 usage->buffer_capacity = capacity;
528 usage->parent.destroy = lttng_evaluation_buffer_usage_destroy;
529 end:
530 return &usage->parent;
531 }
532
533 /*
534 * Get the sampled buffer usage which caused the associated condition to
535 * evaluate to "true".
536 */
537 enum lttng_evaluation_status
538 lttng_evaluation_buffer_usage_get_usage_percentage(
539 struct lttng_evaluation *evaluation, double *usage_percent)
540 {
541 struct lttng_evaluation_buffer_usage *usage;
542 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
543
544 if (!evaluation || !is_usage_evaluation(evaluation) || !usage_percent) {
545 status = LTTNG_EVALUATION_STATUS_INVALID;
546 goto end;
547 }
548
549 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
550 parent);
551 *usage_percent = (double) usage->buffer_use /
552 (double) usage->buffer_capacity;
553 end:
554 return status;
555 }
556
557 enum lttng_evaluation_status
558 lttng_evaluation_buffer_usage_get_usage(struct lttng_evaluation *evaluation,
559 uint64_t *usage_bytes)
560 {
561 struct lttng_evaluation_buffer_usage *usage;
562 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
563
564 if (!evaluation || !is_usage_evaluation(evaluation) || !usage_bytes) {
565 status = LTTNG_EVALUATION_STATUS_INVALID;
566 goto end;
567 }
568
569 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
570 parent);
571 *usage_bytes = usage->buffer_use;
572 end:
573 return status;
574 }
This page took 0.041413 seconds and 5 git commands to generate.