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