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.internal.ctf.core.event; |
866e5b51 | 14 | |
8e964be1 MK |
15 | import java.util.HashMap; |
16 | import java.util.Map; | |
17 | import java.util.Set; | |
18 | ||
a4fa4e36 | 19 | import org.eclipse.jdt.annotation.NonNull; |
5b341dc8 | 20 | import org.eclipse.jdt.annotation.Nullable; |
680f9173 | 21 | import org.eclipse.tracecompass.ctf.core.CTFException; |
5b341dc8 | 22 | import org.eclipse.tracecompass.ctf.core.CTFStrings; |
f357bcd4 AM |
23 | import org.eclipse.tracecompass.ctf.core.event.EventDefinition; |
24 | import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration; | |
25 | import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer; | |
fbe6fa6f | 26 | import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope; |
5b341dc8 | 27 | import org.eclipse.tracecompass.ctf.core.event.types.Definition; |
778bce67 | 28 | import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition; |
5b341dc8 | 29 | import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition; |
f357bcd4 AM |
30 | import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration; |
31 | import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition; | |
5b341dc8 | 32 | import org.eclipse.tracecompass.ctf.core.trace.CTFIOException; |
f357bcd4 AM |
33 | import org.eclipse.tracecompass.ctf.core.trace.CTFStream; |
34 | import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader; | |
5b341dc8 | 35 | import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition; |
866e5b51 FC |
36 | |
37 | /** | |
be6df2d8 AM |
38 | * Representation of one type of event. A bit like "int" or "long" but for trace |
39 | * events. | |
866e5b51 | 40 | */ |
8e964be1 | 41 | public class EventDeclaration implements IEventDeclaration { |
866e5b51 FC |
42 | |
43 | // ------------------------------------------------------------------------ | |
44 | // Attributes | |
45 | // ------------------------------------------------------------------------ | |
46 | ||
47 | /** | |
48 | * Name of the event | |
49 | */ | |
75259c16 | 50 | private String fName; |
866e5b51 FC |
51 | |
52 | /** | |
53 | * Event context structure declaration | |
54 | */ | |
75259c16 | 55 | private StructDeclaration fContext = null; |
866e5b51 FC |
56 | |
57 | /** | |
58 | * Event fields structure declaration | |
59 | */ | |
75259c16 | 60 | private StructDeclaration fFields = null; |
866e5b51 | 61 | |
866e5b51 FC |
62 | /** |
63 | * Stream to which belongs this event. | |
64 | */ | |
d84419e1 | 65 | private CTFStream fStream = null; |
866e5b51 | 66 | |
53047a66 MK |
67 | /** |
68 | * Loglevel of an event | |
69 | */ | |
75259c16 | 70 | private long fLogLevel; |
53047a66 | 71 | |
8e964be1 | 72 | /** Map of this event type's custom CTF attributes */ |
75259c16 | 73 | private final Map<String, String> fCustomAttributes = new HashMap<>(); |
8e964be1 | 74 | |
5f715709 MK |
75 | private int fId = (int) UNSET_EVENT_ID; |
76 | ||
866e5b51 FC |
77 | // ------------------------------------------------------------------------ |
78 | // Constructors | |
79 | // ------------------------------------------------------------------------ | |
80 | ||
be6df2d8 AM |
81 | /** |
82 | * Default constructor. Use the setters afterwards to set the fields | |
83 | * accordingly. | |
84 | */ | |
8e964be1 MK |
85 | public EventDeclaration() { |
86 | } | |
be6df2d8 | 87 | |
94c255ef MK |
88 | /** |
89 | * Creates an instance of EventDefinition corresponding to this declaration. | |
90 | * | |
91 | * @param streamInputReader | |
92 | * The StreamInputReader for which this definition is created. | |
93 | * @param eventHeaderDef | |
94 | * The event header definition | |
95 | * @param input | |
96 | * the bitbuffer input source | |
5b341dc8 | 97 | * @param prevTimestamp |
94c255ef MK |
98 | * The timestamp when the event was taken |
99 | * @return A new EventDefinition. | |
100 | * @throws CTFException | |
101 | * As a bitbuffer is used to read, it could have wrapped | |
102 | * IOExceptions. | |
103 | */ | |
5b341dc8 | 104 | public EventDefinition createDefinition(CTFStreamInputReader streamInputReader, ICompositeDefinition eventHeaderDef, @NonNull BitBuffer input, long prevTimestamp) throws CTFException { |
94c255ef MK |
105 | StructDeclaration streamEventContextDecl = streamInputReader.getStreamEventContextDecl(); |
106 | StructDefinition streamEventContext = streamEventContextDecl != null ? streamEventContextDecl.createDefinition(fStream.getTrace(), ILexicalScope.STREAM_EVENT_CONTEXT, input) : null; | |
107 | ICompositeDefinition packetContext = streamInputReader.getPacketReader().getCurrentPacketEventHeader(); | |
108 | StructDefinition eventContext = fContext != null ? fContext.createFieldDefinition(eventHeaderDef, fStream.getTrace(), ILexicalScope.CONTEXT, input) : null; | |
109 | StructDefinition eventPayload = fFields != null ? fFields.createFieldDefinition(eventHeaderDef, fStream.getTrace(), ILexicalScope.FIELDS, input) : null; | |
5b341dc8 | 110 | long timestamp = calculateTimestamp(eventHeaderDef, prevTimestamp, eventPayload); |
94c255ef | 111 | |
94c255ef MK |
112 | return new EventDefinition( |
113 | this, | |
114 | streamInputReader, | |
115 | timestamp, | |
116 | eventHeaderDef, | |
117 | streamEventContext, | |
118 | eventContext, | |
119 | packetContext, | |
120 | eventPayload); | |
121 | } | |
122 | ||
5b341dc8 MK |
123 | private static long calculateTimestamp(@Nullable ICompositeDefinition eventHeaderDef, long prevTimestamp, StructDefinition eventPayload) throws CTFIOException { |
124 | long timestamp = 0; | |
125 | Definition def = null; | |
126 | if (eventHeaderDef instanceof EventHeaderDefinition) { | |
127 | EventHeaderDefinition eventHeaderDefinition = (EventHeaderDefinition) eventHeaderDef; | |
128 | timestamp = calculateTimestamp(eventHeaderDefinition.getTimestamp(), eventHeaderDefinition.getTimestampLength(), prevTimestamp); | |
129 | } else if (eventHeaderDef instanceof StructDefinition) { | |
130 | StructDefinition structDefinition = (StructDefinition) eventHeaderDef; | |
131 | def = structDefinition.lookupDefinition(CTFStrings.TIMESTAMP); | |
132 | } else if (eventHeaderDef != null) { | |
133 | throw new CTFIOException("Event header def is not a Struct or an Event Header"); //$NON-NLS-1$ | |
134 | } | |
135 | if (def == null && eventPayload != null) { | |
136 | def = eventPayload.lookupDefinition(CTFStrings.TIMESTAMP); | |
137 | } | |
138 | if (def instanceof IntegerDefinition) { | |
139 | IntegerDefinition timestampDef = (IntegerDefinition) def; | |
140 | timestamp = calculateTimestamp(timestampDef, prevTimestamp); | |
141 | } | |
142 | return timestamp; | |
143 | } | |
144 | ||
8e964be1 | 145 | @Override |
680f9173 | 146 | public EventDefinition createDefinition(CTFStreamInputReader streamInputReader, @NonNull BitBuffer input, long timestamp) throws CTFException { |
a4fa4e36 | 147 | StructDeclaration streamEventContextDecl = streamInputReader.getStreamEventContextDecl(); |
fbe6fa6f | 148 | StructDefinition streamEventContext = streamEventContextDecl != null ? streamEventContextDecl.createDefinition(fStream.getTrace(), ILexicalScope.STREAM_EVENT_CONTEXT, input) : null; |
778bce67 | 149 | ICompositeDefinition packetContext = streamInputReader.getPacketReader().getCurrentPacketEventHeader(); |
fbe6fa6f MK |
150 | StructDefinition eventContext = fContext != null ? fContext.createDefinition(fStream.getTrace(), ILexicalScope.CONTEXT, input) : null; |
151 | StructDefinition eventPayload = fFields != null ? fFields.createDefinition(fStream.getTrace(), ILexicalScope.FIELDS, input) : null; | |
a4fa4e36 MK |
152 | |
153 | // a bit lttng specific | |
154 | // CTF doesn't require a timestamp, | |
155 | // but it's passed to us | |
156 | return new EventDefinition( | |
157 | this, | |
158 | streamInputReader, | |
159 | timestamp, | |
160 | streamEventContext, | |
161 | eventContext, | |
162 | packetContext, | |
163 | eventPayload); | |
866e5b51 FC |
164 | } |
165 | ||
166 | // ------------------------------------------------------------------------ | |
167 | // Getters/Setters/Predicates | |
168 | // ------------------------------------------------------------------------ | |
169 | ||
9ac2eb62 MK |
170 | /** |
171 | * Sets a name for an event Declaration | |
8e964be1 MK |
172 | * |
173 | * @param name | |
174 | * the name | |
9ac2eb62 | 175 | */ |
866e5b51 | 176 | public void setName(String name) { |
75259c16 | 177 | fName = name; |
866e5b51 FC |
178 | } |
179 | ||
8e964be1 | 180 | @Override |
866e5b51 | 181 | public String getName() { |
75259c16 | 182 | return fName; |
866e5b51 FC |
183 | } |
184 | ||
9ac2eb62 MK |
185 | /** |
186 | * Sets the context for an event declaration (see CTF specification) | |
8e964be1 MK |
187 | * |
188 | * @param context | |
189 | * the context in structdeclaration format | |
9ac2eb62 | 190 | */ |
866e5b51 | 191 | public void setContext(StructDeclaration context) { |
75259c16 | 192 | fContext = context; |
866e5b51 FC |
193 | } |
194 | ||
9ac2eb62 MK |
195 | /** |
196 | * Sets the fields of an event declaration | |
8e964be1 MK |
197 | * |
198 | * @param fields | |
199 | * the fields in structdeclaration format | |
9ac2eb62 | 200 | */ |
866e5b51 | 201 | public void setFields(StructDeclaration fields) { |
75259c16 | 202 | fFields = fields; |
866e5b51 FC |
203 | } |
204 | ||
8e964be1 | 205 | @Override |
866e5b51 | 206 | public StructDeclaration getFields() { |
75259c16 | 207 | return fFields; |
866e5b51 FC |
208 | } |
209 | ||
8e964be1 | 210 | @Override |
866e5b51 | 211 | public StructDeclaration getContext() { |
75259c16 | 212 | return fContext; |
866e5b51 FC |
213 | } |
214 | ||
9ac2eb62 | 215 | /** |
ecb12461 | 216 | * Sets the id of an event declaration |
8e964be1 MK |
217 | * |
218 | * @param id | |
219 | * the id | |
9ac2eb62 | 220 | */ |
866e5b51 | 221 | public void setId(long id) { |
5f715709 MK |
222 | if (id < 0 || id > Integer.MAX_VALUE) { |
223 | throw new IllegalArgumentException("id out of range"); //$NON-NLS-1$ | |
224 | } | |
225 | fId = (int) id; | |
866e5b51 FC |
226 | } |
227 | ||
8e964be1 | 228 | @Override |
866e5b51 | 229 | public Long getId() { |
5f715709 MK |
230 | return Long.valueOf(fId); |
231 | } | |
232 | ||
233 | /** | |
234 | * Faster get id assuming you have less than a billion event types | |
235 | * | |
236 | * @return the event id | |
237 | */ | |
238 | public int id() { | |
75259c16 | 239 | return fId; |
866e5b51 FC |
240 | } |
241 | ||
9ac2eb62 | 242 | /** |
ecb12461 | 243 | * Sets the stream of an event declaration |
8e964be1 MK |
244 | * |
245 | * @param stream | |
246 | * the stream | |
9ac2eb62 | 247 | */ |
d84419e1 | 248 | public void setStream(CTFStream stream) { |
75259c16 | 249 | fStream = stream; |
866e5b51 FC |
250 | } |
251 | ||
8e964be1 | 252 | @Override |
d84419e1 | 253 | public CTFStream getStream() { |
75259c16 | 254 | return fStream; |
866e5b51 FC |
255 | } |
256 | ||
9ac2eb62 MK |
257 | /** |
258 | * Is the name of the event declaration set | |
8e964be1 | 259 | * |
9ac2eb62 MK |
260 | * @return is the name set? |
261 | */ | |
866e5b51 | 262 | public boolean nameIsSet() { |
75259c16 | 263 | return fName != null; |
866e5b51 FC |
264 | } |
265 | ||
9ac2eb62 MK |
266 | /** |
267 | * Is the context set | |
8e964be1 | 268 | * |
9ac2eb62 MK |
269 | * @return is the context set |
270 | */ | |
866e5b51 | 271 | public boolean contextIsSet() { |
75259c16 | 272 | return fContext != null; |
866e5b51 FC |
273 | } |
274 | ||
9ac2eb62 MK |
275 | /** |
276 | * Is a field set? | |
8e964be1 | 277 | * |
9ac2eb62 MK |
278 | * @return Is the field set? |
279 | */ | |
866e5b51 | 280 | public boolean fieldsIsSet() { |
75259c16 | 281 | return fFields != null; |
866e5b51 FC |
282 | } |
283 | ||
9ac2eb62 MK |
284 | /** |
285 | * Is the id set? | |
8e964be1 | 286 | * |
9ac2eb62 MK |
287 | * @return is the id set? |
288 | */ | |
866e5b51 | 289 | public boolean idIsSet() { |
8e0c9d81 | 290 | return (fId != UNSET_EVENT_ID); |
866e5b51 FC |
291 | } |
292 | ||
9ac2eb62 MK |
293 | /** |
294 | * Is the stream set? | |
8e964be1 | 295 | * |
9ac2eb62 MK |
296 | * @return is the stream set? |
297 | */ | |
866e5b51 | 298 | public boolean streamIsSet() { |
75259c16 | 299 | return fStream != null; |
866e5b51 FC |
300 | } |
301 | ||
8e964be1 | 302 | @Override |
53047a66 | 303 | public long getLogLevel() { |
75259c16 | 304 | return fLogLevel; |
53047a66 MK |
305 | } |
306 | ||
9ac2eb62 MK |
307 | /** |
308 | * Sets the log level | |
8e964be1 MK |
309 | * |
310 | * @param level | |
311 | * the log level | |
9ac2eb62 | 312 | */ |
8e964be1 | 313 | public void setLogLevel(long level) { |
75259c16 | 314 | fLogLevel = level; |
53047a66 MK |
315 | } |
316 | ||
8e964be1 MK |
317 | @Override |
318 | public Set<String> getCustomAttributes() { | |
75259c16 | 319 | return fCustomAttributes.keySet(); |
8e964be1 MK |
320 | } |
321 | ||
322 | @Override | |
323 | public String getCustomAttribute(String key) { | |
75259c16 | 324 | return fCustomAttributes.get(key); |
8e964be1 MK |
325 | } |
326 | ||
327 | /** | |
328 | * Sets a custom attribute value. | |
329 | * | |
330 | * @param key | |
331 | * the key of the attribute | |
332 | * @param value | |
333 | * the value of the attribute | |
8e964be1 MK |
334 | */ |
335 | public void setCustomAttribute(String key, String value) { | |
75259c16 | 336 | fCustomAttributes.put(key, value); |
8e964be1 MK |
337 | } |
338 | ||
5b341dc8 MK |
339 | /** |
340 | * Calculates the timestamp value of the event, possibly using the timestamp | |
341 | * from the last event. | |
342 | * | |
343 | * @param timestampDef | |
344 | * Integer definition of the timestamp. | |
345 | * @return The calculated timestamp value. | |
346 | */ | |
347 | private static long calculateTimestamp(IntegerDefinition timestampDef, long lastTimestamp) { | |
348 | int len = timestampDef.getDeclaration().getLength(); | |
349 | final long value = timestampDef.getValue(); | |
350 | ||
351 | return calculateTimestamp(value, len, lastTimestamp); | |
352 | } | |
353 | ||
354 | private static long calculateTimestamp(final long value, int len, long prevTimestamp) { | |
355 | long newval; | |
356 | long majorasbitmask; | |
357 | long lastTimestamp = prevTimestamp; | |
358 | /* | |
359 | * If the timestamp length is 64 bits, it is a full timestamp. | |
360 | */ | |
361 | if (len == Long.SIZE) { | |
362 | lastTimestamp = value; | |
363 | return lastTimestamp; | |
364 | } | |
365 | ||
366 | /* | |
367 | * Bit mask to keep / remove all old / new bits. | |
368 | */ | |
369 | majorasbitmask = (1L << len) - 1; | |
370 | ||
371 | /* | |
372 | * If the new value is smaller than the corresponding bits of the last | |
373 | * timestamp, we assume an overflow of the compact representation. | |
374 | */ | |
375 | newval = value; | |
376 | if (newval < (lastTimestamp & majorasbitmask)) { | |
377 | newval = newval + (1L << len); | |
378 | } | |
379 | ||
380 | /* Keep only the high bits of the old value */ | |
381 | lastTimestamp = lastTimestamp & ~majorasbitmask; | |
382 | ||
383 | /* Then add the low bits of the new value */ | |
384 | lastTimestamp = lastTimestamp + newval; | |
385 | ||
386 | return lastTimestamp; | |
387 | } | |
388 | ||
866e5b51 FC |
389 | // ------------------------------------------------------------------------ |
390 | // Operations | |
391 | // ------------------------------------------------------------------------ | |
392 | ||
393 | @Override | |
394 | public boolean equals(Object obj) { | |
395 | if (this == obj) { | |
396 | return true; | |
397 | } | |
398 | if (obj == null) { | |
399 | return false; | |
400 | } | |
401 | if (!(obj instanceof EventDeclaration)) { | |
402 | return false; | |
403 | } | |
404 | EventDeclaration other = (EventDeclaration) obj; | |
75259c16 MK |
405 | if (fContext == null) { |
406 | if (other.fContext != null) { | |
866e5b51 FC |
407 | return false; |
408 | } | |
75259c16 | 409 | } else if (!fContext.equals(other.fContext)) { |
866e5b51 FC |
410 | return false; |
411 | } | |
75259c16 MK |
412 | if (fFields == null) { |
413 | if (other.fFields != null) { | |
866e5b51 FC |
414 | return false; |
415 | } | |
75259c16 | 416 | } else if (!fFields.equals(other.fFields)) { |
866e5b51 FC |
417 | return false; |
418 | } | |
5f715709 | 419 | if (fId != (other.fId)) { |
866e5b51 FC |
420 | return false; |
421 | } | |
75259c16 MK |
422 | if (fName == null) { |
423 | if (other.fName != null) { | |
866e5b51 FC |
424 | return false; |
425 | } | |
75259c16 | 426 | } else if (!fName.equals(other.fName)) { |
866e5b51 FC |
427 | return false; |
428 | } | |
75259c16 MK |
429 | if (fStream == null) { |
430 | if (other.fStream != null) { | |
866e5b51 FC |
431 | return false; |
432 | } | |
75259c16 | 433 | } else if (!fStream.equals(other.fStream)) { |
866e5b51 FC |
434 | return false; |
435 | } | |
75259c16 | 436 | if (!fCustomAttributes.equals(other.fCustomAttributes)) { |
8e964be1 MK |
437 | return false; |
438 | } | |
866e5b51 FC |
439 | return true; |
440 | } | |
441 | ||
442 | @Override | |
443 | public int hashCode() { | |
444 | final int prime = 31; | |
445 | int result = 1; | |
446 | result = (prime * result) | |
75259c16 MK |
447 | + ((fContext == null) ? 0 : fContext.hashCode()); |
448 | result = (prime * result) + ((fFields == null) ? 0 : fFields.hashCode()); | |
5f715709 | 449 | result = (prime * result) + fId; |
75259c16 MK |
450 | result = (prime * result) + ((fName == null) ? 0 : fName.hashCode()); |
451 | result = (prime * result) + ((fStream == null) ? 0 : fStream.hashCode()); | |
452 | result = (prime * result) + fCustomAttributes.hashCode(); | |
866e5b51 FC |
453 | return result; |
454 | } | |
455 | ||
456 | } |