Move "active" code out of debug statements
[lttv.git] / lttv / lttv / filter.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2005 Michel Dagenais and Simon Bouvier-Zappa
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 /*! \file lttv/lttv/filter.c
20 * \brief Defines the core filter of application
21 *
22 * consist in AND, OR and NOT nested expressions, forming a tree with
23 * simple relations as leaves. The simple relations test if a field
24 * in an event is equal, not equal, smaller, smaller or equal, larger, or
25 * larger or equal to a specified value.
26 *
27 * Fields specified in a simple expression can take following
28 * values
29 *
30 * \verbatim
31 * LttvTracefileContext{}
32 * |->event\
33 * | |->name (String, converted to GQuark) (channel.event)
34 * | |->subname (String, converted to GQuark)
35 * | |->category (String, not yet implemented)
36 * | |->time (LttTime)
37 * | |->tsc (LttCycleCount --> uint64)
38 * | |->target_pid (target PID of the event)
39 * | |->fields
40 * | |->"channel name"
41 * | |->"event name"
42 * | |->"field name"
43 * | |->"sub-field name"
44 * | |->...
45 * | |->"leaf-field name" (field type)
46 * |->channel (or tracefile)
47 * | |->name (String, converted to GQuark)
48 * |->trace
49 * | |->name (String, converted to GQuark)
50 * |->state
51 * |->pid (guint)
52 * |->ppid (guint)
53 * |->creation_time (LttTime)
54 * |->insertion_time (LttTime)
55 * |->process_name (String, converted to GQuark)
56 * |->thread_brand (String, converted to GQuark)
57 * |->execution_mode (LttvExecutionMode)
58 * |->execution_submode (LttvExecutionSubmode)
59 * |->process_status (LttvProcessStatus)
60 * |->cpu (guint)
61 * \endverbatim
62 */
63
64 /*
65 * \todo
66 * - refine switch of expression in multiple uses functions
67 * - remove the idle expressions in the tree
68 */
69
70 #ifdef HAVE_CONFIG_H
71 #include <config.h>
72 #endif
73
74 //#define TEST
75 #ifdef TEST
76 #include <time.h>
77 #include <sys/time.h>
78 #endif
79
80 #include <lttv/lttv.h>
81 #include <lttv/filter.h>
82 #include <ltt/trace.h>
83 #include <stdlib.h>
84 #include <string.h>
85
86 /**
87 * @fn LttvSimpleExpression* lttv_simple_expression_new()
88 *
89 * Constructor for LttvSimpleExpression
90 * @return pointer to new LttvSimpleExpression
91 */
92 LttvSimpleExpression*
93 lttv_simple_expression_new() {
94
95 LttvSimpleExpression* se = g_new(LttvSimpleExpression,1);
96
97 se->field = LTTV_FILTER_UNDEFINED;
98 se->op = NULL;
99 se->offset = 0;
100
101 return se;
102 }
103
104 /*
105 * Keeps the array order.
106 */
107 static inline gpointer ltt_g_ptr_array_remove_index_slow(GPtrArray *fp,
108 int index)
109 {
110 gpointer ptr;
111 int i;
112
113 if (fp->len == 0)
114 return NULL;
115
116 ptr = g_ptr_array_index(fp, index);
117 for (i = index; i < fp->len - 1; i++) {
118 g_ptr_array_index(fp, i) = g_ptr_array_index(fp, i + 1);
119 }
120 g_ptr_array_remove_index(fp, fp->len - 1);
121 return ptr;
122 }
123
124 /**
125 * @fn gboolean lttv_simple_expression_assign_field(GPtrArray*,LttvSimpleExpression*)
126 *
127 * Parse through filtering field hierarchy as specified
128 * by user. This function compares each value to
129 * predetermined quarks
130 * @param fp The field path list
131 * @param se current simple expression
132 * @return success/failure of operation
133 */
134 gboolean
135 lttv_simple_expression_assign_field(GPtrArray* fp, LttvSimpleExpression* se) {
136
137 GString* f = NULL;
138
139 if(fp->len < 2) return FALSE;
140 f=ltt_g_ptr_array_remove_index_slow(fp,0);
141 g_assert(f);
142
143
144 /*
145 * Parse through the specified
146 * hardcoded fields.
147 *
148 * Take note however that the
149 * 'event' subfields might change
150 * depending on values specified
151 * in core.xml file. Hence, if
152 * none of the subfields in the
153 * array match the hardcoded
154 * subfields, it will be considered
155 * as a dynamic field
156 */
157
158 if(!g_strcasecmp(f->str,"trace") ) {
159 /*
160 * Possible values:
161 * trace.name
162 */
163 g_string_free(f,TRUE);
164 f=ltt_g_ptr_array_remove_index_slow(fp,0);
165 if(!g_strcasecmp(f->str,"name")) {
166 se->field = LTTV_FILTER_TRACE_NAME;
167 }
168 } else if(!g_strcasecmp(f->str,"traceset") ) {
169 /*
170 * FIXME: not yet implemented !
171 */
172 } else if(!g_strcasecmp(f->str,"tracefile")
173 || !g_strcasecmp(f->str,"channel") ) {
174 /*
175 * Possible values:
176 * tracefile.name
177 * channel.name
178 */
179 g_string_free(f,TRUE);
180 f=ltt_g_ptr_array_remove_index_slow(fp,0);
181 if(!g_strcasecmp(f->str,"name")) {
182 se->field = LTTV_FILTER_TRACEFILE_NAME;
183 }
184 } else if(!g_strcasecmp(f->str,"state") ) {
185 /*
186 * Possible values:
187 * state.pid
188 * state.ppid
189 * state.creation_time
190 * state.insertion_time
191 * state.process_name
192 * state.thread_brand
193 * state.execution_mode
194 * state.execution_submode
195 * state.process_status
196 * state.cpu
197 */
198 g_string_free(f,TRUE);
199 f=ltt_g_ptr_array_remove_index_slow(fp,0);
200 if(!g_strcasecmp(f->str,"pid") ) {
201 se->field = LTTV_FILTER_STATE_PID;
202 }
203 else if(!g_strcasecmp(f->str,"ppid") ) {
204 se->field = LTTV_FILTER_STATE_PPID;
205 }
206 else if(!g_strcasecmp(f->str,"creation_time") ) {
207 se->field = LTTV_FILTER_STATE_CT;
208 }
209 else if(!g_strcasecmp(f->str,"insertion_time") ) {
210 se->field = LTTV_FILTER_STATE_IT;
211 }
212 else if(!g_strcasecmp(f->str,"process_name") ) {
213 se->field = LTTV_FILTER_STATE_P_NAME;
214 }
215 else if(!g_strcasecmp(f->str,"thread_brand") ) {
216 se->field = LTTV_FILTER_STATE_T_BRAND;
217 }
218 else if(!g_strcasecmp(f->str,"execution_mode") ) {
219 se->field = LTTV_FILTER_STATE_EX_MODE;
220 }
221 else if(!g_strcasecmp(f->str,"execution_submode") ) {
222 se->field = LTTV_FILTER_STATE_EX_SUBMODE;
223 }
224 else if(!g_strcasecmp(f->str,"process_status") ) {
225 se->field = LTTV_FILTER_STATE_P_STATUS;
226 }
227 else if(!g_strcasecmp(f->str,"cpu") ) {
228 se->field = LTTV_FILTER_STATE_CPU;
229 }
230 } else if(!g_strcasecmp(f->str,"event") ) {
231 /*
232 * Possible values:
233 * event.name
234 * event.channel
235 * event.category
236 * event.time
237 * event.tsc
238 * event.target_pid
239 * event.field
240 */
241 g_string_free(f,TRUE);
242 f=ltt_g_ptr_array_remove_index_slow(fp,0);
243
244 if(!g_strcasecmp(f->str,"name") ) {
245 se->field = LTTV_FILTER_EVENT_NAME;
246 }
247 else if(!g_strcasecmp(f->str,"subname") ) {
248 se->field = LTTV_FILTER_EVENT_SUBNAME;
249 }
250 else if(!g_strcasecmp(f->str,"category") ) {
251 /*
252 * FIXME: Category not yet functional in lttv
253 */
254 se->field = LTTV_FILTER_EVENT_CATEGORY;
255 }
256 else if(!g_strcasecmp(f->str,"time") ) {
257 se->field = LTTV_FILTER_EVENT_TIME;
258 }
259 else if(!g_strcasecmp(f->str,"tsc") ) {
260 se->field = LTTV_FILTER_EVENT_TSC;
261 }
262 else if(!g_strcasecmp(f->str,"target_pid") ) {
263 se->field = LTTV_FILTER_EVENT_TARGET_PID;
264 }
265 else if(!g_strcasecmp(f->str,"field") ) {
266 se->field = LTTV_FILTER_EVENT_FIELD;
267 g_string_free(f,TRUE);
268 f=ltt_g_ptr_array_remove_index_slow(fp,0);
269
270 } else {
271 //g_string_free(f,TRUE);
272 //f=ltt_g_ptr_array_remove_index_slow(fp,0);
273 g_warning("Unknown event filter subtype %s", f->str);
274 }
275 } else {
276 g_string_free(f,TRUE);
277 f=ltt_g_ptr_array_remove_index_slow(fp,0);
278
279 g_warning("Unrecognized field in filter string");
280 }
281
282 /* free memory for last string */
283 g_string_free(f,TRUE);
284
285 /* array should be empty */
286 g_assert(fp->len == 0);
287
288 if(se->field == LTTV_FILTER_UNDEFINED) {
289 g_warning("The specified field was not recognized !");
290 return FALSE;
291 }
292 return TRUE;
293 }
294
295 /**
296 * @fn gboolean lttv_simple_expression_assign_operator(LttvSimpleExpression*,LttvExpressionOp)
297 *
298 * Sets the function pointer for the current
299 * Simple Expression
300 * @param se current simple expression
301 * @param op current operator
302 * @return success/failure of operation
303 */
304 gboolean
305 lttv_simple_expression_assign_operator(LttvSimpleExpression* se, LttvExpressionOp op) {
306
307 switch(se->field) {
308 /*
309 * string
310 */
311 case LTTV_FILTER_TRACE_NAME:
312 case LTTV_FILTER_TRACEFILE_NAME:
313 case LTTV_FILTER_STATE_P_NAME:
314 case LTTV_FILTER_STATE_T_BRAND:
315 case LTTV_FILTER_EVENT_SUBNAME:
316 case LTTV_FILTER_STATE_EX_MODE:
317 case LTTV_FILTER_STATE_EX_SUBMODE:
318 case LTTV_FILTER_STATE_P_STATUS:
319 switch(op) {
320 case LTTV_FIELD_EQ:
321 se->op = lttv_apply_op_eq_quark;
322 break;
323 case LTTV_FIELD_NE:
324 se->op = lttv_apply_op_ne_quark;
325 break;
326 default:
327 g_warning("Error encountered in operator assignment = or != expected");
328 return FALSE;
329 }
330 break;
331 /*
332 * two strings.
333 */
334 case LTTV_FILTER_EVENT_NAME:
335 switch(op) {
336 case LTTV_FIELD_EQ:
337 se->op = lttv_apply_op_eq_quarks;
338 break;
339 case LTTV_FIELD_NE:
340 se->op = lttv_apply_op_ne_quarks;
341 break;
342 default:
343 g_warning("Error encountered in operator assignment = or != expected");
344 return FALSE;
345 }
346 /*
347 * integer
348 */
349 case LTTV_FILTER_EVENT_TSC:
350 switch(op) {
351 case LTTV_FIELD_EQ:
352 se->op = lttv_apply_op_eq_uint64;
353 break;
354 case LTTV_FIELD_NE:
355 se->op = lttv_apply_op_ne_uint64;
356 break;
357 case LTTV_FIELD_LT:
358 se->op = lttv_apply_op_lt_uint64;
359 break;
360 case LTTV_FIELD_LE:
361 se->op = lttv_apply_op_le_uint64;
362 break;
363 case LTTV_FIELD_GT:
364 se->op = lttv_apply_op_gt_uint64;
365 break;
366 case LTTV_FIELD_GE:
367 se->op = lttv_apply_op_ge_uint64;
368 break;
369 default:
370 g_warning("Error encountered in operator assignment");
371 return FALSE;
372 }
373 break;
374 /*
375 * unsigned integers
376 */
377 case LTTV_FILTER_STATE_CPU:
378 case LTTV_FILTER_STATE_PID:
379 case LTTV_FILTER_STATE_PPID:
380 case LTTV_FILTER_EVENT_TARGET_PID:
381 switch(op) {
382 case LTTV_FIELD_EQ:
383 se->op = lttv_apply_op_eq_uint;
384 break;
385 case LTTV_FIELD_NE:
386 se->op = lttv_apply_op_ne_uint;
387 break;
388 case LTTV_FIELD_LT:
389 se->op = lttv_apply_op_lt_uint;
390 break;
391 case LTTV_FIELD_LE:
392 se->op = lttv_apply_op_le_uint;
393 break;
394 case LTTV_FIELD_GT:
395 se->op = lttv_apply_op_gt_uint;
396 break;
397 case LTTV_FIELD_GE:
398 se->op = lttv_apply_op_ge_uint;
399 break;
400 default:
401 g_warning("Error encountered in operator assignment");
402 return FALSE;
403 }
404 break;
405
406 /*
407 * Enums
408 * Entered as string, converted to enum
409 *
410 * can only be compared with 'equal' or 'not equal' operators
411 *
412 * unsigned int of 16 bits are used here since enums
413 * should not go over 2^16-1 values
414 */
415 // case /*NOTHING*/:
416 // switch(op) {
417 // case LTTV_FIELD_EQ:
418 // se->op = lttv_apply_op_eq_uint16;
419 // break;
420 // case LTTV_FIELD_NE:
421 // se->op = lttv_apply_op_ne_uint16;
422 // break;
423 // default:
424 // g_warning("Error encountered in operator assignment = or != expected");
425 // return FALSE;
426 // }
427 // break;
428 /*
429 * Ltttime
430 */
431 case LTTV_FILTER_STATE_CT:
432 case LTTV_FILTER_STATE_IT:
433 case LTTV_FILTER_EVENT_TIME:
434 switch(op) {
435 case LTTV_FIELD_EQ:
436 se->op = lttv_apply_op_eq_ltttime;
437 break;
438 case LTTV_FIELD_NE:
439 se->op = lttv_apply_op_ne_ltttime;
440 break;
441 case LTTV_FIELD_LT:
442 se->op = lttv_apply_op_lt_ltttime;
443 break;
444 case LTTV_FIELD_LE:
445 se->op = lttv_apply_op_le_ltttime;
446 break;
447 case LTTV_FIELD_GT:
448 se->op = lttv_apply_op_gt_ltttime;
449 break;
450 case LTTV_FIELD_GE:
451 se->op = lttv_apply_op_ge_ltttime;
452 break;
453 default:
454 g_warning("Error encountered in operator assignment");
455 return FALSE;
456 }
457 break;
458 default:
459 g_warning("Error encountered in operator assignation ! Field type:%i",se->field);
460 return FALSE;
461 }
462
463 return TRUE;
464
465 }
466
467 /**
468 * @fn gboolean lttv_simple_expression_assign_value(LttvSimpleExpression*,char*)
469 *
470 * Assign the value field to the current LttvSimpleExpression
471 * @param se pointer to the current LttvSimpleExpression
472 * @param value string value for simple expression
473 */
474 gboolean
475 lttv_simple_expression_assign_value(LttvSimpleExpression* se, char* value) {
476
477 unsigned i;
478 gboolean is_double = FALSE;
479 LttTime t = ltt_time_zero;
480 GString* v;
481 guint string_len;
482
483 switch(se->field) {
484 /*
485 * Strings
486 * entered as strings, converted to Quarks
487 */
488 case LTTV_FILTER_TRACE_NAME:
489 case LTTV_FILTER_TRACEFILE_NAME:
490 case LTTV_FILTER_STATE_P_NAME:
491 case LTTV_FILTER_STATE_T_BRAND:
492 case LTTV_FILTER_EVENT_SUBNAME:
493 case LTTV_FILTER_STATE_EX_MODE:
494 case LTTV_FILTER_STATE_EX_SUBMODE:
495 case LTTV_FILTER_STATE_P_STATUS:
496 // se->value.v_string = value;
497 se->value.v_quark = g_quark_from_string(value);
498 g_free(value);
499 break;
500 /*
501 * Two strings.
502 */
503 case LTTV_FILTER_EVENT_NAME:
504 {
505 /* channel.event */
506 char *end = strchr(value, '.');
507 if (end) {
508 *end = '\0';
509 end++;
510 se->value.v_quarks.q[0] = g_quark_from_string(value);
511 se->value.v_quarks.q[1] = g_quark_from_string(end);
512 } else {
513 se->value.v_quarks.q[0] = (GQuark)0;
514 se->value.v_quarks.q[1] = g_quark_from_string(value);
515 }
516 g_free(value);
517 }
518 break;
519 /*
520 * integer -- supposed to be uint64
521 */
522 case LTTV_FILTER_EVENT_TSC:
523 se->value.v_uint64 = atoi(value);
524 g_free(value);
525 break;
526 /*
527 * unsigned integers
528 */
529 case LTTV_FILTER_STATE_PID:
530 case LTTV_FILTER_STATE_PPID:
531 case LTTV_FILTER_STATE_CPU:
532 case LTTV_FILTER_EVENT_TARGET_PID:
533 se->value.v_uint = atoi(value);
534 g_free(value);
535 break;
536 /*
537 * LttTime
538 */
539 case LTTV_FILTER_STATE_CT:
540 case LTTV_FILTER_STATE_IT:
541 case LTTV_FILTER_EVENT_TIME:
542 //se->value.v_double = atof(value);
543 /*
544 * parsing logic could be optimised,
545 * but as for now, simpler this way
546 */
547 v = g_string_new("");
548 string_len = strlen(value);
549 for(i=0;i<string_len;i++) {
550 if(value[i] == '.') {
551 /* cannot specify number with more than one '.' */
552 if(is_double) return FALSE;
553 else is_double = TRUE;
554 t.tv_sec = atoi(v->str);
555 g_string_free(v,TRUE);
556 v = g_string_new("");
557 } else v = g_string_append_c(v,value[i]);
558 }
559 /* number can be integer or double */
560 if(is_double) t.tv_nsec = atoi(v->str);
561 else {
562 t.tv_sec = atoi(v->str);
563 t.tv_nsec = 0;
564 }
565
566 g_string_free(v,TRUE);
567
568 se->value.v_ltttime = t;
569 g_free(value);
570 break;
571 default:
572 g_warning("Error encountered in value assignation ! Field type = %i",se->field);
573 g_free(value);
574 return FALSE;
575 }
576
577 return TRUE;
578
579 }
580
581 /**
582 * @fn void lttv_simple_expression_destroy(LttvSimpleExpression*)
583 *
584 * Disallocate memory for the current
585 * simple expression
586 * @param se pointer to the current LttvSimpleExpression
587 */
588 void
589 lttv_simple_expression_destroy(LttvSimpleExpression* se) {
590
591 // g_free(se->value);
592 // switch(se->field) {
593 // case LTTV_FILTER_TRACE_NAME:
594 // case LTTV_FILTER_TRACEFILE_NAME:
595 // case LTTV_FILTER_STATE_P_NAME:
596 // case LTTV_FILTER_EVENT_NAME:
597 // g_free(se->value.v_string);
598 // break;
599 // }
600 g_free(se);
601
602 }
603
604 /**
605 * @fn gint lttv_struct_type(gint)
606 *
607 * Finds the structure type depending
608 * on the fields in parameters
609 * @params ft Field of the current structure
610 * @return LttvStructType enum or -1 for error
611 */
612 gint
613 lttv_struct_type(gint ft) {
614
615 switch(ft) {
616 case LTTV_FILTER_TRACE_NAME:
617 return LTTV_FILTER_TRACE;
618 break;
619 case LTTV_FILTER_TRACEFILE_NAME:
620 return LTTV_FILTER_TRACEFILE;
621 break;
622 case LTTV_FILTER_STATE_PID:
623 case LTTV_FILTER_STATE_PPID:
624 case LTTV_FILTER_STATE_CT:
625 case LTTV_FILTER_STATE_IT:
626 case LTTV_FILTER_STATE_P_NAME:
627 case LTTV_FILTER_STATE_T_BRAND:
628 case LTTV_FILTER_STATE_EX_MODE:
629 case LTTV_FILTER_STATE_EX_SUBMODE:
630 case LTTV_FILTER_STATE_P_STATUS:
631 case LTTV_FILTER_STATE_CPU:
632 return LTTV_FILTER_STATE;
633 break;
634 case LTTV_FILTER_EVENT_NAME:
635 case LTTV_FILTER_EVENT_SUBNAME:
636 case LTTV_FILTER_EVENT_CATEGORY:
637 case LTTV_FILTER_EVENT_TIME:
638 case LTTV_FILTER_EVENT_TSC:
639 case LTTV_FILTER_EVENT_TARGET_PID:
640 case LTTV_FILTER_EVENT_FIELD:
641 return LTTV_FILTER_EVENT;
642 break;
643 default:
644 return -1;
645 }
646 }
647
648 /**
649 * @fn gboolean lttv_apply_op_eq_uint(gpointer,LttvFieldValue)
650 *
651 * Applies the 'equal' operator to the
652 * specified structure and value
653 * @param v1 left member of comparison
654 * @param v2 right member of comparison
655 * @return success/failure of operation
656 */
657 gboolean lttv_apply_op_eq_uint(const gpointer v1, LttvFieldValue v2) {
658
659 guint* r = (guint*) v1;
660 return (*r == v2.v_uint);
661
662 }
663
664 /**
665 * @fn gboolean lttv_apply_op_eq_uint64(gpointer,LttvFieldValue)
666 *
667 * Applies the 'equal' operator to the
668 * specified structure and value
669 * @param v1 left member of comparison
670 * @param v2 right member of comparison
671 * @return success/failure of operation
672 */
673 gboolean lttv_apply_op_eq_uint64(const gpointer v1, LttvFieldValue v2) {
674
675 guint64* r = (guint64*) v1;
676 return (*r == v2.v_uint64);
677
678 }
679
680 /**
681 * @fn gboolean lttv_apply_op_eq_uint32(gpointer,LttvFieldValue)
682 *
683 * Applies the 'equal' operator to the
684 * specified structure and value
685 * @param v1 left member of comparison
686 * @param v2 right member of comparison
687 * @return success/failure of operation
688 */
689 gboolean lttv_apply_op_eq_uint32(const gpointer v1, LttvFieldValue v2) {
690 guint32* r = (guint32*) v1;
691 return (*r == v2.v_uint32);
692 }
693
694 /**
695 * @fn gboolean lttv_apply_op_eq_uint16(gpointer,LttvFieldValue)
696 *
697 * Applies the 'equal' operator to the
698 * specified structure and value
699 * @param v1 left member of comparison
700 * @param v2 right member of comparison
701 * @return success/failure of operation
702 */
703 gboolean lttv_apply_op_eq_uint16(const gpointer v1, LttvFieldValue v2) {
704 guint16* r = (guint16*) v1;
705 return (*r == v2.v_uint16);
706 }
707
708 /**
709 * @fn gboolean lttv_apply_op_eq_double(gpointer,LttvFieldValue)
710 *
711 * Applies the 'equal' operator to the
712 * specified structure and value
713 * @param v1 left member of comparison
714 * @param v2 right member of comparison
715 * @return success/failure of operation
716 */
717 gboolean lttv_apply_op_eq_double(const gpointer v1, LttvFieldValue v2) {
718 double* r = (double*) v1;
719 return (*r == v2.v_double);
720 }
721
722 /**
723 * @fn gboolean lttv_apply_op_eq_string(gpointer,LttvFieldValue)
724 *
725 * Applies the 'equal' operator to the
726 * specified structure and value
727 * @param v1 left member of comparison
728 * @param v2 right member of comparison
729 * @return success/failure of operation
730 */
731 gboolean lttv_apply_op_eq_string(const gpointer v1, LttvFieldValue v2) {
732 char* r = (char*) v1;
733 return (!g_strcasecmp(r,v2.v_string));
734 }
735
736 /**
737 * @fn gboolean lttv_apply_op_eq_quark(gpointer,LttvFieldValue)
738 *
739 * Applies the 'equal' operator to the
740 * specified structure and value
741 * @param v1 left member of comparison
742 * @param v2 right member of comparison
743 * @return success/failure of operation
744 */
745 gboolean lttv_apply_op_eq_quark(const gpointer v1, LttvFieldValue v2) {
746 GQuark* r = (GQuark*) v1;
747 return (*r == v2.v_quark);
748 }
749
750 /**
751 * @fn gboolean lttv_apply_op_eq_quarks(gpointer,LttvFieldValue)
752 *
753 * Applies the 'equal' operator to the
754 * specified structure and value
755 * @param v1 left member of comparison
756 * @param v2 right member of comparison
757 * @return success/failure of operation
758 */
759 gboolean lttv_apply_op_eq_quarks(const gpointer v1, LttvFieldValue v2) {
760 GQuark *r1 = (GQuark *) v1;
761 GQuark *r2 = r1 + 1;
762 if (likely(*r1 != (GQuark)0) && *r1 != v2.v_quarks.q[0])
763 return 0;
764 if (*r2 != v2.v_quarks.q[1])
765 return 0;
766 return 1;
767 }
768
769 /**
770 * @fn gboolean lttv_apply_op_eq_ltttime(gpointer,LttvFieldValue)
771 *
772 * Applies the 'equal' operator to the
773 * specified structure and value
774 * @param v1 left member of comparison
775 * @param v2 right member of comparison
776 * @return success/failure of operation
777 */
778 gboolean lttv_apply_op_eq_ltttime(const gpointer v1, LttvFieldValue v2) {
779 LttTime* r = (LttTime*) v1;
780 return ltt_time_compare(*r, v2.v_ltttime)==0?1:0;
781 }
782
783 /**
784 * @fn gboolean lttv_apply_op_ne_uint(gpointer,LttvFieldValue)
785 *
786 * Applies the 'not equal' operator to the
787 * specified structure and value
788 * @param v1 left member of comparison
789 * @param v2 right member of comparison
790 * @return success/failure of operation
791 */
792 gboolean lttv_apply_op_ne_uint(const gpointer v1, LttvFieldValue v2) {
793 guint* r = (guint*) v1;
794 return (*r != v2.v_uint);
795 }
796
797 /**
798 * @fn gboolean lttv_apply_op_ne_uint64(gpointer,LttvFieldValue)
799 *
800 * Applies the 'not equal' operator to the
801 * specified structure and value
802 * @param v1 left member of comparison
803 * @param v2 right member of comparison
804 * @return success/failure of operation
805 */
806 gboolean lttv_apply_op_ne_uint64(const gpointer v1, LttvFieldValue v2) {
807 guint64* r = (guint64*) v1;
808 return (*r != v2.v_uint64);
809 }
810
811 /**
812 * @fn gboolean lttv_apply_op_ne_uint32(gpointer,LttvFieldValue)
813 *
814 * Applies the 'not equal' operator to the
815 * specified structure and value
816 * @param v1 left member of comparison
817 * @param v2 right member of comparison
818 * @return success/failure of operation
819 */
820 gboolean lttv_apply_op_ne_uint32(const gpointer v1, LttvFieldValue v2) {
821 guint32* r = (guint32*) v1;
822 return (*r != v2.v_uint32);
823 }
824
825 /**
826 * @fn gboolean lttv_apply_op_ne_uint16(gpointer,LttvFieldValue)
827 *
828 * Applies the 'not equal' operator to the
829 * specified structure and value
830 * @param v1 left member of comparison
831 * @param v2 right member of comparison
832 * @return success/failure of operation
833 */
834 gboolean lttv_apply_op_ne_uint16(const gpointer v1, LttvFieldValue v2) {
835 guint16* r = (guint16*) v1;
836 return (*r != v2.v_uint16);
837 }
838
839 /**
840 * @fn gboolean lttv_apply_op_ne_double(gpointer,LttvFieldValue)
841 *
842 * Applies the 'not equal' operator to the
843 * specified structure and value
844 * @param v1 left member of comparison
845 * @param v2 right member of comparison
846 * @return success/failure of operation
847 */
848 gboolean lttv_apply_op_ne_double(const gpointer v1, LttvFieldValue v2) {
849 double* r = (double*) v1;
850 return (*r != v2.v_double);
851 }
852
853 /**
854 * @fn gboolean lttv_apply_op_ne_string(gpointer,LttvFieldValue)
855 *
856 * Applies the 'not equal' operator to the
857 * specified structure and value
858 * @param v1 left member of comparison
859 * @param v2 right member of comparison
860 * @return success/failure of operation
861 */
862 gboolean lttv_apply_op_ne_string(const gpointer v1, LttvFieldValue v2) {
863 char* r = (char*) v1;
864 return (g_strcasecmp(r,v2.v_string));
865 }
866
867 /**
868 * @fn gboolean lttv_apply_op_ne_quark(gpointer,LttvFieldValue)
869 *
870 * Applies the 'not equal' operator to the
871 * specified structure and value
872 * @param v1 left member of comparison
873 * @param v2 right member of comparison
874 * @return success/failure of operation
875 */
876 gboolean lttv_apply_op_ne_quark(const gpointer v1, LttvFieldValue v2) {
877 GQuark* r = (GQuark*) v1;
878 return (*r != v2.v_quark);
879 }
880
881 /**
882 * @fn gboolean lttv_apply_op_ne_quarks(gpointer,LttvFieldValue)
883 *
884 * Applies the 'equal' operator to the
885 * specified structure and value
886 * @param v1 left member of comparison
887 * @param v2 right member of comparison
888 * @return success/failure of operation
889 */
890 gboolean lttv_apply_op_ne_quarks(const gpointer v1, LttvFieldValue v2) {
891 GQuark *r1 = (GQuark *) v1;
892 GQuark *r2 = r1 + 1;
893 if ((*r1 == (GQuark)0 || *r1 == v2.v_quarks.q[0]) && *r2 == v2.v_quarks.q[1])
894 return 0;
895 else
896 return 1;
897 }
898
899 /**
900 * @fn gboolean lttv_apply_op_ne_ltttime(gpointer,LttvFieldValue)
901 *
902 * Applies the 'not equal' operator to the
903 * specified structure and value
904 * @param v1 left member of comparison
905 * @param v2 right member of comparison
906 * @return success/failure of operation
907 */
908 gboolean lttv_apply_op_ne_ltttime(const gpointer v1, LttvFieldValue v2) {
909 LttTime* r = (LttTime*) v1;
910 return ltt_time_compare(*r, v2.v_ltttime)!=0?1:0;
911 }
912
913 /**
914 * @fn gboolean lttv_apply_op_lt_uint(gpointer,LttvFieldValue)
915 *
916 * Applies the 'lower than' operator to the
917 * specified structure and value
918 * @param v1 left member of comparison
919 * @param v2 right member of comparison
920 * @return success/failure of operation
921 */
922 gboolean lttv_apply_op_lt_uint(const gpointer v1, LttvFieldValue v2) {
923 guint* r = (guint*) v1;
924 return (*r < v2.v_uint);
925 }
926
927 /**
928 * @fn gboolean lttv_apply_op_lt_uint64(gpointer,LttvFieldValue)
929 *
930 * Applies the 'lower than' operator to the
931 * specified structure and value
932 * @param v1 left member of comparison
933 * @param v2 right member of comparison
934 * @return success/failure of operation
935 */
936 gboolean lttv_apply_op_lt_uint64(const gpointer v1, LttvFieldValue v2) {
937 guint64* r = (guint64*) v1;
938 return (*r < v2.v_uint64);
939 }
940
941 /**
942 * @fn gboolean lttv_apply_op_lt_uint32(gpointer,LttvFieldValue)
943 *
944 * Applies the 'lower than' operator to the
945 * specified structure and value
946 * @param v1 left member of comparison
947 * @param v2 right member of comparison
948 * @return success/failure of operation
949 */
950 gboolean lttv_apply_op_lt_uint32(const gpointer v1, LttvFieldValue v2) {
951 guint32* r = (guint32*) v1;
952 return (*r < v2.v_uint32);
953 }
954
955 /**
956 * @fn gboolean lttv_apply_op_lt_uint16(gpointer,LttvFieldValue)
957 *
958 * Applies the 'lower than' operator to the
959 * specified structure and value
960 * @param v1 left member of comparison
961 * @param v2 right member of comparison
962 * @return success/failure of operation
963 */
964 gboolean lttv_apply_op_lt_uint16(const gpointer v1, LttvFieldValue v2) {
965 guint16* r = (guint16*) v1;
966 return (*r < v2.v_uint16);
967 }
968
969 /**
970 * @fn gboolean lttv_apply_op_lt_double(gpointer,LttvFieldValue)
971 *
972 * Applies the 'lower than' operator to the
973 * specified structure and value
974 * @param v1 left member of comparison
975 * @param v2 right member of comparison
976 * @return success/failure of operation
977 */
978 gboolean lttv_apply_op_lt_double(const gpointer v1, LttvFieldValue v2) {
979 double* r = (double*) v1;
980 return (*r < v2.v_double);
981 }
982
983 /**
984 * @fn gboolean lttv_apply_op_lt_ltttime(gpointer,LttvFieldValue)
985 *
986 * Applies the 'lower than' operator to the
987 * specified structure and value
988 * @param v1 left member of comparison
989 * @param v2 right member of comparison
990 * @return success/failure of operation
991 */
992 gboolean lttv_apply_op_lt_ltttime(const gpointer v1, LttvFieldValue v2) {
993 LttTime* r = (LttTime*) v1;
994 // return ((r->tv_sec < v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec < v2.v_ltttime.tv_nsec)));
995 return ltt_time_compare(*r, v2.v_ltttime)==-1?1:0;
996 }
997
998 /**
999 * @fn gboolean lttv_apply_op_le_uint(gpointer,LttvFieldValue)
1000 *
1001 * Applies the 'lower or equal' operator to the
1002 * specified structure and value
1003 * @param v1 left member of comparison
1004 * @param v2 right member of comparison
1005 * @return success/failure of operation
1006 */
1007 gboolean lttv_apply_op_le_uint(const gpointer v1, LttvFieldValue v2) {
1008 guint* r = (guint*) v1;
1009 return (*r <= v2.v_uint);
1010 }
1011
1012 /**
1013 * @fn gboolean lttv_apply_op_le_uint64(gpointer,LttvFieldValue)
1014 *
1015 * Applies the 'lower or equal' operator to the
1016 * specified structure and value
1017 * @param v1 left member of comparison
1018 * @param v2 right member of comparison
1019 * @return success/failure of operation
1020 */
1021 gboolean lttv_apply_op_le_uint64(const gpointer v1, LttvFieldValue v2) {
1022 guint64* r = (guint64*) v1;
1023 return (*r <= v2.v_uint64);
1024 }
1025
1026 /**
1027 * @fn gboolean lttv_apply_op_le_uint32(gpointer,LttvFieldValue)
1028 *
1029 * Applies the 'lower or equal' operator to the
1030 * specified structure and value
1031 * @param v1 left member of comparison
1032 * @param v2 right member of comparison
1033 * @return success/failure of operation
1034 */
1035 gboolean lttv_apply_op_le_uint32(const gpointer v1, LttvFieldValue v2) {
1036 guint32* r = (guint32*) v1;
1037 return (*r <= v2.v_uint32);
1038 }
1039
1040 /**
1041 * @fn gboolean lttv_apply_op_le_uint16(gpointer,LttvFieldValue)
1042 *
1043 * Applies the 'lower or equal' operator to the
1044 * specified structure and value
1045 * @param v1 left member of comparison
1046 * @param v2 right member of comparison
1047 * @return success/failure of operation
1048 */
1049 gboolean lttv_apply_op_le_uint16(const gpointer v1, LttvFieldValue v2) {
1050 guint16* r = (guint16*) v1;
1051 return (*r <= v2.v_uint16);
1052 }
1053
1054 /**
1055 * @fn gboolean lttv_apply_op_le_double(gpointer,LttvFieldValue)
1056 *
1057 * Applies the 'lower or equal' operator to the
1058 * specified structure and value
1059 * @param v1 left member of comparison
1060 * @param v2 right member of comparison
1061 * @return success/failure of operation
1062 */
1063 gboolean lttv_apply_op_le_double(const gpointer v1, LttvFieldValue v2) {
1064 double* r = (double*) v1;
1065 return (*r <= v2.v_double);
1066 }
1067
1068 /**
1069 * @fn gboolean lttv_apply_op_le_ltttime(gpointer,LttvFieldValue)
1070 *
1071 * Applies the 'lower or equal' operator to the
1072 * specified structure and value
1073 * @param v1 left member of comparison
1074 * @param v2 right member of comparison
1075 * @return success/failure of operation
1076 */
1077 gboolean lttv_apply_op_le_ltttime(const gpointer v1, LttvFieldValue v2) {
1078 LttTime* r = (LttTime*) v1;
1079 // return ((r->tv_sec < v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec <= v2.v_ltttime.tv_nsec)));
1080 return ltt_time_compare(*r, v2.v_ltttime)<1?1:0;
1081 }
1082
1083
1084 /**
1085 * @fn gboolean lttv_apply_op_gt_uint(gpointer,LttvFieldValue)
1086 *
1087 * Applies the 'greater than' operator to the
1088 * specified structure and value
1089 * @param v1 left member of comparison
1090 * @param v2 right member of comparison
1091 * @return success/failure of operation
1092 */
1093 gboolean lttv_apply_op_gt_uint(const gpointer v1, LttvFieldValue v2) {
1094 guint* r = (guint*) v1;
1095 return (*r > v2.v_uint);
1096 }
1097
1098 /**
1099 * @fn gboolean lttv_apply_op_gt_uint64(gpointer,LttvFieldValue)
1100 *
1101 * Applies the 'greater than' operator to the
1102 * specified structure and value
1103 * @param v1 left member of comparison
1104 * @param v2 right member of comparison
1105 * @return success/failure of operation
1106 */
1107 gboolean lttv_apply_op_gt_uint64(const gpointer v1, LttvFieldValue v2) {
1108 guint64* r = (guint64*) v1;
1109 return (*r > v2.v_uint64);
1110 }
1111
1112 /**
1113 * @fn gboolean lttv_apply_op_gt_uint32(gpointer,LttvFieldValue)
1114 *
1115 * Applies the 'greater than' operator to the
1116 * specified structure and value
1117 * @param v1 left member of comparison
1118 * @param v2 right member of comparison
1119 * @return success/failure of operation
1120 */
1121 gboolean lttv_apply_op_gt_uint32(const gpointer v1, LttvFieldValue v2) {
1122 guint32* r = (guint32*) v1;
1123 return (*r > v2.v_uint32);
1124 }
1125
1126 /**
1127 * @fn gboolean lttv_apply_op_gt_uint16(gpointer,LttvFieldValue)
1128 *
1129 * Applies the 'greater than' operator to the
1130 * specified structure and value
1131 * @param v1 left member of comparison
1132 * @param v2 right member of comparison
1133 * @return success/failure of operation
1134 */
1135 gboolean lttv_apply_op_gt_uint16(const gpointer v1, LttvFieldValue v2) {
1136 guint16* r = (guint16*) v1;
1137 return (*r > v2.v_uint16);
1138 }
1139
1140 /**
1141 * @fn gboolean lttv_apply_op_gt_double(gpointer,LttvFieldValue)
1142 *
1143 * Applies the 'greater than' operator to the
1144 * specified structure and value
1145 * @param v1 left member of comparison
1146 * @param v2 right member of comparison
1147 * @return success/failure of operation
1148 */
1149 gboolean lttv_apply_op_gt_double(const gpointer v1, LttvFieldValue v2) {
1150 double* r = (double*) v1;
1151 return (*r > v2.v_double);
1152 }
1153
1154 /**
1155 * @fn gboolean lttv_apply_op_gt_ltttime(gpointer,LttvFieldValue)
1156 *
1157 * Applies the 'greater than' operator to the
1158 * specified structure and value
1159 * @param v1 left member of comparison
1160 * @param v2 right member of comparison
1161 * @return success/failure of operation
1162 */
1163 gboolean lttv_apply_op_gt_ltttime(const gpointer v1, LttvFieldValue v2) {
1164 LttTime* r = (LttTime*) v1;
1165 // return ((r->tv_sec > v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec > v2.v_ltttime.tv_nsec)));
1166 return ltt_time_compare(*r, v2.v_ltttime)==1?1:0;
1167 }
1168
1169 /**
1170 * @fn gboolean lttv_apply_op_ge_uint(gpointer,LttvFieldValue)
1171 *
1172 * Applies the 'greater or equal' operator to the
1173 * specified structure and value
1174 * @param v1 left member of comparison
1175 * @param v2 right member of comparison
1176 * @return success/failure of operation
1177 */
1178 gboolean lttv_apply_op_ge_uint(const gpointer v1, LttvFieldValue v2) {
1179 guint* r = (guint*) v1;
1180 return (*r >= v2.v_uint);
1181 }
1182
1183 /**
1184 * @fn gboolean lttv_apply_op_ge_uint64(gpointer,LttvFieldValue)
1185 *
1186 * Applies the 'greater or equal' operator to the
1187 * specified structure and value
1188 * @param v1 left member of comparison
1189 * @param v2 right member of comparison
1190 * @return success/failure of operation
1191 */
1192 gboolean lttv_apply_op_ge_uint64(const gpointer v1, LttvFieldValue v2) {
1193 guint64* r = (guint64*) v1;
1194 return (*r >= v2.v_uint64);
1195 }
1196
1197 /**
1198 * @fn gboolean lttv_apply_op_ge_uint32(gpointer,LttvFieldValue)
1199 *
1200 * Applies the 'greater or equal' operator to the
1201 * specified structure and value
1202 * @param v1 left member of comparison
1203 * @param v2 right member of comparison
1204 * @return success/failure of operation
1205 */
1206 gboolean lttv_apply_op_ge_uint32(const gpointer v1, LttvFieldValue v2) {
1207 guint32* r = (guint32*) v1;
1208 return (*r >= v2.v_uint32);
1209 }
1210
1211 /**
1212 * @fn gboolean lttv_apply_op_ge_uint16(gpointer,LttvFieldValue)
1213 *
1214 * Applies the 'greater or equal' operator to the
1215 * specified structure and value
1216 * @param v1 left member of comparison
1217 * @param v2 right member of comparison
1218 * @return success/failure of operation
1219 */
1220 gboolean lttv_apply_op_ge_uint16(const gpointer v1, LttvFieldValue v2) {
1221 guint16* r = (guint16*) v1;
1222 return (*r >= v2.v_uint16);
1223 }
1224
1225 /**
1226 * @fn gboolean lttv_apply_op_ge_double(gpointer,LttvFieldValue)
1227 *
1228 * Applies the 'greater or equal' operator to the
1229 * specified structure and value
1230 * @param v1 left member of comparison
1231 * @param v2 right member of comparison
1232 * @return success/failure of operation
1233 */
1234 gboolean lttv_apply_op_ge_double(const gpointer v1, LttvFieldValue v2) {
1235 double* r = (double*) v1;
1236 return (*r >= v2.v_double);
1237 }
1238
1239 /**
1240 * @fn gboolean lttv_apply_op_ge_ltttime(gpointer,LttvFieldValue)
1241 *
1242 * Applies the 'greater or equal' operator to the
1243 * specified structure and value
1244 * @param v1 left member of comparison
1245 * @param v2 right member of comparison
1246 * @return success/failure of operation
1247 */
1248 gboolean lttv_apply_op_ge_ltttime(const gpointer v1, LttvFieldValue v2) {
1249 LttTime* r = (LttTime*) v1;
1250 // return ((r->tv_sec > v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec >= v2.v_ltttime.tv_nsec)));
1251 return ltt_time_compare(*r, v2.v_ltttime)>-1?1:0;
1252 }
1253
1254
1255
1256 /**
1257 * Makes a copy of the current filter tree
1258 * @param tree pointer to the current tree
1259 * @return new copy of the filter tree
1260 */
1261 LttvFilterTree*
1262 lttv_filter_tree_clone(const LttvFilterTree* tree) {
1263
1264 LttvFilterTree* newtree = lttv_filter_tree_new();
1265
1266 newtree->node = tree->node;
1267
1268 newtree->left = tree->left;
1269 if(newtree->left == LTTV_TREE_NODE) {
1270 newtree->l_child.t = lttv_filter_tree_clone(tree->l_child.t);
1271 } else if(newtree->left == LTTV_TREE_LEAF) {
1272 newtree->l_child.leaf = lttv_simple_expression_new();
1273 newtree->l_child.leaf->field = tree->l_child.leaf->field;
1274 newtree->l_child.leaf->offset = tree->l_child.leaf->offset;
1275 newtree->l_child.leaf->op = tree->l_child.leaf->op;
1276 /* FIXME: special case for string copy ! */
1277 newtree->l_child.leaf->value = tree->l_child.leaf->value;
1278 }
1279
1280 newtree->right = tree->right;
1281 if(newtree->right == LTTV_TREE_NODE) {
1282 newtree->r_child.t = lttv_filter_tree_clone(tree->r_child.t);
1283 } else if(newtree->right == LTTV_TREE_LEAF) {
1284 newtree->r_child.leaf = lttv_simple_expression_new();
1285 newtree->r_child.leaf->field = tree->r_child.leaf->field;
1286 newtree->r_child.leaf->offset = tree->r_child.leaf->offset;
1287 newtree->r_child.leaf->op = tree->r_child.leaf->op;
1288 newtree->r_child.leaf->value = tree->r_child.leaf->value;
1289 }
1290
1291 return newtree;
1292
1293 }
1294
1295 /**
1296 * Makes a copy of the current filter
1297 * @param filter pointer to the current filter
1298 * @return new copy of the filter
1299 */
1300 LttvFilter*
1301 lttv_filter_clone(const LttvFilter* filter) {
1302
1303 if(!filter) return NULL;
1304
1305 LttvFilter* newfilter = g_new(LttvFilter,1);
1306
1307 strcpy(newfilter->expression,filter->expression);
1308
1309 newfilter->head = lttv_filter_tree_clone(filter->head);
1310
1311 return newfilter;
1312
1313 }
1314
1315
1316 /**
1317 * @fn LttvFilter* lttv_filter_new()
1318 *
1319 * Creates a new LttvFilter
1320 * @return the current LttvFilter or NULL if error
1321 */
1322 LttvFilter*
1323 lttv_filter_new() {
1324
1325 LttvFilter* filter = g_new(LttvFilter,1);
1326 filter->expression = NULL;
1327 filter->head = NULL;
1328
1329 return filter;
1330
1331 }
1332
1333 /**
1334 * @fn gboolean lttv_filter_update(LttvFilter*)
1335 *
1336 * Updates the current LttvFilter by building
1337 * its tree based upon the expression string
1338 * @param filter pointer to the current LttvFilter
1339 * @return Failure/Success of operation
1340 */
1341 gboolean
1342 lttv_filter_update(LttvFilter* filter) {
1343
1344 // g_print("filter::lttv_filter_new()\n"); /* debug */
1345
1346 if(filter->expression == NULL) return FALSE;
1347
1348 int
1349 i,
1350 p_nesting=0, /* parenthesis nesting value */
1351 not=0;
1352 guint expression_len;
1353
1354 /* trees */
1355 LttvFilterTree
1356 *tree = lttv_filter_tree_new(), /* main tree */
1357 *subtree = NULL, /* buffer for subtrees */
1358 *t1, /* buffer #1 */
1359 *t2, /* buffer #2 */
1360 *t3; /* buffer #3 */
1361
1362 /*
1363 * the filter
1364 * If the tree already exists,
1365 * destroy it and build a new one
1366 */
1367 if(filter->head != NULL) lttv_filter_tree_destroy(filter->head);
1368 filter->head = NULL; /* will be assigned at the end */
1369
1370 /*
1371 * Tree Stack
1372 * each element of the list
1373 * is a sub tree created
1374 * by the use of parenthesis in the
1375 * global expression. The final tree
1376 * will be the one left at the root of
1377 * the list
1378 */
1379 GPtrArray *tree_stack = g_ptr_array_new();
1380 g_ptr_array_add( tree_stack,(gpointer) tree );
1381
1382 /* temporary values */
1383 GString *a_field_component = g_string_new("");
1384 GString *a_string_spaces = g_string_new("");
1385 GPtrArray *a_field_path = g_ptr_array_new();
1386
1387 /* simple expression buffer */
1388 LttvSimpleExpression* a_simple_expression = lttv_simple_expression_new();
1389
1390 gint nest_quotes = 0;
1391
1392 /*
1393 * Parse entire expression and construct
1394 * the binary tree. There are two steps
1395 * in browsing that string
1396 * 1. finding boolean ops " &,|,^,! " and parenthesis " {,(,[,],),} "
1397 * 2. finding simple expressions
1398 * - field path ( separated by dots )
1399 * - op ( >, <, =, >=, <=, !=)
1400 * - value ( integer, string ... )
1401 * To spare computing time, the whole
1402 * string is parsed in this loop for a
1403 * O(n) complexity order.
1404 *
1405 * When encountering logical op &,|,^
1406 * 1. parse the last value if any
1407 * 2. create a new tree
1408 * 3. add the expression (simple exp, or exp (subtree)) to the tree
1409 * 4. concatenate this tree with the current tree on top of the stack
1410 * When encountering math ops >,>=,<,<=,=,!=
1411 * 1. add to op to the simple expression
1412 * 2. concatenate last field component to field path
1413 * When encountering concatening ops .
1414 * 1. concatenate last field component to field path
1415 * When encountering opening parenthesis (,{,[
1416 * 1. create a new subtree on top of tree stack
1417 * When encountering closing parenthesis ),},]
1418 * 1. add the expression on right child of the current tree
1419 * 2. the subtree is completed, allocate a new subtree
1420 * 3. pop the tree value from the tree stack
1421 */
1422
1423 #ifdef TEST
1424 struct timeval starttime;
1425 struct timeval endtime;
1426 gettimeofday(&starttime, NULL);
1427 #endif
1428
1429 expression_len = strlen(filter->expression);
1430 for(i=0;i<expression_len;i++) {
1431 // debug
1432 // g_print("%c\n ",filter->expression[i]);
1433 if(nest_quotes) {
1434 switch(filter->expression[i]) {
1435 case '\\' :
1436 if(filter->expression[i+1] == '\"') {
1437 i++;
1438 }
1439 break;
1440 case '\"':
1441 nest_quotes = 0;
1442 i++;
1443 break;
1444 }
1445 if(a_string_spaces->len != 0) {
1446 a_field_component = g_string_append(
1447 a_field_component, a_string_spaces->str);
1448 a_string_spaces = g_string_set_size(a_string_spaces, 0);
1449 }
1450 a_field_component = g_string_append_c(a_field_component,
1451 filter->expression[i]);
1452 continue;
1453 }
1454
1455 switch(filter->expression[i]) {
1456 /*
1457 * logical operators
1458 */
1459 case '&': /* and */
1460
1461 /* get current tree in tree stack */
1462 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
1463
1464 /* get current node at absolute right */
1465 while(t1->right != LTTV_TREE_IDLE) {
1466 g_assert(t1->right == LTTV_TREE_NODE);
1467 t1 = t1->r_child.t;
1468 }
1469 t2 = lttv_filter_tree_new();
1470 t2->node = LTTV_LOGICAL_AND;
1471 t1->right = LTTV_TREE_NODE;
1472 t1->r_child.t = t2;
1473 if(not) { /* add not operator to tree */
1474 t3 = lttv_filter_tree_new();
1475 t3->node = LTTV_LOGICAL_NOT;
1476 t2->left = LTTV_TREE_NODE;
1477 t2->l_child.t = t3;
1478 t2 = t3;
1479 not = 0;
1480 }
1481 if(subtree != NULL) { /* append subtree to current tree */
1482 t2->left = LTTV_TREE_NODE;
1483 t2->l_child.t = subtree;
1484 subtree = NULL;
1485 } else { /* append a simple expression */
1486 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1487 a_field_component = g_string_new("");
1488 g_string_free(a_string_spaces, TRUE);
1489 a_string_spaces = g_string_new("");
1490 t2->left = LTTV_TREE_LEAF;
1491 t2->l_child.leaf = a_simple_expression;
1492 a_simple_expression = lttv_simple_expression_new();
1493 }
1494 break;
1495
1496 case '|': /* or */
1497
1498 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
1499 while(t1->right != LTTV_TREE_IDLE) {
1500 g_assert(t1->right == LTTV_TREE_NODE);
1501 t1 = t1->r_child.t;
1502 }
1503 t2 = lttv_filter_tree_new();
1504 t2->node = LTTV_LOGICAL_OR;
1505 t1->right = LTTV_TREE_NODE;
1506 t1->r_child.t = t2;
1507 if(not) { // add not operator to tree
1508 t3 = lttv_filter_tree_new();
1509 t3->node = LTTV_LOGICAL_NOT;
1510 t2->left = LTTV_TREE_NODE;
1511 t2->l_child.t = t3;
1512 t2 = t3;
1513 not = 0;
1514 }
1515 if(subtree != NULL) { /* append subtree to current tree */
1516 t2->left = LTTV_TREE_NODE;
1517 t2->l_child.t = subtree;
1518 subtree = NULL;
1519 } else { /* append a simple expression */
1520 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1521 a_field_component = g_string_new("");
1522 g_string_free(a_string_spaces, TRUE);
1523 a_string_spaces = g_string_new("");
1524 t2->left = LTTV_TREE_LEAF;
1525 t2->l_child.leaf = a_simple_expression;
1526 a_simple_expression = lttv_simple_expression_new();
1527 }
1528 break;
1529
1530 case '^': /* xor */
1531
1532 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
1533 while(t1->right != LTTV_TREE_IDLE) {
1534 g_assert(t1->right == LTTV_TREE_NODE);
1535 t1 = t1->r_child.t;
1536 }
1537 t2 = lttv_filter_tree_new();
1538 t2->node = LTTV_LOGICAL_XOR;
1539 t1->right = LTTV_TREE_NODE;
1540 t1->r_child.t = t2;
1541 if(not) { // add not operator to tree
1542 t3 = lttv_filter_tree_new();
1543 t3->node = LTTV_LOGICAL_NOT;
1544 t2->left = LTTV_TREE_NODE;
1545 t2->l_child.t = t3;
1546 t2 = t3;
1547 not = 0;
1548 }
1549 if(subtree != NULL) { /* append subtree to current tree */
1550 t2->left = LTTV_TREE_NODE;
1551 t2->l_child.t = subtree;
1552 subtree = NULL;
1553 } else { /* append a simple expression */
1554 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1555 a_field_component = g_string_new("");
1556 g_string_free(a_string_spaces, TRUE);
1557 a_string_spaces = g_string_new("");
1558 t2->left = LTTV_TREE_LEAF;
1559 t2->l_child.leaf = a_simple_expression;
1560 a_simple_expression = lttv_simple_expression_new();
1561 }
1562 break;
1563
1564 case '!': /* not, or not equal (math op) */
1565
1566 if(filter->expression[i+1] == '=') { /* != */
1567 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1568 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
1569 a_field_component = g_string_new("");
1570 g_string_free(a_string_spaces, TRUE);
1571 a_string_spaces = g_string_new("");
1572 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_NE);
1573 i++;
1574 } else { /* ! */
1575 not=1;
1576 }
1577 break;
1578
1579 case '(': /* start of parenthesis */
1580 case '[':
1581 case '{':
1582
1583 p_nesting++; /* incrementing parenthesis nesting value */
1584 t1 = lttv_filter_tree_new();
1585 if(not) { /* add not operator to tree */
1586 t3 = lttv_filter_tree_new();
1587 t3->node = LTTV_LOGICAL_NOT;
1588 t1->right = LTTV_TREE_NODE;
1589 t1->r_child.t = t3;
1590 not = 0;
1591 }
1592 g_ptr_array_add( tree_stack,(gpointer) t1 );
1593 break;
1594
1595 case ')': /* end of parenthesis */
1596 case ']':
1597 case '}':
1598
1599 p_nesting--; /* decrementing parenthesis nesting value */
1600 if(p_nesting<0 || tree_stack->len<2) {
1601 g_warning("Wrong filtering options, the string\n\"%s\"\n\
1602 is not valid due to parenthesis incorrect use",filter->expression);
1603 return FALSE;
1604 }
1605
1606 /* there must at least be the root tree left in the array */
1607 g_assert(tree_stack->len>0);
1608
1609 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
1610 while(t1->right != LTTV_TREE_IDLE) {
1611 t1 = t1->r_child.t;
1612 }
1613 if(not) { // add not operator to tree
1614 g_print("ici");
1615 t3 = lttv_filter_tree_new();
1616 t3->node = LTTV_LOGICAL_NOT;
1617 t1->right = LTTV_TREE_NODE;
1618 t1->r_child.t = t3;
1619 t1 = t3;
1620 not = 0;
1621 }
1622 if(subtree != NULL) { /* append subtree to current tree */
1623 t1->right = LTTV_TREE_NODE;
1624 t1->r_child.t = subtree;
1625 subtree = g_ptr_array_index(tree_stack,tree_stack->len-1);
1626 g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
1627 } else { /* assign subtree as current tree */
1628 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1629 a_field_component = g_string_new("");
1630 g_string_free(a_string_spaces, TRUE);
1631 a_string_spaces = g_string_new("");
1632 t1->right = LTTV_TREE_LEAF;
1633 t1->r_child.leaf = a_simple_expression;
1634 a_simple_expression = lttv_simple_expression_new();
1635 subtree = g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
1636 }
1637 break;
1638
1639 /*
1640 * mathematic operators
1641 */
1642 case '<': /* lower, lower or equal */
1643
1644 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1645 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
1646 a_field_component = g_string_new("");
1647 g_string_free(a_string_spaces, TRUE);
1648 a_string_spaces = g_string_new("");
1649 if(filter->expression[i+1] == '=') { /* <= */
1650 i++;
1651 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_LE);
1652 } else lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_LT);
1653 break;
1654
1655 case '>': /* higher, higher or equal */
1656
1657 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1658 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
1659 a_field_component = g_string_new("");
1660 g_string_free(a_string_spaces, TRUE);
1661 a_string_spaces = g_string_new("");
1662 if(filter->expression[i+1] == '=') { /* >= */
1663 i++;
1664 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_GE);
1665 } else lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_GT);
1666 break;
1667
1668 case '=': /* equal */
1669
1670 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1671 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
1672 a_field_component = g_string_new("");
1673 g_string_free(a_string_spaces, TRUE);
1674 a_string_spaces = g_string_new("");
1675 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_EQ);
1676 break;
1677
1678 /*
1679 * Field concatening caracter
1680 */
1681 case '.': /* dot */
1682
1683 /*
1684 * divide field expression into elements
1685 * in a_field_path array.
1686 *
1687 * A dot can also be present in double values
1688 */
1689 if(a_simple_expression->field == LTTV_FILTER_UNDEFINED) {
1690 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1691 a_field_component = g_string_new("");
1692 g_string_free(a_string_spaces, TRUE);
1693 a_string_spaces = g_string_new("");
1694 } else {
1695 /* Operator found, we are in the value field */
1696 g_string_append_c(a_field_component, filter->expression[i]);
1697 }
1698 break;
1699 case ' ': /* keep spaces that are within a field component */
1700 if(a_field_component->len == 0) break; /* ignore */
1701 else
1702 a_string_spaces = g_string_append_c(a_string_spaces,
1703 filter->expression[i]);
1704
1705 case '\n': /* ignore */
1706 break;
1707 case '\"':
1708 nest_quotes?(nest_quotes=0):(nest_quotes=1);
1709 break;
1710 default: /* concatening current string */
1711 if(a_string_spaces->len != 0) {
1712 a_field_component = g_string_append(
1713 a_field_component, a_string_spaces->str);
1714 a_string_spaces = g_string_set_size(a_string_spaces, 0);
1715 }
1716 a_field_component = g_string_append_c(a_field_component,
1717 filter->expression[i]);
1718 }
1719 }
1720
1721 /*
1722 * Preliminary check to see
1723 * if tree was constructed correctly
1724 */
1725 if( p_nesting>0 ) {
1726 g_warning("Wrong filtering options, the string\n\"%s\"\n\
1727 is not valid due to parenthesis incorrect use",filter->expression);
1728 return FALSE;
1729 }
1730
1731 if(tree_stack->len != 1) /* only root tree should remain */
1732 return FALSE;
1733
1734 /*
1735 * processing last element of expression
1736 */
1737 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
1738 while(t1->right != LTTV_TREE_IDLE) {
1739 g_assert(t1->right == LTTV_TREE_NODE);
1740 t1 = t1->r_child.t;
1741 }
1742 if(not) { // add not operator to tree
1743 t3 = lttv_filter_tree_new();
1744 t3->node = LTTV_LOGICAL_NOT;
1745 t1->right = LTTV_TREE_NODE;
1746 t1->r_child.t = t3;
1747 t1 = t3;
1748 not = 0;
1749 }
1750 if(subtree != NULL) { /* add the subtree */
1751 t1->right = LTTV_TREE_NODE;
1752 t1->r_child.t = subtree;
1753 subtree = NULL;
1754 } else { /* add a leaf */
1755 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1756 a_field_component = NULL;
1757 g_string_free(a_string_spaces, TRUE);
1758 a_string_spaces = NULL;
1759 t1->right = LTTV_TREE_LEAF;
1760 t1->r_child.leaf = a_simple_expression;
1761 a_simple_expression = NULL;
1762 }
1763
1764
1765 /* free the pointer array */
1766 g_assert(a_field_path->len == 0);
1767 g_ptr_array_free(a_field_path,TRUE);
1768
1769 /* free the tree stack -- but keep the root tree */
1770 filter->head = ltt_g_ptr_array_remove_index_slow(tree_stack,0);
1771 g_ptr_array_free(tree_stack,TRUE);
1772
1773 /* free the field buffer if allocated */
1774 if(a_field_component != NULL) g_string_free(a_field_component,TRUE);
1775 if(a_string_spaces != NULL) g_string_free(a_string_spaces, TRUE);
1776
1777 /* free the simple expression buffer if allocated */
1778 if(a_simple_expression != NULL) lttv_simple_expression_destroy(a_simple_expression);
1779
1780 g_assert(filter->head != NULL); /* tree should exist */
1781 g_assert(subtree == NULL); /* remaining subtree should be included in main tree */
1782
1783 #ifdef TEST
1784 gettimeofday(&endtime, NULL);
1785
1786 /* Calcul du temps de l'algorithme */
1787 double time1 = starttime.tv_sec + (starttime.tv_usec/1000000.0);
1788 double time2 = endtime.tv_sec + (endtime.tv_usec/1000000.0);
1789 // g_print("Tree build took %.10f ms for strlen of %i\n",(time2-time1)*1000,strlen(filter->expression));
1790 g_print("%.10f %i\n",(time2-time1)*1000,strlen(filter->expression));
1791 #endif
1792
1793 /* debug */
1794 g_debug("+++++++++++++++ BEGIN PRINT ++++++++++++++++\n");
1795 lttv_print_tree(filter->head,0) ;
1796 g_debug("+++++++++++++++ END PRINT ++++++++++++++++++\n");
1797
1798 /* success */
1799 return TRUE;
1800
1801 }
1802
1803 /**
1804 * @fn void lttv_filter_destroy(LttvFilter*)
1805 *
1806 * Destroy the current LttvFilter
1807 * @param filter pointer to the current LttvFilter
1808 */
1809 void
1810 lttv_filter_destroy(LttvFilter* filter) {
1811
1812 if(!filter) return;
1813
1814 if(filter->expression)
1815 g_free(filter->expression);
1816 if(filter->head)
1817 lttv_filter_tree_destroy(filter->head);
1818 g_free(filter);
1819
1820 }
1821
1822 /**
1823 * @fn LttvFilterTree* lttv_filter_tree_new()
1824 *
1825 * Assign a new tree for the current expression
1826 * or sub expression
1827 * @return pointer of LttvFilterTree
1828 */
1829 LttvFilterTree*
1830 lttv_filter_tree_new() {
1831 LttvFilterTree* tree;
1832
1833 tree = g_new(LttvFilterTree,1);
1834 tree->node = 0; //g_new(lttv_expression,1);
1835 tree->left = LTTV_TREE_IDLE;
1836 tree->right = LTTV_TREE_IDLE;
1837 tree->r_child.t = NULL;
1838 tree->l_child.t = NULL;
1839
1840 return tree;
1841 }
1842
1843 /**
1844 * @fn void lttv_filter_append_expression(LttvFilter*,char*)
1845 *
1846 * Append a new expression to the expression
1847 * defined in the current filter
1848 * @param filter pointer to the current LttvFilter
1849 * @param expression string that must be appended
1850 * @return Success/Failure of operation
1851 */
1852 gboolean
1853 lttv_filter_append_expression(LttvFilter* filter, const char *expression) {
1854
1855 if(expression == NULL) return FALSE;
1856 if(filter == NULL) return FALSE;
1857 if(expression[0] == '\0') return FALSE; /* Empty expression */
1858
1859 GString* s = g_string_new("");
1860 if(filter->expression != NULL) {
1861 s = g_string_append(s,filter->expression);
1862 s = g_string_append_c(s,'&');
1863 }
1864 s = g_string_append(s,expression);
1865
1866 g_free(filter->expression);
1867 filter->expression = g_string_free(s,FALSE);
1868
1869 /* TRUE if construction of tree proceeded without errors */
1870 return lttv_filter_update(filter);
1871
1872 }
1873
1874 /**
1875 * @fn void lttv_filter_clear_expression(LttvFilter*)
1876 *
1877 * Clear the filter expression from the
1878 * current filter and sets its pointer to NULL
1879 * @param filter pointer to the current LttvFilter
1880 */
1881 void
1882 lttv_filter_clear_expression(LttvFilter* filter) {
1883
1884 if(filter->expression != NULL) {
1885 g_free(filter->expression);
1886 filter->expression = NULL;
1887 }
1888
1889 }
1890
1891 /**
1892 * @fn void lttv_filter_tree_destroy(LttvFilterTree*)
1893 *
1894 * Destroys the tree and his sub-trees
1895 * @param tree Tree which must be destroyed
1896 */
1897 void
1898 lttv_filter_tree_destroy(LttvFilterTree* tree) {
1899
1900 if(tree == NULL) return;
1901
1902 if(tree->left == LTTV_TREE_LEAF) lttv_simple_expression_destroy(tree->l_child.leaf);
1903 else if(tree->left == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->l_child.t);
1904
1905 if(tree->right == LTTV_TREE_LEAF) lttv_simple_expression_destroy(tree->r_child.leaf);
1906 else if(tree->right == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->r_child.t);
1907
1908 // g_free(tree->node);
1909 g_free(tree);
1910 }
1911
1912 /**
1913 * Global parsing function for the current
1914 * LttvFilterTree
1915 * @param t pointer to the current LttvFilterTree
1916 * @param event current LttEvent, NULL if not used
1917 * @param tracefile current LttTracefile, NULL if not used
1918 * @param trace current LttTrace, NULL if not used
1919 * @param state current LttvProcessState, NULL if not used
1920 * @param context current LttvTracefileContext, NULL if not used
1921 * @return response of filter
1922 */
1923 gboolean
1924 lttv_filter_tree_parse(
1925 const LttvFilterTree* t,
1926 const LttEvent* event,
1927 const LttTracefile* tracefile,
1928 const LttTrace* trace,
1929 const LttvTracefileContext* context,
1930 const LttvProcessState* state,
1931 const LttvTraceContext* tc
1932 /*,...*/)
1933 {
1934
1935 /*
1936 * Each tree is parsed in inorder.
1937 * This way, it's possible to apply the left filter of the
1938 * tree, then decide whether or not the right branch should
1939 * be parsed depending on the linking logical operator
1940 *
1941 * Each node consists in a
1942 * 1. logical operator
1943 * 2. left child ( node or simple expression )
1944 * 3. right child ( node or simple expression )
1945 *
1946 * When the child is a simple expression, we must
1947 * before all determine if the expression refers to
1948 * a structure which is whithin observation ( not NULL ).
1949 * -If so, the expression is evaluated.
1950 * -If not, the result is set to TRUE since this particular
1951 * operation does not interfere with the lttv structure
1952 *
1953 * The result of each simple expression will directly
1954 * affect the next branch. This way, depending on
1955 * the linking logical operator, the parser will decide
1956 * to explore or not the next branch.
1957 * 1. AND OPERATOR
1958 * -If result of left branch is 0 / FALSE
1959 * then don't explore right branch and return 0;
1960 * -If result of left branch is 1 / TRUE then explore
1961 * 2. OR OPERATOR
1962 * -If result of left branch is 1 / TRUE
1963 * then don't explore right branch and return 1;
1964 * -If result of left branch is 0 / FALSE then explore
1965 * 3. XOR OPERATOR
1966 * -Result of left branch will not affect exploration of
1967 * right branch
1968 */
1969
1970 gboolean lresult = FALSE, rresult = FALSE;
1971
1972 LttvTraceState *ts = NULL;
1973 LttvTracefileState *tfs = (LttvTracefileState*)context;
1974 if(tc)
1975 ts = (LttvTraceState*)tc;
1976 else if(context)
1977 ts = (LttvTraceState*)context->t_context;
1978
1979 if(tfs) {
1980 guint cpu = tfs->cpu;
1981 if(ts)
1982 state = ts->running_process[cpu];
1983 }
1984
1985 /*
1986 * Parse left branch
1987 */
1988 if(t->left == LTTV_TREE_NODE) {
1989 lresult = lttv_filter_tree_parse(t->l_child.t,event,tracefile,trace,context,NULL,NULL);
1990 }
1991 else if(t->left == LTTV_TREE_LEAF) {
1992 lresult = lttv_filter_tree_parse_branch(t->l_child.leaf,event,tracefile,trace,state,context);
1993 }
1994
1995 /*
1996 * Parse linking operator
1997 * make a cutoff if possible
1998 */
1999 if((t->node & LTTV_LOGICAL_OR) && lresult == TRUE) return TRUE;
2000 if((t->node & LTTV_LOGICAL_AND) && lresult == FALSE) return FALSE;
2001
2002 /*
2003 * Parse right branch
2004 */
2005 if(t->right == LTTV_TREE_NODE) {
2006 rresult = lttv_filter_tree_parse(t->r_child.t,event,tracefile,trace,context,NULL,NULL);
2007 }
2008 else if(t->right == LTTV_TREE_LEAF) {
2009 rresult = lttv_filter_tree_parse_branch(t->r_child.leaf,event,tracefile,trace,state,context);
2010 }
2011
2012
2013 /*
2014 * Apply and return the
2015 * logical link between the
2016 * two operation
2017 */
2018 switch(t->node) {
2019 case LTTV_LOGICAL_OR: return (lresult | rresult);
2020 case LTTV_LOGICAL_AND: return (lresult & rresult);
2021 case LTTV_LOGICAL_NOT:
2022 return (t->left==LTTV_TREE_LEAF)?!lresult:((t->right==LTTV_TREE_LEAF)?!rresult:TRUE);
2023 case LTTV_LOGICAL_XOR: return (lresult ^ rresult);
2024 case 0: return (rresult);
2025 default:
2026 /*
2027 * This case should never be
2028 * parsed, if so, this subtree
2029 * is cancelled !
2030 */
2031 return TRUE;
2032 }
2033
2034 }
2035
2036 /**
2037 * This function parses a particular branch of the tree
2038 * @param se pointer to the current LttvSimpleExpression
2039 * @param event current LttEvent, NULL if not used
2040 * @param tracefile current LttTracefile, NULL if not used
2041 * @param trace current LttTrace, NULL if not used
2042 * @param state current LttvProcessState, NULL if not used
2043 * @param context current LttvTracefileContext, NULL if not used
2044 * @return response of filter
2045 */
2046 gboolean
2047 lttv_filter_tree_parse_branch(
2048 const LttvSimpleExpression* se,
2049 const LttEvent* event,
2050 const LttTracefile* tracefile,
2051 const LttTrace* trace,
2052 const LttvProcessState* state,
2053 const LttvTracefileContext* context) {
2054
2055 LttvFieldValue v;
2056 v = se->value;
2057 switch(se->field) {
2058 case LTTV_FILTER_TRACE_NAME:
2059 if(trace == NULL) return TRUE;
2060 else {
2061 GQuark quark = ltt_trace_name(trace);
2062 return se->op((gpointer)&quark,v);
2063 }
2064 break;
2065 case LTTV_FILTER_TRACEFILE_NAME:
2066 if(tracefile == NULL) return TRUE;
2067 else {
2068 GQuark quark = ltt_tracefile_name(tracefile);
2069 return se->op((gpointer)&quark,v);
2070 }
2071 break;
2072 case LTTV_FILTER_STATE_PID:
2073 if(state == NULL) return TRUE;
2074 else return se->op((gpointer)&state->pid,v);
2075 break;
2076 case LTTV_FILTER_STATE_PPID:
2077 if(state == NULL) return TRUE;
2078 else return se->op((gpointer)&state->ppid,v);
2079 break;
2080 case LTTV_FILTER_STATE_CT:
2081 if(state == NULL) return TRUE;
2082 else {
2083 return se->op((gpointer)&state->creation_time,v);
2084 }
2085 break;
2086 case LTTV_FILTER_STATE_IT:
2087 if(state == NULL) return TRUE;
2088 else {
2089 return se->op((gpointer)&state->insertion_time,v);
2090 }
2091 break;
2092 case LTTV_FILTER_STATE_P_NAME:
2093 if(state == NULL) return TRUE;
2094 else {
2095 GQuark quark = state->name;
2096 return se->op((gpointer)&quark,v);
2097 }
2098 break;
2099 case LTTV_FILTER_STATE_T_BRAND:
2100 if(state == NULL) return TRUE;
2101 else {
2102 GQuark quark = state->brand;
2103 return se->op((gpointer)&quark,v);
2104 }
2105 break;
2106 case LTTV_FILTER_STATE_EX_MODE:
2107 if(state == NULL) return TRUE;
2108 else return se->op((gpointer)&state->state->t,v);
2109 break;
2110 case LTTV_FILTER_STATE_EX_SUBMODE:
2111 if(state == NULL) return TRUE;
2112 else return se->op((gpointer)&state->state->n,v);
2113 break;
2114 case LTTV_FILTER_STATE_P_STATUS:
2115 if(state == NULL) return TRUE;
2116 else return se->op((gpointer)&state->state->s,v);
2117 break;
2118 case LTTV_FILTER_STATE_CPU:
2119 if(state == NULL) return TRUE;
2120 else {
2121 return se->op((gpointer)&state->cpu,v);
2122 }
2123 break;
2124 case LTTV_FILTER_EVENT_NAME:
2125 if(event == NULL) return TRUE;
2126 else {
2127 struct marker_info *info;
2128 GQuark qtuple[2];
2129 LttTracefile *tf = context->tf;
2130 qtuple[0] = ltt_tracefile_name(tracefile);
2131 info = marker_get_info_from_id(tf->mdata, event->event_id);
2132 g_assert(info != NULL);
2133 qtuple[1] = info->name;
2134 return se->op((gpointer)qtuple,v);
2135 }
2136 break;
2137 case LTTV_FILTER_EVENT_SUBNAME:
2138 if(event == NULL) return TRUE;
2139 else {
2140 struct marker_info *info;
2141 LttTracefile *tf = context->tf;
2142 info = marker_get_info_from_id(tf->mdata, event->event_id);
2143 g_assert(info != NULL);
2144 GQuark quark = info->name;
2145 return se->op((gpointer)&quark,v);
2146 }
2147 break;
2148 case LTTV_FILTER_EVENT_CATEGORY:
2149 /*
2150 * TODO: Not yet implemented
2151 */
2152 return TRUE;
2153 break;
2154 case LTTV_FILTER_EVENT_TIME:
2155 if(event == NULL) return TRUE;
2156 else {
2157 LttTime time = ltt_event_time(event);
2158 return se->op((gpointer)&time,v);
2159 }
2160 break;
2161 case LTTV_FILTER_EVENT_TSC:
2162 if(event == NULL) return TRUE;
2163 else {
2164 LttCycleCount count = ltt_event_cycle_count(event);
2165 return se->op((gpointer)&count,v);
2166 }
2167 break;
2168 case LTTV_FILTER_EVENT_TARGET_PID:
2169 if(context == NULL) return TRUE;
2170 else {
2171 guint target_pid =
2172 lttv_state_get_target_pid((LttvTracefileState*)context);
2173 return se->op((gpointer)&target_pid,v);
2174 }
2175 break;
2176 case LTTV_FILTER_EVENT_FIELD:
2177 /*
2178 * TODO: Use the offset to
2179 * find the dynamic field
2180 * in the event struct
2181 */
2182 return TRUE;
2183 default:
2184 /*
2185 * This case should never be
2186 * parsed, if so, the whole
2187 * filtering is cancelled
2188 */
2189 g_warning("Error while parsing the filter tree");
2190 return TRUE;
2191 }
2192
2193 /* should never get here */
2194 return TRUE;
2195
2196 }
2197
2198
2199
2200 /**
2201 * Debug function. Prints tree memory allocation.
2202 * @param t the pointer to the current LttvFilterTree
2203 */
2204 void
2205 lttv_print_tree(const LttvFilterTree* t, const int count) {
2206
2207 g_debug("node:%p lchild:%p rchild:%p depth:%i\n",t, //t->l_child.t,t->r_child.t);
2208 (t->left==LTTV_TREE_NODE)?t->l_child.t:NULL,
2209 (t->right==LTTV_TREE_NODE)?t->r_child.t:NULL,
2210 count);
2211 g_debug("logic operator: %s\n",(t->node&1)?"OR":((t->node&2)?"AND":((t->node&4)?"NOT":((t->node&8)?"XOR":"IDLE"))));
2212 g_debug("|-> left branch %p is a %s\n",t->l_child.t,(t->left==LTTV_TREE_NODE)?"NODE":((t->left==LTTV_TREE_LEAF)?"LEAF":"IDLE"));
2213 if(t->left == LTTV_TREE_LEAF) {
2214 g_debug("| |-> field type number: %i\n",t->l_child.leaf->field);
2215 g_debug("| |-> offset is: %i\n",t->l_child.leaf->offset);
2216 g_debug("| |-> operator function is: %p\n",t->l_child.leaf->op);
2217 }
2218 g_debug("|-> right branch %p is a %s\n",t->r_child.t,(t->right==LTTV_TREE_NODE)?"NODE":((t->right==LTTV_TREE_LEAF)?"LEAF":"IDLE"));
2219 if(t->right == LTTV_TREE_LEAF) {
2220 g_debug("| |-> field type number: %i\n",t->r_child.leaf->field);
2221 g_debug("| |-> offset is: %i\n",t->r_child.leaf->offset);
2222 g_debug("| |-> operator function is: %p\n",t->r_child.leaf->op);
2223 }
2224
2225 if(t->left == LTTV_TREE_NODE) lttv_print_tree(t->l_child.t,count+1);
2226 if(t->right == LTTV_TREE_NODE) lttv_print_tree(t->r_child.t,count+1);
2227 }
2228
2229 /**
2230 * @fn static void module_init()
2231 *
2232 * Initializes the filter module and specific values
2233 */
2234 static void module_init()
2235 {
2236
2237 }
2238
2239 /**
2240 * Destroys the filter module and specific values
2241 */
2242 static void module_destroy()
2243 {
2244
2245 }
2246
2247
2248 LTTV_MODULE("filter", "Filters traceset and events", \
2249 "Filters traceset and events specifically to user input", \
2250 module_init, module_destroy)
2251
2252
2253
This page took 0.116866 seconds and 4 git commands to generate.