diff -r ed1c9f64298a -r 5b9d4d8641ce trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/engine/BaseDataReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/engine/BaseDataReader.java Wed Jun 23 14:49:59 2010 +0300 @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Nokia Corporation - initial contribution. + * + * Contributors: + * + * Description: + * + * Base DataReader class + * + */ +package com.nokia.traceviewer.engine; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Base DataReader class + */ +public abstract class BaseDataReader extends Thread implements DataReader, + TraceViewerConst, BTraceConstants { + + /** + * Sleeping time + */ + protected static final int SLEEP_TIME = 200; + + /** + * Pause waiting time + */ + protected static final int PAUSE_TIME = 300; + + /** + * Trace configuration to be used in this Reader + */ + protected TraceConfiguration traceConfiguration; + + /** + * Trace properties, passed to MediaCallback + */ + protected TraceProperties trace; + + /** + * Data source + */ + protected FileChannel sourceChannel; + + /** + * Buffer for data received from data source + */ + protected ByteBuffer receiveBuffer; + + /** + * Media processor + */ + protected MediaCallback mediaCallback; + + /** + * File path from where to read + */ + protected String filePath; + + /** + * Random access file we use to read the binary + */ + protected RandomAccessFile readFile; + + /** + * Filemap that hold the trace block positions + */ + protected FileMap fileMap; + + /** + * Trace count in this file + */ + protected int traceCount; + + /** + * File start offset + */ + protected long fileStartOffset; + + /** + * Multipart trace array + */ + protected static Map multiPartTraceArray; + + /** + * Constructor + */ + public BaseDataReader() { + fileMap = new FileMap(); + } + + /** + * Creates file channel + */ + protected void createFileChannel() { + try { + if (readFile != null) { + // Close previous file channel + readFile.close(); + } + readFile = new RandomAccessFile(filePath, "r"); //$NON-NLS-1$ + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + if (readFile != null) { + sourceChannel = readFile.getChannel(); + } + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.engine.DataReader#getFilePath() + */ + public String getFilePath() { + return filePath; + } + + /* + * (non-Javadoc) + * + * @see + * com.nokia.traceviewer.engine.DataReader#setFilePath(java.lang.String) + */ + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.engine.DataReader#setFileStartOffset(long) + */ + public void setFileStartOffset(long fileStartOffset) { + this.fileStartOffset = fileStartOffset; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.engine.DataReader#getFileStartOffset() + */ + public long getFileStartOffset() { + return fileStartOffset; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.engine.DataReader#getFileMap() + */ + public FileMap getFileMap() { + return fileMap; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.engine.DataReader#clearFile() + */ + public void clearFile() { + fileMap.clearMap(); + traceCount = 0; + fileStartOffset = 0; + if (readFile != null) { + createFileChannel(); + + // Set everything to zero + setFilePosition(0); + } + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.engine.DataReader#getTraceCount() + */ + public int getTraceCount() { + return traceCount; + } + + /* + * (non-Javadoc) + * + * @see + * com.nokia.traceviewer.engine.DataReader#createScrollReader(com.nokia. + * traceviewer.engine.MediaCallback, + * com.nokia.traceviewer.engine.TraceConfiguration) + */ + public DataScrollReader createScrollReader(MediaCallback mediaCallback, + TraceConfiguration conf) { + return null; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.engine.DataReader#getTraceConfiguration() + */ + public TraceConfiguration getTraceConfiguration() { + return traceConfiguration; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.engine.DataReader#setFilePosition(long) + */ + public void setFilePosition(long filePos) { + try { + if (readFile != null) { + readFile.seek(filePos); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Parses BTrace variables + * + * @param buf + * buffer where the data is located + * @param bTraceHeaderOffset + * BTrace header offset + * @param trace + * trace where the variables are inserted + */ + protected void parseBTraceVariables(ByteBuffer buf, int bTraceHeaderOffset, + TraceProperties trace) { + int variablesFound = 0; + + // Get BTrace header bytes + byte recordSize = buf.get(bTraceHeaderOffset); + byte flags = buf.get(bTraceHeaderOffset + 1); + byte category = buf.get(bTraceHeaderOffset + 2); + byte subCategory = buf.get(bTraceHeaderOffset + 3); + + // Set BTrace header bytes + trace.bTraceInformation.setRecordSize(recordSize); + trace.bTraceInformation.setFlags(flags); + trace.bTraceInformation.setCategory(category); + trace.bTraceInformation.setSubCategory(subCategory); + + // Loop through flags + for (int i = 0; i < FLAGS_LENGTH; i++) { + if ((flags & (1 << i)) != 0) { + + switch (i) { + + // Header2 present (bit number 0) + case HEADER2_PRESENT_BIT: + trace.bTraceInformation.setHeader2Present(true); + + // CPU Id + int cpuId = buf.getInt(bTraceHeaderOffset + + BTRACE_HEADER_LENGTH); + cpuId = Integer.reverseBytes(cpuId); + cpuId = (cpuId & CPU_ID_MASK) >> CPU_ID_SHIFT; + trace.bTraceInformation.setCpuId(cpuId); + + // Multipart trace + int multipart = 0; + multipart |= buf.getInt(bTraceHeaderOffset + + BTRACE_HEADER_LENGTH); + multipart = Integer.reverseBytes(multipart); + multipart = multipart & MULTIPART_MASK; + trace.bTraceInformation.setMultiPart(multipart); + break; + + // Timestamp present (bit number 1) + case TIMESTAMP_PRESENT_BIT: + int timestamp = buf.getInt(bTraceHeaderOffset + + BTRACE_HEADER_LENGTH + + (variablesFound * BTRACE_VARIABLE_LENGTH)); + + timestamp = Integer.reverseBytes(timestamp); + trace.bTraceInformation.setTimestampPresent(true); + trace.bTraceInformation.setTimestamp(timestamp); + break; + + // Timestamp2 present (bit number 2) + case TIMESTAMP2_PRESENT_BIT: + int timestamp2 = buf.getInt(bTraceHeaderOffset + + BTRACE_HEADER_LENGTH + + (variablesFound * BTRACE_VARIABLE_LENGTH)); + + timestamp2 = Integer.reverseBytes(timestamp2); + trace.bTraceInformation.setTimestamp2Present(true); + trace.bTraceInformation.setTimestamp2(timestamp2); + break; + + // Context ID present (bit number 3) + case CONTEXT_ID_PRESENT_BIT: + int contextId = buf.getInt(bTraceHeaderOffset + + BTRACE_HEADER_LENGTH + + (variablesFound * BTRACE_VARIABLE_LENGTH)); + + contextId = Integer.reverseBytes(contextId); + trace.bTraceInformation.setContextIdPresent(true); + trace.bTraceInformation.setThreadId(contextId); + break; + + // Program counter present (bit number 4) + case PROGRAM_COUNTER_PRESENT_BIT: + int programCounter = buf.getInt(bTraceHeaderOffset + + BTRACE_HEADER_LENGTH + + (variablesFound * BTRACE_VARIABLE_LENGTH)); + + programCounter = Integer.reverseBytes(programCounter); + trace.bTraceInformation.setProgramCounterPresent(true); + trace.bTraceInformation.setProgramCounter(programCounter); + break; + + // Extra value present (bit number 5) + case EXTRA_VALUE_PRESENT_BIT: + int extraValue = buf.getInt(bTraceHeaderOffset + + BTRACE_HEADER_LENGTH + + (variablesFound * BTRACE_VARIABLE_LENGTH)); + + extraValue = Integer.reverseBytes(extraValue); + trace.bTraceInformation.setExtraValuePresent(true); + trace.bTraceInformation.setExtraValue(extraValue); + break; + + // Record truncated (bit number 6) + case RECORD_TRUNCATED_BIT: + trace.bTraceInformation.setTruncated(true); + variablesFound--; + break; + + // Record missing (bit number 7) + case RECORD_MISSING_BIT: + trace.bTraceInformation.setTraceMissing(true); + variablesFound--; + break; + } + + // Add variable count for each found flag + variablesFound++; + } + } + + // Data starts after BTrace header + possible variables + trace.dataStart = bTraceHeaderOffset + BTRACE_HEADER_LENGTH + + (variablesFound * BTRACE_VARIABLE_LENGTH); + + // Get length of the BTrace data + int btraceDataLength = buf.get(bTraceHeaderOffset) & BYTE_MASK; + + // If length is FF, use the length from header instead + if (btraceDataLength == BYTE_MASK) { + trace.dataLength = trace.messageLength + - (trace.dataStart - trace.messageStart); + } else { + trace.dataLength = btraceDataLength + - ((variablesFound + 1) * BTRACE_VARIABLE_LENGTH); + } + } + + /** + * Handles multipart trace + * + * @param trace + * trace properties + * @param multiPartValue + * multi part value + * @param bTraceHeaderOffset + * BTrace header offset + * @return true if trace should be given to DataProcessors + */ + protected boolean handleMultiPart(TraceProperties trace, + int multiPartValue, int bTraceHeaderOffset) { + boolean valid = true; + if (multiPartTraceArray == null) { + multiPartTraceArray = Collections + .synchronizedMap(new HashMap()); + } + + Integer key = Integer.valueOf(trace.bTraceInformation.getExtraValue()); + MultiPartItem item = multiPartTraceArray.get(key); + + // First or middle part + if (multiPartValue == 1 || multiPartValue == 2) { + valid = false; + + // Add trace to array + if (item == null) { + MultiPartItem newItem = new MultiPartItem(); + newItem.addPart(trace, false); + multiPartTraceArray.put(key, newItem); + + // Don't add parts if trace is already completed + } else if (!item.isCompleted()) { + item.addPart(trace, false); + } + + // Last part + } else if (multiPartValue == 3 && item != null) { + if (!item.isCompleted()) { + item.addPart(trace, true); + item.setCompleted(true); + } + + // Create byte array + int totalMessageLength = item.getTotalMessageLength(); + byte byteArr[] = new byte[totalMessageLength]; + + // First copy the header from the last trace part + int initialHeaderSize = trace.dataStart - trace.messageStart; + trace.byteBuffer.position(trace.messageStart); + trace.byteBuffer.get(byteArr, 0, initialHeaderSize); + + // Then the old data + Iterator headerLenIterator = item + .getTracePartHeaderSizes().iterator(); + Iterator byteIterator = item.getTraceParts().iterator(); + int startOffset = initialHeaderSize; + + // Copy all the stuff from parts + while (headerLenIterator.hasNext()) { + int headerLen = headerLenIterator.next().intValue(); + byte[] partBytes = byteIterator.next(); + System.arraycopy(partBytes, headerLen, byteArr, startOffset, + partBytes.length - headerLen); + startOffset += (partBytes.length - headerLen); + } + + // Set multipart item to the trace + trace.bTraceInformation.setMultiPartTraceParts(item); + + // Set record size + int recordSize = totalMessageLength; + if (recordSize > 0xFF) { + recordSize = 0xFF; + } + bTraceHeaderOffset -= trace.messageStart; + byteArr[bTraceHeaderOffset] = (byte) recordSize; + trace.bTraceInformation.setRecordSize((byte) recordSize); + + // Remove multipart info from BTrace header + int bTraceHeader2Offset = bTraceHeaderOffset + BTRACE_HEADER_LENGTH; + byteArr[bTraceHeader2Offset] &= ~MULTIPART_MASK; + + // Set protocol specific stuff to multi part trace + byteArr = setProtocolSpecificStuffToMultiPartTrace(byteArr, trace); + + trace.byteBuffer = ByteBuffer.wrap(byteArr); + } + + return valid; + } + + /** + * Sets protocol specific stuff to multi part trace + * + * @param byteArr + * byte array containing the multi part trace + * @param trace + * Trace properties + * @return byte array containing the trace after procotol specific stuff is + * added + */ + protected abstract byte[] setProtocolSpecificStuffToMultiPartTrace( + byte[] byteArr, TraceProperties trace); +}