1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2005 Michel Dagenais
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,
20 consist in AND, OR and NOT nested expressions, forming a tree with
21 simple relations as leaves. The simple relations test is a field
22 in an event is equal, not equal, smaller, smaller or equal, larger, or
23 larger or equal to a specified value.
31 #include <lttv/filter.h>
38 simple expr [ op expr ]
40 read_simple_expression
41 read_field_path [ rel value ]
44 read_field_component [. field path]
53 path(component...) -> field
59 LTTV_FILTER_TRACEFILE
,
72 LTTV_FILTER_EX_SUBMODE
,
78 * Parse through filtering field hierarchy as specified
79 * by user. This function compares each value to
80 * predetermined quarks
81 * @param fp The field path list
82 * @return success/failure of operation
85 parse_field_path(GList
* fp
) {
87 GString
* f
= g_list_first(fp
)->data
;
89 if(g_quark_try_string(f
->str
) == LTTV_FILTER_EVENT
) {
90 // parse_subfield(fp, LTTV_FILTER_EVENT);
92 } else if(g_quark_try_string(f
->str
) == LTTV_FILTER_TRACEFILE
) {
94 } else if(g_quark_try_string(f
->str
) == LTTV_FILTER_TRACE
) {
96 } else if(g_quark_try_string(f
->str
) == LTTV_FILTER_STATE
) {
99 g_warning("Unrecognized field in filter string");
106 * Add an filtering option to the current tree
107 * @param expression Current expression to parse
108 * @return success/failure of operation
111 parse_simple_expression(GString
* expression
) {
121 * Creates a new lttv_filter
122 * @param expression filtering options string
123 * @param t pointer to the current LttvTrace
124 * @return the current lttv_filter or NULL if error
127 lttv_filter_new(char *expression
, LttvTraceState
*tcs
) {
129 g_print("filter::lttv_filter_new()\n"); /* debug */
133 p_nesting
=0, /* parenthesis nesting value */
134 b
=0; /* current breakpoint in expression string */
136 /* temporary values */
137 GString
*a_field_component
= g_string_new("");
138 GList
*a_field_path
= NULL
;
139 lttv_simple_expression a_simple_expression
;
142 * 1. parse expression
143 * 2. construct binary tree
144 * 3. return corresponding filter
148 * Binary tree memory allocation
149 * - based upon a preliminary block size
151 // gulong size = (strlen(expression)/AVERAGE_EXPRESSION_LENGTH)*MAX_FACTOR;
152 // tree = g_malloc(size*sizeof(lttv_filter_tree));
155 * Parse entire expression and construct
156 * the binary tree. There are two steps
157 * in browsing that string
158 * 1. finding boolean ops ( &,|,^,! ) and parenthesis
159 * 2. finding simple expressions
160 * - field path ( separated by dots )
161 * - op ( >, <, =, >=, <=, !=)
162 * - value ( integer, string ... )
163 * To spare computing time, the whole
164 * string is parsed in this loop for a
165 * O(n) complexity order.
167 for(i
=0;i
<strlen(expression
);i
++) {
168 g_print("%s\n",a_field_component
->str
);
169 switch(expression
[i
]) {
176 g_list_append( a_field_path
, a_field_component
);
177 a_field_component
= g_string_new("");
179 case '!': /* not, or not equal (math op) */
180 if(expression
[i
+1] == '=') { /* != */
181 a_simple_expression
.op
= LTTV_FIELD_NE
;
184 g_print("%s\n",a_field_component
);
185 a_field_component
= g_string_new("");
188 case '(': /* start of parenthesis */
191 p_nesting
++; /* incrementing parenthesis nesting value */
193 case ')': /* end of parenthesis */
196 p_nesting
--; /* decrementing parenthesis nesting value */
200 * mathematic operators
202 case '<': /* lower, lower or equal */
203 if(expression
[i
+1] == '=') { /* <= */
205 a_simple_expression
.op
= LTTV_FIELD_LE
;
206 } else a_simple_expression
.op
= LTTV_FIELD_LT
;
208 case '>': /* higher, higher or equal */
209 if(expression
[i
+1] == '=') { /* >= */
211 a_simple_expression
.op
= LTTV_FIELD_GE
;
212 } else a_simple_expression
.op
= LTTV_FIELD_GT
;
214 case '=': /* equal */
215 a_simple_expression
.op
= LTTV_FIELD_EQ
;
218 * Field concatening caracter
221 g_list_append( a_field_path
, a_field_component
);
222 a_field_component
= g_string_new("");
224 default: /* concatening current string */
225 g_string_append_c(a_field_component
,expression
[i
]);
232 g_warning("Wrong filtering options, the string\n\"%s\"\n\
233 is not valid due to parenthesis incorrect use",expression
);
239 * Apply the filter to a specific trace
240 * @param filter the current filter applied
241 * @param tracefile the trace to apply the filter to
242 * @return success/failure of operation
245 lttv_filter_tracefile(lttv_filter_t
*filter
, LttTracefile
*tracefile
) {
251 char *f_name, *e_name;
261 GString *fe_name = g_string_new("");
263 nb = ltt_trace_eventtype_number(tcs->parent.t);
264 g_print("NB:%i\n",nb);
265 for(i = 0 ; i < nb ; i++) {
266 et = ltt_trace_eventtype_get(tcs->parent.t, i);
267 e_name = ltt_eventtype_name(et);
268 f_name = ltt_facility_name(ltt_eventtype_facility(et));
269 g_string_printf(fe_name, "%s.%s", f_name, e_name);
270 g_print("facility:%s and event:%s\n",f_name,e_name);
276 lttv_filter_tracestate(lttv_filter_t
*filter
, LttvTraceState
*tracestate
) {
281 * Apply the filter to a specific event
282 * @param filter the current filter applied
283 * @param event the event to apply the filter to
284 * @return success/failure of operation
287 lttv_filter_event(lttv_filter_t
*filter
, LttEvent
*event
) {
292 * Initializes the filter module and specific values
294 static void module_init()
298 * Quarks initialization
299 * for hardcoded filtering options
301 * TODO: traceset has no yet been defined
305 LTTV_FILTER_EVENT
= g_quark_from_string("event");
306 LTTV_FILTER_TRACE
= g_quark_from_string("trace");
307 LTTV_FILTER_TRACESET
= g_quark_from_string("traceset");
308 LTTV_FILTER_STATE
= g_quark_from_string("state");
309 LTTV_FILTER_TRACEFILE
= g_quark_from_string("tracefile");
311 /* event.name, tracefile.name, trace.name */
312 LTTV_FILTER_NAME
= g_quark_from_string("name");
314 /* event sub fields */
315 LTTV_FILTER_CATEGORY
= g_quark_from_string("category");
316 LTTV_FILTER_TIME
= g_quark_from_string("time");
317 LTTV_FILTER_TSC
= g_quark_from_string("tsc");
319 /* state sub fields */
320 LTTV_FILTER_PID
= g_quark_from_string("pid");
321 LTTV_FILTER_PPID
= g_quark_from_string("ppid");
322 LTTV_FILTER_C_TIME
= g_quark_from_string("creation_time");
323 LTTV_FILTER_I_TIME
= g_quark_from_string("insertion_time");
324 LTTV_FILTER_P_NAME
= g_quark_from_string("process_name");
325 LTTV_FILTER_EX_MODE
= g_quark_from_string("execution_mode");
326 LTTV_FILTER_EX_SUBMODE
= g_quark_from_string("execution_submode");
327 LTTV_FILTER_P_STATUS
= g_quark_from_string("process_status");
328 LTTV_FILTER_CPU
= g_quark_from_string("cpu");
333 * Destroys the filter module and specific values
335 static void module_destroy()
340 LTTV_MODULE("filter", "Filters traceset and events", \
341 "Filters traceset and events specifically to user input", \
342 module_init
, module_destroy
)