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