*/
public class CtfKernelStateInput extends AbstractStateChangeInput {
+ /**
+ * Version number of this state provider. Please bump this if you modify the
+ * contents of the generated state history in some way.
+ */
+ private static final int VERSION = 0;
+
/* Event names HashMap. TODO: This can be discarded once we move to Java 7 */
private final HashMap<String, Integer> knownEventNames;
knownEventNames = fillEventNames();
}
+ @Override
+ public int getVersion() {
+ return VERSION;
+ }
+
@Override
public void assignTargetStateSystem(ITmfStateSystemBuilder ssb) {
/* We can only set up the locations once the state system is assigned */
AttributeNotFoundException, StateValueTypeException {
ITmfStateValue value;
- IStateHistoryBackend backend = new HistoryTreeBackend(testHtFile, 0);
+ IStateHistoryBackend backend = new HistoryTreeBackend(testHtFile, 0, 0L);
ss = new StateSystem(backend, true);
/* Build the thing */
import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
+import org.eclipse.linuxtools.tmf.core.statesystem.IStateChangeInput;
import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
/**
public class VerifyHistoryFile {
// Enter the .ht file name to test here
- public final static String pathToHistoryFile = "";
+ public static final String pathToHistoryFile = "";
private static File htFile;
private static IStateHistoryBackend htBackend;
TimeRangeException, AttributeNotFoundException,
StateSystemDisposedException {
htFile = new File(pathToHistoryFile);
- htBackend = new HistoryTreeBackend(htFile);
+ htBackend = new HistoryTreeBackend(htFile, IStateChangeInput.IGNORE_PROVIDER_VERSION);
ss = HistoryBuilder.openExistingHistory(htBackend);
startTime = ss.getStartTime();
* Copyright (c) 2012 Ericsson
* Copyright (c) 2010, 2011 École Polytechnique de Montréal
* Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
- *
+ *
* 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
- *
+ *
*******************************************************************************/
package org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree;
/**
* Configuration object for a StateHistoryTree.
- *
+ *
* @author alexmont
- *
+ *
*/
final class HTConfig {
public final File stateFile;
public final int blockSize;
public final int maxChildren;
+ public final int providerVersion;
public final long treeStart;
- HTConfig(File newStateFile, int blockSize, int maxChildren, long startTime) {
+ HTConfig(File newStateFile, int blockSize, int maxChildren,
+ int providerVersion, long startTime) {
this.stateFile = newStateFile;
this.blockSize = blockSize;
this.maxChildren = maxChildren;
+ this.providerVersion = providerVersion;
this.treeStart = startTime;
}
/**
* Version using default values for blocksize and maxchildren
- *
+ *
* @param stateFileName
* @param startTime
*/
- HTConfig(File newStateFile, long startTime) {
- this(newStateFile, 64 * 1024, 50, startTime);
+ HTConfig(File newStateFile, int providerVersion, long startTime) {
+ this(newStateFile, 64 * 1024, 50, providerVersion, startTime);
}
}
import java.util.Vector;
import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
+import org.eclipse.linuxtools.tmf.core.statesystem.IStateChangeInput;
/**
* Meta-container for the History Tree. This structure contains all the
private static final int HISTORY_FILE_MAGIC_NUMBER = 0x05FFA900;
- /*
- * File format version. Increment minor on backwards-compatible changes.
- * Increment major + set minor back to 0 when breaking compatibility.
- */
- private static final int MAJOR_VERSION = 3;
- private static final byte MINOR_VERSION = 0;
+ /** File format version. Increment when breaking compatibility. */
+ private static final int FILE_VERSION = 3;
// ------------------------------------------------------------------------
// Tree-specific configuration
*
* @param existingFileName
* Path/filename of the history-file we are to open
+ * @param expProviderVersion
+ * The expected version of the state provider
* @throws IOException
*/
- HistoryTree(File existingStateFile) throws IOException {
+ HistoryTree(File existingStateFile, int expProviderVersion) throws IOException {
/*
* Open the file ourselves, get the tree header information we need,
* then pass on the descriptor to the TreeIO object.
throw new IOException("Selected state file does not exist"); //$NON-NLS-1$
}
if (existingStateFile.length() <= 0) {
- throw new IOException("Invalid state file selected, " + //$NON-NLS-1$
- "target file is empty"); //$NON-NLS-1$
+ throw new IOException("Empty target file"); //$NON-NLS-1$
}
FileInputStream fis = new FileInputStream(existingStateFile);
if (res != HISTORY_FILE_MAGIC_NUMBER) {
fc.close();
fis.close();
- throw new IOException("Selected file does not" + //$NON-NLS-1$
- "look like a History Tree file"); //$NON-NLS-1$
+ throw new IOException("Wrong magic number"); //$NON-NLS-1$
}
- res = buffer.getInt(); /* Major version number */
- if (res != MAJOR_VERSION) {
+ res = buffer.getInt(); /* File format version number */
+ if (res != FILE_VERSION) {
fc.close();
fis.close();
- throw new IOException("Select History Tree file is of an older " //$NON-NLS-1$
- + "format. Please use a previous version of " //$NON-NLS-1$
- + "the parser to open it."); //$NON-NLS-1$
+ throw new IOException("Mismatching History Tree file format versions"); //$NON-NLS-1$
}
- res = buffer.getInt(); /* Minor version number */
+ res = buffer.getInt(); /* Event handler's version number */
+ if (res != expProviderVersion &&
+ expProviderVersion != IStateChangeInput.IGNORE_PROVIDER_VERSION) {
+ /*
+ * The existing history was built using a event handler that doesn't
+ * match the current one in the framework. Information could be all
+ * wrong, so we'll force a rebuild of the history file instead.
+ */
+ fc.close();
+ fis.close();
+ throw new IOException("Mismatching event handler versions"); //$NON-NLS-1$
+ }
bs = buffer.getInt(); /* Block Size */
maxc = buffer.getInt(); /* Max nb of children per node */
rootNodeSeqNb = buffer.getInt();
startTime = buffer.getLong();
- this.config = new HTConfig(existingStateFile, bs, maxc, startTime);
+ this.config = new HTConfig(existingStateFile, bs, maxc, expProviderVersion, startTime);
fc.close();
fis.close();
/*
buffer.putInt(HISTORY_FILE_MAGIC_NUMBER);
- buffer.putInt(MAJOR_VERSION);
- buffer.putInt(MINOR_VERSION);
+ buffer.putInt(FILE_VERSION);
+ buffer.putInt(config.providerVersion);
buffer.putInt(config.blockSize);
buffer.putInt(config.maxChildren);
* multiple of 4096.
* @param maxChildren
* The maximum number of children each core node can have
+ * @param providerVersion
+ * Version of of the state provider. We will only try to reopen
+ * existing files if this version matches the one in the
+ * framework.
* @param startTime
* The earliest time stamp that will be stored in the history
* @throws IOException
* Thrown if we can't create the file for some reason
*/
public HistoryTreeBackend(File newStateFile, int blockSize,
- int maxChildren, long startTime) throws IOException {
- final HTConfig conf = new HTConfig(newStateFile, blockSize, maxChildren, startTime);
+ int maxChildren, int providerVersion, long startTime) throws IOException {
+ final HTConfig conf = new HTConfig(newStateFile, blockSize, maxChildren,
+ providerVersion, startTime);
sht = new HistoryTree(conf);
treeIO = sht.getTreeIO();
}
* @param newStateFile
* The filename/location where to store the state history (Should
* end in .ht)
+ * @param providerVersion
+ * Version of of the state provider. We will only try to reopen
+ * existing files if this version matches the one in the
+ * framework.
* @param startTime
* The earliest time stamp that will be stored in the history
* @throws IOException
* Thrown if we can't create the file for some reason
*/
- public HistoryTreeBackend(File newStateFile, long startTime)
+ public HistoryTreeBackend(File newStateFile, int providerVersion, long startTime)
throws IOException {
- this(newStateFile, 64 * 1024, 50, startTime);
+ this(newStateFile, 64 * 1024, 50, providerVersion, startTime);
}
/**
*
* @param existingStateFile
* Filename/location of the history we want to load
+ * @param providerVersion
+ * Expected version of of the state provider plugin.
* @throws IOException
- * If we can't read the file, if it doesn't exist or is not
- * recognized
+ * If we can't read the file, if it doesn't exist, is not
+ * recognized, or if the version of the file does not match the
+ * expected providerVersion.
*/
- public HistoryTreeBackend(File existingStateFile) throws IOException {
- sht = new HistoryTree(existingStateFile);
+ public HistoryTreeBackend(File existingStateFile, int providerVersion)
+ throws IOException {
+ sht = new HistoryTree(existingStateFile, providerVersion);
treeIO = sht.getTreeIO();
isFinishedBuilding = true;
}
* The maximum number of children allowed for each core node
* @param startTime
* The earliest timestamp stored in the history
+ * @param providerVersion
+ * Version of of the state provider. We will only try to reopen
+ * existing files if this version matches the one in the
+ * framework.
* @param queueSize
* The size of the interval insertion queue. 2000 - 10000 usually
* works well
* If there was a problem opening the history file for writing
*/
public ThreadedHistoryTreeBackend(File newStateFile, int blockSize,
- int maxChildren, long startTime, int queueSize) throws IOException {
- super(newStateFile, blockSize, maxChildren, startTime);
+ int maxChildren, long startTime, int providerVersion, int queueSize)
+ throws IOException {
+ super(newStateFile, blockSize, maxChildren, providerVersion, startTime);
intervalQueue = new ArrayBlockingQueue<HTInterval>(queueSize);
shtThread = new Thread(this, "History Tree Thread"); //$NON-NLS-1$
* in ".ht"
* @param startTime
* The earliest timestamp stored in the history
+ * @param providerVersion
+ * Version of of the state provider. We will only try to reopen
+ * existing files if this version matches the one in the
+ * framework.
* @param queueSize
* The size of the interval insertion queue. 2000 - 10000 usually
* works well
* If there was a problem opening the history file for writing
*/
public ThreadedHistoryTreeBackend(File newStateFile, long startTime,
- int queueSize) throws IOException {
- super(newStateFile, startTime);
+ int providerVersion, int queueSize) throws IOException {
+ super(newStateFile, providerVersion, startTime);
intervalQueue = new ArrayBlockingQueue<HTInterval>(queueSize);
shtThread = new Thread(this, "History Tree Thread"); //$NON-NLS-1$
*/
public interface IStateChangeInput {
+ /**
+ * Special state provider version number that will tell the backend to
+ * ignore the version check and open an existing file even if the versions
+ * don't match.
+ * @since 2.0
+ */
+ public final static int IGNORE_PROVIDER_VERSION = -42;
+
+ /**
+ * Event handler plugins should provide a version number. This is used to
+ * determine if a potential existing file can be re-opened later (if the
+ * versions in the file and in the viewer match), or if the file should be
+ * rebuilt from scratch (if the versions don't match).
+ *
+ * @return The version number of the input plugin
+ * @since 2.0
+ */
+ public int getVersion();
+
/**
* Get the trace with which this state input plugin is associated.
*
// at least if its range matches the trace's range.
if (htFile.exists()) {
/* Load an existing history */
+ final int version = (htInput == null) ?
+ IStateChangeInput.IGNORE_PROVIDER_VERSION :
+ htInput.getVersion();
try {
- htBackend = new HistoryTreeBackend(htFile);
+ htBackend = new HistoryTreeBackend(htFile, version);
ITmfStateSystem ss = HistoryBuilder.openExistingHistory(htBackend);
return ss;
} catch (IOException e) {
return null;
}
try {
- htBackend = new ThreadedHistoryTreeBackend(htFile, htInput.getStartTime(), QUEUE_SIZE);
+ htBackend = new ThreadedHistoryTreeBackend(htFile,
+ htInput.getStartTime(), htInput.getVersion(), QUEUE_SIZE);
StateSystem ss = new StateSystem(htBackend);
htInput.assignTargetStateSystem(ss);
builder = new HistoryBuilder(htInput, ss, htBackend, buildManually);
*/
class StatsStateProvider extends AbstractStateChangeInput {
+ /**
+ * Version number of this input handler. Please bump this if you modify the
+ * contents of the generated state history in some way.
+ */
+ private static final int VERSION = 0;
+
/* Commonly-used attributes */
private int typeAttribute = -1;
super(trace, ITmfEvent.class ,"TMF Statistics"); //$NON-NLS-1$
}
+ @Override
+ public int getVersion() {
+ return VERSION;
+ }
+
@Override
public void assignTargetStateSystem(ITmfStateSystemBuilder ssb) {
super.assignTargetStateSystem(ssb);