ss: no longer have a strings section in the HTNodes
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Tue, 15 Mar 2016 00:28:02 +0000 (20:28 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 23 Mar 2016 12:14:46 +0000 (08:14 -0400)
The state systems nodes had a string section to allow for faster seeks
on the state system file if the entire interval was not loaded to memory.
This is never the case and it adds an extra integer to each non-integer state
as well as extra (but well tested) logic.

This patch makes the state sytem store each interval sequentially on a
given node.

Expect minimal performance difference, however, the size of the state system
may shrink a bit (approx 5%).

Change-Id: I01bc8594b7944fad97b6c9b715b848b6afa39913
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Signed-off-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-on: https://git.eclipse.org/r/68404
Reviewed-by: Hudson CI
statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeTest.java
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HTInterval.java
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HTNode.java
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTree.java

index 701913be41a4bc903aa757c29ad37bf38139341c..c90f7142a19d4e8fccfd32ebb866a9f4694dde2c 100644 (file)
@@ -36,18 +36,22 @@ import org.junit.Test;
  */
 public class HistoryTreeTest {
 
+
     /* Minimal allowed blocksize */
     private static final int BLOCK_SIZE = HistoryTree.TREE_HEADER_SIZE;
-    /* The extra size used by long and double values */
-    private static final int LONG_DOUBLE_SIZE = 8;
-    /* The number of extra characters to store a string interval */
-    private static final int STRING_PADDING = 2;
+
+    private static final HTInterval NULL_INTERVAL = new HTInterval(10, 20, 1, TmfStateValue.nullValue());
 
     /* String with 23 characters, interval in file will be 25 bytes long */
     private static final String TEST_STRING = "abcdefghifklmnopqrstuvw";
     private static final TmfStateValue STRING_VALUE = TmfStateValue.newValueString(TEST_STRING);
+    private static final HTInterval STRING_INTERVAL = new HTInterval(10, 20, 1, STRING_VALUE);
+
     private static final TmfStateValue LONG_VALUE = TmfStateValue.newValueLong(10L);
+    private static final HTInterval LONG_INTERVAL = new HTInterval(10, 20, 1, LONG_VALUE);
+
     private static final TmfStateValue INT_VALUE = TmfStateValue.newValueInt(1);
+    private static final HTInterval INT_INTERVAL = new HTInterval(10, 20, 1, INT_VALUE);
 
     private @Nullable File fTempFile;
 
@@ -132,8 +136,9 @@ public class HistoryTreeTest {
 
         /* Fill the following leaf node */
         HTNode node = ht.getLatestLeaf();
+        int intervalSize = STRING_INTERVAL.getSizeOnDisk();
         int nodeFreeSpace = node.getNodeFreeSpace();
-        int nbIntervals = nodeFreeSpace / (HTInterval.DATA_ENTRY_SIZE + TEST_STRING.length() + STRING_PADDING);
+        int nbIntervals = nodeFreeSpace / intervalSize;
         long ret = fillValues(ht, STRING_VALUE, nbIntervals, leafNodeStart);
 
         /* Make sure we haven't changed the depth or node count */
@@ -158,27 +163,31 @@ public class HistoryTreeTest {
 
         /* Add null intervals up to ~10% */
         int nodeFreeSpace = node.getNodeFreeSpace();
-        int nbIntervals = nodeFreeSpace / 10 / HTInterval.DATA_ENTRY_SIZE;
+        int intervalSize = NULL_INTERVAL.getSizeOnDisk();
+        int nbIntervals = nodeFreeSpace / 10 / intervalSize;
         long start = fillValues(ht, TmfStateValue.nullValue(), nbIntervals, 1);
-        assertEquals(nodeFreeSpace - nbIntervals * HTInterval.DATA_ENTRY_SIZE, node.getNodeFreeSpace());
+        assertEquals(nodeFreeSpace - nbIntervals * intervalSize , node.getNodeFreeSpace());
 
         /* Add integer intervals up to ~20% */
         nodeFreeSpace = node.getNodeFreeSpace();
-        nbIntervals = nodeFreeSpace / 10 / HTInterval.DATA_ENTRY_SIZE;
+        intervalSize = INT_INTERVAL.getSizeOnDisk();
+        nbIntervals = nodeFreeSpace / 10 / intervalSize;
         start = fillValues(ht, INT_VALUE, nbIntervals, start);
-        assertEquals(nodeFreeSpace - nbIntervals * HTInterval.DATA_ENTRY_SIZE, node.getNodeFreeSpace());
+        assertEquals(nodeFreeSpace - nbIntervals * intervalSize , node.getNodeFreeSpace());
 
         /* Add long intervals up to ~30% */
         nodeFreeSpace = node.getNodeFreeSpace();
-        nbIntervals = nodeFreeSpace / 10 / (HTInterval.DATA_ENTRY_SIZE + LONG_DOUBLE_SIZE);
+        intervalSize = LONG_INTERVAL.getSizeOnDisk();
+        nbIntervals = nodeFreeSpace / 10 / intervalSize;
         start = fillValues(ht, LONG_VALUE, nbIntervals, start);
-        assertEquals(nodeFreeSpace - nbIntervals * (HTInterval.DATA_ENTRY_SIZE + LONG_DOUBLE_SIZE), node.getNodeFreeSpace());
+        assertEquals(nodeFreeSpace - nbIntervals * intervalSize , node.getNodeFreeSpace());
 
         /* Add string intervals up to ~40% */
         nodeFreeSpace = node.getNodeFreeSpace();
-        nbIntervals = nodeFreeSpace / 10 / (HTInterval.DATA_ENTRY_SIZE + TEST_STRING.length() + STRING_PADDING);
+        intervalSize = STRING_INTERVAL.getSizeOnDisk();
+        nbIntervals = nodeFreeSpace / 10 / intervalSize;
         start = fillValues(ht, STRING_VALUE, nbIntervals, start);
-        assertEquals(nodeFreeSpace - nbIntervals * (HTInterval.DATA_ENTRY_SIZE + TEST_STRING.length() + STRING_PADDING), node.getNodeFreeSpace());
+        assertEquals(nodeFreeSpace - nbIntervals * intervalSize , node.getNodeFreeSpace());
 
     }
 
@@ -193,7 +202,7 @@ public class HistoryTreeTest {
         /* Fill a first node */
         HTNode node = ht.getLatestLeaf();
         int nodeFreeSpace = node.getNodeFreeSpace();
-        int nbIntervals = nodeFreeSpace / (HTInterval.DATA_ENTRY_SIZE + TEST_STRING.length() + STRING_PADDING);
+        int nbIntervals = nodeFreeSpace / (STRING_INTERVAL.getSizeOnDisk());
         long start = fillValues(ht, STRING_VALUE, nbIntervals, 1);
 
         /* Add intervals that should add a sibling to the node */
@@ -206,7 +215,7 @@ public class HistoryTreeTest {
         /* Fill the latest leaf node (2nd child) */
         node = ht.getLatestLeaf();
         nodeFreeSpace = node.getNodeFreeSpace();
-        nbIntervals = nodeFreeSpace / (HTInterval.DATA_ENTRY_SIZE + TEST_STRING.length() + STRING_PADDING);
+        nbIntervals = nodeFreeSpace / (STRING_INTERVAL.getSizeOnDisk());
         start = fillValues(ht, STRING_VALUE, nbIntervals, start);
 
         /*
@@ -219,7 +228,7 @@ public class HistoryTreeTest {
         /* Fill the latest leaf node (3rd and last child) */
         node = ht.getLatestLeaf();
         nodeFreeSpace = node.getNodeFreeSpace();
-        nbIntervals = nodeFreeSpace / (HTInterval.DATA_ENTRY_SIZE + TEST_STRING.length() + STRING_PADDING);
+        nbIntervals = nodeFreeSpace / (STRING_INTERVAL.getSizeOnDisk());
         start = fillValues(ht, STRING_VALUE, nbIntervals, start);
 
         /* The new node created here should generate a new branch */
index dc5a31d9960afd025f51feaa10fe3afcfa5cab56..99abcf558864d4f873d3fe22c1b1b52b182f029d 100644 (file)
@@ -19,7 +19,6 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
@@ -35,18 +34,6 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
 
     private static final String errMsg = "Invalid interval data. Maybe your file is corrupt?"; //$NON-NLS-1$
 
-    /**
-     * Size of an entry in the data section.
-     *
-     * <pre>
-     *   16  2 x Timevalue/long (interval start + end)
-     * +  4  int (key)
-     * +  1  byte (type)
-     * +  4  int (valueOffset)
-     * </pre>
-     */
-    public static final int DATA_ENTRY_SIZE = 25;
-
     /* 'Byte' equivalent for state values types */
     private static final byte TYPE_NULL = -1;
     private static final byte TYPE_INTEGER = 0;
@@ -54,21 +41,13 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
     private static final byte TYPE_LONG = 2;
     private static final byte TYPE_DOUBLE = 3;
 
-    /* String entry sizes of different state values */
-    private static final int NO_ENTRY_SIZE = 0;
-    private static final int LONG_ENTRY_SIZE = 8;
-    private static final int DOUBLE_ENTRY_SIZE = 8;
-    // sizes of string values depend on the string itself
-
     private final long start;
     private final long end;
     private final int attribute;
     private final @NonNull TmfStateValue sv;
 
-    /*
-     * Size of the strings section entry used by this interval (= 0 if not used)
-     */
-    private final int stringsEntrySize;
+    /** Number of bytes used by this interval when it is written to disk */
+    private final int fSizeOnDisk;
 
     /**
      * Standard constructor
@@ -95,7 +74,41 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
         this.end = intervalEnd;
         this.attribute = attribute;
         this.sv = value;
-        this.stringsEntrySize = computeStringsEntrySize();
+        this.fSizeOnDisk = computeSizeOnDisk(sv);
+    }
+
+    /**
+     * Compute how much space (in bytes) an interval will take in its serialized
+     * form on disk. This is dependent on its state value.
+     */
+    private static int computeSizeOnDisk(ITmfStateValue sv) {
+        /*
+         * Minimum size is 2x long (start and end), 1x int (attribute) and 1x
+         * byte (value type).
+         */
+        int minSize = Long.BYTES + Long.BYTES + Integer.BYTES + Byte.BYTES;
+
+        switch (sv.getType()) {
+        case NULL:
+            return minSize;
+        case INTEGER:
+            return (minSize + Integer.BYTES);
+        case LONG:
+            return (minSize + Long.BYTES);
+        case DOUBLE:
+            return (minSize + Double.BYTES);
+        case STRING:
+            /*
+             * String's length + 2 (1 byte for size, 1 byte for \0 at the end
+             */
+            return (minSize + sv.unboxStr().getBytes().length + 2);
+        default:
+            /*
+             * It's very important that we know how to write the state value in
+             * the file!!
+             */
+            throw new IllegalStateException();
+        }
     }
 
     /**
@@ -114,13 +127,24 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
         this.end = intervalEnd;
         this.attribute = attribute;
         this.sv = value;
-        this.stringsEntrySize = size;
+        this.fSizeOnDisk = size;
     }
 
     /**
      * Reader factory method. Builds the interval using an already-allocated
      * ByteBuffer, which normally comes from a NIO FileChannel.
      *
+     * The interval is just a start, end, attribute and value, this is the
+     * layout of the HTInterval on disk
+     * <ul>
+     * <li>start (8 bytes)</li>
+     * <li>end (8 bytes)</li>
+     * <li>attribute (4 bytes)</li>
+     * <li>sv type (1 byte)</li>
+     * <li>sv ( 0 bytes for null, 4 for int , 8 for long and double, and the
+     * length of the string +2 for strings (it's variable))</li>
+     * </ul>
+     *
      * @param buffer
      *            The ByteBuffer from which to read the information
      * @return The interval object
@@ -132,10 +156,10 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
         long intervalStart, intervalEnd;
         int attribute;
         TmfStateValue value;
-        int valueOrOffset, valueSize, res;
         byte valueType;
         byte array[];
 
+        int posStart = buffer.position();
         /* Read the Data Section entry */
         intervalStart = buffer.getLong();
         intervalEnd = buffer.getLong();
@@ -143,77 +167,39 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
 
         /* Read the 'type' of the value, then react accordingly */
         valueType = buffer.get();
-        valueOrOffset = buffer.getInt();
         switch (valueType) {
 
         case TYPE_NULL:
             value = TmfStateValue.nullValue();
-            valueSize = NO_ENTRY_SIZE;
             break;
 
         case TYPE_INTEGER:
-            /* "ValueOrOffset" is the straight value */
-            value = TmfStateValue.newValueInt(valueOrOffset);
-            valueSize = NO_ENTRY_SIZE;
+            value = TmfStateValue.newValueInt(buffer.getInt());
             break;
 
         case TYPE_STRING:
-            /* Go read the matching entry in the Strings section of the block */
-            buffer.mark();
-            buffer.position(valueOrOffset);
-
             /* the first byte = the size to read */
-            valueSize = buffer.get();
+            int valueSize = buffer.get();
 
-            /*
-             * Careful though, 'valueSize' is the total size of the entry,
-             * including the 'size' byte at the start and end (0'ed) byte at the
-             * end. Here we want 'array' to only contain the real payload of the
-             * value.
-             */
-            array = new byte[valueSize - 2];
+            array = new byte[valueSize];
             buffer.get(array);
             value = TmfStateValue.newValueString(new String(array));
 
             /* Confirm the 0'ed byte at the end */
-            res = buffer.get();
+            byte res = buffer.get();
             if (res != 0) {
                 throw new IOException(errMsg);
             }
-
-            /*
-             * Restore the file pointer's position (so we can read the next
-             * interval)
-             */
-            buffer.reset();
             break;
 
         case TYPE_LONG:
             /* Go read the matching entry in the Strings section of the block */
-            buffer.mark();
-            buffer.position(valueOrOffset);
             value = TmfStateValue.newValueLong(buffer.getLong());
-            valueSize = LONG_ENTRY_SIZE;
-
-            /*
-             * Restore the file pointer's position (so we can read the next
-             * interval)
-             */
-            buffer.reset();
             break;
 
         case TYPE_DOUBLE:
             /* Go read the matching entry in the Strings section of the block */
-            buffer.mark();
-            buffer.position(valueOrOffset);
             value = TmfStateValue.newValueDouble(buffer.getDouble());
-            valueSize = DOUBLE_ENTRY_SIZE;
-
-            /*
-             * Restore the file pointer's position (so we can read the next
-             * interval)
-             */
-            buffer.reset();
             break;
 
         default:
@@ -222,7 +208,7 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
         }
 
         try {
-            interval = new HTInterval(intervalStart, intervalEnd, attribute, value, valueSize);
+            interval = new HTInterval(intervalStart, intervalEnd, attribute, value, buffer.position() - posStart);
         } catch (TimeRangeException e) {
             throw new IOException(errMsg);
         }
@@ -234,109 +220,59 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
      * corresponding to this interval in a ByteBuffer (mapped to a block in the
      * history-file, hopefully)
      *
+     * The interval is just a start, end, attribute and value, this is the
+     * layout of the HTInterval on disk
+     * <ul>
+     * <li>start (8 bytes)</li>
+     * <li>end (8 bytes)</li>
+     * <li>attribute (4 bytes)</li>
+     * <li>sv type (1 byte)</li>
+     * <li>sv ( 0 bytes for null, 4 for int , 8 for long and double, and the
+     * length of the string +2 for strings (it's variable))</li>
+     * </ul>
+     *
      * @param buffer
      *            The already-allocated ByteBuffer corresponding to a SHT Node
-     * @param endPosOfStringEntry
-     *            The initial (before calling this function for this interval)
-     *            position of the Strings Entry for this node. This will change
-     *            from one call to the other if we're writing String
-     *            StateValues.
-     * @return The size of the Strings Entry that was written, if any.
      */
-    public int writeInterval(ByteBuffer buffer, int endPosOfStringEntry) {
+    public void writeInterval(ByteBuffer buffer) {
+        final byte byteFromType = getByteFromType(sv.getType());
+
         buffer.putLong(start);
         buffer.putLong(end);
         buffer.putInt(attribute);
-        buffer.put(getByteFromType(sv.getType()));
-
-        switch (getByteFromType(sv.getType())) {
+        buffer.put(byteFromType);
 
+        switch (byteFromType) {
         case TYPE_NULL:
+            break;
         case TYPE_INTEGER:
-            /* We write the 'valueOffset' field as a straight value. */
-            try {
-                buffer.putInt(sv.unboxInt());
-            } catch (StateValueTypeException e) {
-                /*
-                 * This should not happen, since the value told us it was of
-                 * type Null or Integer (corrupted value?)
-                 */
-                e.printStackTrace();
-            }
+            buffer.putInt(sv.unboxInt());
             break;
 
         case TYPE_STRING:
-            byte[] byteArrayToWrite;
-            try {
-                byteArrayToWrite = sv.unboxStr().getBytes();
-            } catch (StateValueTypeException e1) {
-                /* Should not happen, we're in a switch/case for string type */
-                throw new RuntimeException();
-            }
-
-            /* we use the valueOffset as an offset. */
-            buffer.putInt(endPosOfStringEntry - stringsEntrySize);
-            buffer.mark();
-            buffer.position(endPosOfStringEntry - stringsEntrySize);
+            String string = sv.unboxStr();
+            byte[] strArray = string.getBytes();
 
             /*
-             * write the Strings entry (1st byte = size, then the bytes, then the 0)
+             * Write the Strings entry (1st byte = size, then the bytes, then
+             * the 0). We have checked the string length at the constructor.
              */
-            buffer.put((byte) stringsEntrySize);
-            buffer.put(byteArrayToWrite);
+            buffer.put((byte) strArray.length);
+            buffer.put(strArray);
             buffer.put((byte) 0);
-            assert (buffer.position() == endPosOfStringEntry);
-            buffer.reset();
             break;
 
         case TYPE_LONG:
-            /* we use the valueOffset as an offset. */
-            buffer.putInt(endPosOfStringEntry - stringsEntrySize);
-            buffer.mark();
-            buffer.position(endPosOfStringEntry - stringsEntrySize);
-
-            /*
-             * write the Long in the Strings section
-             */
-            try {
-                buffer.putLong(sv.unboxLong());
-            } catch (StateValueTypeException e) {
-                /*
-                 * This should not happen, since the value told us it was of
-                 * type Long (corrupted value?)
-                 */
-                e.printStackTrace();
-            }
-            assert (buffer.position() == endPosOfStringEntry);
-            buffer.reset();
+            buffer.putLong(sv.unboxLong());
             break;
 
         case TYPE_DOUBLE:
-            /* we use the valueOffset as an offset. */
-            buffer.putInt(endPosOfStringEntry - stringsEntrySize);
-            buffer.mark();
-            buffer.position(endPosOfStringEntry - stringsEntrySize);
-
-            /* Write the Double in the Strings section */
-            try {
-                buffer.putDouble(sv.unboxDouble());
-            } catch (StateValueTypeException e) {
-                /*
-                 * This should not happen, since the value told us it was of
-                 * type Double (corrupted value?)
-                 */
-                e.printStackTrace();
-            }
-            if (buffer.position() != endPosOfStringEntry) {
-                throw new IllegalStateException();
-            }
-            buffer.reset();
+            buffer.putDouble(sv.unboxDouble());
             break;
 
         default:
             break;
         }
-        return stringsEntrySize;
     }
 
     @Override
@@ -369,44 +305,13 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
         return false;
     }
 
-    int getStringsEntrySize() {
-        return stringsEntrySize;
-    }
-
     /**
      * Total serialized size of this interval
      *
      * @return The interval size
      */
-    public int getIntervalSize() {
-        return stringsEntrySize + DATA_ENTRY_SIZE;
-    }
-
-    private int computeStringsEntrySize() {
-        switch(sv.getType()) {
-        case NULL:
-        case INTEGER:
-            /* Those don't use the strings section at all */
-            return NO_ENTRY_SIZE;
-        case LONG:
-            /* The value's bytes are written directly into the strings section */
-            return LONG_ENTRY_SIZE;
-        case DOUBLE:
-            /* The value is also written directly into the strings section */
-            return DOUBLE_ENTRY_SIZE;
-        case STRING:
-            try {
-                /* String's length + 2 (1 byte for size, 1 byte for \0 at the end */
-                return sv.unboxStr().getBytes().length + 2;
-            } catch (StateValueTypeException e) {
-                /* We're inside a switch/case for the string type, can't happen */
-                throw new IllegalStateException(e);
-            }
-        default:
-            /* It's very important that we know how to write the state value in
-             * the file!! */
-            throw new IllegalStateException();
-        }
+    public int getSizeOnDisk() {
+        return fSizeOnDisk;
     }
 
     /**
@@ -458,11 +363,11 @@ public final class HTInterval implements ITmfStateInterval, Comparable<HTInterva
     }
 
     /**
-     * Here we determine how state values "types" are written in the 8-bit
-     * field that indicates the value type in the file.
+     * Here we determine how state values "types" are written in the 8-bit field
+     * that indicates the value type in the file.
      */
     private static byte getByteFromType(ITmfStateValue.Type type) {
-        switch(type) {
+        switch (type) {
         case NULL:
             return TYPE_NULL;
         case INTEGER:
index b006d190af7412debc039617d4d84f04e6cdfe20..6fb5d644a510e2b14c62f161a16500b714d13c0d 100644 (file)
@@ -121,9 +121,6 @@ public abstract class HTNode {
     private final int fSequenceNumber;
     private int fParentSequenceNumber; /* = -1 if this node is the root node */
 
-    /* Where the Strings section begins (from the start of the node */
-    private int fStringSectionOffset;
-
     /* Sum of bytes of all intervals in the node */
     private int fSizeOfIntervalSection;
 
@@ -154,7 +151,6 @@ public abstract class HTNode {
         fSequenceNumber = seqNumber;
         fParentSequenceNumber = parentSeqNumber;
 
-        fStringSectionOffset = config.getBlockSize();
         fSizeOfIntervalSection = 0;
         fIsOnDisk = false;
         fIntervals = new ArrayList<>();
@@ -193,7 +189,6 @@ public abstract class HTNode {
         int seqNb = buffer.getInt();
         int parentSeqNb = buffer.getInt();
         int intervalCount = buffer.getInt();
-        int stringSectionOffset = buffer.getInt();
         buffer.get(); // TODO Used to be "isDone", to be removed from the header
 
         /* Now the rest of the header depends on the node type */
@@ -222,12 +217,11 @@ public abstract class HTNode {
         for (i = 0; i < intervalCount; i++) {
             HTInterval interval = HTInterval.readFrom(buffer);
             newNode.fIntervals.add(interval);
-            newNode.fSizeOfIntervalSection += HTInterval.DATA_ENTRY_SIZE;
+            newNode.fSizeOfIntervalSection += interval.getSizeOnDisk();
         }
 
         /* Assign the node's other information we have read previously */
         newNode.fNodeEnd = end;
-        newNode.fStringSectionOffset = stringSectionOffset;
         newNode.fIsOnDisk = true;
 
         return newNode;
@@ -250,7 +244,6 @@ public abstract class HTNode {
         fRwl.readLock().lock();
         try {
             final int blockSize = fConfig.getBlockSize();
-            int curStringsEntryEndPos = blockSize;
 
             ByteBuffer buffer = ByteBuffer.allocate(blockSize);
             buffer.order(ByteOrder.LITTLE_ENDIAN);
@@ -263,40 +256,22 @@ public abstract class HTNode {
             buffer.putInt(fSequenceNumber);
             buffer.putInt(fParentSequenceNumber);
             buffer.putInt(fIntervals.size());
-            buffer.putInt(fStringSectionOffset);
             buffer.put((byte) 1); // TODO Used to be "isDone", to be removed from header
 
             /* Now call the inner method to write the specific header part */
             writeSpecificHeader(buffer);
 
             /* Back to us, we write the intervals */
-            for (HTInterval interval : fIntervals) {
-                int size = interval.writeInterval(buffer, curStringsEntryEndPos);
-                curStringsEntryEndPos -= size;
-            }
+            fIntervals.forEach(i -> i.writeInterval(buffer));
 
             /*
-             * Write padding between the end of the Data section and the start
-             * of the Strings section (needed to fill the node in case there is
-             * no Strings section)
+             * Fill the rest with zeros
              */
-            while (buffer.position() < fStringSectionOffset) {
+            while (buffer.position() < blockSize) {
                 buffer.put((byte) 0);
             }
 
-            /*
-             * If the offsets were right, the size of the Strings section should
-             * be == to the expected size
-             */
-            if (curStringsEntryEndPos != fStringSectionOffset) {
-                throw new IllegalStateException("Wrong size of Strings section: Actual: " + curStringsEntryEndPos + ", Expected: " + fStringSectionOffset); //$NON-NLS-1$ //$NON-NLS-2$
-            }
-
             /* Finally, write everything in the Buffer to disk */
-
-            // if we don't do this, flip() will lose what's after.
-            buffer.position(blockSize);
-
             buffer.flip();
             int res = fc.write(buffer);
             if (res != blockSize) {
@@ -391,7 +366,7 @@ public abstract class HTNode {
         fRwl.writeLock().lock();
         try {
             /* Just in case, should be checked before even calling this function */
-            assert (newInterval.getIntervalSize() <= getNodeFreeSpace());
+            assert (newInterval.getSizeOnDisk() <= getNodeFreeSpace());
 
             /* Find the insert position to keep the list sorted */
             int index = fIntervals.size();
@@ -400,10 +375,8 @@ public abstract class HTNode {
             }
 
             fIntervals.add(index, newInterval);
-            fSizeOfIntervalSection += HTInterval.DATA_ENTRY_SIZE;
+            fSizeOfIntervalSection += newInterval.getSizeOnDisk();
 
-            /* Update the in-node offset "pointer" */
-            fStringSectionOffset -= (newInterval.getStringsEntrySize());
         } finally {
             fRwl.writeLock().unlock();
         }
@@ -577,7 +550,7 @@ public abstract class HTNode {
      */
     public int getNodeFreeSpace() {
         fRwl.readLock().lock();
-        int ret = fStringSectionOffset - getDataSectionEndOffset();
+        int ret = fConfig.getBlockSize() - getDataSectionEndOffset();
         fRwl.readLock().unlock();
 
         return ret;
index 1aa0c7528c9f5298dde953f543967f79612b7ca5..e4154496ac0bd10aca3261fe1d2240bd2964f81d 100644 (file)
@@ -51,7 +51,7 @@ public class HistoryTree {
     private static final int HISTORY_FILE_MAGIC_NUMBER = 0x05FFA900;
 
     /** File format version. Increment when breaking compatibility. */
-    private static final int FILE_VERSION = 5;
+    private static final int FILE_VERSION = 6;
 
     // ------------------------------------------------------------------------
     // Tree-specific configuration
@@ -462,7 +462,7 @@ public class HistoryTree {
         HTNode targetNode = fLatestBranch.get(indexOfNode);
 
         /* Verify if there is enough room in this node to store this interval */
-        if (interval.getIntervalSize() > targetNode.getNodeFreeSpace()) {
+        if (interval.getSizeOnDisk() > targetNode.getNodeFreeSpace()) {
             /* Nope, not enough room. Insert in a new sibling instead. */
             addSiblingNode(indexOfNode);
             tryInsertAtNode(interval, fLatestBranch.size() - 1);
This page took 0.034199 seconds and 5 git commands to generate.