~ubuntu-branches/ubuntu/vivid/eclipse-linuxtools/vivid-proposed

« back to all changes in this revision

Viewing changes to lttng/org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/StreamInputPacketReader.java

  • Committer: Package Import Robot
  • Author(s): Jakub Adam, Jakub Adam, tony mancill
  • Date: 2014-10-11 11:44:05 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20141011114405-yazjvxfzzhmi5sgj
Tags: 3.1.0-1
[ Jakub Adam ]
* New upstream release (Closes: #761524).
* Refreshed d/patches.
* Don't build removed feature org.eclipse.linuxtools.tools.launch
  - merged into org.eclipse.linuxtools.profiling.
* Use javac target 1.7.
* Build new feature org.eclipse.linuxtools.dataviewers.feature
  - required by Valgrind integration.
* Build-depend on eclipse-remote-services-api and eclipse-cdt-autotools.
* Bump Standards-Version to 3.9.6.
* Override incompatible-java-bytecode-format - linuxtools needs Java 7.
* Remove unused codeless-jar override.

[ tony mancill ]
* Tweak short package description to make lintian happy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*******************************************************************************
2
 
 * Copyright (c) 2011-2013 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
 
package org.eclipse.linuxtools.ctf.core.trace;
13
 
 
14
 
import java.io.IOException;
15
 
import java.nio.MappedByteBuffer;
16
 
import java.nio.channels.FileChannel.MapMode;
17
 
import java.util.Collection;
18
 
 
19
 
import org.eclipse.linuxtools.ctf.core.CTFStrings;
20
 
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
21
 
import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
22
 
import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
23
 
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
24
 
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
25
 
import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
26
 
import org.eclipse.linuxtools.ctf.core.event.types.SimpleDatatypeDefinition;
27
 
import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
28
 
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
29
 
import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
30
 
import org.eclipse.linuxtools.internal.ctf.core.event.EventDeclaration;
31
 
import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
32
 
 
33
 
/**
34
 
 * CTF trace packet reader. Reads the events of a packet of a trace file.
35
 
 *
36
 
 * @version 1.0
37
 
 * @author Matthew Khouzam
38
 
 * @author Simon Marchi
39
 
 */
40
 
public class StreamInputPacketReader implements IDefinitionScope {
41
 
 
42
 
    // ------------------------------------------------------------------------
43
 
    // Attributes
44
 
    // ------------------------------------------------------------------------
45
 
 
46
 
    /** BitBuffer used to read the trace file. */
47
 
    private final BitBuffer bitBuffer;
48
 
 
49
 
    /** StreamInputReader that uses this StreamInputPacketReader. */
50
 
    private final StreamInputReader streamInputReader;
51
 
 
52
 
    /** Trace packet header. */
53
 
    private final StructDefinition tracePacketHeaderDef;
54
 
 
55
 
    /** Stream packet context definition. */
56
 
    private final StructDefinition streamPacketContextDef;
57
 
 
58
 
    /** Stream event header definition. */
59
 
    private final StructDefinition streamEventHeaderDef;
60
 
 
61
 
    /** Stream event context definition. */
62
 
    private final StructDefinition streamEventContextDef;
63
 
 
64
 
    /** Reference to the index entry of the current packet. */
65
 
    private StreamInputPacketIndexEntry currentPacket = null;
66
 
 
67
 
    /**
68
 
     * Last timestamp recorded.
69
 
     *
70
 
     * Needed to calculate the complete timestamp values for the events with
71
 
     * compact headers.
72
 
     */
73
 
    private long lastTimestamp = 0;
74
 
 
75
 
    /** CPU id of current packet. */
76
 
    private int currentCpu = 0;
77
 
 
78
 
    private int lostEventsInThisPacket;
79
 
 
80
 
    private long lostEventsDuration;
81
 
 
82
 
    private boolean hasLost = false;
83
 
 
84
 
    // ------------------------------------------------------------------------
85
 
    // Constructors
86
 
    // ------------------------------------------------------------------------
87
 
 
88
 
    /**
89
 
     * Constructs a StreamInputPacketReader.
90
 
     *
91
 
     * @param streamInputReader
92
 
     *            The StreamInputReader to which this packet reader belongs to.
93
 
     */
94
 
    public StreamInputPacketReader(StreamInputReader streamInputReader) {
95
 
        this.streamInputReader = streamInputReader;
96
 
 
97
 
        /* Set the BitBuffer's byte order. */
98
 
        bitBuffer = new BitBuffer();
99
 
        bitBuffer.setByteOrder(streamInputReader.getByteOrder());
100
 
 
101
 
        /* Create trace packet header definition. */
102
 
        final Stream currentStream = streamInputReader.getStreamInput().getStream();
103
 
        StructDeclaration tracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
104
 
        if (tracePacketHeaderDecl != null) {
105
 
            tracePacketHeaderDef = tracePacketHeaderDecl.createDefinition(this, "trace.packet.header"); //$NON-NLS-1$
106
 
        } else {
107
 
            tracePacketHeaderDef = null;
108
 
        }
109
 
 
110
 
        /* Create stream packet context definition. */
111
 
        StructDeclaration streamPacketContextDecl = currentStream.getPacketContextDecl();
112
 
        if (streamPacketContextDecl != null) {
113
 
            streamPacketContextDef = streamPacketContextDecl.createDefinition(this, "stream.packet.context"); //$NON-NLS-1$
114
 
        } else {
115
 
            streamPacketContextDef = null;
116
 
        }
117
 
 
118
 
        /* Create stream event header definition. */
119
 
        StructDeclaration streamEventHeaderDecl = currentStream.getEventHeaderDecl();
120
 
        if (streamEventHeaderDecl != null) {
121
 
            streamEventHeaderDef = streamEventHeaderDecl.createDefinition(this, "stream.event.header"); //$NON-NLS-1$
122
 
        } else {
123
 
            streamEventHeaderDef = null;
124
 
        }
125
 
 
126
 
        /* Create stream event context definition. */
127
 
        StructDeclaration streamEventContextDecl = currentStream.getEventContextDecl();
128
 
        if (streamEventContextDecl != null) {
129
 
            streamEventContextDef = streamEventContextDecl.createDefinition(this, "stream.event.context"); //$NON-NLS-1$
130
 
        } else {
131
 
            streamEventContextDef = null;
132
 
        }
133
 
 
134
 
        /* Create event definitions */
135
 
        Collection<IEventDeclaration> eventDecls = streamInputReader.getStreamInput().getStream().getEvents().values();
136
 
 
137
 
        for (IEventDeclaration event : eventDecls) {
138
 
            if (!streamInputReader.getEventDefinitions().containsKey(event.getId())) {
139
 
                EventDefinition eventDef = event.createDefinition(streamInputReader);
140
 
                streamInputReader.addEventDefinition(event.getId(), eventDef);
141
 
            }
142
 
        }
143
 
    }
144
 
 
145
 
    /**
146
 
     * Dispose the StreamInputPacketReader
147
 
     *
148
 
     * @since 2.0
149
 
     */
150
 
    public void dispose() {
151
 
        bitBuffer.setByteBuffer(null);
152
 
    }
153
 
 
154
 
    // ------------------------------------------------------------------------
155
 
    // Getters/Setters/Predicates
156
 
    // ------------------------------------------------------------------------
157
 
 
158
 
    /**
159
 
     * Gets the current packet
160
 
     *
161
 
     * @return the current packet
162
 
     */
163
 
    StreamInputPacketIndexEntry getCurrentPacket() {
164
 
        return this.currentPacket;
165
 
    }
166
 
 
167
 
    /**
168
 
     * Gets the steamPacketContext Definition
169
 
     *
170
 
     * @return steamPacketContext Definition
171
 
     */
172
 
    public StructDefinition getStreamPacketContextDef() {
173
 
        return this.streamPacketContextDef;
174
 
    }
175
 
 
176
 
    /**
177
 
     * Gets the stream's event context definition.
178
 
     *
179
 
     * @return The streamEventContext definition
180
 
     */
181
 
    public StructDefinition getStreamEventContextDef() {
182
 
        return streamEventContextDef;
183
 
    }
184
 
 
185
 
    /**
186
 
     * Gets the CPU (core) number
187
 
     *
188
 
     * @return the CPU (core) number
189
 
     */
190
 
    public int getCPU() {
191
 
        return this.currentCpu;
192
 
    }
193
 
 
194
 
    @Override
195
 
    public String getPath() {
196
 
        return ""; //$NON-NLS-1$
197
 
    }
198
 
 
199
 
    // ------------------------------------------------------------------------
200
 
    // Operations
201
 
    // ------------------------------------------------------------------------
202
 
 
203
 
    /**
204
 
     * Changes the current packet to the given one.
205
 
     *
206
 
     * @param currentPacket
207
 
     *            The index entry of the packet to switch to.
208
 
     */
209
 
    void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) {
210
 
        StreamInputPacketIndexEntry prevPacket = null;
211
 
        this.currentPacket = currentPacket;
212
 
 
213
 
        if (this.currentPacket != null) {
214
 
            /*
215
 
             * Change the map of the BitBuffer.
216
 
             */
217
 
            MappedByteBuffer bb = null;
218
 
            try {
219
 
                bb = streamInputReader.getStreamInput().getFileChannel()
220
 
                        .map(MapMode.READ_ONLY,
221
 
                                this.currentPacket.getOffsetBytes(),
222
 
                                (this.currentPacket.getPacketSizeBits() + 7) / 8);
223
 
            } catch (IOException e) {
224
 
                /*
225
 
                 * The streamInputReader object is already allocated, so this
226
 
                 * shouldn't fail bar some very bad kernel or RAM errors...
227
 
                 */
228
 
                e.printStackTrace();
229
 
            }
230
 
 
231
 
            bitBuffer.setByteBuffer(bb);
232
 
 
233
 
            /*
234
 
             * Read trace packet header.
235
 
             */
236
 
            if (tracePacketHeaderDef != null) {
237
 
                tracePacketHeaderDef.read(bitBuffer);
238
 
            }
239
 
 
240
 
            /*
241
 
             * Read stream packet context.
242
 
             */
243
 
            if (getStreamPacketContextDef() != null) {
244
 
                getStreamPacketContextDef().read(bitBuffer);
245
 
 
246
 
                /* Read CPU ID */
247
 
                if (this.getCurrentPacket().getTarget() != null) {
248
 
                    this.currentCpu = (int) this.getCurrentPacket().getTargetId();
249
 
                }
250
 
 
251
 
                /* Read number of lost events */
252
 
                lostEventsInThisPacket = (int) this.getCurrentPacket().getLostEvents();
253
 
                if (lostEventsInThisPacket != 0) {
254
 
                    hasLost = true;
255
 
                    /*
256
 
                     * Compute the duration of the lost event time range. If the
257
 
                     * current packet is the first packet, duration will be set
258
 
                     * to 1.
259
 
                     */
260
 
                    long lostEventsStartTime;
261
 
                    int index = this.streamInputReader.getStreamInput().getIndex().getEntries().indexOf(currentPacket);
262
 
                    if (index == 0) {
263
 
                        lostEventsStartTime = currentPacket.getTimestampBegin() + 1;
264
 
                    } else {
265
 
                        prevPacket = this.streamInputReader.getStreamInput().getIndex().getEntries().get(index - 1);
266
 
                        lostEventsStartTime = prevPacket.getTimestampEnd();
267
 
                    }
268
 
                    lostEventsDuration = Math.abs(lostEventsStartTime - currentPacket.getTimestampBegin());
269
 
                }
270
 
            }
271
 
 
272
 
            /*
273
 
             * Use the timestamp begin of the packet as the reference for the
274
 
             * timestamp reconstitution.
275
 
             */
276
 
            lastTimestamp = currentPacket.getTimestampBegin();
277
 
        } else {
278
 
            bitBuffer.setByteBuffer(null);
279
 
 
280
 
            lastTimestamp = 0;
281
 
        }
282
 
    }
283
 
 
284
 
    /**
285
 
     * Returns whether it is possible to read any more events from this packet.
286
 
     *
287
 
     * @return True if it is possible to read any more events from this packet.
288
 
     */
289
 
    public boolean hasMoreEvents() {
290
 
        if (currentPacket != null) {
291
 
            return hasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
292
 
        }
293
 
        return false;
294
 
    }
295
 
 
296
 
    /**
297
 
     * Reads the next event of the packet into the right event definition.
298
 
     *
299
 
     * @return The event definition containing the event data that was just
300
 
     *         read.
301
 
     * @throws CTFReaderException
302
 
     *             If there was a problem reading the trace
303
 
     */
304
 
    public EventDefinition readNextEvent() throws CTFReaderException {
305
 
        /* Default values for those fields */
306
 
        long eventID = EventDeclaration.UNSET_EVENT_ID;
307
 
        long timestamp = 0;
308
 
        if (hasLost) {
309
 
            hasLost = false;
310
 
            EventDefinition eventDef = EventDeclaration.getLostEventDeclaration().createDefinition(streamInputReader);
311
 
            ((IntegerDefinition) eventDef.getFields().getDefinitions().get(CTFStrings.LOST_EVENTS_FIELD)).setValue(lostEventsInThisPacket);
312
 
            ((IntegerDefinition) eventDef.getFields().getDefinitions().get(CTFStrings.LOST_EVENTS_DURATION)).setValue(lostEventsDuration);
313
 
            eventDef.setTimestamp(this.lastTimestamp);
314
 
            return eventDef;
315
 
        }
316
 
 
317
 
        final StructDefinition sehd = streamEventHeaderDef;
318
 
        final BitBuffer currentBitBuffer = bitBuffer;
319
 
 
320
 
        /* Read the stream event header. */
321
 
        if (sehd != null) {
322
 
            sehd.read(currentBitBuffer);
323
 
 
324
 
            /* Check for the event id. */
325
 
            Definition idDef = sehd.lookupDefinition("id"); //$NON-NLS-1$
326
 
            if (idDef instanceof SimpleDatatypeDefinition) {
327
 
                eventID = ((SimpleDatatypeDefinition) idDef).getIntegerValue();
328
 
            } // else, eventID remains 0
329
 
 
330
 
            /*
331
 
             * Get the timestamp from the event header (may be overridden later
332
 
             * on)
333
 
             */
334
 
            IntegerDefinition timestampDef = sehd.lookupInteger("timestamp"); //$NON-NLS-1$
335
 
            if (timestampDef != null) {
336
 
                timestamp = calculateTimestamp(timestampDef);
337
 
            } // else timestamp remains 0
338
 
 
339
 
            /* Check for the variant v. */
340
 
            Definition variantDef = sehd.lookupDefinition("v"); //$NON-NLS-1$
341
 
            if (variantDef instanceof VariantDefinition) {
342
 
 
343
 
                /* Get the variant current field */
344
 
                StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
345
 
 
346
 
                /*
347
 
                 * Try to get the id field in the current field of the variant.
348
 
                 * If it is present, it overrides the previously read event id.
349
 
                 */
350
 
                Definition idIntegerDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
351
 
                if (idIntegerDef instanceof IntegerDefinition) {
352
 
                    eventID = ((IntegerDefinition) idIntegerDef).getValue();
353
 
                }
354
 
 
355
 
                /*
356
 
                 * Get the timestamp. This would overwrite any previous
357
 
                 * timestamp definition
358
 
                 */
359
 
                Definition def = variantCurrentField.lookupDefinition("timestamp"); //$NON-NLS-1$
360
 
                if (def instanceof IntegerDefinition) {
361
 
                    timestamp = calculateTimestamp((IntegerDefinition) def);
362
 
                }
363
 
            }
364
 
        }
365
 
 
366
 
        /* Read the stream event context. */
367
 
        if (streamEventContextDef != null) {
368
 
            streamEventContextDef.read(currentBitBuffer);
369
 
        }
370
 
 
371
 
        /* Get the right event definition using the event id. */
372
 
        EventDefinition eventDef = streamInputReader.getEventDefinitions().get(eventID);
373
 
        if (eventDef == null) {
374
 
            throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
375
 
        }
376
 
 
377
 
        /* Read the event context. */
378
 
        if (eventDef.getEventContext() != null) {
379
 
            eventDef.getEventContext().read(currentBitBuffer);
380
 
        }
381
 
 
382
 
        /* Read the event fields. */
383
 
        if (eventDef.getFields() != null) {
384
 
            eventDef.getFields().read(currentBitBuffer);
385
 
        }
386
 
 
387
 
        /*
388
 
         * Set the event timestamp using the timestamp calculated by
389
 
         * updateTimestamp.
390
 
         */
391
 
        eventDef.setTimestamp(timestamp);
392
 
 
393
 
        return eventDef;
394
 
    }
395
 
 
396
 
    /**
397
 
     * Calculates the timestamp value of the event, possibly using the timestamp
398
 
     * from the last event.
399
 
     *
400
 
     * @param timestampDef
401
 
     *            Integer definition of the timestamp.
402
 
     * @return The calculated timestamp value.
403
 
     */
404
 
    private long calculateTimestamp(IntegerDefinition timestampDef) {
405
 
        long newval;
406
 
        long majorasbitmask;
407
 
        int len = timestampDef.getDeclaration().getLength();
408
 
 
409
 
        /*
410
 
         * If the timestamp length is 64 bits, it is a full timestamp.
411
 
         */
412
 
        if (timestampDef.getDeclaration().getLength() == 64) {
413
 
            lastTimestamp = timestampDef.getValue();
414
 
            return lastTimestamp;
415
 
        }
416
 
 
417
 
        /*
418
 
         * Bit mask to keep / remove all old / new bits.
419
 
         */
420
 
        majorasbitmask = (1L << len) - 1;
421
 
 
422
 
        /*
423
 
         * If the new value is smaller than the corresponding bits of the last
424
 
         * timestamp, we assume an overflow of the compact representation.
425
 
         */
426
 
        newval = timestampDef.getValue();
427
 
        if (newval < (lastTimestamp & majorasbitmask)) {
428
 
            newval = newval + (1L << len);
429
 
        }
430
 
 
431
 
        /* Keep only the high bits of the old value */
432
 
        lastTimestamp = lastTimestamp & ~majorasbitmask;
433
 
 
434
 
        /* Then add the low bits of the new value */
435
 
        lastTimestamp = lastTimestamp + newval;
436
 
 
437
 
        return lastTimestamp;
438
 
    }
439
 
 
440
 
    @Override
441
 
    public Definition lookupDefinition(String lookupPath) {
442
 
        return null;
443
 
    }
444
 
}