aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rwxr-xr-xevent-viewer.py172
-rw-r--r--tracecmd.py11
3 files changed, 160 insertions, 25 deletions
diff --git a/Makefile b/Makefile
index 32f85f1..1bcc153 100644
--- a/Makefile
+++ b/Makefile
@@ -87,8 +87,10 @@ plugin_mac80211.so: plugin_mac80211.o
87.PHONY: python 87.PHONY: python
88python: $(TCMD_LIB_OBJS) 88python: $(TCMD_LIB_OBJS)
89 swig -Wall -python -noproxy ctracecmd.i 89 swig -Wall -python -noproxy ctracecmd.i
90 #swig -Wall -python ctracecmd.i
90 gcc -fpic -c `python-config --includes` ctracecmd_wrap.c 91 gcc -fpic -c `python-config --includes` ctracecmd_wrap.c
91 $(CC) --shared $^ ctracecmd_wrap.o -o ctracecmd.so 92 $(CC) --shared $^ ctracecmd_wrap.o -o ctracecmd.so
93 #$(CC) --shared $^ ctracecmd_wrap.o -o _ctracecmd.so
92 94
93 95
94.PHONY: force 96.PHONY: force
diff --git a/event-viewer.py b/event-viewer.py
index a8ccd5b..6f35642 100755
--- a/event-viewer.py
+++ b/event-viewer.py
@@ -1,8 +1,10 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2 2
3import getopt
3from gobject import * 4from gobject import *
4import gtk 5import gtk
5from tracecmd import * 6from tracecmd import *
7import time
6 8
7app = None 9app = None
8data_func_cnt = 0 10data_func_cnt = 0
@@ -15,21 +17,136 @@ EVENT_COL_W = 150
15PID_COL_W = 75 17PID_COL_W = 75
16COMM_COL_W = 250 18COMM_COL_W = 250
17 19
18class EventStore(gtk.ListStore): 20
21def timing(func):
22 def wrapper(*arg):
23 start = time.time()
24 ret = func(*arg)
25 end = time.time()
26 print '@%s took %0.3f s' % (func.func_name, (end-start))
27 return ret
28 return wrapper
29
30
31class EventStore(gtk.GenericTreeModel):
32 class EventRef(object):
33 '''Inner class to build the trace event index'''
34 def __init__(self, index, timestamp, offset, cpu):
35 self.index = index
36 self.offset = offset
37 self.ts = timestamp
38 self.cpu = cpu
39
40 def __cmp__(self, other):
41 if self.ts < other.ts:
42 return -1
43 if self.ts > other.ts:
44 return 1
45 if self.offset < other.offset:
46 return -1
47 if self.offset > other.offset:
48 return 1
49 return 0
50
51 # The store only returns the record offset into the trace
52 # The view is responsible for looking up the Event with the offset
53 column_types = (long,)
54
55 @timing
19 def __init__(self, trace): 56 def __init__(self, trace):
20 gtk.ListStore.__init__(self, gobject.TYPE_PYOBJECT) 57 gtk.GenericTreeModel.__init__(self)
21 self.trace = trace 58 self.trace = trace
59 self.refs = []
60 self._load_trace()
61 self._sort()
62 self._reindex()
63
64 @timing
65 def _load_trace(self):
66 print "Building trace index..."
67 index = 0
22 for cpu in range(0, trace.cpus): 68 for cpu in range(0, trace.cpus):
23 ev = trace.read_event(cpu) 69 rec = tracecmd_read_data(self.trace.handle, cpu)
24 while ev: 70 while rec:
25 # store the record offset into the trace file 71 offset = record_offset_get(rec)
26 self.append([record_offset_get(ev.rec)]) 72 ts = record_ts_get(rec)
27 ev = trace.read_event(cpu) 73 self.refs.append(self.EventRef(index, ts, offset, cpu))
28 print "Loaded %d events across %d cpus" % (len(self), trace.cpus) 74 index = index + 1
75 rec = tracecmd_read_data(self.trace.handle, cpu)
76 print "Loaded %d events from trace" % (index)
77
78 @timing
79 def _sort(self):
80 self.refs.sort()
81
82 @timing
83 def _reindex(self):
84 for i in range(0, len(self.refs)):
85 self.refs[i].index = i
86
87 def on_get_flags(self):
88 return gtk.TREE_MODEL_LIST_ONLY | gtk.TREE_MODEL_ITERS_PERSIST
89
90 def on_get_n_columns(self):
91 return len(self.column_types)
92
93 def on_get_column_type(self, col):
94 return self.column_types[col]
95
96 def on_get_iter(self, path):
97 return self.refs[path[0]]
98
99 def on_get_path(self, ref):
100 return ref.index
101
102 def on_get_value(self, ref, col):
103 '''
104 The Event record was getting deleted when passed back via this
105 method, now it just returns the ref itself. Use get_event() instead.
106 '''
107 if col == 0:
108 #return self.trace.read_event_at(ref.offset)
109 return ref
110 return None
111
112 def on_iter_next(self, ref):
113 try:
114 return self.refs[ref.index+1]
115 except IndexError:
116 return None
117
118 def on_iter_children(self, ref):
119 if ref:
120 return None
121 return self.refs[0]
122
123 def on_iter_has_child(self, ref):
124 return False
125
126 def on_iter_n_children(self, ref):
127 if ref:
128 return 0
129 return len(self.refs)
130
131 def on_iter_nth_child(self, ref, n):
132 if ref:
133 return None
134 try:
135 return self.refs[n]
136 except IndexError:
137 return None
138
139 def on_iter_parent(self, child):
140 return None
29 141
30 def get_event(self, iter): 142 def get_event(self, iter):
31 offset = self.get_value(iter, 0) 143 '''This allocates a record which must be freed by the caller'''
32 return self.trace.read_event_at(offset) 144 try:
145 ref = self.refs[self.get_path(iter)[0]]
146 ev = self.trace.read_event_at(ref.offset)
147 return ev
148 except IndexError:
149 return None
33 150
34 151
35class EventView(gtk.TreeView): 152class EventView(gtk.TreeView):
@@ -81,29 +198,29 @@ class EventView(gtk.TreeView):
81 global app, data_func_cnt 198 global app, data_func_cnt
82 199
83 ev = model.get_event(iter) 200 ev = model.get_event(iter)
201 #ev = model.get_value(iter, 0)
84 if not ev: 202 if not ev:
85 return False 203 return False
204
86 if data == "ts": 205 if data == "ts":
87 cell.set_property("markup", "%d.%d" % (ev.ts/1000000000, 206 cell.set_property("markup", "%d.%d" % (ev.ts/1000000000,
88 ev.ts%1000000000)) 207 ev.ts%1000000000))
89 data_func_cnt = data_func_cnt + 1 208 data_func_cnt = data_func_cnt + 1
90 if app: 209 if app:
91 app.inc_data_func() 210 app.inc_data_func()
92 return True 211 elif data == "cpu":
93 if data == "cpu":
94 cell.set_property("markup", ev.cpu) 212 cell.set_property("markup", ev.cpu)
95 return True 213 elif data == "event":
96 if data == "event":
97 cell.set_property("markup", ev.name) 214 cell.set_property("markup", ev.name)
98 return True 215 elif data == "pid":
99 if data == "pid":
100 cell.set_property("markup", ev.pid) 216 cell.set_property("markup", ev.pid)
101 return True 217 elif data == "comm":
102 if data == "comm":
103 cell.set_property("markup", ev.comm) 218 cell.set_property("markup", ev.comm)
104 return True 219 else:
220 print "Unknown Column:", data
221 return False
105 222
106 return False 223 return True
107 224
108 225
109class EventViewerApp(gtk.Window): 226class EventViewerApp(gtk.Window):
@@ -116,9 +233,8 @@ class EventViewerApp(gtk.Window):
116 self.connect("destroy", gtk.main_quit) 233 self.connect("destroy", gtk.main_quit)
117 self.set_title("Event Viewer") 234 self.set_title("Event Viewer")
118 235
119 236 store = EventStore(trace)
120 es = EventStore(trace) 237 view = EventView(store)
121 view = EventView(es)
122 238
123 sw = gtk.ScrolledWindow() 239 sw = gtk.ScrolledWindow()
124 sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) 240 sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
@@ -143,6 +259,14 @@ class EventViewerApp(gtk.Window):
143 259
144 260
145if __name__ == "__main__": 261if __name__ == "__main__":
146 trace = Trace("trace.dat") 262 if len(sys.argv) >=2:
263 filename = sys.argv[1]
264 else:
265 filename = "trace.dat"
266
267 print "Initializing trace..."
268 trace = Trace(filename)
269 print "Initializing app..."
147 app = EventViewerApp(trace) 270 app = EventViewerApp(trace)
271 print "Go!"
148 gtk.main() 272 gtk.main()
diff --git a/tracecmd.py b/tracecmd.py
index fdcda76..e7ea5f6 100644
--- a/tracecmd.py
+++ b/tracecmd.py
@@ -44,6 +44,9 @@ class Event(object):
44 (self.ts/1000000000, self.ts%1000000000, self.cpu, self.name, 44 (self.ts/1000000000, self.ts%1000000000, self.cpu, self.name,
45 self.num_field("common_pid"), self.comm, self.type) 45 self.num_field("common_pid"), self.comm, self.type)
46 46
47 def __del__(self):
48 free_record(self.rec);
49
47 50
48 # TODO: consider caching the results of the properties 51 # TODO: consider caching the results of the properties
49 @property 52 @property
@@ -100,6 +103,8 @@ class Trace(object):
100 def read_event(self, cpu): 103 def read_event(self, cpu):
101 rec = tracecmd_read_data(self.handle, cpu) 104 rec = tracecmd_read_data(self.handle, cpu)
102 if rec: 105 if rec:
106 #rec.acquire()
107 #rec.thisown = 1
103 return Event(self, rec, cpu) 108 return Event(self, rec, cpu)
104 return None 109 return None
105 110
@@ -108,7 +113,11 @@ class Trace(object):
108 # SWIG only returns the CPU if the record is None for some reason 113 # SWIG only returns the CPU if the record is None for some reason
109 if isinstance(res, int): 114 if isinstance(res, int):
110 return None 115 return None
111 return Event(self, res[0], res[1]) 116 rec,cpu = res
117 #rec.acquire()
118 #rec.thisown = 1
119 ev = Event(self, rec, cpu)
120 return ev
112 121
113 def peek_event(self, cpu): 122 def peek_event(self, cpu):
114 pass 123 pass