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