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