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