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; | |
17 | import java.util.Collections; | |
866e5b51 | 18 | import java.util.HashSet; |
5f715709 | 19 | import java.util.List; |
866e5b51 FC |
20 | import java.util.Set; |
21 | ||
5f715709 MK |
22 | import org.eclipse.jdt.annotation.NonNull; |
23 | import org.eclipse.jdt.annotation.Nullable; | |
680f9173 | 24 | import org.eclipse.tracecompass.ctf.core.CTFException; |
f357bcd4 AM |
25 | import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration; |
26 | import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration; | |
27 | import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration; | |
28 | import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration; | |
29 | import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration; | |
30 | import org.eclipse.tracecompass.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. | |
36 | */ | |
d84419e1 | 37 | public class CTFStream { |
866e5b51 FC |
38 | |
39 | // ------------------------------------------------------------------------ | |
40 | // Attributes | |
41 | // ------------------------------------------------------------------------ | |
42 | ||
866e5b51 FC |
43 | /** |
44 | * The numerical ID of the stream | |
45 | */ | |
2ab0ccec | 46 | private Long fId = null; |
866e5b51 FC |
47 | |
48 | /** | |
49 | * Declarations of the stream-specific structures | |
50 | */ | |
2ab0ccec | 51 | private StructDeclaration fPacketContextDecl = null; |
6c7592e1 | 52 | private IDeclaration fEventHeaderDecl = null; |
2ab0ccec | 53 | private StructDeclaration fEventContextDecl = null; |
866e5b51 FC |
54 | |
55 | /** | |
56 | * The trace to which the stream belongs | |
57 | */ | |
2ab0ccec | 58 | private CTFTrace fTrace = null; |
866e5b51 FC |
59 | |
60 | /** | |
61 | * Maps event ids to events | |
62 | */ | |
5f715709 MK |
63 | private final ArrayList<IEventDeclaration> fEvents = new ArrayList<>(); |
64 | ||
65 | private boolean fEventUnsetId = 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; |
866e5b51 FC |
98 | } |
99 | ||
9ac2eb62 MK |
100 | /** |
101 | * Gets the id of a stream | |
6c7592e1 | 102 | * |
9ac2eb62 MK |
103 | * @return id the id of a stream |
104 | */ | |
866e5b51 | 105 | public Long getId() { |
2ab0ccec | 106 | return fId; |
866e5b51 FC |
107 | } |
108 | ||
9ac2eb62 MK |
109 | /** |
110 | * Is the id of a stream set | |
be6df2d8 AM |
111 | * |
112 | * @return If the ID is set or not | |
9ac2eb62 MK |
113 | */ |
114 | public boolean isIdSet() { | |
2ab0ccec | 115 | return fId != null; |
866e5b51 FC |
116 | } |
117 | ||
9ac2eb62 MK |
118 | /** |
119 | * | |
120 | * @return is the event header set (timestamp and stuff) (see Ctf Spec) | |
121 | */ | |
122 | public boolean isEventHeaderSet() { | |
2ab0ccec | 123 | return fEventHeaderDecl != null; |
866e5b51 FC |
124 | } |
125 | ||
9ac2eb62 | 126 | /** |
6c7592e1 MK |
127 | * |
128 | * @return is the event context set (pid and stuff) (see Ctf Spec) | |
129 | */ | |
9ac2eb62 | 130 | public boolean isEventContextSet() { |
2ab0ccec | 131 | return fEventContextDecl != null; |
866e5b51 FC |
132 | } |
133 | ||
9ac2eb62 MK |
134 | /** |
135 | * | |
136 | * @return Is the packet context set (see Ctf Spec) | |
137 | */ | |
138 | public boolean isPacketContextSet() { | |
2ab0ccec | 139 | return fPacketContextDecl != null; |
866e5b51 FC |
140 | } |
141 | ||
9ac2eb62 | 142 | /** |
6c7592e1 | 143 | * Sets the event header |
9ac2eb62 | 144 | * |
6c7592e1 MK |
145 | * @param eventHeader |
146 | * the current event header for all events in this stream | |
9ac2eb62 | 147 | */ |
866e5b51 | 148 | public void setEventHeader(StructDeclaration eventHeader) { |
2ab0ccec | 149 | fEventHeaderDecl = eventHeader; |
866e5b51 FC |
150 | } |
151 | ||
9ac2eb62 | 152 | /** |
6c7592e1 | 153 | * Sets the event header, this typically has the id and the timestamp |
9ac2eb62 | 154 | * |
6c7592e1 MK |
155 | * @param eventHeader |
156 | * the current event header for all events in this stream | |
6c7592e1 MK |
157 | */ |
158 | public void setEventHeader(IEventHeaderDeclaration eventHeader) { | |
159 | fEventHeaderDecl = eventHeader; | |
160 | } | |
161 | ||
162 | /** | |
163 | * | |
164 | * @param eventContext | |
165 | * the context for all events in this stream | |
9ac2eb62 | 166 | */ |
866e5b51 | 167 | public void setEventContext(StructDeclaration eventContext) { |
2ab0ccec | 168 | fEventContextDecl = eventContext; |
866e5b51 FC |
169 | } |
170 | ||
9ac2eb62 MK |
171 | /** |
172 | * | |
6c7592e1 MK |
173 | * @param packetContext |
174 | * the packet context for all packets in this stream | |
9ac2eb62 | 175 | */ |
866e5b51 | 176 | public void setPacketContext(StructDeclaration packetContext) { |
2ab0ccec | 177 | fPacketContextDecl = packetContext; |
866e5b51 FC |
178 | } |
179 | ||
6c7592e1 MK |
180 | /** |
181 | * Gets the event header declaration | |
182 | * | |
183 | * @return the event header declaration in declaration form | |
6c7592e1 MK |
184 | */ |
185 | public IDeclaration getEventHeaderDeclaration() { | |
2ab0ccec | 186 | return fEventHeaderDecl; |
866e5b51 FC |
187 | } |
188 | ||
9ac2eb62 MK |
189 | /** |
190 | * | |
191 | * @return the event context declaration in structdeclaration form | |
192 | */ | |
866e5b51 | 193 | public StructDeclaration getEventContextDecl() { |
2ab0ccec | 194 | return fEventContextDecl; |
866e5b51 FC |
195 | } |
196 | ||
9ac2eb62 MK |
197 | /** |
198 | * | |
199 | * @return the packet context declaration in structdeclaration form | |
200 | */ | |
866e5b51 | 201 | public StructDeclaration getPacketContextDecl() { |
2ab0ccec | 202 | return fPacketContextDecl; |
866e5b51 FC |
203 | } |
204 | ||
9ac2eb62 MK |
205 | /** |
206 | * | |
207 | * @return the set of all stream inputs for this stream | |
208 | */ | |
d84419e1 | 209 | public Set<CTFStreamInput> getStreamInputs() { |
2ab0ccec | 210 | return fInputs; |
866e5b51 FC |
211 | } |
212 | ||
9ac2eb62 MK |
213 | /** |
214 | * | |
215 | * @return the parent trace | |
216 | */ | |
866e5b51 | 217 | public CTFTrace getTrace() { |
2ab0ccec | 218 | return fTrace; |
866e5b51 FC |
219 | } |
220 | ||
5f715709 MK |
221 | /** |
222 | * Get all the event declarations in this stream. | |
223 | * | |
224 | * @return The event declarations for this stream | |
5f715709 MK |
225 | */ |
226 | public @NonNull Collection<IEventDeclaration> getEventDeclarations() { | |
227 | List<IEventDeclaration> retVal = new ArrayList<>(fEvents); | |
228 | retVal.removeAll(Collections.<IEventDeclaration> singletonList(null)); | |
229 | return retVal; | |
230 | } | |
231 | ||
232 | /** | |
233 | * Get the event declaration for a given ID. | |
234 | * | |
235 | * @param eventId | |
236 | * The ID, can be {@link EventDeclaration#UNSET_EVENT_ID}, or any | |
237 | * positive value | |
238 | * @return The event declaration with the given ID for this stream, or | |
239 | * 'null' if there are no declaration with this ID | |
240 | * @throws IllegalArgumentException | |
241 | * If the passed ID is invalid | |
5f715709 MK |
242 | */ |
243 | public @Nullable IEventDeclaration getEventDeclaration(int eventId) { | |
244 | int eventIndex = (eventId == EventDeclaration.UNSET_EVENT_ID) ? 0 : eventId; | |
245 | if (eventIndex < 0) { | |
246 | /* Any negative value other than UNSET_EVENT_ID is invalid */ | |
247 | throw new IllegalArgumentException("Event ID cannot be negative."); //$NON-NLS-1$ | |
248 | } | |
249 | if (eventIndex >= fEvents.size()) { | |
250 | /* This ID could be valid, but there are no declarations with it */ | |
251 | return null; | |
252 | } | |
253 | return fEvents.get(eventIndex); | |
866e5b51 FC |
254 | } |
255 | ||
256 | // ------------------------------------------------------------------------ | |
257 | // Operations | |
258 | // ------------------------------------------------------------------------ | |
259 | ||
260 | /** | |
5f715709 | 261 | * Adds an event to the event list. |
866e5b51 FC |
262 | * |
263 | * An event in a stream can omit its id if it is the only event in this | |
264 | * stream. An event for which no id has been specified has a null id. It is | |
265 | * thus not possible to add an event with the null key if the map is not | |
266 | * empty. It is also not possible to add an event to the map if the null key | |
267 | * is present in the map. | |
268 | * | |
269 | * @param event | |
be6df2d8 | 270 | * The event to add |
866e5b51 | 271 | * @throws ParseException |
be6df2d8 AM |
272 | * If there was a problem reading the event or adding it to the |
273 | * stream | |
866e5b51 | 274 | */ |
8e964be1 | 275 | public void addEvent(IEventDeclaration event) throws ParseException { |
5f715709 | 276 | if (fEventUnsetId) { |
6c7592e1 | 277 | throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$ |
866e5b51 | 278 | } |
5f715709 | 279 | int id = ((EventDeclaration) event).id(); |
866e5b51 FC |
280 | |
281 | /* | |
282 | * If there is an event without id (the null key), it must be the only | |
283 | * one | |
284 | */ | |
5f715709 MK |
285 | if (id == EventDeclaration.UNSET_EVENT_ID) { |
286 | if (!fEvents.isEmpty()) { | |
287 | throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$ | |
288 | } | |
289 | fEventUnsetId = true; | |
290 | fEvents.add(event); | |
291 | } else { | |
292 | /* Check if an event with the same ID already exists */ | |
293 | if (fEvents.size() > id && fEvents.get(id) != null) { | |
294 | throw new ParseException("Event id already exists"); //$NON-NLS-1$ | |
295 | } | |
296 | ensureSize(fEvents, id); | |
297 | /* Put the event in the list */ | |
298 | fEvents.set(id, event); | |
866e5b51 | 299 | } |
5f715709 | 300 | } |
866e5b51 | 301 | |
5f715709 MK |
302 | /** |
303 | * Add a list of event declarations to this stream. There must be no overlap | |
304 | * between the two lists of event declarations. This will merge the two | |
305 | * lists and preserve the indexes of both lists. | |
306 | * | |
307 | * @param events | |
308 | * list of the events to add | |
680f9173 | 309 | * @throws CTFException |
5f715709 | 310 | * if the list already contains data |
5f715709 | 311 | */ |
680f9173 | 312 | public void addEvents(Collection<IEventDeclaration> events) throws CTFException { |
5f715709 | 313 | if (fEventUnsetId) { |
680f9173 | 314 | throw new CTFException("Cannot add to a stream with an unidentified event"); //$NON-NLS-1$ |
866e5b51 | 315 | } |
5f715709 MK |
316 | if (fEvents.isEmpty()) { |
317 | fEvents.addAll(events); | |
318 | return; | |
319 | } | |
320 | for (IEventDeclaration event : events) { | |
321 | if (event != null) { | |
322 | int index = event.getId().intValue(); | |
323 | ensureSize(fEvents, index); | |
324 | if (fEvents.get(index) != null) { | |
680f9173 | 325 | throw new CTFException("Both lists have an event defined at position " + index); //$NON-NLS-1$ |
5f715709 MK |
326 | } |
327 | fEvents.set(index, event); | |
328 | } | |
329 | } | |
330 | } | |
331 | ||
332 | private static void ensureSize(ArrayList<? extends Object> list, int index) { | |
333 | list.ensureCapacity(index); | |
334 | while (list.size() <= index) { | |
335 | list.add(null); | |
b73145e2 | 336 | } |
866e5b51 FC |
337 | } |
338 | ||
339 | /** | |
340 | * Add an input to this Stream | |
341 | * | |
342 | * @param input | |
343 | * The StreamInput to add. | |
344 | */ | |
d84419e1 | 345 | public void addInput(CTFStreamInput input) { |
2ab0ccec | 346 | fInputs.add(input); |
866e5b51 FC |
347 | } |
348 | ||
866e5b51 FC |
349 | @Override |
350 | public String toString() { | |
2ab0ccec MK |
351 | return "Stream [id=" + fId + ", packetContextDecl=" + fPacketContextDecl //$NON-NLS-1$ //$NON-NLS-2$ |
352 | + ", eventHeaderDecl=" + fEventHeaderDecl //$NON-NLS-1$ | |
353 | + ", eventContextDecl=" + fEventContextDecl + ", trace=" + fTrace //$NON-NLS-1$ //$NON-NLS-2$ | |
354 | + ", events=" + fEvents + ", inputs=" + fInputs + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
866e5b51 FC |
355 | } |
356 | } |