Commit | Line | Data |
---|---|---|
866e5b51 | 1 | /******************************************************************************* |
60ae41e1 | 2 | * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others |
866e5b51 FC |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are made | |
5 | * available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: Matthew Khouzam - Initial API and implementation | |
10 | * Contributors: Simon Marchi - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
486efb2e | 13 | package org.eclipse.linuxtools.ctf.core.trace; |
866e5b51 | 14 | |
5f715709 MK |
15 | import java.util.ArrayList; |
16 | import java.util.Collection; | |
17 | import java.util.Collections; | |
866e5b51 | 18 | import java.util.HashSet; |
5f715709 | 19 | import java.util.List; |
0594c61c | 20 | import java.util.Map; |
866e5b51 FC |
21 | import java.util.Set; |
22 | ||
5f715709 MK |
23 | import org.eclipse.jdt.annotation.NonNull; |
24 | import org.eclipse.jdt.annotation.Nullable; | |
8e964be1 | 25 | import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration; |
6c7592e1 MK |
26 | import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration; |
27 | import org.eclipse.linuxtools.ctf.core.event.types.IEventHeaderDeclaration; | |
866e5b51 | 28 | import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration; |
b73145e2 | 29 | import org.eclipse.linuxtools.internal.ctf.core.event.EventDeclaration; |
ce2388e0 | 30 | import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException; |
866e5b51 FC |
31 | |
32 | /** | |
33 | * <b><u>Stream</u></b> | |
34 | * <p> | |
35 | * Represents a stream in a trace. | |
6c7592e1 | 36 | * |
d84419e1 | 37 | * @since 3.0 |
866e5b51 | 38 | */ |
d84419e1 | 39 | public class CTFStream { |
866e5b51 FC |
40 | |
41 | // ------------------------------------------------------------------------ | |
42 | // Attributes | |
43 | // ------------------------------------------------------------------------ | |
44 | ||
866e5b51 FC |
45 | /** |
46 | * The numerical ID of the stream | |
47 | */ | |
2ab0ccec | 48 | private Long fId = null; |
866e5b51 FC |
49 | |
50 | /** | |
51 | * Declarations of the stream-specific structures | |
52 | */ | |
2ab0ccec | 53 | private StructDeclaration fPacketContextDecl = null; |
6c7592e1 | 54 | private IDeclaration fEventHeaderDecl = null; |
2ab0ccec | 55 | private StructDeclaration fEventContextDecl = null; |
866e5b51 FC |
56 | |
57 | /** | |
58 | * The trace to which the stream belongs | |
59 | */ | |
2ab0ccec | 60 | private CTFTrace fTrace = null; |
866e5b51 FC |
61 | |
62 | /** | |
63 | * Maps event ids to events | |
64 | */ | |
5f715709 MK |
65 | private final ArrayList<IEventDeclaration> fEvents = new ArrayList<>(); |
66 | ||
67 | private boolean fEventUnsetId = false; | |
866e5b51 FC |
68 | |
69 | /** | |
70 | * The inputs associated to this stream | |
71 | */ | |
d84419e1 | 72 | private final Set<CTFStreamInput> fInputs = new HashSet<>(); |
866e5b51 FC |
73 | |
74 | // ------------------------------------------------------------------------ | |
75 | // Constructors | |
76 | // ------------------------------------------------------------------------ | |
77 | ||
78 | /** | |
79 | * Constructs a Stream that belongs to a Trace | |
80 | * | |
81 | * @param trace | |
82 | * The trace to which belongs this stream. | |
83 | */ | |
d84419e1 | 84 | public CTFStream(CTFTrace trace) { |
2ab0ccec | 85 | fTrace = trace; |
866e5b51 FC |
86 | } |
87 | ||
88 | // ------------------------------------------------------------------------ | |
89 | // Getters/Setters/Predicates | |
90 | // ------------------------------------------------------------------------ | |
91 | ||
9ac2eb62 MK |
92 | /** |
93 | * Sets the id of a stream | |
6c7592e1 MK |
94 | * |
95 | * @param id | |
96 | * the id of a stream | |
9ac2eb62 | 97 | */ |
866e5b51 | 98 | public void setId(long id) { |
2ab0ccec | 99 | fId = id; |
866e5b51 FC |
100 | } |
101 | ||
9ac2eb62 MK |
102 | /** |
103 | * Gets the id of a stream | |
6c7592e1 | 104 | * |
9ac2eb62 MK |
105 | * @return id the id of a stream |
106 | */ | |
866e5b51 | 107 | public Long getId() { |
2ab0ccec | 108 | return fId; |
866e5b51 FC |
109 | } |
110 | ||
9ac2eb62 MK |
111 | /** |
112 | * Is the id of a stream set | |
be6df2d8 AM |
113 | * |
114 | * @return If the ID is set or not | |
9ac2eb62 MK |
115 | */ |
116 | public boolean isIdSet() { | |
2ab0ccec | 117 | return fId != null; |
866e5b51 FC |
118 | } |
119 | ||
9ac2eb62 MK |
120 | /** |
121 | * | |
122 | * @return is the event header set (timestamp and stuff) (see Ctf Spec) | |
123 | */ | |
124 | public boolean isEventHeaderSet() { | |
2ab0ccec | 125 | return fEventHeaderDecl != null; |
866e5b51 FC |
126 | } |
127 | ||
9ac2eb62 | 128 | /** |
6c7592e1 MK |
129 | * |
130 | * @return is the event context set (pid and stuff) (see Ctf Spec) | |
131 | */ | |
9ac2eb62 | 132 | public boolean isEventContextSet() { |
2ab0ccec | 133 | return fEventContextDecl != null; |
866e5b51 FC |
134 | } |
135 | ||
9ac2eb62 MK |
136 | /** |
137 | * | |
138 | * @return Is the packet context set (see Ctf Spec) | |
139 | */ | |
140 | public boolean isPacketContextSet() { | |
2ab0ccec | 141 | return fPacketContextDecl != null; |
866e5b51 FC |
142 | } |
143 | ||
9ac2eb62 | 144 | /** |
6c7592e1 | 145 | * Sets the event header |
9ac2eb62 | 146 | * |
6c7592e1 MK |
147 | * @param eventHeader |
148 | * the current event header for all events in this stream | |
9ac2eb62 | 149 | */ |
866e5b51 | 150 | public void setEventHeader(StructDeclaration eventHeader) { |
2ab0ccec | 151 | fEventHeaderDecl = eventHeader; |
866e5b51 FC |
152 | } |
153 | ||
9ac2eb62 | 154 | /** |
6c7592e1 | 155 | * Sets the event header, this typically has the id and the timestamp |
9ac2eb62 | 156 | * |
6c7592e1 MK |
157 | * @param eventHeader |
158 | * the current event header for all events in this stream | |
159 | * @since 3.1 | |
160 | */ | |
161 | public void setEventHeader(IEventHeaderDeclaration eventHeader) { | |
162 | fEventHeaderDecl = eventHeader; | |
163 | } | |
164 | ||
165 | /** | |
166 | * | |
167 | * @param eventContext | |
168 | * the context for all events in this stream | |
9ac2eb62 | 169 | */ |
866e5b51 | 170 | public void setEventContext(StructDeclaration eventContext) { |
2ab0ccec | 171 | fEventContextDecl = eventContext; |
866e5b51 FC |
172 | } |
173 | ||
9ac2eb62 MK |
174 | /** |
175 | * | |
6c7592e1 MK |
176 | * @param packetContext |
177 | * the packet context for all packets in this stream | |
9ac2eb62 | 178 | */ |
866e5b51 | 179 | public void setPacketContext(StructDeclaration packetContext) { |
2ab0ccec | 180 | fPacketContextDecl = packetContext; |
866e5b51 FC |
181 | } |
182 | ||
9ac2eb62 MK |
183 | /** |
184 | * | |
185 | * @return the event header declaration in structdeclaration form | |
6c7592e1 | 186 | * @deprecated use {@link CTFStream#getEventHeaderDeclaration()} |
9ac2eb62 | 187 | */ |
6c7592e1 | 188 | @Deprecated |
866e5b51 | 189 | public StructDeclaration getEventHeaderDecl() { |
6c7592e1 MK |
190 | return (StructDeclaration) ((fEventHeaderDecl instanceof StructDeclaration) ? fEventHeaderDecl : null); |
191 | } | |
192 | ||
193 | /** | |
194 | * Gets the event header declaration | |
195 | * | |
196 | * @return the event header declaration in declaration form | |
197 | * @since 3.1 | |
198 | */ | |
199 | public IDeclaration getEventHeaderDeclaration() { | |
2ab0ccec | 200 | return fEventHeaderDecl; |
866e5b51 FC |
201 | } |
202 | ||
9ac2eb62 MK |
203 | /** |
204 | * | |
205 | * @return the event context declaration in structdeclaration form | |
206 | */ | |
866e5b51 | 207 | public StructDeclaration getEventContextDecl() { |
2ab0ccec | 208 | return fEventContextDecl; |
866e5b51 FC |
209 | } |
210 | ||
9ac2eb62 MK |
211 | /** |
212 | * | |
213 | * @return the packet context declaration in structdeclaration form | |
214 | */ | |
866e5b51 | 215 | public StructDeclaration getPacketContextDecl() { |
2ab0ccec | 216 | return fPacketContextDecl; |
866e5b51 FC |
217 | } |
218 | ||
9ac2eb62 MK |
219 | /** |
220 | * | |
221 | * @return the set of all stream inputs for this stream | |
222 | */ | |
d84419e1 | 223 | public Set<CTFStreamInput> getStreamInputs() { |
2ab0ccec | 224 | return fInputs; |
866e5b51 FC |
225 | } |
226 | ||
9ac2eb62 MK |
227 | /** |
228 | * | |
229 | * @return the parent trace | |
230 | */ | |
866e5b51 | 231 | public CTFTrace getTrace() { |
2ab0ccec | 232 | return fTrace; |
866e5b51 FC |
233 | } |
234 | ||
9ac2eb62 MK |
235 | /** |
236 | * | |
6c7592e1 MK |
237 | * @return all the event declarations for this stream, using the id as a key |
238 | * for the hashmap. | |
5f715709 | 239 | * @deprecated use {@link CTFStream#getEventDeclarations()} |
9ac2eb62 | 240 | */ |
5f715709 | 241 | @Deprecated |
0594c61c | 242 | public Map<Long, IEventDeclaration> getEvents() { |
5f715709 MK |
243 | throw new UnsupportedOperationException(); |
244 | } | |
245 | ||
246 | /** | |
247 | * Get all the event declarations in this stream. | |
248 | * | |
249 | * @return The event declarations for this stream | |
a465519a | 250 | * @since 3.2 |
5f715709 MK |
251 | */ |
252 | public @NonNull Collection<IEventDeclaration> getEventDeclarations() { | |
253 | List<IEventDeclaration> retVal = new ArrayList<>(fEvents); | |
254 | retVal.removeAll(Collections.<IEventDeclaration> singletonList(null)); | |
255 | return retVal; | |
256 | } | |
257 | ||
258 | /** | |
259 | * Get the event declaration for a given ID. | |
260 | * | |
261 | * @param eventId | |
262 | * The ID, can be {@link EventDeclaration#UNSET_EVENT_ID}, or any | |
263 | * positive value | |
264 | * @return The event declaration with the given ID for this stream, or | |
265 | * 'null' if there are no declaration with this ID | |
266 | * @throws IllegalArgumentException | |
267 | * If the passed ID is invalid | |
a465519a | 268 | * @since 3.2 |
5f715709 MK |
269 | */ |
270 | public @Nullable IEventDeclaration getEventDeclaration(int eventId) { | |
271 | int eventIndex = (eventId == EventDeclaration.UNSET_EVENT_ID) ? 0 : eventId; | |
272 | if (eventIndex < 0) { | |
273 | /* Any negative value other than UNSET_EVENT_ID is invalid */ | |
274 | throw new IllegalArgumentException("Event ID cannot be negative."); //$NON-NLS-1$ | |
275 | } | |
276 | if (eventIndex >= fEvents.size()) { | |
277 | /* This ID could be valid, but there are no declarations with it */ | |
278 | return null; | |
279 | } | |
280 | return fEvents.get(eventIndex); | |
866e5b51 FC |
281 | } |
282 | ||
283 | // ------------------------------------------------------------------------ | |
284 | // Operations | |
285 | // ------------------------------------------------------------------------ | |
286 | ||
287 | /** | |
5f715709 | 288 | * Adds an event to the event list. |
866e5b51 FC |
289 | * |
290 | * An event in a stream can omit its id if it is the only event in this | |
291 | * stream. An event for which no id has been specified has a null id. It is | |
292 | * thus not possible to add an event with the null key if the map is not | |
293 | * empty. It is also not possible to add an event to the map if the null key | |
294 | * is present in the map. | |
295 | * | |
296 | * @param event | |
be6df2d8 | 297 | * The event to add |
866e5b51 | 298 | * @throws ParseException |
be6df2d8 AM |
299 | * If there was a problem reading the event or adding it to the |
300 | * stream | |
866e5b51 | 301 | */ |
8e964be1 | 302 | public void addEvent(IEventDeclaration event) throws ParseException { |
5f715709 | 303 | if (fEventUnsetId) { |
6c7592e1 | 304 | throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$ |
866e5b51 | 305 | } |
5f715709 | 306 | int id = ((EventDeclaration) event).id(); |
866e5b51 FC |
307 | |
308 | /* | |
309 | * If there is an event without id (the null key), it must be the only | |
310 | * one | |
311 | */ | |
5f715709 MK |
312 | if (id == EventDeclaration.UNSET_EVENT_ID) { |
313 | if (!fEvents.isEmpty()) { | |
314 | throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$ | |
315 | } | |
316 | fEventUnsetId = true; | |
317 | fEvents.add(event); | |
318 | } else { | |
319 | /* Check if an event with the same ID already exists */ | |
320 | if (fEvents.size() > id && fEvents.get(id) != null) { | |
321 | throw new ParseException("Event id already exists"); //$NON-NLS-1$ | |
322 | } | |
323 | ensureSize(fEvents, id); | |
324 | /* Put the event in the list */ | |
325 | fEvents.set(id, event); | |
866e5b51 | 326 | } |
5f715709 | 327 | } |
866e5b51 | 328 | |
5f715709 MK |
329 | /** |
330 | * Add a list of event declarations to this stream. There must be no overlap | |
331 | * between the two lists of event declarations. This will merge the two | |
332 | * lists and preserve the indexes of both lists. | |
333 | * | |
334 | * @param events | |
335 | * list of the events to add | |
336 | * @throws CTFReaderException | |
337 | * if the list already contains data | |
a465519a | 338 | * @since 3.2 |
5f715709 MK |
339 | */ |
340 | public void addEvents(Collection<IEventDeclaration> events) throws CTFReaderException { | |
341 | if (fEventUnsetId) { | |
342 | throw new CTFReaderException("Cannot add to a stream with an unidentified event"); //$NON-NLS-1$ | |
866e5b51 | 343 | } |
5f715709 MK |
344 | if (fEvents.isEmpty()) { |
345 | fEvents.addAll(events); | |
346 | return; | |
347 | } | |
348 | for (IEventDeclaration event : events) { | |
349 | if (event != null) { | |
350 | int index = event.getId().intValue(); | |
351 | ensureSize(fEvents, index); | |
352 | if (fEvents.get(index) != null) { | |
353 | throw new CTFReaderException("Both lists have an event defined at position " + index); //$NON-NLS-1$ | |
354 | } | |
355 | fEvents.set(index, event); | |
356 | } | |
357 | } | |
358 | } | |
359 | ||
360 | private static void ensureSize(ArrayList<? extends Object> list, int index) { | |
361 | list.ensureCapacity(index); | |
362 | while (list.size() <= index) { | |
363 | list.add(null); | |
b73145e2 | 364 | } |
866e5b51 FC |
365 | } |
366 | ||
367 | /** | |
368 | * Add an input to this Stream | |
369 | * | |
370 | * @param input | |
371 | * The StreamInput to add. | |
372 | */ | |
d84419e1 | 373 | public void addInput(CTFStreamInput input) { |
2ab0ccec | 374 | fInputs.add(input); |
866e5b51 FC |
375 | } |
376 | ||
866e5b51 FC |
377 | @Override |
378 | public String toString() { | |
2ab0ccec MK |
379 | return "Stream [id=" + fId + ", packetContextDecl=" + fPacketContextDecl //$NON-NLS-1$ //$NON-NLS-2$ |
380 | + ", eventHeaderDecl=" + fEventHeaderDecl //$NON-NLS-1$ | |
381 | + ", eventContextDecl=" + fEventContextDecl + ", trace=" + fTrace //$NON-NLS-1$ //$NON-NLS-2$ | |
382 | + ", events=" + fEvents + ", inputs=" + fInputs + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
866e5b51 FC |
383 | } |
384 | } |