1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2005 Michel Dagenais and Simon Bouvier-Zappa
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;
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.
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,
19 /*! \file lttv/lttv/filter.c
20 * \brief Defines the core filter of application
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.
27 * Fields specified in a simple expression can take following
30 * LttvTracefileContext{}\
32 * | |->name (String, converted to GQuark)
33 * | |->category (String, not yet implemented)
35 * | |->tsc (LttCycleCount)
39 * | |->"sub-field name"
41 * | |->"leaf-field name" (field type)
43 * | |->name (String, converted to GQuark)
45 * | |->name (String, converted to GQuark)
49 * |->creation_time (LttTime)
50 * |->insertion_time (LttTime)
51 * |->process_name (String, converted to GQuark)
52 * |->execution_mode (LttvExecutionMode)
53 * |->execution_submode (LttvExecutionSubmode)
54 * |->process_status (LttvProcessStatus)
60 * - refine switch of expression in multiple uses functions
61 * - remove the idle expressions in the tree ****
64 #include <lttv/filter.h>
67 * @fn LttvSimpleExpression* lttv_simple_expression_new()
69 * Constructor for LttvSimpleExpression
70 * @return pointer to new LttvSimpleExpression
73 lttv_simple_expression_new() {
75 LttvSimpleExpression
* se
= g_new(LttvSimpleExpression
,1);
77 se
->field
= LTTV_FILTER_UNDEFINED
;
85 * @fn gboolean lttv_simple_expression_assign_field(GPtrArray*,LttvSimpleExpression*)
87 * Parse through filtering field hierarchy as specified
88 * by user. This function compares each value to
89 * predetermined quarks
90 * @param fp The field path list
91 * @param se current simple expression
92 * @return success/failure of operation
95 lttv_simple_expression_assign_field(GPtrArray
* fp
, LttvSimpleExpression
* se
) {
99 if(fp
->len
< 2) return FALSE
;
100 g_assert(f
=g_ptr_array_remove_index(fp
,0));
103 * Parse through the specified
106 * Take note however that the
107 * 'event' subfields might change
108 * depending on values specified
109 * in core.xml file. Hence, if
110 * none of the subfields in the
111 * array match the hardcoded
112 * subfields, it will be considered
115 if(!g_strcasecmp(f
->str
,"trace") ) {
120 g_string_free(f
,TRUE
);
121 f
=g_ptr_array_remove_index(fp
,0);
122 if(!g_strcasecmp(f
->str
,"name")) {
123 se
->field
= LTTV_FILTER_TRACE_NAME
;
125 } else if(!g_strcasecmp(f
->str
,"traceset") ) {
127 * FIXME: not yet implemented !
129 } else if(!g_strcasecmp(f
->str
,"tracefile") ) {
134 g_string_free(f
,TRUE
);
135 f
=g_ptr_array_remove_index(fp
,0);
136 if(!g_strcasecmp(f
->str
,"name")) {
137 se
->field
= LTTV_FILTER_TRACEFILE_NAME
;
139 } else if(!g_strcasecmp(f
->str
,"state") ) {
144 * state.creation_time
145 * state.insertion_time
147 * state.execution_mode
148 * state.execution_submode
149 * state.process_status
152 g_string_free(f
,TRUE
);
153 f
=g_ptr_array_remove_index(fp
,0);
154 if(!g_strcasecmp(f
->str
,"pid") ) {
155 se
->field
= LTTV_FILTER_STATE_PID
;
157 else if(!g_strcasecmp(f
->str
,"ppid") ) {
158 se
->field
= LTTV_FILTER_STATE_PPID
;
160 else if(!g_strcasecmp(f
->str
,"creation_time") ) {
161 se
->field
= LTTV_FILTER_STATE_CT
;
163 else if(!g_strcasecmp(f
->str
,"insertion_time") ) {
164 se
->field
= LTTV_FILTER_STATE_IT
;
166 else if(!g_strcasecmp(f
->str
,"process_name") ) {
167 se
->field
= LTTV_FILTER_STATE_P_NAME
;
169 else if(!g_strcasecmp(f
->str
,"execution_mode") ) {
170 se
->field
= LTTV_FILTER_STATE_EX_MODE
;
172 else if(!g_strcasecmp(f
->str
,"execution_submode") ) {
173 se
->field
= LTTV_FILTER_STATE_EX_SUBMODE
;
175 else if(!g_strcasecmp(f
->str
,"process_status") ) {
176 se
->field
= LTTV_FILTER_STATE_P_STATUS
;
178 else if(!g_strcasecmp(f
->str
,"cpu") ) {
179 se
->field
= LTTV_FILTER_STATE_CPU
;
181 } else if(!g_strcasecmp(f
->str
,"event") ) {
189 g_string_free(f
,TRUE
);
190 f
=g_ptr_array_remove_index(fp
,0);
191 if(!g_strcasecmp(f
->str
,"name") ) {
192 se
->field
= LTTV_FILTER_EVENT_NAME
;
194 else if(!g_strcasecmp(f
->str
,"category") ) {
196 * FIXME: Category not yet functional in lttv
198 se
->field
= LTTV_FILTER_EVENT_CATEGORY
;
200 else if(!g_strcasecmp(f
->str
,"time") ) {
201 se
->field
= LTTV_FILTER_EVENT_TIME
;
203 else if(!g_strcasecmp(f
->str
,"tsc") ) {
204 se
->field
= LTTV_FILTER_EVENT_TSC
;
206 else { /* core.xml specified options */
207 se
->field
= LTTV_FILTER_EVENT_FIELD
;
210 g_warning("Unrecognized field in filter string");
213 /* free memory for last string */
214 g_string_free(f
,TRUE
);
216 /* array should be empty */
217 g_assert(fp
->len
== 0);
219 if(se
->field
== LTTV_FILTER_UNDEFINED
) {
220 g_warning("The specified field was not recognized !");
227 * @fn gboolean lttv_simple_expression_assign_operator(LttvSimpleExpression*,LttvExpressionOp)
229 * Sets the function pointer for the current
231 * @param se current simple expression
232 * @param op current operator
233 * @return success/failure of operation
235 gboolean
lttv_simple_expression_assign_operator(LttvSimpleExpression
* se
, LttvExpressionOp op
) {
241 case LTTV_FILTER_TRACE_NAME
:
242 case LTTV_FILTER_TRACEFILE_NAME
:
243 case LTTV_FILTER_STATE_P_NAME
:
244 case LTTV_FILTER_EVENT_NAME
:
247 se
->op
= lttv_apply_op_eq_quark
;
250 se
->op
= lttv_apply_op_ne_quark
;
253 g_warning("Error encountered in operator assignment = or != expected");
260 case LTTV_FILTER_STATE_PID
:
261 case LTTV_FILTER_STATE_PPID
:
262 case LTTV_FILTER_STATE_EX_MODE
:
263 case LTTV_FILTER_STATE_EX_SUBMODE
:
264 case LTTV_FILTER_STATE_P_STATUS
:
267 se
->op
= lttv_apply_op_eq_uint64
;
270 se
->op
= lttv_apply_op_ne_uint64
;
273 se
->op
= lttv_apply_op_lt_uint64
;
276 se
->op
= lttv_apply_op_le_uint64
;
279 se
->op
= lttv_apply_op_gt_uint64
;
282 se
->op
= lttv_apply_op_ge_uint64
;
285 g_warning("Error encountered in operator assignment");
292 case LTTV_FILTER_STATE_CT
:
293 case LTTV_FILTER_STATE_IT
:
294 case LTTV_FILTER_EVENT_TIME
:
295 case LTTV_FILTER_EVENT_TSC
:
298 se
->op
= lttv_apply_op_eq_ltttime
;
301 se
->op
= lttv_apply_op_ne_ltttime
;
304 se
->op
= lttv_apply_op_lt_ltttime
;
307 se
->op
= lttv_apply_op_le_ltttime
;
310 se
->op
= lttv_apply_op_gt_ltttime
;
313 se
->op
= lttv_apply_op_ge_ltttime
;
316 g_warning("Error encountered in operator assignment");
321 g_warning("Error encountered in operator assignation ! Field type:%i",se
->field
);
330 * @fn gboolean lttv_simple_expression_assign_value(LttvSimpleExpression*,char*)
332 * Assign the value field to the current LttvSimpleExpression
333 * @param se pointer to the current LttvSimpleExpression
334 * @param value string value for simple expression
336 gboolean
lttv_simple_expression_assign_value(LttvSimpleExpression
* se
, char* value
) {
338 // g_print("se->value:%s\n",value);
340 gboolean is_double
= FALSE
;
341 LttTime t
= ltt_time_zero
;
349 case LTTV_FILTER_TRACE_NAME
:
350 case LTTV_FILTER_TRACEFILE_NAME
:
351 case LTTV_FILTER_STATE_P_NAME
:
352 case LTTV_FILTER_EVENT_NAME
:
353 // se->value.v_string = value;
354 se
->value
.v_uint32
= g_quark_to_string(value
);
360 case LTTV_FILTER_STATE_PID
:
361 case LTTV_FILTER_STATE_PPID
:
362 case LTTV_FILTER_STATE_EX_MODE
:
363 case LTTV_FILTER_STATE_EX_SUBMODE
:
364 case LTTV_FILTER_STATE_P_STATUS
:
365 se
->value
.v_uint64
= atoi(value
);
371 case LTTV_FILTER_STATE_CT
:
372 case LTTV_FILTER_STATE_IT
:
373 case LTTV_FILTER_EVENT_TIME
:
374 case LTTV_FILTER_EVENT_TSC
:
375 //se->value.v_double = atof(value);
377 * parsing logic could be optimised,
378 * but as for now, simpler this way
380 v
= g_string_new("");
381 for(i
=0;i
<strlen(value
);i
++) {
382 if(value
[i
] == '.') {
383 /* cannot specify number with more than one '.' */
384 if(is_double
) return FALSE
;
385 else is_double
= TRUE
;
387 g_string_free(v
,TRUE
);
388 v
= g_string_new("");
389 } else g_string_append_c(v
,value
[i
]);
391 /* number can be integer or double */
392 if(is_double
) t
.tv_nsec
= atoi(v
);
393 else t
.tv_sec
= atoi(v
);
395 g_string_free(v
,TRUE
);
397 se
->value
.v_ltttime
= t
;
401 g_warning("Error encountered in value assignation ! Field type = %i",se
->field
);
411 * @fn void lttv_simple_expression_destroy(LttvSimpleExpression*)
413 * Disallocate memory for the current
415 * @param se pointer to the current LttvSimpleExpression
418 lttv_simple_expression_destroy(LttvSimpleExpression
* se
) {
420 // g_free(se->value);
422 case LTTV_FILTER_TRACE_NAME
:
423 case LTTV_FILTER_TRACEFILE_NAME
:
424 case LTTV_FILTER_STATE_P_NAME
:
425 case LTTV_FILTER_EVENT_NAME
:
426 g_free(se
->value
.v_string
);
434 * @fn gint lttv_struct_type(gint)
436 * Finds the structure type depending
437 * on the fields in parameters
438 * @params ft Field of the current structure
439 * @return LttvStructType enum or -1 for error
442 lttv_struct_type(gint ft
) {
445 case LTTV_FILTER_TRACE_NAME
:
446 return LTTV_FILTER_TRACE
;
448 case LTTV_FILTER_TRACEFILE_NAME
:
449 return LTTV_FILTER_TRACEFILE
;
451 case LTTV_FILTER_STATE_PID
:
452 case LTTV_FILTER_STATE_PPID
:
453 case LTTV_FILTER_STATE_CT
:
454 case LTTV_FILTER_STATE_IT
:
455 case LTTV_FILTER_STATE_P_NAME
:
456 case LTTV_FILTER_STATE_EX_MODE
:
457 case LTTV_FILTER_STATE_EX_SUBMODE
:
458 case LTTV_FILTER_STATE_P_STATUS
:
459 case LTTV_FILTER_STATE_CPU
:
460 return LTTV_FILTER_STATE
;
462 case LTTV_FILTER_EVENT_NAME
:
463 case LTTV_FILTER_EVENT_CATEGORY
:
464 case LTTV_FILTER_EVENT_TIME
:
465 case LTTV_FILTER_EVENT_TSC
:
466 case LTTV_FILTER_EVENT_FIELD
:
467 return LTTV_FILTER_EVENT
;
475 * @fn gboolean lttv_apply_op_eq_uint64(gpointer,LttvFieldValue)
477 * Applies the 'equal' operator to the
478 * specified structure and value
479 * @param v1 left member of comparison
480 * @param v2 right member of comparison
481 * @return success/failure of operation
483 gboolean
lttv_apply_op_eq_uint64(const gpointer v1
, LttvFieldValue v2
) {
485 guint64
* r
= (guint64
*) v1
;
486 return (*r
== v2
.v_uint64
);
491 * @fn gboolean lttv_apply_op_eq_uint32(gpointer,LttvFieldValue)
493 * Applies the 'equal' operator to the
494 * specified structure and value
495 * @param v1 left member of comparison
496 * @param v2 right member of comparison
497 * @return success/failure of operation
499 gboolean
lttv_apply_op_eq_uint32(const gpointer v1
, LttvFieldValue v2
) {
500 guint32
* r
= (guint32
*) v1
;
501 return (*r
== v2
.v_uint32
);
505 * @fn gboolean lttv_apply_op_eq_uint16(gpointer,LttvFieldValue)
507 * Applies the 'equal' operator to the
508 * specified structure and value
509 * @param v1 left member of comparison
510 * @param v2 right member of comparison
511 * @return success/failure of operation
513 gboolean
lttv_apply_op_eq_uint16(const gpointer v1
, LttvFieldValue v2
) {
514 guint16
* r
= (guint16
*) v1
;
515 return (*r
== v2
.v_uint16
);
519 * @fn gboolean lttv_apply_op_eq_double(gpointer,LttvFieldValue)
521 * Applies the 'equal' operator to the
522 * specified structure and value
523 * @param v1 left member of comparison
524 * @param v2 right member of comparison
525 * @return success/failure of operation
527 gboolean
lttv_apply_op_eq_double(const gpointer v1
, LttvFieldValue v2
) {
528 double* r
= (double*) v1
;
529 return (*r
== v2
.v_double
);
533 * @fn gboolean lttv_apply_op_eq_string(gpointer,LttvFieldValue)
535 * Applies the 'equal' operator to the
536 * specified structure and value
537 * @param v1 left member of comparison
538 * @param v2 right member of comparison
539 * @return success/failure of operation
541 gboolean
lttv_apply_op_eq_string(const gpointer v1
, LttvFieldValue v2
) {
542 char* r
= (char*) v1
;
543 return (!g_strcasecmp(r
,v2
.v_string
));
547 * @fn gboolean lttv_apply_op_eq_quark(gpointer,LttvFieldValue)
549 * Applies the 'equal' operator to the
550 * specified structure and value
551 * @param v1 left member of comparison
552 * @param v2 right member of comparison
553 * @return success/failure of operation
555 gboolean
lttv_apply_op_eq_quark(const gpointer v1
, LttvFieldValue v2
) {
556 GQuark
* r
= (GQuark
*) v1
;
557 g_print("v1:%i v2:%i\n",*r
,v2
.v_uint32
);
558 return (*r
== v2
.v_uint32
);
562 * @fn gboolean lttv_apply_op_eq_ltttime(gpointer,LttvFieldValue)
564 * Applies the 'equal' operator to the
565 * specified structure and value
566 * @param v1 left member of comparison
567 * @param v2 right member of comparison
568 * @return success/failure of operation
570 gboolean
lttv_apply_op_eq_ltttime(const gpointer v1
, LttvFieldValue v2
) {
571 LttTime
* r
= (LttTime
*) v1
;
572 // return ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec == v2.v_ltttime.tv_nsec));
573 return ltt_time_compare(*r
, v2
.v_ltttime
)==0?1:0;
578 * @fn gboolean lttv_apply_op_ne_uint64(gpointer,LttvFieldValue)
580 * Applies the 'not equal' operator to the
581 * specified structure and value
582 * @param v1 left member of comparison
583 * @param v2 right member of comparison
584 * @return success/failure of operation
586 gboolean
lttv_apply_op_ne_uint64(const gpointer v1
, LttvFieldValue v2
) {
587 guint64
* r
= (guint64
*) v1
;
588 return (*r
!= v2
.v_uint64
);
592 * @fn gboolean lttv_apply_op_ne_uint32(gpointer,LttvFieldValue)
594 * Applies the 'not equal' operator to the
595 * specified structure and value
596 * @param v1 left member of comparison
597 * @param v2 right member of comparison
598 * @return success/failure of operation
600 gboolean
lttv_apply_op_ne_uint32(const gpointer v1
, LttvFieldValue v2
) {
601 guint32
* r
= (guint32
*) v1
;
602 return (*r
!= v2
.v_uint32
);
606 * @fn gboolean lttv_apply_op_ne_uint16(gpointer,LttvFieldValue)
608 * Applies the 'not equal' operator to the
609 * specified structure and value
610 * @param v1 left member of comparison
611 * @param v2 right member of comparison
612 * @return success/failure of operation
614 gboolean
lttv_apply_op_ne_uint16(const gpointer v1
, LttvFieldValue v2
) {
615 guint16
* r
= (guint16
*) v1
;
616 return (*r
!= v2
.v_uint16
);
620 * @fn gboolean lttv_apply_op_ne_double(gpointer,LttvFieldValue)
622 * Applies the 'not equal' operator to the
623 * specified structure and value
624 * @param v1 left member of comparison
625 * @param v2 right member of comparison
626 * @return success/failure of operation
628 gboolean
lttv_apply_op_ne_double(const gpointer v1
, LttvFieldValue v2
) {
629 double* r
= (double*) v1
;
630 return (*r
!= v2
.v_double
);
634 * @fn gboolean lttv_apply_op_ne_string(gpointer,LttvFieldValue)
636 * Applies the 'not equal' operator to the
637 * specified structure and value
638 * @param v1 left member of comparison
639 * @param v2 right member of comparison
640 * @return success/failure of operation
642 gboolean
lttv_apply_op_ne_string(const gpointer v1
, LttvFieldValue v2
) {
643 char* r
= (char*) v1
;
644 return (g_strcasecmp(r
,v2
.v_string
));
648 * @fn gboolean lttv_apply_op_ne_quark(gpointer,LttvFieldValue)
650 * Applies the 'not equal' operator to the
651 * specified structure and value
652 * @param v1 left member of comparison
653 * @param v2 right member of comparison
654 * @return success/failure of operation
656 gboolean
lttv_apply_op_ne_quark(const gpointer v1
, LttvFieldValue v2
) {
657 GQuark
* r
= (GQuark
*) v1
;
658 return (*r
!= v2
.v_uint32
);
663 * @fn gboolean lttv_apply_op_ne_ltttime(gpointer,LttvFieldValue)
665 * Applies the 'not equal' operator to the
666 * specified structure and value
667 * @param v1 left member of comparison
668 * @param v2 right member of comparison
669 * @return success/failure of operation
671 gboolean
lttv_apply_op_ne_ltttime(const gpointer v1
, LttvFieldValue v2
) {
672 LttTime
* r
= (LttTime
*) v1
;
673 return ltt_time_compare(*r
, v2
.v_ltttime
)!=0?1:0;
678 * @fn gboolean lttv_apply_op_lt_uint64(gpointer,LttvFieldValue)
680 * Applies the 'lower than' operator to the
681 * specified structure and value
682 * @param v1 left member of comparison
683 * @param v2 right member of comparison
684 * @return success/failure of operation
686 gboolean
lttv_apply_op_lt_uint64(const gpointer v1
, LttvFieldValue v2
) {
687 guint64
* r
= (guint64
*) v1
;
688 return (*r
< v2
.v_uint64
);
692 * @fn gboolean lttv_apply_op_lt_uint32(gpointer,LttvFieldValue)
694 * Applies the 'lower than' operator to the
695 * specified structure and value
696 * @param v1 left member of comparison
697 * @param v2 right member of comparison
698 * @return success/failure of operation
700 gboolean
lttv_apply_op_lt_uint32(const gpointer v1
, LttvFieldValue v2
) {
701 guint32
* r
= (guint32
*) v1
;
702 return (*r
< v2
.v_uint32
);
706 * @fn gboolean lttv_apply_op_lt_uint16(gpointer,LttvFieldValue)
708 * Applies the 'lower than' operator to the
709 * specified structure and value
710 * @param v1 left member of comparison
711 * @param v2 right member of comparison
712 * @return success/failure of operation
714 gboolean
lttv_apply_op_lt_uint16(const gpointer v1
, LttvFieldValue v2
) {
715 guint16
* r
= (guint16
*) v1
;
716 return (*r
< v2
.v_uint16
);
720 * @fn gboolean lttv_apply_op_lt_double(gpointer,LttvFieldValue)
722 * Applies the 'lower than' operator to the
723 * specified structure and value
724 * @param v1 left member of comparison
725 * @param v2 right member of comparison
726 * @return success/failure of operation
728 gboolean
lttv_apply_op_lt_double(const gpointer v1
, LttvFieldValue v2
) {
729 double* r
= (double*) v1
;
730 return (*r
< v2
.v_double
);
734 * @fn gboolean lttv_apply_op_lt_ltttime(gpointer,LttvFieldValue)
736 * Applies the 'lower than' operator to the
737 * specified structure and value
738 * @param v1 left member of comparison
739 * @param v2 right member of comparison
740 * @return success/failure of operation
742 gboolean
lttv_apply_op_lt_ltttime(const gpointer v1
, LttvFieldValue v2
) {
743 LttTime
* r
= (LttTime
*) v1
;
744 // 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)));
745 return ltt_time_compare(*r
, v2
.v_ltttime
)==-1?1:0;
750 * @fn gboolean lttv_apply_op_le_uint64(gpointer,LttvFieldValue)
752 * Applies the 'lower or equal' operator to the
753 * specified structure and value
754 * @param v1 left member of comparison
755 * @param v2 right member of comparison
756 * @return success/failure of operation
758 gboolean
lttv_apply_op_le_uint64(const gpointer v1
, LttvFieldValue v2
) {
759 guint64
* r
= (guint64
*) v1
;
760 return (*r
<= v2
.v_uint64
);
764 * @fn gboolean lttv_apply_op_le_uint32(gpointer,LttvFieldValue)
766 * Applies the 'lower or equal' operator to the
767 * specified structure and value
768 * @param v1 left member of comparison
769 * @param v2 right member of comparison
770 * @return success/failure of operation
772 gboolean
lttv_apply_op_le_uint32(const gpointer v1
, LttvFieldValue v2
) {
773 guint32
* r
= (guint32
*) v1
;
774 return (*r
<= v2
.v_uint32
);
778 * @fn gboolean lttv_apply_op_le_uint16(gpointer,LttvFieldValue)
780 * Applies the 'lower or 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
786 gboolean
lttv_apply_op_le_uint16(const gpointer v1
, LttvFieldValue v2
) {
787 guint16
* r
= (guint16
*) v1
;
788 return (*r
<= v2
.v_uint16
);
792 * @fn gboolean lttv_apply_op_le_double(gpointer,LttvFieldValue)
794 * Applies the 'lower or equal' operator to the
795 * specified structure and value
796 * @param v1 left member of comparison
797 * @param v2 right member of comparison
798 * @return success/failure of operation
800 gboolean
lttv_apply_op_le_double(const gpointer v1
, LttvFieldValue v2
) {
801 double* r
= (double*) v1
;
802 return (*r
<= v2
.v_double
);
806 * @fn gboolean lttv_apply_op_le_ltttime(gpointer,LttvFieldValue)
808 * Applies the 'lower or equal' operator to the
809 * specified structure and value
810 * @param v1 left member of comparison
811 * @param v2 right member of comparison
812 * @return success/failure of operation
814 gboolean
lttv_apply_op_le_ltttime(const gpointer v1
, LttvFieldValue v2
) {
815 LttTime
* r
= (LttTime
*) v1
;
816 // 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)));
817 return ltt_time_compare(*r
, v2
.v_ltttime
)<1?1:0;
822 * @fn gboolean lttv_apply_op_gt_uint64(gpointer,LttvFieldValue)
824 * Applies the 'greater than' operator to the
825 * specified structure and value
826 * @param v1 left member of comparison
827 * @param v2 right member of comparison
828 * @return success/failure of operation
830 gboolean
lttv_apply_op_gt_uint64(const gpointer v1
, LttvFieldValue v2
) {
831 guint64
* r
= (guint64
*) v1
;
832 return (*r
> v2
.v_uint64
);
836 * @fn gboolean lttv_apply_op_gt_uint32(gpointer,LttvFieldValue)
838 * Applies the 'greater than' operator to the
839 * specified structure and value
840 * @param v1 left member of comparison
841 * @param v2 right member of comparison
842 * @return success/failure of operation
844 gboolean
lttv_apply_op_gt_uint32(const gpointer v1
, LttvFieldValue v2
) {
845 guint32
* r
= (guint32
*) v1
;
846 return (*r
> v2
.v_uint32
);
850 * @fn gboolean lttv_apply_op_gt_uint16(gpointer,LttvFieldValue)
852 * Applies the 'greater than' operator to the
853 * specified structure and value
854 * @param v1 left member of comparison
855 * @param v2 right member of comparison
856 * @return success/failure of operation
858 gboolean
lttv_apply_op_gt_uint16(const gpointer v1
, LttvFieldValue v2
) {
859 guint16
* r
= (guint16
*) v1
;
860 return (*r
> v2
.v_uint16
);
864 * @fn gboolean lttv_apply_op_gt_double(gpointer,LttvFieldValue)
866 * Applies the 'greater than' operator to the
867 * specified structure and value
868 * @param v1 left member of comparison
869 * @param v2 right member of comparison
870 * @return success/failure of operation
872 gboolean
lttv_apply_op_gt_double(const gpointer v1
, LttvFieldValue v2
) {
873 double* r
= (double*) v1
;
874 return (*r
> v2
.v_double
);
878 * @fn gboolean lttv_apply_op_gt_ltttime(gpointer,LttvFieldValue)
880 * Applies the 'greater than' operator to the
881 * specified structure and value
882 * @param v1 left member of comparison
883 * @param v2 right member of comparison
884 * @return success/failure of operation
886 gboolean
lttv_apply_op_gt_ltttime(const gpointer v1
, LttvFieldValue v2
) {
887 LttTime
* r
= (LttTime
*) v1
;
888 // 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)));
889 return ltt_time_compare(*r
, v2
.v_ltttime
)==1?1:0;
894 * @fn gboolean lttv_apply_op_ge_uint64(gpointer,LttvFieldValue)
896 * Applies the 'greater or equal' operator to the
897 * specified structure and value
898 * @param v1 left member of comparison
899 * @param v2 right member of comparison
900 * @return success/failure of operation
902 gboolean
lttv_apply_op_ge_uint64(const gpointer v1
, LttvFieldValue v2
) {
903 guint64
* r
= (guint64
*) v1
;
904 return (*r
>= v2
.v_uint64
);
908 * @fn gboolean lttv_apply_op_ge_uint32(gpointer,LttvFieldValue)
910 * Applies the 'greater or equal' operator to the
911 * specified structure and value
912 * @param v1 left member of comparison
913 * @param v2 right member of comparison
914 * @return success/failure of operation
916 gboolean
lttv_apply_op_ge_uint32(const gpointer v1
, LttvFieldValue v2
) {
917 guint32
* r
= (guint32
*) v1
;
918 return (*r
>= v2
.v_uint32
);
922 * @fn gboolean lttv_apply_op_ge_uint16(gpointer,LttvFieldValue)
924 * Applies the 'greater or equal' operator to the
925 * specified structure and value
926 * @param v1 left member of comparison
927 * @param v2 right member of comparison
928 * @return success/failure of operation
930 gboolean
lttv_apply_op_ge_uint16(const gpointer v1
, LttvFieldValue v2
) {
931 guint16
* r
= (guint16
*) v1
;
932 return (*r
>= v2
.v_uint16
);
936 * @fn gboolean lttv_apply_op_ge_double(gpointer,LttvFieldValue)
938 * Applies the 'greater or equal' operator to the
939 * specified structure and value
940 * @param v1 left member of comparison
941 * @param v2 right member of comparison
942 * @return success/failure of operation
944 gboolean
lttv_apply_op_ge_double(const gpointer v1
, LttvFieldValue v2
) {
945 double* r
= (double*) v1
;
946 return (*r
>= v2
.v_double
);
950 * @fn gboolean lttv_apply_op_ge_ltttime(gpointer,LttvFieldValue)
952 * Applies the 'greater or equal' operator to the
953 * specified structure and value
954 * @param v1 left member of comparison
955 * @param v2 right member of comparison
956 * @return success/failure of operation
958 gboolean
lttv_apply_op_ge_ltttime(const gpointer v1
, LttvFieldValue v2
) {
959 LttTime
* r
= (LttTime
*) v1
;
960 // 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)));
961 return ltt_time_compare(*r
, v2
.v_ltttime
)>-1?1:0;
967 * Makes a copy of the current filter tree
968 * @param tree pointer to the current tree
969 * @return new copy of the filter tree
972 lttv_filter_tree_clone(const LttvFilterTree
* tree
) {
974 LttvFilterTree
* newtree
= lttv_filter_tree_new();
976 newtree
->node
= tree
->node
;
978 newtree
->left
= tree
->left
;
979 if(newtree
->left
== LTTV_TREE_NODE
) {
980 newtree
->l_child
.t
= lttv_filter_tree_clone(tree
->l_child
.t
);
981 } else if(newtree
->left
== LTTV_TREE_LEAF
) {
982 newtree
->l_child
.leaf
= lttv_simple_expression_new();
983 newtree
->l_child
.leaf
->field
= tree
->l_child
.leaf
->field
;
984 newtree
->l_child
.leaf
->offset
= tree
->l_child
.leaf
->offset
;
985 newtree
->l_child
.leaf
->op
= tree
->l_child
.leaf
->op
;
986 /* FIXME: special case for string copy ! */
987 newtree
->l_child
.leaf
->value
= tree
->l_child
.leaf
->value
;
990 newtree
->right
= tree
->right
;
991 if(newtree
->right
== LTTV_TREE_NODE
) {
992 newtree
->r_child
.t
= lttv_filter_tree_clone(tree
->r_child
.t
);
993 } else if(newtree
->right
== LTTV_TREE_LEAF
) {
994 newtree
->r_child
.leaf
= lttv_simple_expression_new();
995 newtree
->r_child
.leaf
->field
= tree
->r_child
.leaf
->field
;
996 newtree
->r_child
.leaf
->offset
= tree
->r_child
.leaf
->offset
;
997 newtree
->r_child
.leaf
->op
= tree
->r_child
.leaf
->op
;
998 newtree
->r_child
.leaf
->value
= tree
->r_child
.leaf
->value
;
1006 * Makes a copy of the current filter
1007 * @param filter pointer to the current filter
1008 * @return new copy of the filter
1011 lttv_filter_clone(const LttvFilter
* filter
) {
1013 LttvFilter
* newfilter
= g_new(LttvFilter
,1);
1015 strcpy(newfilter
->expression
,filter
->expression
);
1017 newfilter
->head
= lttv_filter_tree_clone(filter
->head
);
1025 * @fn LttvFilter* lttv_filter_new()
1027 * Creates a new LttvFilter
1028 * @return the current LttvFilter or NULL if error
1033 LttvFilter
* filter
= g_new(LttvFilter
,1);
1034 filter
->expression
= NULL
;
1035 filter
->head
= NULL
;
1042 * @fn gboolean lttv_filter_update(LttvFilter*)
1044 * Updates the current LttvFilter by building
1045 * its tree based upon the expression string
1046 * @param filter pointer to the current LttvFilter
1047 * @return Failure/Success of operation
1050 lttv_filter_update(LttvFilter
* filter
) {
1052 // g_print("filter::lttv_filter_new()\n"); /* debug */
1054 if(filter
->expression
== NULL
) return FALSE
;
1058 p_nesting
=0; /* parenthesis nesting value */
1062 *tree
= lttv_filter_tree_new(), /* main tree */
1063 *subtree
= NULL
, /* buffer for subtrees */
1064 *t1
, /* buffer #1 */
1065 *t2
; /* buffer #2 */
1069 * If the tree already exists,
1070 * destroy it and build a new one
1072 if(filter
->head
!= NULL
) lttv_filter_tree_destroy(filter
->head
);
1073 filter
->head
= NULL
; /* will be assigned at the end */
1077 * each element of the list
1078 * is a sub tree created
1079 * by the use of parenthesis in the
1080 * global expression. The final tree
1081 * will be the one left at the root of
1084 GPtrArray
*tree_stack
= g_ptr_array_new();
1085 g_ptr_array_add( tree_stack
,(gpointer
) tree
);
1087 /* temporary values */
1088 GString
*a_field_component
= g_string_new("");
1089 GPtrArray
*a_field_path
= g_ptr_array_new();
1091 /* simple expression buffer */
1092 LttvSimpleExpression
* a_simple_expression
= lttv_simple_expression_new();
1095 * Parse entire expression and construct
1096 * the binary tree. There are two steps
1097 * in browsing that string
1098 * 1. finding boolean ops " &,|,^,! " and parenthesis " {,(,[,],),} "
1099 * 2. finding simple expressions
1100 * - field path ( separated by dots )
1101 * - op ( >, <, =, >=, <=, !=)
1102 * - value ( integer, string ... )
1103 * To spare computing time, the whole
1104 * string is parsed in this loop for a
1105 * O(n) complexity order.
1107 * When encountering logical op &,|,^
1108 * 1. parse the last value if any
1109 * 2. create a new tree
1110 * 3. add the expression (simple exp, or exp (subtree)) to the tree
1111 * 4. concatenate this tree with the current tree on top of the stack
1112 * When encountering math ops >,>=,<,<=,=,!=
1113 * 1. add to op to the simple expression
1114 * 2. concatenate last field component to field path
1115 * When encountering concatening ops .
1116 * 1. concatenate last field component to field path
1117 * When encountering opening parenthesis (,{,[
1118 * 1. create a new subtree on top of tree stack
1119 * When encountering closing parenthesis ),},]
1120 * 1. add the expression on right child of the current tree
1121 * 2. the subtree is completed, allocate a new subtree
1122 * 3. pop the tree value from the tree stack
1125 for(i
=0;i
<strlen(filter
->expression
);i
++) {
1127 //g_print("%c ",filter->expression[i]);
1129 switch(filter
->expression
[i
]) {
1135 t1
= (LttvFilterTree
*)g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1136 while(t1
->right
!= LTTV_TREE_IDLE
) {
1137 g_assert(t1
->right
== LTTV_TREE_NODE
);
1140 t2
= lttv_filter_tree_new();
1141 t2
->node
= LTTV_LOGICAL_AND
;
1142 if(subtree
!= NULL
) { /* append subtree to current tree */
1143 t2
->left
= LTTV_TREE_NODE
;
1144 t2
->l_child
.t
= subtree
;
1146 t1
->right
= LTTV_TREE_NODE
;
1148 } else { /* append a simple expression */
1149 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1150 a_field_component
= g_string_new("");
1151 t2
->left
= LTTV_TREE_LEAF
;
1152 t2
->l_child
.leaf
= a_simple_expression
;
1153 a_simple_expression
= lttv_simple_expression_new();
1154 t1
->right
= LTTV_TREE_NODE
;
1161 t1
= (LttvFilterTree
*)g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1162 while(t1
->right
!= LTTV_TREE_IDLE
) {
1163 g_assert(t1
->right
== LTTV_TREE_NODE
);
1166 t2
= lttv_filter_tree_new();
1167 t2
->node
= LTTV_LOGICAL_OR
;
1168 if(subtree
!= NULL
) { /* append subtree to current tree */
1169 t2
->left
= LTTV_TREE_NODE
;
1170 t2
->l_child
.t
= subtree
;
1172 t1
->right
= LTTV_TREE_NODE
;
1174 } else { /* append a simple expression */
1175 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1176 a_field_component
= g_string_new("");
1177 t2
->left
= LTTV_TREE_LEAF
;
1178 t2
->l_child
.leaf
= a_simple_expression
;
1179 a_simple_expression
= lttv_simple_expression_new();
1180 t1
->right
= LTTV_TREE_NODE
;
1187 t1
= (LttvFilterTree
*)g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1188 while(t1
->right
!= LTTV_TREE_IDLE
) {
1189 g_assert(t1
->right
== LTTV_TREE_NODE
);
1192 t2
= lttv_filter_tree_new();
1193 t2
->node
= LTTV_LOGICAL_XOR
;
1194 if(subtree
!= NULL
) { /* append subtree to current tree */
1195 t2
->left
= LTTV_TREE_NODE
;
1196 t2
->l_child
.t
= subtree
;
1198 t1
->right
= LTTV_TREE_NODE
;
1200 } else { /* append a simple expression */
1201 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1202 a_field_component
= g_string_new("");
1203 t2
->left
= LTTV_TREE_LEAF
;
1204 t2
->l_child
.leaf
= a_simple_expression
;
1205 a_simple_expression
= lttv_simple_expression_new();
1206 t1
->right
= LTTV_TREE_NODE
;
1211 case '!': /* not, or not equal (math op) */
1213 if(filter
->expression
[i
+1] == '=') { /* != */
1214 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1215 lttv_simple_expression_assign_field(a_field_path
,a_simple_expression
);
1216 a_field_component
= g_string_new("");
1217 lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_NE
);
1220 t1
= (LttvFilterTree
*)g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1221 while(t1
->right
!= LTTV_TREE_IDLE
) {
1222 g_assert(t1
->right
== LTTV_TREE_NODE
);
1225 t2
= lttv_filter_tree_new();
1226 t2
->node
= LTTV_LOGICAL_NOT
;
1227 t1
->right
= LTTV_TREE_NODE
;
1232 case '(': /* start of parenthesis */
1236 p_nesting
++; /* incrementing parenthesis nesting value */
1237 t1
= lttv_filter_tree_new();
1238 g_ptr_array_add( tree_stack
,(gpointer
) t1
);
1241 case ')': /* end of parenthesis */
1245 p_nesting
--; /* decrementing parenthesis nesting value */
1246 if(p_nesting
<0 || tree_stack
->len
<2) {
1247 g_warning("Wrong filtering options, the string\n\"%s\"\n\
1248 is not valid due to parenthesis incorrect use",filter
->expression
);
1252 /* there must at least be the root tree left in the array */
1253 g_assert(tree_stack
->len
>0);
1255 if(subtree
!= NULL
) { /* append subtree to current tree */
1256 t1
= g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1257 while(t1
->right
!= LTTV_TREE_IDLE
) {
1258 g_assert(t1
->right
== LTTV_TREE_NODE
);
1261 t1
->right
= LTTV_TREE_NODE
;
1262 t1
->r_child
.t
= subtree
;
1263 subtree
= g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1264 g_ptr_array_remove_index(tree_stack
,tree_stack
->len
-1);
1265 } else { /* assign subtree as current tree */
1266 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1267 a_field_component
= g_string_new("");
1268 t1
= g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1269 while(t1
->right
!= LTTV_TREE_IDLE
) {
1270 g_assert(t1
->right
== LTTV_TREE_NODE
);
1271 g_assert(t1
->r_child
.t
!= NULL
);
1274 t1
->right
= LTTV_TREE_LEAF
;
1275 t1
->r_child
.leaf
= a_simple_expression
;
1276 a_simple_expression
= lttv_simple_expression_new();
1277 subtree
= g_ptr_array_remove_index(tree_stack
,tree_stack
->len
-1);
1282 * mathematic operators
1284 case '<': /* lower, lower or equal */
1286 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1287 lttv_simple_expression_assign_field(a_field_path
,a_simple_expression
);
1288 a_field_component
= g_string_new("");
1289 if(filter
->expression
[i
+1] == '=') { /* <= */
1291 lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_LE
);
1292 } else lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_LT
);
1295 case '>': /* higher, higher or equal */
1297 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1298 lttv_simple_expression_assign_field(a_field_path
,a_simple_expression
);
1299 a_field_component
= g_string_new("");
1300 if(filter
->expression
[i
+1] == '=') { /* >= */
1302 lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_GE
);
1303 } else lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_GT
);
1306 case '=': /* equal */
1308 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1309 lttv_simple_expression_assign_field(a_field_path
,a_simple_expression
);
1310 a_field_component
= g_string_new("");
1311 lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_EQ
);
1315 * Field concatening caracter
1320 * divide field expression into elements
1321 * in a_field_path array.
1323 * A dot can also be present in double values
1325 if(a_simple_expression
->field
== LTTV_FILTER_UNDEFINED
) {
1326 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1327 a_field_component
= g_string_new("");
1330 case ' ': /* ignore */
1331 case '\n': /* ignore */
1333 default: /* concatening current string */
1334 g_string_append_c(a_field_component
,filter
->expression
[i
]);
1339 * Preliminary check to see
1340 * if tree was constructed correctly
1343 g_warning("Wrong filtering options, the string\n\"%s\"\n\
1344 is not valid due to parenthesis incorrect use",filter
->expression
);
1348 if(tree_stack
->len
!= 1) /* only root tree should remain */
1351 /* processing last element of expression */
1352 t1
= g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1353 while(t1
->right
!= LTTV_TREE_IDLE
) {
1354 g_assert(t1
->right
== LTTV_TREE_NODE
);
1357 if(subtree
!= NULL
) { /* add the subtree */
1358 t1
->right
= LTTV_TREE_NODE
;
1359 t1
->r_child
.t
= subtree
;
1361 } else { /* add a leaf */
1362 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1363 a_field_component
= NULL
;
1364 t1
->right
= LTTV_TREE_LEAF
;
1365 t1
->r_child
.leaf
= a_simple_expression
;
1366 a_simple_expression
= NULL
;
1370 /* free the pointer array */
1371 g_assert(a_field_path
->len
== 0);
1372 g_ptr_array_free(a_field_path
,TRUE
);
1374 /* free the tree stack -- but keep the root tree */
1375 filter
->head
= g_ptr_array_remove_index(tree_stack
,0);
1376 g_ptr_array_free(tree_stack
,TRUE
);
1378 /* free the field buffer if allocated */
1379 if(a_field_component
!= NULL
) g_string_free(a_field_component
,TRUE
);
1381 /* free the simple expression buffer if allocated */
1382 if(a_simple_expression
!= NULL
) lttv_simple_expression_destroy(a_simple_expression
);
1384 g_assert(filter
->head
!= NULL
); /* tree should exist */
1385 g_assert(subtree
== NULL
); /* remaining subtree should be included in main tree */
1388 g_print("+++++++++++++++ BEGIN PRINT ++++++++++++++++\n");
1389 lttv_print_tree(filter
->head
) ;
1390 g_print("+++++++++++++++ END PRINT ++++++++++++++++++\n");
1398 * @fn void lttv_filter_destroy(LttvFilter*)
1400 * Destroy the current LttvFilter
1401 * @param filter pointer to the current LttvFilter
1404 lttv_filter_destroy(LttvFilter
* filter
) {
1406 g_free(filter
->expression
);
1407 lttv_filter_tree_destroy(filter
->head
);
1413 * @fn LttvFilterTree* lttv_filter_tree_new()
1415 * Assign a new tree for the current expression
1417 * @return pointer of LttvFilterTree
1420 lttv_filter_tree_new() {
1421 LttvFilterTree
* tree
;
1423 tree
= g_new(LttvFilterTree
,1);
1424 tree
->node
= 0; //g_new(lttv_expression,1);
1425 tree
->left
= LTTV_TREE_IDLE
;
1426 tree
->right
= LTTV_TREE_IDLE
;
1427 tree
->r_child
.t
= NULL
;
1428 tree
->l_child
.t
= NULL
;
1434 * @fn void lttv_filter_append_expression(LttvFilter*,char*)
1436 * Append a new expression to the expression
1437 * defined in the current filter
1438 * @param filter pointer to the current LttvFilter
1439 * @param expression string that must be appended
1440 * @return Success/Failure of operation
1442 gboolean
lttv_filter_append_expression(LttvFilter
* filter
, char *expression
) {
1444 if(expression
== NULL
) return FALSE
;
1445 if(filter
== NULL
) {
1446 filter
= lttv_filter_new();
1447 filter
->expression
= expression
;
1448 } else if(filter
->expression
== NULL
) {
1449 filter
->expression
= expression
;
1451 filter
->expression
= g_strconcat(filter
->expression
,"&",expression
);
1453 /* clear expression */
1457 return lttv_filter_update(filter
);
1462 * @fn void lttv_filter_clear_expression(LttvFilter*)
1464 * Clear the filter expression from the
1465 * current filter and sets its pointer to NULL
1466 * @param filter pointer to the current LttvFilter
1468 void lttv_filter_clear_expression(LttvFilter
* filter
) {
1470 if(filter
->expression
!= NULL
) {
1471 g_free(filter
->expression
);
1472 filter
->expression
= NULL
;
1478 * @fn void lttv_filter_tree_destroy(LttvFilterTree*)
1480 * Destroys the tree and his sub-trees
1481 * @param tree Tree which must be destroyed
1484 lttv_filter_tree_destroy(LttvFilterTree
* tree
) {
1486 if(tree
== NULL
) return;
1488 if(tree
->left
== LTTV_TREE_LEAF
) lttv_simple_expression_destroy(tree
->l_child
.leaf
);
1489 else if(tree
->left
== LTTV_TREE_NODE
) lttv_filter_tree_destroy(tree
->l_child
.t
);
1491 if(tree
->right
== LTTV_TREE_LEAF
) lttv_simple_expression_destroy(tree
->r_child
.leaf
);
1492 else if(tree
->right
== LTTV_TREE_NODE
) lttv_filter_tree_destroy(tree
->r_child
.t
);
1494 // g_free(tree->node);
1499 * Global parsing function for the current
1501 * @param t pointer to the current LttvFilterTree
1502 * @param event current LttEvent, NULL if not used
1503 * @param tracefile current LttTracefile, NULL if not used
1504 * @param trace current LttTrace, NULL if not used
1505 * @param state current LttvProcessState, NULL if not used
1506 * @param context current LttvTracefileContext, NULL if not used
1507 * @return response of filter
1510 lttv_filter_tree_parse(
1511 const LttvFilterTree
* t
,
1512 const LttEvent
* event
,
1513 const LttTracefile
* tracefile
,
1514 const LttTrace
* trace
,
1515 const LttvProcessState
* state
,
1516 const LttvTracefileContext
* context
1521 * Each tree is parsed in inorder.
1522 * This way, it's possible to apply the left filter of the
1523 * tree, then decide whether or not the right branch should
1524 * be parsed depending on the linking logical operator
1526 * Each node consists in a
1527 * 1. logical operator
1528 * 2. left child ( node or simple expression )
1529 * 3. right child ( node or simple expression )
1531 * When the child is a simple expression, we must
1532 * before all determine if the expression refers to
1533 * a structure which is whithin observation ( not NULL ).
1534 * -If so, the expression is evaluated.
1535 * -If not, the result is set to TRUE since this particular
1536 * operation does not interfere with the lttv structure
1538 * The result of each simple expression will directly
1539 * affect the next branch. This way, depending on
1540 * the linking logical operator, the parser will decide
1541 * to explore or not the next branch.
1543 * -If result of left branch is 0 / FALSE
1544 * then don't explore right branch and return 0;
1545 * -If result of left branch is 1 / TRUE then explore
1547 * -If result of left branch is 1 / TRUE
1548 * then don't explore right branch and return 1;
1549 * -If result of left branch is 0 / FALSE then explore
1551 * -Result of left branch will not affect exploration of
1555 gboolean lresult
= FALSE
, rresult
= FALSE
;
1560 if(t
->left
== LTTV_TREE_NODE
) {
1561 lresult
= lttv_filter_tree_parse(t
->l_child
.t
,event
,tracefile
,trace
,state
,context
);
1563 else if(t
->left
== LTTV_TREE_LEAF
) {
1564 lresult
= lttv_filter_tree_parse_branch(t
->l_child
.leaf
,event
,tracefile
,trace
,state
,context
);
1568 * Parse linking operator
1569 * make a cutoff if possible
1571 if((t
->node
& LTTV_LOGICAL_OR
) && lresult
== TRUE
) return TRUE
;
1572 if((t
->node
& LTTV_LOGICAL_AND
) && lresult
== FALSE
) return FALSE
;
1575 * Parse right branch
1577 if(t
->right
== LTTV_TREE_NODE
) {
1578 rresult
= lttv_filter_tree_parse(t
->r_child
.t
,event
,tracefile
,trace
,state
,context
);
1580 else if(t
->right
== LTTV_TREE_LEAF
) {
1581 rresult
= lttv_filter_tree_parse_branch(t
->r_child
.leaf
,event
,tracefile
,trace
,state
,context
);
1585 * Apply and return the
1586 * logical link between the
1590 case LTTV_LOGICAL_OR
: return (lresult
| rresult
);
1591 case LTTV_LOGICAL_AND
: return (lresult
& rresult
);
1592 case LTTV_LOGICAL_NOT
: return (!rresult
);
1593 case LTTV_LOGICAL_XOR
: return (lresult
^ rresult
);
1594 case 0: return (rresult
);
1597 * This case should never be
1598 * parsed, if so, this subtree
1607 * This function parses a particular branch of the tree
1608 * @param se pointer to the current LttvSimpleExpression
1609 * @param event current LttEvent, NULL if not used
1610 * @param tracefile current LttTracefile, NULL if not used
1611 * @param trace current LttTrace, NULL if not used
1612 * @param state current LttvProcessState, NULL if not used
1613 * @param context current LttvTracefileContext, NULL if not used
1614 * @return response of filter
1616 gboolean
lttv_filter_tree_parse_branch(
1617 const LttvSimpleExpression
* se
,
1618 const LttEvent
* event
,
1619 const LttTracefile
* tracefile
,
1620 const LttTrace
* trace
,
1621 const LttvProcessState
* state
,
1622 const LttvTracefileContext
* context
) {
1627 case LTTV_FILTER_TRACE_NAME
:
1628 if(trace
== NULL
) return TRUE
;
1630 GQuark quark
= g_quark_to_string(ltt_trace_name(trace
));
1631 return se
->op((gpointer
)&quark
,v
);
1634 case LTTV_FILTER_TRACEFILE_NAME
:
1635 if(tracefile
== NULL
) return TRUE
;
1637 GQuark quark
= g_quark_to_string(ltt_tracefile_name(tracefile
));
1638 return se
->op((gpointer
)&quark
,v
);
1641 case LTTV_FILTER_STATE_PID
:
1642 if(state
== NULL
) return TRUE
;
1643 else return se
->op((gpointer
)&state
->pid
,v
);
1645 case LTTV_FILTER_STATE_PPID
:
1646 if(state
== NULL
) return TRUE
;
1647 else return se
->op((gpointer
)&state
->ppid
,v
);
1649 case LTTV_FILTER_STATE_CT
:
1650 if(state
== NULL
) return TRUE
;
1652 return se
->op((gpointer
)&state
->creation_time
,v
);
1655 case LTTV_FILTER_STATE_IT
:
1656 if(state
== NULL
) return TRUE
;
1658 return se
->op((gpointer
)&state
->insertion_time
,v
);
1661 case LTTV_FILTER_STATE_P_NAME
:
1663 * All 'unnamed' for the moment
1665 if(state
== NULL
) return TRUE
;
1667 GQuark quark
= g_quark_to_string(state
->name
);
1668 return se
->op((gpointer
)&quark
,v
);
1671 case LTTV_FILTER_STATE_EX_MODE
:
1672 if(state
== NULL
) return TRUE
;
1673 else return se
->op((gpointer
)&state
->state
->t
,v
);
1675 case LTTV_FILTER_STATE_EX_SUBMODE
:
1676 if(state
== NULL
) return TRUE
;
1677 else return se
->op((gpointer
)&state
->state
->n
,v
);
1679 case LTTV_FILTER_STATE_P_STATUS
:
1680 if(state
== NULL
) return TRUE
;
1681 else return se
->op((gpointer
)&state
->state
->s
,v
);
1683 case LTTV_FILTER_STATE_CPU
:
1684 if(context
== NULL
) return TRUE
;
1686 /* FIXME: not sure of that one */
1687 return se
->op((gpointer
)g_quark_to_string(((LttvTracefileState
*)context
)->cpu_name
),v
);
1690 case LTTV_FILTER_EVENT_NAME
:
1691 if(event
== NULL
) return TRUE
;
1694 et
= ltt_event_eventtype(event
);
1695 g_print("v:%s\n",ltt_eventtype_name(et
));
1696 GQuark quark
= g_quark_to_string(ltt_eventtype_name(et
));
1697 return se
->op((gpointer
)&quark
,v
);
1701 case LTTV_FILTER_EVENT_CATEGORY
:
1703 * TODO: Not yet implemented
1707 case LTTV_FILTER_EVENT_TIME
:
1708 if(event
== NULL
) return TRUE
;
1710 LttTime time
= ltt_event_time(event
);
1711 return se
->op((gpointer
)&time
,v
);
1714 case LTTV_FILTER_EVENT_TSC
:
1715 // if(event == NULL) return TRUE;
1717 // double val = ltt_time_to_double(event->event_time);
1718 // return se->op((gpointer)&val,v);
1721 * FIXME: Where is event.tsc
1725 case LTTV_FILTER_EVENT_FIELD
:
1727 * TODO: Use the offset to
1728 * find the dynamic field
1729 * in the event struct
1734 * This case should never be
1735 * parsed, if so, the whole
1736 * filtering is cancelled
1738 g_warning("Error while parsing the filter tree");
1742 /* should never get here */
1750 * Debug function. Prints tree memory allocation.
1751 * @param t the pointer to the current LttvFilterTree
1754 lttv_print_tree(const LttvFilterTree
* t
) {
1756 g_print("node:%p lchild:%p rchild:%p\n",t
, //t->l_child.t,t->r_child.t);
1757 (t
->left
==LTTV_TREE_NODE
)?t
->l_child
.t
:NULL
,
1758 (t
->right
==LTTV_TREE_NODE
)?t
->r_child
.t
:NULL
);
1759 g_print("node type: %i / [left] %i / [right] %i\n",t
->node
,t
->left
,t
->right
);
1760 if(t
->left
== LTTV_TREE_NODE
) lttv_print_tree(t
->l_child
.t
);
1761 else if(t
->left
== LTTV_TREE_LEAF
) {
1762 g_print("%p: left is %i %p value\n",t
,t
->l_child
.leaf
->field
,t
->l_child
.leaf
->op
);
1764 if(t
->right
== LTTV_TREE_NODE
) lttv_print_tree(t
->r_child
.t
);
1765 else if(t
->right
== LTTV_TREE_LEAF
) {
1766 g_print("%p: right is %i %p value\n",t
,t
->r_child
.leaf
->field
,t
->r_child
.leaf
->op
);
1772 * @fn static void module_init()
1774 * Initializes the filter module and specific values
1776 static void module_init()
1782 * Destroys the filter module and specific values
1784 static void module_destroy()
1790 LTTV_MODULE("filter", "Filters traceset and events", \
1791 "Filters traceset and events specifically to user input", \
1792 module_init
, module_destroy
)