3172b9daa219862dc9553c5abe5af7d0f952d887
[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 }
131
132 private static long calculateTimestamp(@Nullable ICompositeDefinition eventHeaderDef, long prevTimestamp, StructDefinition eventPayload, StructDefinition eventContext) throws CTFIOException {
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);
138 def = eventHeaderDefinition;
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 }
148 if (def == null && eventContext != null) {
149 def = eventContext.lookupDefinition(CTFStrings.TIMESTAMP);
150 }
151 if (def instanceof IntegerDefinition) {
152 IntegerDefinition timestampDef = (IntegerDefinition) def;
153 timestamp = calculateTimestamp(timestampDef, prevTimestamp);
154 }
155 return timestamp;
156 }
157
158 @Override
159 public EventDefinition createDefinition(CTFStreamInputReader streamInputReader, @NonNull BitBuffer input, long timestamp) throws CTFException {
160 StructDeclaration streamEventContextDecl = streamInputReader.getStreamEventContextDecl();
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;
164 ICompositeDefinition packetContext = streamInputReader.getCurrentPacketReader().getCurrentPacketEventHeader();
165 StructDefinition eventContext = fContext != null ? fContext.createDefinition(trace, ILexicalScope.CONTEXT, input) : null;
166 StructDefinition eventPayload = fFields != null ? fFields.createDefinition(trace, ILexicalScope.FIELDS, input) : null;
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,
173 streamInputReader.getCPU(),
174 timestamp,
175 null,
176 streamEventContext,
177 eventContext,
178 packetContext,
179 eventPayload);
180 }
181
182 // ------------------------------------------------------------------------
183 // Getters/Setters/Predicates
184 // ------------------------------------------------------------------------
185
186 /**
187 * Sets a name for an event Declaration
188 *
189 * @param name
190 * the name
191 */
192 public void setName(String name) {
193 fName = name;
194 }
195
196 @Override
197 public String getName() {
198 return fName;
199 }
200
201 /**
202 * Sets the context for an event declaration (see CTF specification)
203 *
204 * @param context
205 * the context in structdeclaration format
206 */
207 public void setContext(StructDeclaration context) {
208 fContext = context;
209 }
210
211 /**
212 * Sets the fields of an event declaration
213 *
214 * @param fields
215 * the fields in structdeclaration format
216 */
217 public void setFields(StructDeclaration fields) {
218 fFields = fields;
219 }
220
221 @Override
222 public StructDeclaration getFields() {
223 return fFields;
224 }
225
226 @Override
227 public StructDeclaration getContext() {
228 return fContext;
229 }
230
231 /**
232 * Sets the id of an event declaration
233 *
234 * @param id
235 * the id
236 */
237 public void setId(long id) {
238 if (id < 0 || id > Integer.MAX_VALUE) {
239 throw new IllegalArgumentException("id out of range"); //$NON-NLS-1$
240 }
241 fId = (int) id;
242 }
243
244 @Override
245 public Long getId() {
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() {
255 return fId;
256 }
257
258 /**
259 * Sets the stream of an event declaration
260 *
261 * @param stream
262 * the stream
263 */
264 public void setStream(CTFStream stream) {
265 fStream = stream;
266 }
267
268 @Override
269 public CTFStream getStream() {
270 return fStream;
271 }
272
273 /**
274 * Is the name of the event declaration set
275 *
276 * @return is the name set?
277 */
278 public boolean nameIsSet() {
279 return fName != null;
280 }
281
282 /**
283 * Is the context set
284 *
285 * @return is the context set
286 */
287 public boolean contextIsSet() {
288 return fContext != null;
289 }
290
291 /**
292 * Is a field set?
293 *
294 * @return Is the field set?
295 */
296 public boolean fieldsIsSet() {
297 return fFields != null;
298 }
299
300 /**
301 * Is the id set?
302 *
303 * @return is the id set?
304 */
305 public boolean idIsSet() {
306 return (fId != UNSET_EVENT_ID);
307 }
308
309 /**
310 * Is the stream set?
311 *
312 * @return is the stream set?
313 */
314 public boolean streamIsSet() {
315 return fStream != null;
316 }
317
318 @Override
319 public long getLogLevel() {
320 return fLogLevel;
321 }
322
323 /**
324 * Sets the log level
325 *
326 * @param level
327 * the log level
328 */
329 public void setLogLevel(long level) {
330 fLogLevel = level;
331 }
332
333 @Override
334 public Set<String> getCustomAttributes() {
335 return fCustomAttributes.keySet();
336 }
337
338 @Override
339 public String getCustomAttribute(String key) {
340 return fCustomAttributes.get(key);
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
350 */
351 public void setCustomAttribute(String key, String value) {
352 fCustomAttributes.put(key, value);
353 }
354
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
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;
421 if (fId != (other.fId)) {
422 return false;
423 }
424 if (!NonNullUtils.equalsNullable(fContext, other.fContext)) {
425 return false;
426 }
427 if (!NonNullUtils.equalsNullable(fFields, other.fFields)) {
428 return false;
429 }
430 if (!NonNullUtils.equalsNullable(fName, other.fName)) {
431 return false;
432 }
433 if (!NonNullUtils.equalsNullable(fStream, other.fStream)) {
434 return false;
435 }
436 if (!fCustomAttributes.equals(other.fCustomAttributes)) {
437 return false;
438 }
439 return true;
440 }
441
442 @Override
443 public int hashCode() {
444 final int prime = 31;
445 int result = 1;
446 result = (prime * result)
447 + ((fContext == null) ? 0 : fContext.hashCode());
448 result = (prime * result) + ((fFields == null) ? 0 : fFields.hashCode());
449 result = (prime * result) + fId;
450 result = (prime * result) + ((fName == null) ? 0 : fName.hashCode());
451 final CTFStream stream = fStream;
452 result = (prime * result) + ((stream == null) ? 0 : stream.hashCode());
453 result = (prime * result) + fCustomAttributes.hashCode();
454 return result;
455 }
456
457 }
This page took 0.045641 seconds and 4 git commands to generate.