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 | ||
f357bcd4 | 13 | package org.eclipse.tracecompass.ctf.core.trace; |
866e5b51 | 14 | |
5f715709 MK |
15 | import java.util.ArrayList; |
16 | import java.util.Collection; | |
866e5b51 | 17 | import java.util.HashSet; |
5f715709 | 18 | import java.util.List; |
866e5b51 FC |
19 | import java.util.Set; |
20 | ||
5f715709 MK |
21 | import org.eclipse.jdt.annotation.NonNull; |
22 | import org.eclipse.jdt.annotation.Nullable; | |
680f9173 | 23 | import org.eclipse.tracecompass.ctf.core.CTFException; |
f357bcd4 AM |
24 | import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration; |
25 | import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration; | |
26 | import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration; | |
27 | import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration; | |
28 | import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration; | |
29 | import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException; | |
866e5b51 FC |
30 | |
31 | /** | |
32 | * <b><u>Stream</u></b> | |
33 | * <p> | |
34 | * Represents a stream in a trace. | |
35 | */ | |
d84419e1 | 36 | public class CTFStream { |
866e5b51 FC |
37 | |
38 | // ------------------------------------------------------------------------ | |
39 | // Attributes | |
40 | // ------------------------------------------------------------------------ | |
41 | ||
866e5b51 FC |
42 | /** |
43 | * The numerical ID of the stream | |
44 | */ | |
994e0846 | 45 | private long fId = 0; |
866e5b51 FC |
46 | |
47 | /** | |
48 | * Declarations of the stream-specific structures | |
49 | */ | |
2ab0ccec | 50 | private StructDeclaration fPacketContextDecl = null; |
6c7592e1 | 51 | private IDeclaration fEventHeaderDecl = null; |
2ab0ccec | 52 | private StructDeclaration fEventContextDecl = null; |
866e5b51 FC |
53 | |
54 | /** | |
55 | * The trace to which the stream belongs | |
56 | */ | |
2ab0ccec | 57 | private CTFTrace fTrace = null; |
866e5b51 FC |
58 | |
59 | /** | |
60 | * Maps event ids to events | |
61 | */ | |
4c4e2816 | 62 | private final ArrayList<@Nullable IEventDeclaration> fEvents = new ArrayList<>(); |
5f715709 MK |
63 | |
64 | private boolean fEventUnsetId = false; | |
994e0846 | 65 | private boolean fStreamIdSet = false; |
866e5b51 FC |
66 | |
67 | /** | |
68 | * The inputs associated to this stream | |
69 | */ | |
d84419e1 | 70 | private final Set<CTFStreamInput> fInputs = new HashSet<>(); |
866e5b51 FC |
71 | |
72 | // ------------------------------------------------------------------------ | |
73 | // Constructors | |
74 | // ------------------------------------------------------------------------ | |
75 | ||
76 | /** | |
77 | * Constructs a Stream that belongs to a Trace | |
78 | * | |
79 | * @param trace | |
80 | * The trace to which belongs this stream. | |
81 | */ | |
d84419e1 | 82 | public CTFStream(CTFTrace trace) { |
2ab0ccec | 83 | fTrace = trace; |
866e5b51 FC |
84 | } |
85 | ||
86 | // ------------------------------------------------------------------------ | |
87 | // Getters/Setters/Predicates | |
88 | // ------------------------------------------------------------------------ | |
89 | ||
9ac2eb62 MK |
90 | /** |
91 | * Sets the id of a stream | |
6c7592e1 MK |
92 | * |
93 | * @param id | |
94 | * the id of a stream | |
9ac2eb62 | 95 | */ |
866e5b51 | 96 | public void setId(long id) { |
2ab0ccec | 97 | fId = id; |
994e0846 | 98 | fStreamIdSet = true; |
866e5b51 FC |
99 | } |
100 | ||
9ac2eb62 MK |
101 | /** |
102 | * Gets the id of a stream | |
6c7592e1 | 103 | * |
9ac2eb62 | 104 | * @return id the id of a stream |
994e0846 | 105 | * @since 1.0 |
9ac2eb62 | 106 | */ |
994e0846 | 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() { | |
994e0846 | 117 | return fStreamIdSet; |
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 | |
6c7592e1 MK |
159 | */ |
160 | public void setEventHeader(IEventHeaderDeclaration eventHeader) { | |
161 | fEventHeaderDecl = eventHeader; | |
162 | } | |
163 | ||
164 | /** | |
165 | * | |
166 | * @param eventContext | |
167 | * the context for all events in this stream | |
9ac2eb62 | 168 | */ |
866e5b51 | 169 | public void setEventContext(StructDeclaration eventContext) { |
2ab0ccec | 170 | fEventContextDecl = eventContext; |
866e5b51 FC |
171 | } |
172 | ||
9ac2eb62 MK |
173 | /** |
174 | * | |
6c7592e1 MK |
175 | * @param packetContext |
176 | * the packet context for all packets in this stream | |
9ac2eb62 | 177 | */ |
866e5b51 | 178 | public void setPacketContext(StructDeclaration packetContext) { |
2ab0ccec | 179 | fPacketContextDecl = packetContext; |
866e5b51 FC |
180 | } |
181 | ||
6c7592e1 MK |
182 | /** |
183 | * Gets the event header declaration | |
184 | * | |
185 | * @return the event header declaration in declaration form | |
6c7592e1 MK |
186 | */ |
187 | public IDeclaration getEventHeaderDeclaration() { | |
2ab0ccec | 188 | return fEventHeaderDecl; |
866e5b51 FC |
189 | } |
190 | ||
9ac2eb62 MK |
191 | /** |
192 | * | |
193 | * @return the event context declaration in structdeclaration form | |
194 | */ | |
866e5b51 | 195 | public StructDeclaration getEventContextDecl() { |
2ab0ccec | 196 | return fEventContextDecl; |
866e5b51 FC |
197 | } |
198 | ||
9ac2eb62 MK |
199 | /** |
200 | * | |
201 | * @return the packet context declaration in structdeclaration form | |
202 | */ | |
866e5b51 | 203 | public StructDeclaration getPacketContextDecl() { |
2ab0ccec | 204 | return fPacketContextDecl; |
866e5b51 FC |
205 | } |
206 | ||
9ac2eb62 MK |
207 | /** |
208 | * | |
209 | * @return the set of all stream inputs for this stream | |
210 | */ | |
d84419e1 | 211 | public Set<CTFStreamInput> getStreamInputs() { |
2ab0ccec | 212 | return fInputs; |
866e5b51 FC |
213 | } |
214 | ||
9ac2eb62 MK |
215 | /** |
216 | * | |
217 | * @return the parent trace | |
218 | */ | |
866e5b51 | 219 | public CTFTrace getTrace() { |
2ab0ccec | 220 | return fTrace; |
866e5b51 FC |
221 | } |
222 | ||
5f715709 MK |
223 | /** |
224 | * Get all the event declarations in this stream. | |
225 | * | |
226 | * @return The event declarations for this stream | |
5f715709 | 227 | */ |
df2597e0 AM |
228 | public @NonNull Collection<@NonNull IEventDeclaration> getEventDeclarations() { |
229 | List<@NonNull IEventDeclaration> retVal = new ArrayList<>(); | |
230 | for (IEventDeclaration eventDeclaration : fEvents) { | |
231 | if (eventDeclaration != null) { | |
232 | retVal.add(eventDeclaration); | |
233 | } | |
234 | } | |
5f715709 MK |
235 | return retVal; |
236 | } | |
237 | ||
238 | /** | |
239 | * Get the event declaration for a given ID. | |
240 | * | |
241 | * @param eventId | |
242 | * The ID, can be {@link EventDeclaration#UNSET_EVENT_ID}, or any | |
243 | * positive value | |
244 | * @return The event declaration with the given ID for this stream, or | |
245 | * 'null' if there are no declaration with this ID | |
246 | * @throws IllegalArgumentException | |
247 | * If the passed ID is invalid | |
5f715709 MK |
248 | */ |
249 | public @Nullable IEventDeclaration getEventDeclaration(int eventId) { | |
a433ce7d | 250 | int eventIndex = (eventId == IEventDeclaration.UNSET_EVENT_ID) ? 0 : eventId; |
5f715709 MK |
251 | if (eventIndex < 0) { |
252 | /* Any negative value other than UNSET_EVENT_ID is invalid */ | |
253 | throw new IllegalArgumentException("Event ID cannot be negative."); //$NON-NLS-1$ | |
254 | } | |
255 | if (eventIndex >= fEvents.size()) { | |
256 | /* This ID could be valid, but there are no declarations with it */ | |
257 | return null; | |
258 | } | |
259 | return fEvents.get(eventIndex); | |
866e5b51 FC |
260 | } |
261 | ||
262 | // ------------------------------------------------------------------------ | |
263 | // Operations | |
264 | // ------------------------------------------------------------------------ | |
265 | ||
266 | /** | |
5f715709 | 267 | * Adds an event to the event list. |
866e5b51 FC |
268 | * |
269 | * An event in a stream can omit its id if it is the only event in this | |
270 | * stream. An event for which no id has been specified has a null id. It is | |
271 | * thus not possible to add an event with the null key if the map is not | |
272 | * empty. It is also not possible to add an event to the map if the null key | |
273 | * is present in the map. | |
274 | * | |
275 | * @param event | |
be6df2d8 | 276 | * The event to add |
866e5b51 | 277 | * @throws ParseException |
be6df2d8 AM |
278 | * If there was a problem reading the event or adding it to the |
279 | * stream | |
866e5b51 | 280 | */ |
8e964be1 | 281 | public void addEvent(IEventDeclaration event) throws ParseException { |
5f715709 | 282 | if (fEventUnsetId) { |
6c7592e1 | 283 | throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$ |
866e5b51 | 284 | } |
5f715709 | 285 | int id = ((EventDeclaration) event).id(); |
866e5b51 FC |
286 | |
287 | /* | |
288 | * If there is an event without id (the null key), it must be the only | |
289 | * one | |
290 | */ | |
a433ce7d | 291 | if (id == IEventDeclaration.UNSET_EVENT_ID) { |
5f715709 MK |
292 | if (!fEvents.isEmpty()) { |
293 | throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$ | |
294 | } | |
295 | fEventUnsetId = true; | |
296 | fEvents.add(event); | |
297 | } else { | |
298 | /* Check if an event with the same ID already exists */ | |
299 | if (fEvents.size() > id && fEvents.get(id) != null) { | |
300 | throw new ParseException("Event id already exists"); //$NON-NLS-1$ | |
301 | } | |
302 | ensureSize(fEvents, id); | |
303 | /* Put the event in the list */ | |
304 | fEvents.set(id, event); | |
866e5b51 | 305 | } |
5f715709 | 306 | } |
866e5b51 | 307 | |
5f715709 MK |
308 | /** |
309 | * Add a list of event declarations to this stream. There must be no overlap | |
310 | * between the two lists of event declarations. This will merge the two | |
311 | * lists and preserve the indexes of both lists. | |
312 | * | |
313 | * @param events | |
314 | * list of the events to add | |
680f9173 | 315 | * @throws CTFException |
5f715709 | 316 | * if the list already contains data |
5f715709 | 317 | */ |
680f9173 | 318 | public void addEvents(Collection<IEventDeclaration> events) throws CTFException { |
5f715709 | 319 | if (fEventUnsetId) { |
680f9173 | 320 | throw new CTFException("Cannot add to a stream with an unidentified event"); //$NON-NLS-1$ |
866e5b51 | 321 | } |
5f715709 MK |
322 | if (fEvents.isEmpty()) { |
323 | fEvents.addAll(events); | |
324 | return; | |
325 | } | |
326 | for (IEventDeclaration event : events) { | |
327 | if (event != null) { | |
328 | int index = event.getId().intValue(); | |
329 | ensureSize(fEvents, index); | |
330 | if (fEvents.get(index) != null) { | |
680f9173 | 331 | throw new CTFException("Both lists have an event defined at position " + index); //$NON-NLS-1$ |
5f715709 MK |
332 | } |
333 | fEvents.set(index, event); | |
334 | } | |
335 | } | |
336 | } | |
337 | ||
4c4e2816 | 338 | private static void ensureSize(ArrayList<@Nullable ? extends Object> list, int index) { |
5f715709 MK |
339 | list.ensureCapacity(index); |
340 | while (list.size() <= index) { | |
341 | list.add(null); | |
b73145e2 | 342 | } |
866e5b51 FC |
343 | } |
344 | ||
345 | /** | |
346 | * Add an input to this Stream | |
347 | * | |
348 | * @param input | |
349 | * The StreamInput to add. | |
350 | */ | |
d84419e1 | 351 | public void addInput(CTFStreamInput input) { |
2ab0ccec | 352 | fInputs.add(input); |
866e5b51 FC |
353 | } |
354 | ||
866e5b51 FC |
355 | @Override |
356 | public String toString() { | |
2ab0ccec MK |
357 | return "Stream [id=" + fId + ", packetContextDecl=" + fPacketContextDecl //$NON-NLS-1$ //$NON-NLS-2$ |
358 | + ", eventHeaderDecl=" + fEventHeaderDecl //$NON-NLS-1$ | |
359 | + ", eventContextDecl=" + fEventContextDecl + ", trace=" + fTrace //$NON-NLS-1$ //$NON-NLS-2$ | |
360 | + ", events=" + fEvents + ", inputs=" + fInputs + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
866e5b51 FC |
361 | } |
362 | } |