doc: Make python bindings doc build
[babeltrace.git] / bindings / python / babeltrace / babeltrace / reader_trace_collection.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2013-2017 Jérémie Galarneau <jeremie.galarneau@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 import bt2
24 import babeltrace.common as common
25 from babeltrace import reader_trace_handle
26 from babeltrace import reader_event
27 import os
28
29
30 class TraceCollection:
31 """
32 A :class:`TraceCollection` is a collection of opened traces.
33
34 Once a trace collection is created, you can add traces to the
35 collection by using the :meth:`add_trace` or
36 :meth:`add_traces_recursive`, and then iterate on the merged
37 events using :attr:`events`.
38
39 You may use :meth:`remove_trace` to close and remove a specific
40 trace from a trace collection.
41 """
42
43 def __init__(self, intersect_mode=False):
44 """
45 Creates an empty trace collection.
46 """
47
48 self._intersect_mode = intersect_mode
49 self._trace_handles = set()
50 self._next_th_id = 0
51 self._ctf_plugin = bt2.find_plugin('ctf')
52 assert(self._ctf_plugin is not None)
53 self._fs_comp_cls = self._ctf_plugin.source_component_classes['fs']
54
55 def add_trace(self, path, format_str):
56 """
57 Adds a trace to the trace collection.
58
59 *path* is the exact path of the trace on the filesystem.
60
61 *format_str* is a string indicating the type of trace to
62 add. ``ctf`` is currently the only supported trace format.
63
64 Returns the corresponding :class:`TraceHandle` instance for
65 this opened trace on success, or ``None`` on error.
66
67 This function **does not** recurse directories to find a
68 trace. See :meth:`add_traces_recursive` for a recursive
69 version of this function.
70 """
71
72 if format_str != 'ctf':
73 raise ValueError('only the "ctf" format is supported')
74
75 if not os.path.isfile(os.path.join(path, 'metadata')):
76 raise ValueError('no "metadata" file found in "{}"'.format(path))
77
78 th = reader_trace_handle.TraceHandle.__new__(reader_trace_handle.TraceHandle)
79 th._id = self._next_th_id
80 self._next_th_id += 1
81 th._trace_collection = self
82 th._path = path
83 self._trace_handles.add(th)
84 return th
85
86 def add_traces_recursive(self, path, format_str):
87 """
88 Adds traces to this trace collection by recursively searching
89 in the *path* directory.
90
91 *format_str* is a string indicating the type of trace to add.
92 ``ctf`` is currently the only supported trace format.
93
94 Returns a :class:`dict` object mapping full paths to trace
95 handles for each trace found, or ``None`` on error.
96
97 See also :meth:`add_trace`.
98 """
99
100 trace_handles = {}
101 noTrace = True
102 error = False
103
104 for fullpath, dirs, files in os.walk(path):
105 if "metadata" in files:
106 trace_handle = self.add_trace(fullpath, format_str)
107
108 if trace_handle is None:
109 error = True
110 continue
111
112 trace_handles[fullpath] = trace_handle
113 noTrace = False
114
115 if noTrace and error:
116 return None
117
118 return trace_handles
119
120 def remove_trace(self, handle):
121 """
122 Removes a trace from the trace collection using its trace
123 handle *trace_handle*.
124
125 :class:`TraceHandle` objects are returned by :meth:`add_trace`
126 and :meth:`add_traces_recursive`.
127 """
128
129 if not isinstance(handle, reader_trace_handle.TraceHandle):
130 raise TypeError("'{}' is not a 'TraceHandle' object".format(
131 handle.__class__.__name__))
132
133 # this can raise but it would mean the trace handle is not part
134 # of this trace collection anyway
135 self._trace_handles.remove(handle)
136
137 @property
138 def intersect_mode(self):
139 return self._intersect_mode
140
141 @property
142 def has_intersection(self):
143 return any(th._has_intersection for th in self._trace_handles)
144
145 @property
146 def events(self):
147 """
148 Generates the ordered :class:`Event` objects of all the opened
149 traces contained in this trace collection.
150 """
151
152 return self._gen_events()
153
154 def events_timestamps(self, timestamp_begin, timestamp_end):
155 """
156 Generates the ordered :class:`Event` objects of all the opened
157 traces contained in this trace collection from *timestamp_begin*
158 to *timestamp_end*.
159
160 *timestamp_begin* and *timestamp_end* are given in nanoseconds
161 since Epoch.
162
163 See :attr:`events` for notes and limitations.
164 """
165
166 return self._gen_events(timestamp_begin / 1e9, timestamp_end / 1e9)
167
168 def _gen_events(self, begin_s=None, end_s=None):
169 specs = [bt2.ComponentSpec('ctf', 'fs', th.path) for th in self._trace_handles]
170
171 try:
172 iter_cls = bt2.TraceCollectionMessageIterator
173 tc_iter = iter_cls(specs,
174 stream_intersection_mode=self._intersect_mode,
175 begin=begin_s, end=end_s,
176 message_types=[bt2.EventMessage])
177 return map(reader_event._create_event, tc_iter)
178 except:
179 raise ValueError
180
181 @property
182 def timestamp_begin(self):
183 """
184 Begin timestamp of this trace collection (nanoseconds since Epoch).
185 """
186
187 if not self._trace_handles:
188 return
189
190 return min(th.timestamp_begin for th in self._trace_handles)
191
192 @property
193 def timestamp_end(self):
194 """
195 End timestamp of this trace collection (nanoseconds since Epoch).
196 """
197
198 if not self._trace_handles:
199 return
200
201 return max(th.timestamp_end for th in self._trace_handles)
This page took 0.032764 seconds and 4 git commands to generate.