aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-01-05 21:57:52 -0500
committerSteven Rostedt <rostedt@goodmis.org>2010-01-05 21:57:52 -0500
commit62939f1fea71b8b8edf7985033670af0dce2116a (patch)
treeaf28940cfa0a5c5eed14a62dffc44b3a12b5c70b
parentf7f4f93a3a11cec95d28d544613631b07f95d33e (diff)
trace-view: Implement event filter
This patch now implements the event filtering dialog for the trace-view (list) only. This works with kernelshark too, but only the list is filtered. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--trace-filter.c120
-rw-r--r--trace-hash.c44
-rw-r--r--trace-hash.h2
-rw-r--r--trace-view-store.c215
-rw-r--r--trace-view-store.h38
5 files changed, 412 insertions, 7 deletions
diff --git a/trace-filter.c b/trace-filter.c
index f9c384f..ba3b0fd 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -37,6 +37,7 @@ enum {
37 COL_EVENT, 37 COL_EVENT,
38 COL_ACTIVE, 38 COL_ACTIVE,
39 COL_ACTIVE_START, 39 COL_ACTIVE_START,
40 COL_EVENT_ID,
40 NUM_EVENT_COLS, 41 NUM_EVENT_COLS,
41}; 42};
42 43
@@ -51,20 +52,26 @@ create_tree_event_model(GtkWidget *tree_view)
51 struct event_format **events; 52 struct event_format **events;
52 struct event_format *event; 53 struct event_format *event;
53 char *last_system = NULL; 54 char *last_system = NULL;
55 gboolean all_events;
56 gboolean sysactive;
57 gboolean active;
54 gint i; 58 gint i;
55 59
56 model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view)); 60 model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view));
57 trace_view = TRACE_VIEW_STORE(model); 61 trace_view = TRACE_VIEW_STORE(model);
58 62
63 all_events = trace_view_store_get_all_events_enabled(trace_view);
64
59 pevent = tracecmd_get_pevent(trace_view->handle); 65 pevent = tracecmd_get_pevent(trace_view->handle);
60 66
61 treestore = gtk_tree_store_new(NUM_EVENT_COLS, G_TYPE_STRING, 67 treestore = gtk_tree_store_new(NUM_EVENT_COLS, G_TYPE_STRING,
62 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); 68 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
69 G_TYPE_INT);
63 70
64 gtk_tree_store_append(treestore, &iter_all, NULL); 71 gtk_tree_store_append(treestore, &iter_all, NULL);
65 gtk_tree_store_set(treestore, &iter_all, 72 gtk_tree_store_set(treestore, &iter_all,
66 COL_EVENT, "All", 73 COL_EVENT, "All",
67 COL_ACTIVE, TRUE, 74 COL_ACTIVE, all_events,
68 COL_ACTIVE_START, FALSE, 75 COL_ACTIVE_START, FALSE,
69 -1); 76 -1);
70 77
@@ -76,17 +83,22 @@ create_tree_event_model(GtkWidget *tree_view)
76 event = events[i]; 83 event = events[i];
77 if (!last_system || strcmp(last_system, event->system) != 0) { 84 if (!last_system || strcmp(last_system, event->system) != 0) {
78 gtk_tree_store_append(treestore, &iter_sys, &iter_all); 85 gtk_tree_store_append(treestore, &iter_sys, &iter_all);
86 sysactive = all_events ||
87 trace_view_store_system_enabled(trace_view, event->system);
79 gtk_tree_store_set(treestore, &iter_sys, 88 gtk_tree_store_set(treestore, &iter_sys,
80 COL_EVENT, event->system, 89 COL_EVENT, event->system,
81 COL_ACTIVE, TRUE, 90 COL_ACTIVE, sysactive,
82 -1); 91 -1);
83 last_system = event->system; 92 last_system = event->system;
84 } 93 }
85 94
95 active = all_events || sysactive ||
96 trace_view_store_event_enabled(trace_view, event->id);
86 gtk_tree_store_append(treestore, &iter_events, &iter_sys); 97 gtk_tree_store_append(treestore, &iter_events, &iter_sys);
87 gtk_tree_store_set(treestore, &iter_events, 98 gtk_tree_store_set(treestore, &iter_events,
88 COL_EVENT, event->name, 99 COL_EVENT, event->name,
89 COL_ACTIVE, FALSE, 100 COL_ACTIVE, active,
101 COL_EVENT_ID, event->id,
90 -1); 102 -1);
91 103
92 } 104 }
@@ -263,15 +275,114 @@ static GtkWidget *create_event_list_view(GtkWidget *tree_view)
263 return view; 275 return view;
264} 276}
265 277
278static void update_events(TraceViewStore *store,
279 GtkTreeModel *model,
280 GtkTreeIter *parent)
281{
282 GtkTreeIter event;
283 gboolean active;
284 gint id;
285
286 if (!gtk_tree_model_iter_children(model, &event, parent))
287 return;
288
289 for (;;) {
290
291 gtk_tree_model_get(model, &event,
292 COL_ACTIVE, &active,
293 COL_EVENT_ID, &id,
294 -1);
295
296 if (active)
297 trace_view_store_set_event_enabled(store, id);
298
299 if (!gtk_tree_model_iter_next(model, &event))
300 break;
301 }
302}
303
304static void update_system_events(TraceViewStore *store,
305 GtkTreeModel *model,
306 GtkTreeIter *parent)
307{
308 GtkTreeIter sys;
309 gboolean active;
310 gchar *system;
311
312 if (!gtk_tree_model_iter_children(model, &sys, parent))
313 return;
314
315 for (;;) {
316
317 gtk_tree_model_get(model, &sys,
318 COL_ACTIVE, &active,
319 COL_EVENT, &system,
320 -1);
321
322 if (active)
323 trace_view_store_set_system_enabled(store, system);
324 else
325 update_events(store, model, &sys);
326
327 g_free(system);
328
329 if (!gtk_tree_model_iter_next(model, &sys))
330 break;
331 }
332}
333
334static void accept_events(GtkWidget *trace_tree_view, GtkTreeView *view)
335{
336 GtkTreeModel *model;
337 TraceViewStore *store;
338 GtkTreeIter iter;
339 gboolean active;
340
341 model = gtk_tree_view_get_model(GTK_TREE_VIEW(trace_tree_view));
342 if (!model)
343 return;
344
345 store = TRACE_VIEW_STORE(model);
346
347 model = gtk_tree_view_get_model(view);
348 if (!model)
349 return;
350
351 if (!gtk_tree_model_get_iter_first(model, &iter))
352 return;
353
354 gtk_tree_model_get(model, &iter,
355 COL_ACTIVE, &active,
356 -1);
357
358 if (active) {
359 if (trace_view_store_get_all_events_enabled(store))
360 return;
361
362 trace_view_store_set_all_events_enabled(store);
363 } else
364 update_system_events(store, model, &iter);
365
366 /* Force an update */
367 g_object_ref(store);
368 gtk_tree_view_set_model(GTK_TREE_VIEW(trace_tree_view), NULL);
369 trace_view_store_update_filter(store);
370 gtk_tree_view_set_model(GTK_TREE_VIEW(trace_tree_view), GTK_TREE_MODEL(store));
371 g_object_unref(store);
372
373}
374
266/* Callback for the clicked signal of the Events filter button */ 375/* Callback for the clicked signal of the Events filter button */
267static void 376static void
268event_dialog_response (gpointer data, gint response_id) 377event_dialog_response (gpointer data, gint response_id)
269{ 378{
270 struct dialog_helper *helper = data; 379 struct dialog_helper *helper = data;
380 GtkTreeView *view = helper->data;
271 381
272 switch (response_id) { 382 switch (response_id) {
273 case GTK_RESPONSE_ACCEPT: 383 case GTK_RESPONSE_ACCEPT:
274 printf("accept!\n"); 384 printf("accept!\n");
385 accept_events(helper->trace_tree, view);
275 break; 386 break;
276 case GTK_RESPONSE_REJECT: 387 case GTK_RESPONSE_REJECT:
277 printf("reject!\n"); 388 printf("reject!\n");
@@ -319,6 +430,7 @@ void trace_filter_event_dialog(void *trace_tree)
319 GTK_POLICY_AUTOMATIC, 430 GTK_POLICY_AUTOMATIC,
320 GTK_POLICY_AUTOMATIC); 431 GTK_POLICY_AUTOMATIC);
321 view = create_event_list_view(tree_view); 432 view = create_event_list_view(tree_view);
433 helper->data = view;
322 434
323 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0); 435 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
324 gtk_container_add(GTK_CONTAINER(scrollwin), view); 436 gtk_container_add(GTK_CONTAINER(scrollwin), view);
diff --git a/trace-hash.c b/trace-hash.c
index 99b9feb..8435e6c 100644
--- a/trace-hash.c
+++ b/trace-hash.c
@@ -116,3 +116,47 @@ struct filter_task *filter_task_hash_alloc(void)
116 116
117 return hash; 117 return hash;
118} 118}
119
120void filter_task_hash_free(struct filter_task *hash)
121{
122 if (!hash)
123 return;
124
125 filter_task_clear(hash);
126 g_free(hash->hash);
127 g_free(hash);
128}
129
130struct filter_task *filter_task_hash_copy(struct filter_task *hash)
131{
132 struct filter_task *new_hash;
133 struct filter_task_item *task, **ptask;
134 gint i;
135
136 if (!hash)
137 return NULL;
138
139 new_hash = filter_task_hash_alloc();
140 g_assert(new_hash);
141
142 for (i = 0; i < FILTER_TASK_HASH_SIZE; i++) {
143 task = hash->hash[i];
144 if (!task)
145 continue;
146
147 ptask = &new_hash->hash[i];
148
149 while (task) {
150
151 *ptask = g_new0(typeof(*task), 1);
152 g_assert(*ptask);
153 **ptask = *task;
154
155 ptask = &(*ptask)->next;
156 task = task->next;
157 }
158 }
159
160 return new_hash;
161}
162
diff --git a/trace-hash.h b/trace-hash.h
index cab6195..9948138 100644
--- a/trace-hash.h
+++ b/trace-hash.h
@@ -21,6 +21,8 @@ void filter_task_add_pid(struct filter_task *hash, gint pid);
21void filter_task_remove_pid(struct filter_task *hash, gint pid); 21void filter_task_remove_pid(struct filter_task *hash, gint pid);
22void filter_task_clear(struct filter_task *hash); 22void filter_task_clear(struct filter_task *hash);
23struct filter_task *filter_task_hash_alloc(void); 23struct filter_task *filter_task_hash_alloc(void);
24void filter_task_hash_free(struct filter_task *hash);
25struct filter_task *filter_task_hash_copy(struct filter_task *hash);
24 26
25static inline gint filter_task_count(struct filter_task *hash) 27static inline gint filter_task_count(struct filter_task *hash)
26{ 28{
diff --git a/trace-view-store.c b/trace-view-store.c
index 03664c8..5e81daa 100644
--- a/trace-view-store.c
+++ b/trace-view-store.c
@@ -1,5 +1,6 @@
1#include "trace-view-store.h" 1#include "trace-view-store.h"
2#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h>
3 4
4#include "cpu.h" 5#include "cpu.h"
5 6
@@ -207,6 +208,8 @@ trace_view_store_finalize (GObject *object)
207 g_free(store->rows); 208 g_free(store->rows);
208 g_free(store->cpu_items); 209 g_free(store->cpu_items);
209 210
211 filter_task_hash_free(store->task_filter);
212
210 if (store->spin) { 213 if (store->spin) {
211 gtk_widget_destroy(store->spin); 214 gtk_widget_destroy(store->spin);
212 store->spin = NULL; 215 store->spin = NULL;
@@ -490,6 +493,183 @@ trace_view_store_get_value (GtkTreeModel *tree_model,
490 } 493 }
491} 494}
492 495
496int str_cmp(const void *a, const void *b)
497{
498 char * const * sa = a;
499 char * const * sb = b;
500
501 return strcmp(*sa, *sb);
502}
503
504int id_cmp(const void *a, const void *b)
505{
506 const gint *ia = a;
507 const gint *ib = b;
508
509 if (*ia > *ib)
510 return 1;
511 if (*ia < *ib)
512 return -1;
513 return 0;
514}
515
516gboolean trace_view_store_system_enabled(TraceViewStore *store, const gchar *system)
517{
518 const gchar **sys = &system;
519
520 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), FALSE);
521
522 if (store->all_events)
523 return TRUE;
524
525 if (!store->systems)
526 return FALSE;
527
528 sys = bsearch(sys, store->systems, store->systems_size,
529 sizeof(system), str_cmp);
530
531 return sys != NULL;
532}
533
534gboolean trace_view_store_event_enabled(TraceViewStore *store, gint event_id)
535{
536 gint key = event_id;
537 gint *ret;
538
539 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), FALSE);
540
541 if (store->all_events)
542 return TRUE;
543
544 /* TODO: search for the system of the event? */
545
546 if (!store->event_types)
547 return FALSE;
548
549 ret = bsearch(&key, store->event_types, store->event_types_size,
550 sizeof(gint), id_cmp);
551
552 return ret != NULL;
553}
554
555void trace_view_store_set_all_events_enabled(TraceViewStore *store)
556{
557 gint i;
558
559 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
560
561 if (store->all_events)
562 return;
563
564 if (store->systems_size) {
565 for (i = 0; i < store->systems_size; i++)
566 g_free(store->systems[i]);
567
568 g_free(store->systems);
569 store->systems = NULL;
570 store->systems_size = 0;
571 }
572
573 g_free(store->event_types);
574 store->event_types = NULL;
575 store->event_types_size = 0;
576
577 store->all_events = 1;
578}
579
580static void remove_system(TraceViewStore *store, const gchar *system)
581{
582 const gchar **sys = &system;
583
584 if (!store->systems)
585 return;
586
587 sys = bsearch(sys, store->systems, store->systems_size,
588 sizeof(system), str_cmp);
589
590 if (!sys)
591 return;
592
593 g_free(*((gchar **)sys));
594
595 g_memmove(sys, sys+1, sizeof(*sys) * (store->systems_size -
596 ((gchar **)sys - store->systems)));
597 store->systems_size--;
598 store->systems[store->systems_size] = NULL;
599}
600
601void trace_view_store_set_system_enabled(TraceViewStore *store, const gchar *system)
602{
603 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
604
605 if (store->all_events)
606 /*
607 * We are adding a new filter, so this is the
608 * only system enabled.
609 */
610 store->all_events = 0;
611
612 if (trace_view_store_system_enabled(store, system))
613 return;
614
615 if (!store->systems) {
616 store->systems = g_new0(gchar *, 2);
617 store->systems[0] = g_strdup(system);
618 store->systems_size++;
619 return;
620 }
621
622 store->systems_size++;
623 store->systems = g_realloc(store->systems,
624 sizeof(*store->systems) * (store->systems_size+1));
625 store->systems[store->systems_size - 1] = g_strdup(system);
626 store->systems[store->systems_size] = NULL;
627
628 qsort(store->systems, store->systems_size, sizeof(gchar *), str_cmp);
629}
630
631
632void trace_view_store_set_event_enabled(TraceViewStore *store, gint event_id)
633{
634 struct pevent *pevent;
635 struct event_format *event;
636
637 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
638
639 pevent = tracecmd_get_pevent(store->handle);
640 event = pevent_find_event(pevent, event_id);
641 if (!event)
642 return;
643
644 if (store->all_events)
645 /*
646 * We are adding a new filter, so this is the
647 * only system enabled.
648 */
649 store->all_events = 0;
650
651 remove_system(store, event->system);
652
653 if (trace_view_store_event_enabled(store, event_id))
654 return;
655
656 if (!store->event_types) {
657 store->event_types = g_new0(gint, 2);
658 store->event_types[0] = event_id;
659 store->event_types[1] = -1;
660 store->event_types_size++;
661 return;
662 }
663
664 store->event_types_size++;
665 store->event_types = g_realloc(store->event_types,
666 sizeof(*store->event_types) * (store->event_types_size+1));
667 store->event_types[store->event_types_size - 1] = event_id;
668 store->event_types[store->event_types_size] = -1;
669
670 qsort(store->event_types, store->event_types_size, sizeof(gint), id_cmp);
671}
672
493 673
494/***************************************************************************** 674/*****************************************************************************
495 * 675 *
@@ -1088,14 +1268,23 @@ gint get_next_pid(TraceViewStore *store, struct pevent *pevent, struct record *r
1088void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *filter) 1268void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *filter)
1089{ 1269{
1090 struct tracecmd_input *handle; 1270 struct tracecmd_input *handle;
1271 struct event_format *event;
1091 struct pevent *pevent; 1272 struct pevent *pevent;
1092 struct record *record; 1273 struct record *record;
1274 gint last_event_id = -1;
1275 gint event_id;
1093 gint pid; 1276 gint pid;
1094 gint cpu; 1277 gint cpu;
1095 gint i; 1278 gint i;
1096 1279
1097 g_return_if_fail (TRACE_VIEW_IS_LIST (store)); 1280 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
1098 1281
1282 /* We may pass in the store->task_filter. Don't free it if we do */
1283 if (store->task_filter && store->task_filter != filter)
1284 filter_task_hash_free(store->task_filter);
1285
1286 store->task_filter = filter_task_hash_copy(filter);
1287
1099 handle = store->handle; 1288 handle = store->handle;
1100 pevent = tracecmd_get_pevent(store->handle); 1289 pevent = tracecmd_get_pevent(store->handle);
1101 1290
@@ -1115,7 +1304,22 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi
1115 1304
1116 g_assert(record->offset == store->cpu_list[cpu][i].offset); 1305 g_assert(record->offset == store->cpu_list[cpu][i].offset);
1117 1306
1118 /* TODO: put event filter check here */ 1307 /* The record may be filtered by the events */
1308 if (!store->all_events) {
1309 event_id = pevent_data_type(pevent, record);
1310 if (last_event_id != event_id) {
1311 /* optimize: only search event when new */
1312 event = pevent_find_event(pevent, event_id);
1313 g_assert(event);
1314 }
1315 last_event_id = event_id;
1316 if (!trace_view_store_system_enabled(store, event->system) &&
1317 !trace_view_store_event_enabled(store, event_id)) {
1318 store->cpu_list[cpu][i].visible = 0;
1319 goto skip;
1320 }
1321 }
1322
1119 pid = pevent_data_pid(pevent, record); 1323 pid = pevent_data_pid(pevent, record);
1120 if (!filter || filter_task_find_pid(filter, pid)) 1324 if (!filter || filter_task_find_pid(filter, pid))
1121 store->cpu_list[cpu][i].visible = 1; 1325 store->cpu_list[cpu][i].visible = 1;
@@ -1133,6 +1337,7 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi
1133 store->cpu_list[cpu][i].visible = 0; 1337 store->cpu_list[cpu][i].visible = 0;
1134 } 1338 }
1135 1339
1340 skip:
1136 free_record(record); 1341 free_record(record);
1137 record = tracecmd_read_data(handle, cpu); 1342 record = tracecmd_read_data(handle, cpu);
1138 } 1343 }
@@ -1142,6 +1347,14 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi
1142 merge_sort_rows_ts(store); 1347 merge_sort_rows_ts(store);
1143} 1348}
1144 1349
1350void trace_view_store_update_filter(TraceViewStore *store)
1351{
1352 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
1353
1354 trace_view_store_filter_tasks(store, store->task_filter);
1355}
1356
1357
1145/***************************************************************************** 1358/*****************************************************************************
1146 * 1359 *
1147 * trace_view_store_append_record: Empty lists are boring. This function can 1360 * trace_view_store_append_record: Empty lists are boring. This function can
diff --git a/trace-view-store.h b/trace-view-store.h
index bfa19d9..f6825bc 100644
--- a/trace-view-store.h
+++ b/trace-view-store.h
@@ -94,7 +94,10 @@ struct trace_view_store
94 gint all_events; /* set 1 when all events are enabled */ 94 gint all_events; /* set 1 when all events are enabled */
95 /* else */ 95 /* else */
96 gchar **systems; /* sorted list of systems that are enabled */ 96 gchar **systems; /* sorted list of systems that are enabled */
97 gint **event_types; /* sorted list of events that are enabled */ 97 gint *event_types; /* sorted list of events that are enabled */
98 gint systems_size; /* size of systems array */
99 gint event_types_size; /* size of event_types array */
100 struct filter_task *task_filter; /* hash of tasks to filter on */
98 101
99 gint all_cpus; /* set 1 when all cpus are enabled */ 102 gint all_cpus; /* set 1 when all cpus are enabled */
100 /* else */ 103 /* else */
@@ -125,7 +128,19 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi
125 128
126TraceViewRecord *trace_view_store_get_row(TraceViewStore *store, gint row); 129TraceViewRecord *trace_view_store_get_row(TraceViewStore *store, gint row);
127 130
128/* TraceViewStore methos */ 131gboolean trace_view_store_system_enabled(TraceViewStore *store, const gchar *system);
132
133gboolean trace_view_store_event_enabled(TraceViewStore *store, gint event_id);
134
135void trace_view_store_set_all_events_enabled(TraceViewStore *store);
136
137void trace_view_store_set_system_enabled(TraceViewStore *store, const gchar *system);
138
139void trace_view_store_set_event_enabled(TraceViewStore *store, gint event_id);
140
141void trace_view_store_update_filter(TraceViewStore *store);
142
143/* TraceViewStore methods */
129GtkTreeModelFlags trace_view_store_get_flags (GtkTreeModel *tree_model); 144GtkTreeModelFlags trace_view_store_get_flags (GtkTreeModel *tree_model);
130 145
131gint trace_view_store_get_n_columns (GtkTreeModel *tree_model); 146gint trace_view_store_get_n_columns (GtkTreeModel *tree_model);
@@ -191,4 +206,23 @@ static inline GtkWidget *trace_view_store_get_spin(TraceViewStore *store)
191 return store->spin; 206 return store->spin;
192} 207}
193 208
209static inline gboolean trace_view_store_get_all_events_enabled(TraceViewStore *store)
210{
211 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), FALSE);
212 return store->all_events;
213}
214
215static inline gchar **trace_view_store_get_systems_enabled(TraceViewStore *store)
216{
217 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), NULL);
218 return store->systems;
219}
220
221static inline gint *trace_view_store_get_events_enabled(TraceViewStore *store)
222{
223 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), NULL);
224 return store->event_types;
225}
226
227
194#endif /* _trace_view_store_h_included_ */ 228#endif /* _trace_view_store_h_included_ */