trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/engine/BaseDataReader.java
changeset 11 5b9d4d8641ce
--- /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<Integer, MultiPartItem> 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, MultiPartItem>());
+		}
+
+		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<Integer> headerLenIterator = item
+					.getTracePartHeaderSizes().iterator();
+			Iterator<byte[]> 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);
+}