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