diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/CompactRecordsTable.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/CompactRecordsTable.java index e269c4426848..5d69fe951c1c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/CompactRecordsTable.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/CompactRecordsTable.java @@ -103,7 +103,6 @@ public class CompactRecordsTable extends AbstractRecordsTable { private static final int CAPACITY_MASK = 0x7FFF0000; private static final int CAPACITY_SHIFT = 16; private static final int SPECIAL_POSITIVE_VALUE_FOR_SPECIAL_NEGATIVE_SIZE = 0xFFFF; - private static final int SPECIAL_NEGATIVE_SIZE = -1; @Override public int getSize(int record) { @@ -113,7 +112,7 @@ public class CompactRecordsTable extends AbstractRecordsTable { return myStorage.getInt(getOffset(-currentValue, SIZE_OFFSET_IN_INDIRECT_RECORD)); } int i = currentValue & SIZE_MASK; - if (i == SPECIAL_POSITIVE_VALUE_FOR_SPECIAL_NEGATIVE_SIZE) i = SPECIAL_NEGATIVE_SIZE; + if (i == SPECIAL_POSITIVE_VALUE_FOR_SPECIAL_NEGATIVE_SIZE) i = SPECIAL_NEGATIVE_SIZE_FOR_REMOVED_RECORD; return i; } @@ -130,13 +129,13 @@ public class CompactRecordsTable extends AbstractRecordsTable { } // size to fit in normal record [-1 .. 0xFFFF) - if (size >= 0xFFFF || size < SPECIAL_NEGATIVE_SIZE || forceSplit) { + if (size >= 0xFFFF || size < SPECIAL_NEGATIVE_SIZE_FOR_REMOVED_RECORD || forceSplit) { // introduce indirect record able to hold larger size range extendSizeAndCapacityRecord(record, size, getCapacity(record)); return; } - if (size == SPECIAL_NEGATIVE_SIZE) { + if (size == SPECIAL_NEGATIVE_SIZE_FOR_REMOVED_RECORD) { size = SPECIAL_POSITIVE_VALUE_FOR_SPECIAL_NEGATIVE_SIZE; } @@ -232,7 +231,7 @@ public class CompactRecordsTable extends AbstractRecordsTable { @Override public boolean validId() { assert hasNextId(); - return getSize(nextId) != -1; + return isSizeOfLiveRecord(getSize(nextId)); } }; } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/CompactStorageTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/CompactStorageTest.java index 4cdaecfcd295..020576cb9537 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/CompactStorageTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/CompactStorageTest.java @@ -52,6 +52,9 @@ public class CompactStorageTest extends StorageTestBase { int logicalRecordCount = countLiveLogicalRecords(); assertEquals(recordCount / 2, logicalRecordCount); + int removedRecordId = recordsList.getQuick(0); + assertEquals("No content for reading removed record",0, myStorage.readStream(removedRecordId).available()); + Disposer.dispose(myStorage); // compact is triggered myStorage = createStorage(getFileName()); assertEquals(myStorage.getLiveRecordsCount(), physicalRecordCount / 2); diff --git a/platform/util/src/com/intellij/util/io/storage/AbstractRecordsTable.java b/platform/util/src/com/intellij/util/io/storage/AbstractRecordsTable.java index 8a00546cbe01..2558b2667fba 100644 --- a/platform/util/src/com/intellij/util/io/storage/AbstractRecordsTable.java +++ b/platform/util/src/com/intellij/util/io/storage/AbstractRecordsTable.java @@ -52,6 +52,7 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable { private TIntArrayList myFreeRecordsList = null; private boolean myIsDirty = false; + protected static final int SPECIAL_NEGATIVE_SIZE_FOR_REMOVED_RECORD = -1; public AbstractRecordsTable(final File storageFilePath, final PagePool pool) throws IOException { myStorage = new RandomAccessDataFile(storageFilePath, pool); @@ -93,7 +94,7 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable { } else { final int result = myFreeRecordsList.remove(myFreeRecordsList.size() - 1); - assert getSize(result) == -1; + assert isSizeOfRemovedRecord(getSize(result)); setSize(result, 0); return result; } @@ -127,7 +128,7 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable { @Override public boolean validId() { assert hasNextId(); - return getSize(recordId) != -1; + return isSizeOfLiveRecord(getSize(recordId)); } }; } @@ -147,7 +148,7 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable { private TIntArrayList scanForFreeRecords() throws IOException { final TIntArrayList result = new TIntArrayList(); for (int i = 1; i <= getRecordsCount(); i++) { - if (getSize(i) == -1) { + if (isSizeOfRemovedRecord(getSize(i))) { result.add(i); } } @@ -194,7 +195,7 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable { markDirty(); ensureFreeRecordsScanned(); doCleanRecord(record); - setSize(record, -1); + setSize(record, SPECIAL_NEGATIVE_SIZE_FOR_REMOVED_RECORD); myFreeRecordsList.add(record); } @@ -248,4 +249,12 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable { myStorage.putInt(HEADER_MAGIC_OFFSET, getSafelyClosedMagic()); } } + + protected static boolean isSizeOfRemovedRecord(int length) { + return length == SPECIAL_NEGATIVE_SIZE_FOR_REMOVED_RECORD; + } + + protected static boolean isSizeOfLiveRecord(int length) { + return length != SPECIAL_NEGATIVE_SIZE_FOR_REMOVED_RECORD; + } } \ No newline at end of file diff --git a/platform/util/src/com/intellij/util/io/storage/AbstractStorage.java b/platform/util/src/com/intellij/util/io/storage/AbstractStorage.java index 10e040c72e44..1b91fb327541 100644 --- a/platform/util/src/com/intellij/util/io/storage/AbstractStorage.java +++ b/platform/util/src/com/intellij/util/io/storage/AbstractStorage.java @@ -255,8 +255,8 @@ public abstract class AbstractStorage implements Disposable, Forceable { protected byte[] readBytes(int record) throws IOException { synchronized (myLock) { final int length = myRecordsTable.getSize(record); - if (length == 0) return ArrayUtil.EMPTY_BYTE_ARRAY; - assert length > 0; + if (length == 0 || AbstractRecordsTable.isSizeOfRemovedRecord(length)) return ArrayUtil.EMPTY_BYTE_ARRAY; + assert length > 0:length; final long address = myRecordsTable.getAddress(record); byte[] result = new byte[length];