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