ctf: Don't include all test traces in jar
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / statesystem / backends / historytree / HT_IO.java
index 7270bd88143c7ba2e0f052eea3a1e0f402fa29cf..6326ad333b93119c3f22ca4e416d789b309d3c94 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2013 Ericsson
+ * Copyright (c) 2012, 2014 Ericsson
  * Copyright (c) 2010, 2011 École Polytechnique de Montréal
  * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
  *
@@ -20,45 +20,53 @@ import java.nio.channels.ClosedChannelException;
 import java.nio.channels.FileChannel;
 
 /**
- * This class exists mainly for code isolation/clarification purposes. It
- * contains all the methods and descriptors to handle reading/writing to the
- * tree-file on disk and all the caching mechanisms. Every HistoryTree should
- * contain 1 and only 1 HT_IO element.
+ * This class abstracts inputs/outputs of the HistoryTree nodes.
  *
- * @author alexmont
+ * It contains all the methods and descriptors to handle reading/writing nodes
+ * to the tree-file on disk and all the caching mechanisms.
+ *
+ * This abstraction is mainly for code isolation/clarification purposes.
+ * Every HistoryTree must contain 1 and only 1 HT_IO element.
+ *
+ * @author Alexandre Montplaisir
  *
  */
 class HT_IO {
-
-    /* reference to the tree to which this IO-object belongs */
-    private final HistoryTree tree;
+    /* Configuration of the History Tree */
+    private final HTConfig fConfig;
 
     /* Fields related to the file I/O */
-    private final File historyTreeFile;
     private final FileInputStream fis;
     private final FileOutputStream fos;
     private final FileChannel fcIn;
     private final FileChannel fcOut;
 
+    // TODO test/benchmark optimal cache size
+    private final int CACHE_SIZE = 256;
+    private final HTNode fNodeCache[] = new HTNode[CACHE_SIZE];
+
     /**
      * Standard constructor
      *
-     * @param tree
+     * @param config
+     *             The configuration object for the StateHistoryTree
      * @param newFile
-     *            Are we creating a new file from scratch?
+     *            Flag indicating that the file must be created from scratch
+
      * @throws IOException
+     *             An exception can be thrown when file cannot be accessed
      */
-    HT_IO(HistoryTree tree, boolean newFile) throws IOException {
-        this.tree = tree;
-        historyTreeFile = tree.config.stateFile;
-        boolean success1 = true, success2;
+    public HT_IO(HTConfig config, boolean newFile) throws IOException {
+        fConfig = config;
 
+        File historyTreeFile = config.getStateFile();
         if (newFile) {
+            boolean success1 = true;
             /* Create a new empty History Tree file */
             if (historyTreeFile.exists()) {
                 success1 = historyTreeFile.delete();
             }
-            success2 = historyTreeFile.createNewFile();
+            boolean success2 = historyTreeFile.createNewFile();
             if (!(success1 && success2)) {
                 /* It seems we do not have permission to create the new file */
                 throw new IOException("Cannot create new file at " + //$NON-NLS-1$
@@ -79,47 +87,31 @@ class HT_IO {
     }
 
     /**
-     * Generic "read node" method, which checks if the node is in memory first,
-     * and if it's not it goes to disk to retrieve it.
+     * Read a node from the file on disk.
      *
      * @param seqNumber
-     *            Sequence number of the node we want
-     * @return The wanted node in object form
-     * @throws ClosedChannelException
-     *             If the channel was closed before we could read
-     */
-    HTNode readNode(int seqNumber) throws ClosedChannelException {
-        HTNode node = readNodeFromMemory(seqNumber);
-        if (node == null) {
-            return readNodeFromDisk(seqNumber);
-        }
-        return node;
-    }
-
-    private HTNode readNodeFromMemory(int seqNumber) {
-        for (HTNode node : tree.latestBranch) {
-            if (node.getSequenceNumber() == seqNumber) {
-                return node;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * This method here isn't private, if we know for sure the node cannot be in
-     * memory it's a bit faster to use this directly (when opening a file from
-     * disk for example)
-     *
+     *            The sequence number of the node to read.
+     * @return The object representing the node
      * @throws ClosedChannelException
      *             Usually happens because the file was closed while we were
      *             reading. Instead of using a big reader-writer lock, we'll
      *             just catch this exception.
      */
-    synchronized HTNode readNodeFromDisk(int seqNumber) throws ClosedChannelException {
-        HTNode readNode;
+    public synchronized HTNode readNode(int seqNumber) throws ClosedChannelException {
+        /* Do a cache lookup */
+        int offset = seqNumber & (CACHE_SIZE - 1);
+        HTNode readNode = fNodeCache[offset];
+        if (readNode != null && readNode.getSequenceNumber() == seqNumber) {
+          return readNode;
+        }
+
+        /* Lookup on disk */
         try {
             seekFCToNodePos(fcIn, seqNumber);
-            readNode = HTNode.readNode(tree, fcIn);
+            readNode = HTNode.readNode(fConfig, fcIn);
+
+            /* Put the node in the cache. */
+            fNodeCache[offset] = readNode;
             return readNode;
         } catch (ClosedChannelException e) {
             throw e;
@@ -130,10 +122,15 @@ class HT_IO {
         }
     }
 
-    void writeNode(HTNode node) {
+    public synchronized void writeNode(HTNode node) {
         try {
+            /* Insert the node into the cache. */
+            int seqNumber = node.getSequenceNumber();
+            int offset = seqNumber & (CACHE_SIZE - 1);
+            fNodeCache[offset] = node;
+
             /* Position ourselves at the start of the node and write it */
-            seekFCToNodePos(fcOut, node.getSequenceNumber());
+            seekFCToNodePos(fcOut, seqNumber);
             node.writeSelf(fcOut);
         } catch (IOException e) {
             /* If we were able to open the file, we should be fine now... */
@@ -141,33 +138,24 @@ class HT_IO {
         }
     }
 
-    FileChannel getFcOut() {
+    public FileChannel getFcOut() {
         return this.fcOut;
     }
 
-    FileInputStream supplyATReader() {
+    public FileInputStream supplyATReader(int nodeOffset) {
         try {
             /*
              * Position ourselves at the start of the Mapping section in the
              * file (which is right after the Blocks)
              */
-            seekFCToNodePos(fcIn, tree.getNodeCount());
+            seekFCToNodePos(fcIn, nodeOffset);
         } catch (IOException e) {
             e.printStackTrace();
         }
         return fis;
     }
 
-    File supplyATWriterFile() {
-        return tree.config.stateFile;
-    }
-
-    long supplyATWriterFilePos() {
-        return HistoryTree.getTreeHeaderSize()
-                + ((long) tree.getNodeCount() * tree.config.blockSize);
-    }
-
-    synchronized void closeFile() {
+    public synchronized void closeFile() {
         try {
             fis.close();
             fos.close();
@@ -176,10 +164,11 @@ class HT_IO {
         }
     }
 
-    synchronized void deleteFile() {
+    public synchronized void deleteFile() {
         closeFile();
 
-        if(!historyTreeFile.delete()) {
+        File historyTreeFile = fConfig.getStateFile();
+        if (!historyTreeFile.delete()) {
             /* We didn't succeed in deleting the file */
             //TODO log it?
         }
@@ -189,17 +178,18 @@ class HT_IO {
      * Seek the given FileChannel to the position corresponding to the node that
      * has seqNumber
      *
-     * @param seqNumber
+     * @param fc the channel to seek
+     * @param seqNumber the node sequence number to seek the channel to
      * @throws IOException
      */
     private void seekFCToNodePos(FileChannel fc, int seqNumber)
             throws IOException {
-        fc.position(HistoryTree.getTreeHeaderSize() + (long) seqNumber
-                * tree.config.blockSize);
         /*
-         * cast to (long) is needed to make sure the result is a long too and
+         * Cast to (long) is needed to make sure the result is a long too and
          * doesn't get truncated
          */
+        fc.position(HistoryTree.TREE_HEADER_SIZE
+                + ((long) seqNumber)  * fConfig.getBlockSize());
     }
 
 }
This page took 0.02639 seconds and 5 git commands to generate.