Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 23ad52dc43a1df93ae51664f807d7f2d18461bc6 (plain) (tree)












































































































































































                                                                                 

                                                                                 


                                                         

                                                                                   








































                                                                                      

                                                                                     











                                                                                                                                                               

                                                                                



                                                    

                                                                                   












                                                                                    

                                                                                        


















                                                                                         

                                                                                             
                                             

                                                                       
                        
                                                                              




                                               

                                                                                            
                                            

                                                                     
                        


                                                                 
                            

                                                                              





                                           

                                                                                                
                                                
                                                                                 




                                         

                                                                                              
                                              


                                                                   






                                                                                

                                                                           


                                  
                                                                                     


                                                                                         
                                                                                                         






                                                                                                           
                                                                 








                                                      
                                                                           

         
                                                    


     
/*******************************************************************************
 * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
 *
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors: Matthew Khouzam - Initial API and implementation
 * Contributors: Simon Marchi - Initial API and implementation
 *******************************************************************************/

package org.eclipse.linuxtools.ctf.core.trace;

import java.io.File;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.UUID;

import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;

/**
 * <b><u>StreamInput</u></b>
 * <p>
 * Represents a trace file that belongs to a certain stream.
 */
public class StreamInput implements IDefinitionScope {

    // ------------------------------------------------------------------------
    // Attributes
    // ------------------------------------------------------------------------

    /**
     * The associated Stream
     */
    private final Stream stream;

    /**
     * FileChannel to the trace file
     */
    private final FileChannel fileChannel;

    /**
     * Information on the file (used for debugging)
     */
    public final File file;

    /**
     * The packet index of this input
     */
    private final StreamInputPacketIndex index = new StreamInputPacketIndex();

    private long timestampEnd;

    // ------------------------------------------------------------------------
    // Constructors
    // ------------------------------------------------------------------------

    /**
     * Constructs a StreamInput.
     *
     * @param stream
     *            The stream to which this StreamInput belongs to.
     * @param fileChannel
     *            The FileChannel to the trace file.
     * @param file
     *            Information about the trace file (for debugging purposes).
     */
    public StreamInput(Stream stream, FileChannel fileChannel, File file) {
        this.stream = stream;
        this.fileChannel = fileChannel;
        this.file = file;
    }

    // ------------------------------------------------------------------------
    // Getters/Setters/Predicates
    // ------------------------------------------------------------------------

    public Stream getStream() {
        return stream;
    }

    public StreamInputPacketIndex getIndex() {
        return index;
    }

    public FileChannel getFileChannel() {
        return fileChannel;
    }

    public String getFilename() {
        return file.getName();
    }

    public long getTimestampEnd() {
        return timestampEnd;
    }

    public void setTimestampEnd(long timestampEnd) {
        this.timestampEnd = timestampEnd;
    }

    @Override
    public String getPath() {
        return ""; //$NON-NLS-1$
    }

    // ------------------------------------------------------------------------
    // Operations
    // ------------------------------------------------------------------------

    @Override
    public Definition lookupDefinition(String lookupPath) {
        /* TODO: lookup in different dynamic scopes is not supported yet. */
        return null;
    }

    /**
     * Create the index for this trace file.
     *
     * @throws CTFReaderException
     */
    public void createIndex() throws CTFReaderException {
        /*
         * The size of the file in bytes
         */
        long fileSizeBytes = 0;
        try {
            fileSizeBytes = fileChannel.size();
        } catch (IOException e) {
            throw new CTFReaderException(e);
        }

        /*
         * Offset of the current packet in bytes
         */
        long packetOffsetBytes = 0;

        /*
         * Initial size, it should map at least the packet header + context
         * size.
         *
         * TODO: use a less arbitrary size.
         */
        long mapSize = 4096;

        /*
         * Definition of trace packet header
         */
        StructDefinition tracePacketHeaderDef = null;

        /*
         * Definition of trace stream packet context
         */
        StructDefinition streamPacketContextDef = null;

        /*
         * The BitBuffer to extract data from the StreamInput
         */
        BitBuffer bitBuffer = new BitBuffer();
        bitBuffer.order(this.getStream().getTrace().getByteOrder());

        /*
         * Create the definitions we need to read the packet headers + contexts
         */
        if (getStream().getTrace().getPacketHeader() != null) {
            tracePacketHeaderDef = getStream().getTrace().getPacketHeader()
                    .createDefinition(this, "trace.packet.header"); //$NON-NLS-1$
        }

        if (getStream().getPacketContextDecl() != null) {
            streamPacketContextDef = getStream().getPacketContextDecl()
                    .createDefinition(this, "stream.packet.context"); //$NON-NLS-1$
        }

        /*
         * Scan through the packets of the file.
         */
        while (packetOffsetBytes < fileSizeBytes) {
            /*
             * If there is less data remaining than what we want to map, reduce
             * the map size.
             */
            if ((fileSizeBytes - packetOffsetBytes) < mapSize) {
                mapSize = fileSizeBytes - packetOffsetBytes;
            }

            /*
             * Map the packet.
             */
            MappedByteBuffer bb;
            try {
                bb = fileChannel.map(MapMode.READ_ONLY, packetOffsetBytes,
                        mapSize);
            } catch (IOException e) {
                throw new CTFReaderException(e);
            }
            bitBuffer.setByteBuffer(bb);

            /*
             * Create the index entry
             */
            StreamInputPacketIndexEntry packetIndex = new StreamInputPacketIndexEntry(
                    packetOffsetBytes);

            /*
             * Read the trace packet header if it exists.
             */
            if (tracePacketHeaderDef != null) {
                tracePacketHeaderDef.read(bitBuffer);

                /*
                 * Check the CTF magic number
                 */
                IntegerDefinition magicDef = (IntegerDefinition) tracePacketHeaderDef
                        .lookupDefinition("magic"); //$NON-NLS-1$
                if (magicDef != null) {
                    int magic = (int) magicDef.getValue();
                    if (magic != Utils.CTF_MAGIC) {
                        throw new CTFReaderException(
                                "CTF magic mismatch " + Integer.toHexString(magic) + " vs " + Integer.toHexString(Utils.CTF_MAGIC)); //$NON-NLS-1$//$NON-NLS-2$
                    }

                }

                /*
                 * Check the trace UUID
                 */
                ArrayDefinition uuidDef = (ArrayDefinition) tracePacketHeaderDef
                        .lookupDefinition("uuid"); //$NON-NLS-1$
                if (uuidDef != null) {
                    byte[] uuidArray = new byte[16];

                    for (int i = 0; i < 16; i++) {
                        IntegerDefinition uuidByteDef = (IntegerDefinition) uuidDef
                                .getElem(i);
                        uuidArray[i] = (byte) uuidByteDef.getValue();
                    }

                    UUID uuid = Utils.makeUUID(uuidArray);

                    if (!getStream().getTrace().getUUID().equals(uuid)) {
                        throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$
                    }
                }

                /*
                 * Check that the stream id did not change
                 */
                IntegerDefinition streamIDDef = (IntegerDefinition) tracePacketHeaderDef
                        .lookupDefinition("stream_id"); //$NON-NLS-1$
                if (streamIDDef != null) {
                    long streamID = streamIDDef.getValue();

                    if (streamID != getStream().getId()) {
                        throw new CTFReaderException(
                                "Stream ID changing within a StreamInput"); //$NON-NLS-1$
                    }
                }
            }

            /*
             * Read the stream packet context if it exists.
             */
            if (streamPacketContextDef != null) {
                streamPacketContextDef.read(bitBuffer);

                /*
                 * Read the content size in bits
                 */
                IntegerDefinition contentSizeDef = (IntegerDefinition) streamPacketContextDef
                        .lookupDefinition("content_size"); //$NON-NLS-1$
                if (contentSizeDef != null) {
                    packetIndex.setContentSizeBits((int) contentSizeDef
                            .getValue());
                } else {
                    packetIndex.setContentSizeBits((int) (fileSizeBytes * 8));
                }

                /*
                 * Read the packet size in bits
                 */
                IntegerDefinition packetSizeDef = (IntegerDefinition) streamPacketContextDef
                        .lookupDefinition("packet_size"); //$NON-NLS-1$
                if (packetSizeDef != null) {
                    packetIndex.setPacketSizeBits((int) packetSizeDef
                            .getValue());
                } else {
                    if (packetIndex.getContentSizeBits() != 0) {
                        packetIndex.setPacketSizeBits(packetIndex
                                .getContentSizeBits());
                    } else {
                        packetIndex
                                .setPacketSizeBits((int) (fileSizeBytes * 8));
                    }
                }

                /*
                 * Read the begin timestamp
                 */
                IntegerDefinition timestampBeginDef = (IntegerDefinition) streamPacketContextDef
                        .lookupDefinition("timestamp_begin"); //$NON-NLS-1$
                if (timestampBeginDef != null) {
                    packetIndex.setTimestampBegin( timestampBeginDef.getValue());
                }

                /*
                 * Read the end timestamp
                 */
                IntegerDefinition timestampEndDef = (IntegerDefinition) streamPacketContextDef
                        .lookupDefinition("timestamp_end"); //$NON-NLS-1$
                if (timestampEndDef != null) {
                    packetIndex.setTimestampEnd(timestampEndDef
                            .getValue());
                    setTimestampEnd(packetIndex.getTimestampEnd());
                }
            } else {
                /*
                 * If there is no packet context, infer the content and packet
                 * size from the file size (assume that there is only one packet
                 * and no padding)
                 */
                packetIndex.setContentSizeBits( (int) (fileSizeBytes * 8));
                packetIndex.setPacketSizeBits( (int) (fileSizeBytes * 8));
            }

            /* Basic validation */
            if (packetIndex.getContentSizeBits() > packetIndex.getPacketSizeBits()) {
                throw new CTFReaderException("Content size > packet size"); //$NON-NLS-1$
            }

            if (packetIndex.getPacketSizeBits() > ((fileSizeBytes - packetIndex.getOffsetBytes()) * 8)) {
                throw new CTFReaderException(
                        "Not enough data remaining in the file for the size of this packet"); //$NON-NLS-1$
            }

            /*
             * Offset in the file, in bits
             */
            packetIndex.setDataOffsetBits( bitBuffer.position());

            /*
             * Add the packet index entry to the index
             */
            index.addEntry(packetIndex);

            /*
             * Update the counting packet offset
             */
            packetOffsetBytes += (packetIndex.getPacketSizeBits() + 7) / 8;

        }
        index.getEntries().get(0).setIndexBegin(0L);
    }

}

Back to the top