diff options
Diffstat (limited to 'naive_trace_reader.py')
-rw-r--r-- | naive_trace_reader.py | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/naive_trace_reader.py b/naive_trace_reader.py new file mode 100644 index 0000000..0f117b8 --- /dev/null +++ b/naive_trace_reader.py | |||
@@ -0,0 +1,165 @@ | |||
1 | ############################################################################### | ||
2 | # Description | ||
3 | ############################################################################### | ||
4 | |||
5 | # trace_reader(files) returns an iterator which produces records | ||
6 | # OUT OF ORDER from the files given. (the param is a list of files.) | ||
7 | # | ||
8 | # The non-naive trace_reader has a lot of complex logic which attempts to | ||
9 | # produce records in order (even though they are being pulled from multiple | ||
10 | # files which themselves are only approximately ordered). This trace_reader | ||
11 | # attempts to be as simple as possible and is used in the unit tests to | ||
12 | # make sure the total number of records read by the normal trace_reader is | ||
13 | # the same as the number of records read by this one. | ||
14 | |||
15 | ############################################################################### | ||
16 | # Imports | ||
17 | ############################################################################### | ||
18 | |||
19 | import struct | ||
20 | |||
21 | |||
22 | ############################################################################### | ||
23 | # Public functions | ||
24 | ############################################################################### | ||
25 | |||
26 | # Generator function returning an iterable over records in a trace file. | ||
27 | def trace_reader(files): | ||
28 | for file in files: | ||
29 | f = open(file,'rb') | ||
30 | while True: | ||
31 | data = f.read(RECORD_HEAD_SIZE) | ||
32 | try: | ||
33 | type_num = struct.unpack_from('b',data)[0] | ||
34 | except struct.error: | ||
35 | break #We read to the end of the file | ||
36 | type = _get_type(type_num) | ||
37 | try: | ||
38 | values = struct.unpack_from(StHeader.format + | ||
39 | type.format,data) | ||
40 | record_dict = dict(zip(type.keys,values)) | ||
41 | except struct.error: | ||
42 | f.close() | ||
43 | print "Invalid record detected, stopping." | ||
44 | exit() | ||
45 | |||
46 | # Convert the record_dict into an object | ||
47 | record = _dict2obj(record_dict) | ||
48 | |||
49 | # Give it a type name (easier to work with than type number) | ||
50 | record.type_name = _get_type_name(type_num) | ||
51 | |||
52 | # All records should have a 'record type' field. | ||
53 | # e.g. these are 'event's as opposed to 'error's | ||
54 | record.record_type = "event" | ||
55 | |||
56 | # If there is no timestamp, set the time to 0 | ||
57 | if 'when' not in record.__dict__.keys(): | ||
58 | record.when = 0 | ||
59 | |||
60 | yield record | ||
61 | |||
62 | ############################################################################### | ||
63 | # Private functions | ||
64 | ############################################################################### | ||
65 | |||
66 | # Convert a dict into an object | ||
67 | def _dict2obj(d): | ||
68 | class Obj: pass | ||
69 | o = Obj() | ||
70 | for key in d.keys(): | ||
71 | o.__dict__[key] = d[key] | ||
72 | return o | ||
73 | |||
74 | ############################################################################### | ||
75 | # Trace record data types and accessor functions | ||
76 | ############################################################################### | ||
77 | |||
78 | # Each class below represents a type of event record. The format attribute | ||
79 | # specifies how to decode the binary record and the keys attribute | ||
80 | # specifies how to name the pieces of information decoded. Note that all | ||
81 | # event records have a common initial 24 bytes, represented by the StHeader | ||
82 | # class. | ||
83 | |||
84 | RECORD_HEAD_SIZE = 24 | ||
85 | |||
86 | class StHeader(object): | ||
87 | format = '<bbhi' | ||
88 | formatStr = struct.Struct(format) | ||
89 | keys = ['type','cpu','pid','job'] | ||
90 | message = 'The header.' | ||
91 | |||
92 | class StNameData(object): | ||
93 | format = '16s' | ||
94 | formatStr = struct.Struct(StHeader.format + format) | ||
95 | keys = StHeader.keys + ['name'] | ||
96 | message = 'The name of the executable of this process.' | ||
97 | |||
98 | class StParamData(object): | ||
99 | format = 'IIIc' | ||
100 | formatStr = struct.Struct(StHeader.format + format) | ||
101 | keys = StHeader.keys + ['wcet','period','phase','partition'] | ||
102 | message = 'Regular parameters.' | ||
103 | |||
104 | class StReleaseData(object): | ||
105 | format = 'QQ' | ||
106 | formatStr = struct.Struct(StHeader.format + format) | ||
107 | keys = StHeader.keys + ['when','deadline'] | ||
108 | message = 'A job was/is going to be released.' | ||
109 | |||
110 | #Not yet used by Sched Trace | ||
111 | class StAssignedData(object): | ||
112 | format = 'Qc' | ||
113 | formatStr = struct.Struct(StHeader.format + format) | ||
114 | keys = StHeader.keys + ['when','target'] | ||
115 | message = 'A job was assigned to a CPU.' | ||
116 | |||
117 | class StSwitchToData(object): | ||
118 | format = 'QI' | ||
119 | formatStr = struct.Struct(StHeader.format + format) | ||
120 | keys = StHeader.keys + ['when','exec_time'] | ||
121 | message = 'A process was switched to on a given CPU.' | ||
122 | |||
123 | class StSwitchAwayData(object): | ||
124 | format = 'QI' | ||
125 | formatStr = struct.Struct(StHeader.format + format) | ||
126 | keys = StHeader.keys + ['when','exec_time'] | ||
127 | message = 'A process was switched away on a given CPU.' | ||
128 | |||
129 | class StCompletionData(object): | ||
130 | format = 'Q3xcc' | ||
131 | formatStr = struct.Struct(StHeader.format + format) | ||
132 | keys = StHeader.keys + ['when','forced?','flags'] | ||
133 | message = 'A job completed.' | ||
134 | |||
135 | class StBlockData(object): | ||
136 | format = 'Q' | ||
137 | formatStr = struct.Struct(StHeader.format + format) | ||
138 | keys = StHeader.keys + ['when'] | ||
139 | message = 'A task blocks.' | ||
140 | |||
141 | class StResumeData(object): | ||
142 | format = 'Q' | ||
143 | formatStr = struct.Struct(StHeader.format + format) | ||
144 | keys = StHeader.keys + ['when'] | ||
145 | message = 'A task resumes.' | ||
146 | |||
147 | class StSysReleaseData(object): | ||
148 | format = 'QQ' | ||
149 | formatStr = struct.Struct(StHeader.format + format) | ||
150 | keys = StHeader.keys + ['when','release'] | ||
151 | message = 'All tasks have checked in, task system released by user' | ||
152 | |||
153 | # Return the binary data type, given the type_num | ||
154 | def _get_type(type_num): | ||
155 | types = [None,StNameData,StParamData,StReleaseData,StAssignedData, | ||
156 | StSwitchToData,StSwitchAwayData,StCompletionData,StBlockData, | ||
157 | StResumeData,StSysReleaseData] | ||
158 | return types[type_num] | ||
159 | |||
160 | # Return the type name, given the type_num (this is simply a convenience to | ||
161 | # programmers of other modules) | ||
162 | def _get_type_name(type_num): | ||
163 | type_names = [None,"name","params","release","assign","switch_to", | ||
164 | "switch_away","completion","block","resume","sys_release"] | ||
165 | return type_names[type_num] | ||