diff --git a/platform/util/storages/src/com/intellij/platform/util/io/storages/appendonlylog/AppendOnlyLog.java b/platform/util/storages/src/com/intellij/platform/util/io/storages/appendonlylog/AppendOnlyLog.java index f4f987702841..35b34386debf 100644 --- a/platform/util/storages/src/com/intellij/platform/util/io/storages/appendonlylog/AppendOnlyLog.java +++ b/platform/util/storages/src/com/intellij/platform/util/io/storages/appendonlylog/AppendOnlyLog.java @@ -36,7 +36,7 @@ public interface AppendOnlyLog extends Closeable, Flushable, CleanableStorage { * returned false definitely means id is not valid -- but returned true means 'id _looks_ like a valid record id', * because some implementations can't say for sure is id a valid record id or not. */ - boolean isValidId(long id); + boolean isValidId(long id) throws IOException; /** * @return true if all the records were read, false if reader stops the reading prematurely (by @@ -51,7 +51,7 @@ public interface AppendOnlyLog extends Closeable, Flushable, CleanableStorage { void flush() throws IOException; /** @return true if there are no records in the log */ - boolean isEmpty(); + boolean isEmpty() throws IOException; /** @return number of records appended to the log */ int recordsCount() throws IOException; diff --git a/platform/util/storages/src/com/intellij/platform/util/io/storages/appendonlylog/AppendOnlyLogOverMMappedFile.java b/platform/util/storages/src/com/intellij/platform/util/io/storages/appendonlylog/AppendOnlyLogOverMMappedFile.java index d68152903389..c5b78faaee20 100644 --- a/platform/util/storages/src/com/intellij/platform/util/io/storages/appendonlylog/AppendOnlyLogOverMMappedFile.java +++ b/platform/util/storages/src/com/intellij/platform/util/io/storages/appendonlylog/AppendOnlyLogOverMMappedFile.java @@ -5,8 +5,9 @@ import com.intellij.openapi.util.IntRef; import com.intellij.openapi.util.io.ContentTooBigException; import com.intellij.platform.util.io.storages.AlignmentUtils; import com.intellij.platform.util.io.storages.mmapped.MMappedFileStorage; -import com.intellij.util.io.Unmappable; +import com.intellij.util.io.ClosedStorageException; import com.intellij.util.io.IOUtil; +import com.intellij.util.io.Unmappable; import com.intellij.util.io.blobstorage.ByteBufferReader; import com.intellij.util.io.blobstorage.ByteBufferWriter; import org.jetbrains.annotations.ApiStatus; @@ -388,7 +389,7 @@ public final class AppendOnlyLogOverMMappedFile implements AppendOnlyLog, Unmapp headerPage = storage.pageByOffset(0L); - ByteBuffer headerPageBuffer = headerPage.rawPageBuffer(); + ByteBuffer headerPageBuffer = headerPageBuffer(); if (fileIsEmpty) { HeaderLayout.putMagicWord(headerPageBuffer, MAGIC_WORD); HeaderLayout.putImplementationVersion(headerPageBuffer, CURRENT_IMPLEMENTATION_VERSION); @@ -469,16 +470,16 @@ public final class AppendOnlyLogOverMMappedFile implements AppendOnlyLog, Unmapp * @return version of the log implementation (i.e., this class) used to create the file. * Current version is {@link #CURRENT_IMPLEMENTATION_VERSION} */ - public int getImplementationVersion() { - return HeaderLayout.readImplementationVersion(headerPage.rawPageBuffer()); + public int getImplementationVersion() throws IOException { + return HeaderLayout.readImplementationVersion(headerPageBuffer()); } /** @return version of _data_ stored in records -- up to the client to define/recognize it */ - public int getDataVersion() { + public int getDataVersion() throws IOException { return getIntHeaderField(HeaderLayout.EXTERNAL_VERSION_OFFSET); } - public void setDataVersion(int version) { + public void setDataVersion(int version) throws IOException { setIntHeaderField(HeaderLayout.EXTERNAL_VERSION_OFFSET, version); } @@ -488,7 +489,7 @@ public final class AppendOnlyLogOverMMappedFile implements AppendOnlyLog, Unmapp } /** @return arbitrary (user-defined) value from the Log's header, previously set by {@link #setUserDefinedHeaderField(int, int)} */ - public int getUserDefinedHeaderField(int fieldNo) { + public int getUserDefinedHeaderField(int fieldNo) throws IOException { int headerOffset = HeaderLayout.FIRST_UNUSED_OFFSET + fieldNo * Integer.BYTES; return getIntHeaderField(headerOffset); } @@ -498,7 +499,7 @@ public final class AppendOnlyLogOverMMappedFile implements AppendOnlyLog, Unmapp * There are 5 slots fieldNo=[0..5] available so far */ public void setUserDefinedHeaderField(int fieldNo, - int headerFieldValue) { + int headerFieldValue) throws IOException { int headerOffset = HeaderLayout.FIRST_UNUSED_OFFSET + fieldNo * Integer.BYTES; setIntHeaderField(headerOffset, headerFieldValue); } @@ -628,7 +629,7 @@ public final class AppendOnlyLogOverMMappedFile implements AppendOnlyLog, Unmapp } @Override - public boolean isValidId(long recordId) { + public boolean isValidId(long recordId) throws IOException { if (recordId <= 0) { return false; } @@ -663,7 +664,7 @@ public final class AppendOnlyLogOverMMappedFile implements AppendOnlyLog, Unmapp } @Override - public boolean isEmpty() { + public boolean isEmpty() throws IOException { return firstUnAllocatedOffset() == HeaderLayout.HEADER_SIZE && firstUnCommittedOffset() == HeaderLayout.HEADER_SIZE; } @@ -865,34 +866,34 @@ public final class AppendOnlyLogOverMMappedFile implements AppendOnlyLog, Unmapp } - private long firstUnAllocatedOffset() { + private long firstUnAllocatedOffset() throws IOException { return getLongHeaderField(HeaderLayout.NEXT_RECORD_TO_BE_ALLOCATED_OFFSET); } private boolean casFirstUnAllocatedOffset(long currentValue, - long newValue) { + long newValue) throws IOException { return INT64_OVER_BYTE_BUFFER.compareAndSet( - headerPage.rawPageBuffer(), + headerPageBuffer(), HeaderLayout.NEXT_RECORD_TO_BE_ALLOCATED_OFFSET, currentValue, newValue ); } - private long firstUnCommittedOffset() { + private long firstUnCommittedOffset() throws IOException { return getLongHeaderField(HeaderLayout.NEXT_RECORD_TO_BE_COMMITTED_OFFSET); } - private boolean casFirstUnCommittedOffset(long currentValue, long newValue) { + private boolean casFirstUnCommittedOffset(long currentValue, long newValue) throws IOException { return INT64_OVER_BYTE_BUFFER.compareAndSet( - headerPage.rawPageBuffer(), + headerPageBuffer(), HeaderLayout.NEXT_RECORD_TO_BE_COMMITTED_OFFSET, currentValue, newValue ); } - private int addToDataRecordsCount(int recordsCommitted) { + private int addToDataRecordsCount(int recordsCommitted) throws IOException { return (int)INT32_OVER_BYTE_BUFFER.getAndAdd( - headerPage.rawPageBuffer(), + headerPageBuffer(), HeaderLayout.RECORDS_COUNT_OFFSET, recordsCommitted ); @@ -1112,26 +1113,34 @@ public final class AppendOnlyLogOverMMappedFile implements AppendOnlyLog, Unmapp } - private int getIntHeaderField(int headerRelativeOffsetBytes) { - Objects.checkIndex(headerRelativeOffsetBytes, HeaderLayout.HEADER_SIZE - Integer.BYTES + 1); - return (int)INT32_OVER_BYTE_BUFFER.getVolatile(headerPage.rawPageBuffer(), headerRelativeOffsetBytes); + private ByteBuffer headerPageBuffer() throws IOException { + MMappedFileStorage.Page _headerPage = headerPage; + if(_headerPage == null) { + throw new ClosedStorageException("["+storagePath()+"] is already closed"); + } + return _headerPage.rawPageBuffer(); } - private long getLongHeaderField(int headerRelativeOffsetBytes) { + private int getIntHeaderField(int headerRelativeOffsetBytes) throws IOException { + Objects.checkIndex(headerRelativeOffsetBytes, HeaderLayout.HEADER_SIZE - Integer.BYTES + 1); + return (int)INT32_OVER_BYTE_BUFFER.getVolatile(headerPageBuffer(), headerRelativeOffsetBytes); + } + + private long getLongHeaderField(int headerRelativeOffsetBytes) throws IOException { Objects.checkIndex(headerRelativeOffsetBytes, HeaderLayout.HEADER_SIZE - Long.BYTES + 1); - return (long)INT64_OVER_BYTE_BUFFER.getVolatile(headerPage.rawPageBuffer(), headerRelativeOffsetBytes); + return (long)INT64_OVER_BYTE_BUFFER.getVolatile(headerPageBuffer(), headerRelativeOffsetBytes); } private void setIntHeaderField(int headerRelativeOffsetBytes, - int headerFieldValue) { + int headerFieldValue) throws IOException { Objects.checkIndex(headerRelativeOffsetBytes, HeaderLayout.HEADER_SIZE - Integer.BYTES + 1); - INT32_OVER_BYTE_BUFFER.setVolatile(headerPage.rawPageBuffer(), headerRelativeOffsetBytes, headerFieldValue); + INT32_OVER_BYTE_BUFFER.setVolatile(headerPageBuffer(), headerRelativeOffsetBytes, headerFieldValue); } private void setLongHeaderField(int headerRelativeOffsetBytes, - long headerFieldValue) { + long headerFieldValue) throws IOException { Objects.checkIndex(headerRelativeOffsetBytes, HeaderLayout.HEADER_SIZE - Long.BYTES + 1); - INT64_OVER_BYTE_BUFFER.setVolatile(headerPage.rawPageBuffer(), headerRelativeOffsetBytes, headerFieldValue); + INT64_OVER_BYTE_BUFFER.setVolatile(headerPageBuffer(), headerRelativeOffsetBytes, headerFieldValue); } //================== alignment: ========================================================================