afc42810db4d88448076fb5ce5b926713e1aeefa
[babeltrace.git] / bindings / python / bt2 / bt2 / event.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2016-2017 Philippe Proulx <pproulx@efficios.com>
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22
23 from bt2 import native_bt, object, utils
24 import bt2.clock_class
25 import bt2.packet
26 import bt2.stream
27 import bt2.fields
28 import bt2.clock_value
29 import collections
30 import numbers
31 import copy
32 import abc
33 import bt2
34
35
36 def _create_from_ptr(ptr):
37 # recreate the event class wrapper of this event's class (the
38 # identity could be different, but the underlying address should be
39 # the same)
40 event_class_ptr = native_bt.event_get_class(ptr)
41 utils._handle_ptr(event_class_ptr, "cannot get event object's class")
42 event_class = bt2.EventClass._create_from_ptr(event_class_ptr)
43 event = _Event._create_from_ptr(ptr)
44 event._event_class = event_class
45 return event
46
47
48 class _EventClockValuesIterator(collections.abc.Iterator):
49 def __init__(self, event_clock_values):
50 self._event_clock_values = event_clock_values
51 self._clock_classes = event_clock_values._event._clock_classes
52 self._at = 0
53
54 def __next__(self):
55 if self._at == len(self._clock_classes):
56 raise StopIteration
57
58 self._at += 1
59 return self._clock_classes[at]
60
61
62 class _EventClockValues(collections.abc.Mapping):
63 def __init__(self, event):
64 self._event = event
65
66 def __getitem__(self, clock_class):
67 utils._check_type(clock_class, bt2.ClockClass)
68 clock_value_ptr = native_bt.event_get_clock_value(self._event._ptr,
69 clock_class._ptr)
70
71 if clock_value_ptr is None:
72 return
73
74 clock_value = bt2.clock_value._create_clock_value_from_ptr(clock_value_ptr)
75 return clock_value
76
77 def add(self, clock_value):
78 utils._check_type(clock_value, bt2.clock_value._ClockValue)
79 ret = native_bt.event_set_clock_value(self._ptr,
80 clock_value._ptr)
81 utils._handle_ret(ret, "cannot set event object's clock value")
82
83 def __len__(self):
84 count = len(self._event._clock_classes)
85 assert(count >= 0)
86 return count
87
88 def __iter__(self):
89 return _EventClockValuesIterator(self)
90
91
92 class _Event(object._Object):
93 @property
94 def event_class(self):
95 return self._event_class
96
97 @property
98 def name(self):
99 return self._event_class.name
100
101 @property
102 def id(self):
103 return self._event_class.id
104
105 @property
106 def packet(self):
107 packet_ptr = native_bt.event_get_packet(self._ptr)
108
109 if packet_ptr is None:
110 return packet_ptr
111
112 return bt2.packet._Packet._create_from_ptr(packet_ptr)
113
114 @packet.setter
115 def packet(self, packet):
116 utils._check_type(packet, bt2.packet._Packet)
117 ret = native_bt.event_set_packet(self._ptr, packet._ptr)
118 utils._handle_ret(ret, "cannot set event object's packet object")
119
120 @property
121 def stream(self):
122 stream_ptr = native_bt.event_get_stream(self._ptr)
123
124 if stream_ptr is None:
125 return stream_ptr
126
127 return bt2.stream._Stream._create_from_ptr(stream_ptr)
128
129 @property
130 def header_field(self):
131 field_ptr = native_bt.event_get_header(self._ptr)
132
133 if field_ptr is None:
134 return
135
136 return bt2.fields._create_from_ptr(field_ptr)
137
138 @header_field.setter
139 def header_field(self, header_field):
140 header_field_ptr = None
141
142 if header_field is not None:
143 utils._check_type(header_field, bt2.fields._Field)
144 header_field_ptr = header_field._ptr
145
146 ret = native_bt.event_set_header(self._ptr, header_field_ptr)
147 utils._handle_ret(ret, "cannot set event object's header field")
148
149 @property
150 def stream_event_context_field(self):
151 field_ptr = native_bt.event_get_stream_event_context(self._ptr)
152
153 if field_ptr is None:
154 return
155
156 return bt2.fields._create_from_ptr(field_ptr)
157
158 @stream_event_context_field.setter
159 def stream_event_context_field(self, stream_event_context):
160 stream_event_context_ptr = None
161
162 if stream_event_context is not None:
163 utils._check_type(stream_event_context, bt2.fields._Field)
164 stream_event_context_ptr = stream_event_context._ptr
165
166 ret = native_bt.event_set_stream_event_context(self._ptr,
167 stream_event_context_ptr)
168 utils._handle_ret(ret, "cannot set event object's stream event context field")
169
170 @property
171 def context_field(self):
172 field_ptr = native_bt.event_get_event_context(self._ptr)
173
174 if field_ptr is None:
175 return
176
177 return bt2.fields._create_from_ptr(field_ptr)
178
179 @context_field.setter
180 def context_field(self, context):
181 context_ptr = None
182
183 if context is not None:
184 utils._check_type(context, bt2.fields._Field)
185 context_ptr = context._ptr
186
187 ret = native_bt.event_set_event_context(self._ptr, context_ptr)
188 utils._handle_ret(ret, "cannot set event object's context field")
189
190 @property
191 def payload_field(self):
192 field_ptr = native_bt.event_get_event_payload(self._ptr)
193
194 if field_ptr is None:
195 return
196
197 return bt2.fields._create_from_ptr(field_ptr)
198
199 @payload_field.setter
200 def payload_field(self, payload):
201 payload_ptr = None
202
203 if payload is not None:
204 utils._check_type(payload, bt2.fields._Field)
205 payload_ptr = payload._ptr
206
207 ret = native_bt.event_set_event_payload(self._ptr, payload_ptr)
208 utils._handle_ret(ret, "cannot set event object's payload field")
209
210 def _get_clock_value_cycles(self, clock_class_ptr):
211 clock_value_ptr = native_bt.event_get_clock_value(self._ptr,
212 clock_class_ptr)
213
214 if clock_value_ptr is None:
215 return
216
217 ret, cycles = native_bt.clock_value_get_value(clock_value_ptr)
218 native_bt.put(clock_value_ptr)
219 utils._handle_ret(ret, "cannot get clock value object's cycles")
220 return cycles
221
222 @property
223 def clock_values(self):
224 return _EventClockValues(self)
225
226 def __getitem__(self, key):
227 utils._check_str(key)
228 payload_field = self.payload_field
229
230 if payload_field is not None and key in payload_field:
231 return payload_field[key]
232
233 context_field = self.context_field
234
235 if context_field is not None and key in context_field:
236 return context_field[key]
237
238 sec_field = self.stream_event_context_field
239
240 if sec_field is not None and key in sec_field:
241 return sec_field[key]
242
243 header_field = self.header_field
244
245 if header_field is not None and key in header_field:
246 return header_field[key]
247
248 packet = self.packet
249
250 if packet is None:
251 raise KeyError(key)
252
253 pkt_context_field = packet.context_field
254
255 if pkt_context_field is not None and key in pkt_context_field:
256 return pkt_context_field[key]
257
258 pkt_header_field = packet.header_field
259
260 if pkt_header_field is not None and key in pkt_header_field:
261 return pkt_header_field[key]
262
263 raise KeyError(key)
264
265 @property
266 def _clock_classes(self):
267 stream_class = self.event_class.stream_class
268
269 if stream_class is None:
270 return []
271
272 trace = stream_class.trace
273
274 if trace is None:
275 return []
276
277 clock_classes = []
278
279 for clock_class in trace.clock_classes.values():
280 clock_classes.append(clock_class)
281
282 return clock_classes
283
284 @property
285 def _clock_class_ptrs(self):
286 return [cc._ptr for cc in self._clock_classes]
287
288 def __eq__(self, other):
289 if type(other) is not type(self):
290 return False
291
292 if self.addr == other.addr:
293 return True
294
295 self_clock_values = {}
296 other_clock_values = {}
297
298 for clock_class_ptr in self._clock_class_ptrs:
299 self_clock_values[int(clock_class_ptr)] = self._get_clock_value_cycles(clock_class_ptr)
300
301 for clock_class_ptr in other._clock_class_ptrs:
302 other_clock_values[int(clock_class_ptr)] = self._get_clock_value_cycles(clock_class_ptr)
303
304 self_props = (
305 self.header_field,
306 self.stream_event_context_field,
307 self.context_field,
308 self.payload_field,
309 self_clock_values,
310 )
311 other_props = (
312 other.header_field,
313 other.stream_event_context_field,
314 other.context_field,
315 other.payload_field,
316 other_clock_values,
317 )
318 return self_props == other_props
319
320 def _copy(self, copy_func):
321 cpy = self.event_class()
322
323 # copy fields
324 cpy.header_field = copy_func(self.header_field)
325 cpy.stream_event_context_field = copy_func(self.stream_event_context_field)
326 cpy.context_field = copy_func(self.context_field)
327 cpy.payload_field = copy_func(self.payload_field)
328
329 # Copy known clock value references. It's not necessary to copy
330 # clock class or clock value objects because once a clock value
331 # is created from a clock class, the clock class is frozen.
332 # Thus even if we copy the clock class, the user cannot modify
333 # it, therefore it's useless to copy it.
334 for clock_class in self._clock_classes:
335 clock_value = self.clock_values[clock_class]
336
337 if clock_value is not None:
338 cpy.clock_values.add(clock_value)
339
340 return cpy
341
342 def __copy__(self):
343 return self._copy(copy.copy)
344
345 def __deepcopy__(self, memo):
346 cpy = self._copy(copy.deepcopy)
347 memo[id(self)] = cpy
348 return cpy
This page took 0.036762 seconds and 3 git commands to generate.