diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 494e851f69eb..32de16aba15f 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -45,14 +45,14 @@ class IntToIntBtree { private TIntIntHashMap myCachedMappings; private final int myCachedMappingsSize; - public IntToIntBtree(int _pageSize, File file, boolean initial) throws IOException { + public IntToIntBtree(int _pageSize, File file, PagedFileStorage.StorageLockContext storageLockContext, boolean initial) throws IOException { pageSize = _pageSize; if (initial) { FileUtil.delete(file); } - storage = new ResizeableMappedFile(file, pageSize, PersistentEnumeratorBase.ourLock, 1024 * 1024, true); + storage = new ResizeableMappedFile(file, pageSize, storageLockContext, 1024 * 1024, true); root = new BtreeIndexNodeView(this); if (initial) { diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index 8be638b4636f..571b399201a5 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -34,6 +34,7 @@ import java.util.Comparator; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantLock; /** * @author max @@ -69,7 +70,7 @@ public class PagedFileStorage implements Forceable { "; mmap=" + (!ByteBufferWrapper.NO_MMAP)); } - private final StorageLock myLock; + private final StorageLockContext myStorageLockContext; private int myLastPage = UNKNOWN_PAGE; private int myLastPage2 = UNKNOWN_PAGE; private ByteBufferWrapper myLastBuffer; @@ -81,10 +82,23 @@ public class PagedFileStorage implements Forceable { private static final int MAX_PAGES_COUNT = 0xFFFF; private static final int MAX_LIVE_STORAGES_COUNT = 0xFFFF; + public void lock() { + myStorageLockContext.myReentrantLock.lock(); + } + + public void unlock() { + myStorageLockContext.myReentrantLock.unlock(); + } + + public StorageLockContext getStorageLockContext() { + return myStorageLockContext; + } + public static class StorageLock { private static final int FILE_INDEX_MASK = 0xFFFF0000; private static final int FILE_INDEX_SHIFT = 16; private final boolean checkThreadAccess; + public final StorageLockContext myDefaultStorageLockContext; public StorageLock() { this(true); @@ -92,11 +106,12 @@ public class PagedFileStorage implements Forceable { public StorageLock(boolean checkThreadAccess) { this.checkThreadAccess = checkThreadAccess; + myDefaultStorageLockContext = new StorageLockContext(this); } private final BuffersCache myBuffersCache = new BuffersCache(); private final ConcurrentHashMap myIndex2Storage = new ConcurrentHashMap(); - + private int registerPagedFileStorage(PagedFileStorage storage) { int registered = myIndex2Storage.size(); assert registered <= MAX_LIVE_STORAGES_COUNT; @@ -173,10 +188,10 @@ public class PagedFileStorage implements Forceable { @NotNull private ByteBufferWrapper createValue(Integer key) { - checkThreadAccess(); final int storageIndex = key & FILE_INDEX_MASK; PagedFileStorage owner = getRegisteredPagedFileStorageByIndex(storageIndex); assert owner != null: "No storage for index " + storageIndex; + checkThreadAccess(owner.myStorageLockContext); int off = (key & MAX_PAGES_COUNT) * owner.myPageSize; if (off > owner.length()) { throw new IndexOutOfBoundsException("off=" + off + " key.owner.length()=" + owner.length()); @@ -218,14 +233,14 @@ public class PagedFileStorage implements Forceable { } } - private void checkThreadAccess() { - if (checkThreadAccess && !Thread.holdsLock(StorageLock.this)) { + private void checkThreadAccess(StorageLockContext storageLockContext) { + if (checkThreadAccess && !storageLockContext.myReentrantLock.isHeldByCurrentThread()) { throw new IllegalStateException("Must hold StorageLock lock to access PagedFileStorage"); } } - private @Nullable Map getBuffersOrderedForOwner(int index) { - checkThreadAccess(); + private @Nullable Map getBuffersOrderedForOwner(int index, StorageLockContext storageLockContext) { + checkThreadAccess(storageLockContext); Map mineBuffers = null; for (Map.Entry entry : myMap.entrySet()) { if ((entry.getKey() & FILE_INDEX_MASK) == index) { @@ -243,8 +258,8 @@ public class PagedFileStorage implements Forceable { return mineBuffers; } - private void unmapBuffersForOwner(int index) { - final Map buffers = getBuffersOrderedForOwner(index); + private void unmapBuffersForOwner(int index, StorageLockContext storageLockContext) { + final Map buffers = getBuffersOrderedForOwner(index, storageLockContext); if (buffers != null) { for (Integer key : buffers.keySet()) { @@ -253,8 +268,8 @@ public class PagedFileStorage implements Forceable { } } - private void flushBuffersForOwner(int index) { - Map buffers = getBuffersOrderedForOwner(index); + private void flushBuffersForOwner(int index, StorageLockContext storageLockContext) { + Map buffers = getBuffersOrderedForOwner(index, storageLockContext); if (buffers != null) { for(ByteBufferWrapper buffer:buffers.values()) { @@ -274,14 +289,17 @@ public class PagedFileStorage implements Forceable { @NonNls private static final String RW = "rw"; public PagedFileStorage(File file, StorageLock lock, int pageSize, boolean valuesAreBufferAligned) throws IOException { - myFile = file; - myLock = lock; - myPageSize = Math.max(pageSize > 0 ? pageSize : BUFFER_SIZE, Page.PAGE_SIZE); - myValuesAreBufferAligned = valuesAreBufferAligned; - myStorageIndex = lock.registerPagedFileStorage(this); - myTypedIOBuffer = valuesAreBufferAligned ? null:new byte[8]; + this(file, lock.myDefaultStorageLockContext, pageSize, valuesAreBufferAligned); } + public PagedFileStorage(File file, StorageLockContext storageLockContext, int pageSize, boolean valuesAreBufferAligned) throws IOException { + myFile = file; + myStorageLockContext = storageLockContext; + myPageSize = Math.max(pageSize > 0 ? pageSize : BUFFER_SIZE, Page.PAGE_SIZE); + myValuesAreBufferAligned = valuesAreBufferAligned; + myStorageIndex = storageLockContext.myLock.registerPagedFileStorage(this); + myTypedIOBuffer = valuesAreBufferAligned ? null:new byte[8]; + } public PagedFileStorage(File file, StorageLock lock) throws IOException { this(file, lock, BUFFER_SIZE, false); } @@ -452,13 +470,13 @@ public class PagedFileStorage implements Forceable { } finally { unmapAll(); - myLock.myIndex2Storage.remove(myStorageIndex); + myStorageLockContext.myLock.myIndex2Storage.remove(myStorageIndex); myStorageIndex = -1; } } private void unmapAll() { - myLock.myBuffersCache.unmapBuffersForOwner(myStorageIndex); + myStorageLockContext.myLock.myBuffersCache.unmapBuffersForOwner(myStorageIndex, myStorageLockContext); myLastPage = UNKNOWN_PAGE; myLastPage2 = UNKNOWN_PAGE; @@ -524,21 +542,21 @@ public class PagedFileStorage implements Forceable { private ByteBuffer getBuffer(int page) { if (myLastPage == page) { ByteBuffer buf = myLastBuffer.getCachedBuffer(); - if (buf != null && myLastChangeCount == myLock.myBuffersCache.changeCount) return buf; + if (buf != null && myLastChangeCount == myStorageLockContext.myLock.myBuffersCache.changeCount) return buf; } if (myLastPage2 == page) { ByteBuffer buf = myLastBuffer2.getCachedBuffer(); - if (buf != null && myLastChangeCount2 == myLock.myBuffersCache.changeCount) return buf; + if (buf != null && myLastChangeCount2 == myStorageLockContext.myLock.myBuffersCache.changeCount) return buf; } try { assert page <= MAX_PAGES_COUNT; if (myStorageIndex == -1) { - myStorageIndex = myLock.registerPagedFileStorage(this); + myStorageIndex = myStorageLockContext.myLock.registerPagedFileStorage(this); } - ByteBufferWrapper byteBufferWrapper = myLock.myBuffersCache.get(myStorageIndex | page); + ByteBufferWrapper byteBufferWrapper = myStorageLockContext.myLock.myBuffersCache.get(myStorageIndex | page); ByteBuffer buf = byteBufferWrapper.getBuffer(); if (myLastPage != page) { @@ -551,7 +569,7 @@ public class PagedFileStorage implements Forceable { myLastBuffer = byteBufferWrapper; } - myLastChangeCount = myLock.myBuffersCache.changeCount; + myLastChangeCount = myStorageLockContext.myLock.myBuffersCache.changeCount; return buf; } @@ -562,7 +580,7 @@ public class PagedFileStorage implements Forceable { public void force() { long started = IOStatistics.DEBUG ? System.currentTimeMillis():0; - myLock.myBuffersCache.flushBuffersForOwner(myStorageIndex); + myStorageLockContext.myLock.myBuffersCache.flushBuffersForOwner(myStorageIndex, myStorageLockContext); isDirty = false; if (IOStatistics.DEBUG) { @@ -576,4 +594,14 @@ public class PagedFileStorage implements Forceable { public boolean isDirty() { return isDirty; } + + public static class StorageLockContext { + private final ReentrantLock myReentrantLock; + private final StorageLock myLock; + + public StorageLockContext(StorageLock lock) { + myReentrantLock = new ReentrantLock(); + myLock = lock; + } + } } diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java index 1ed3f47ed6d7..7e57f9af80a8 100644 --- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java @@ -65,18 +65,29 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase dataDescriptor, int initialSize) throws IOException { - super(file, new ResizeableMappedFile(file, initialSize, ourLock, VALUE_PAGE_SIZE, true), dataDescriptor, initialSize, + this(file, dataDescriptor, initialSize, ourLock.myDefaultStorageLockContext); + } + + public PersistentBTreeEnumerator(@NotNull File file, + @NotNull KeyDescriptor dataDescriptor, + int initialSize, + PagedFileStorage.StorageLockContext lockContext) throws IOException { + super(file, new ResizeableMappedFile(file, initialSize, lockContext, VALUE_PAGE_SIZE, true), dataDescriptor, initialSize, ourVersion, new RecordBufferHandler(), false); myInlineKeysNoMapping = myDataDescriptor instanceof InlineKeyDescriptor && !wantKeyMapping(); myExternalKeysNoMapping = !(myDataDescriptor instanceof InlineKeyDescriptor) && !wantKeyMapping(); if (btree == null) { - synchronized (ourLock) { + try { + lockStorage(); storeVars(false); initBtree(false); storeBTreeVars(false); } + finally { + unlockStorage(); + } } } @@ -90,7 +101,7 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorBase 0) { - if (!p.process(value)) return false; - } - else { - int rec = -value; - while (rec != 0) { - int id = myStorage.getInt(rec); - if (!p.process(id)) return false; - rec = myStorage.getInt(rec + COLLISION_OFFSET); - } - } - return true; + if (value > 0) { + if (!p.process(value)) return false; } - }); - } + else { + int rec = -value; + while (rec != 0) { + int id = myStorage.getInt(rec); + if (!p.process(id)) return false; + rec = myStorage.getInt(rec + COLLISION_OFFSET); + } + } + return true; + } + }); } catch (IllegalStateException e) { CorruptedException corruptedException = new CorruptedException(myFile); corruptedException.initCause(e); throw corruptedException; + } finally { + unlockStorage(); } } @@ -244,9 +256,9 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorBase extends PersistentEnumeratorBase { private static final Version ourVersion = new Version(CORRECTLY_CLOSED_MAGIC, DIRTY_MAGIC); public PersistentEnumerator(@NotNull File file, @NotNull KeyDescriptor dataDescriptor, int initialSize) throws IOException { - super(file, new ResizeableMappedFile(file, initialSize, ourLock), dataDescriptor, initialSize, ourVersion, + this(file, dataDescriptor, initialSize, ourLock.myDefaultStorageLockContext); + } + + public PersistentEnumerator(@NotNull File file, + @NotNull KeyDescriptor dataDescriptor, + int initialSize, + PagedFileStorage.StorageLockContext storageLockContext) throws IOException { + super(file, new ResizeableMappedFile(file, initialSize, storageLockContext, -1, false), dataDescriptor, initialSize, ourVersion, new RecordBufferHandler(), true); } @@ -62,7 +69,8 @@ public class PersistentEnumerator extends PersistentEnumeratorBase { } private boolean traverseRecords(int vectorStart, int slotsCount, @NotNull RecordsProcessor p) throws IOException { - synchronized (ourLock) { + lockStorage(); + try { for (int slotIdx = 0; slotIdx < slotsCount; slotIdx++) { final int vector = myStorage.getInt(vectorStart + slotIdx * 4); if (vector < 0) { @@ -76,10 +84,14 @@ public class PersistentEnumerator extends PersistentEnumeratorBase { } return true; } + finally { + unlockStorage(); + } } protected synchronized int enumerateImpl(final Data value, final boolean onlyCheckForExisting, boolean saveNewValue) throws IOException { - synchronized (ourLock) { + lockStorage(); + try { int depth = 0; final int valueHC = myDataDescriptor.getHashCode(value); int hc = valueHC; @@ -163,6 +175,9 @@ public class PersistentEnumerator extends PersistentEnumeratorBase { return newId; } } + finally { + unlockStorage(); + } } protected int writeData(final Data value, int hashCode) { diff --git a/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java b/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java index 561014dfa154..3eaec39499d2 100644 --- a/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java +++ b/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java @@ -161,7 +161,8 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { myStorage = storage; - synchronized (ourLock) { + lockStorage(); + try { if (myStorage.length() == 0) { try { markDirty(true); @@ -203,17 +204,28 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { } } } + finally { + unlockStorage(); + } if (myDataDescriptor instanceof InlineKeyDescriptor) { myKeyStorage = null; myKeyReadStream = null; } else { - myKeyStorage = new ResizeableMappedFile(keystreamFile(), initialSize, ourLock); + myKeyStorage = new ResizeableMappedFile(keystreamFile(), initialSize, myStorage.getPagedFileStorage().getStorageLockContext(), -1, false); myKeyReadStream = new MyDataIS(myKeyStorage); } } + public void lockStorage() { + myStorage.getPagedFileStorage().lock(); + } + + public void unlockStorage() { + myStorage.getPagedFileStorage().unlock(); + } + protected abstract void setupEmptyFile() throws IOException; @NotNull @@ -277,27 +289,43 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { } protected void putMetaData(long data) throws IOException { - synchronized (ourLock) { + lockStorage(); + try { myStorage.putLong(META_DATA_OFFSET, data); } + finally { + unlockStorage(); + } } protected long getMetaData() throws IOException { - synchronized (ourLock) { + lockStorage(); + try { return myStorage.getLong(META_DATA_OFFSET); } + finally { + unlockStorage(); + } } protected void putMetaData2(long data) throws IOException { - synchronized (ourLock) { + lockStorage(); + try { myStorage.putLong(META_DATA_OFFSET + 8, data); } + finally { + unlockStorage(); + } } protected long getMetaData2() throws IOException { - synchronized (ourLock) { + lockStorage(); + try { return myStorage.getLong(META_DATA_OFFSET + 8); } + finally { + unlockStorage(); + } } public boolean processAllDataObject(final Processor processor, @Nullable final DataFilter filter) throws IOException { @@ -365,7 +393,8 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { } protected boolean iterateData(final Processor processor) throws IOException { - synchronized (ourLock) { + lockStorage(); + try { if (myKeyStorage == null) { throw new UnsupportedOperationException("Iteration over InlineIntegerKeyDescriptors is not supported"); } @@ -390,30 +419,35 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { keysStream.close(); } } + finally { + unlockStorage(); + } } private File keystreamFile() { return new File(myFile.getPath() + ".keystream"); } - public synchronized Data valueOf(int idx) throws IOException { - synchronized (ourLock) { - try { - int addr = indexToAddr(idx); + public Data valueOf(int idx) throws IOException { + lockStorage(); + try { + int addr = indexToAddr(idx); - if (myKeyReadStream == null) return ((InlineKeyDescriptor)myDataDescriptor).fromInt(addr); + if (myKeyReadStream == null) return ((InlineKeyDescriptor)myDataDescriptor).fromInt(addr); - myKeyReadStream.setup(addr, myKeyStorage.length()); - return myDataDescriptor.read(myKeyReadStream); - } - catch (IOException io) { - markCorrupted(); - throw io; - } - catch (Throwable e) { - markCorrupted(); - throw new RuntimeException(e); - } + myKeyReadStream.setup(addr, myKeyStorage.length()); + return myDataDescriptor.read(myKeyReadStream); + } + catch (IOException io) { + markCorrupted(); + throw io; + } + catch (Throwable e) { + markCorrupted(); + throw new RuntimeException(e); + } + finally { + unlockStorage(); } } @@ -452,12 +486,16 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { @Override public synchronized void close() throws IOException { - synchronized (ourLock) { + lockStorage(); + try { if (!myClosed) { myClosed = true; doClose(); } } + finally { + unlockStorage(); + } } protected void doClose() throws IOException { @@ -482,11 +520,15 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { } private synchronized void flush() throws IOException { - synchronized (ourLock) { + lockStorage(); + try { if (myStorage.isDirty() || isDirty()) { doFlush(); } } + finally { + unlockStorage(); + } } protected void doFlush() throws IOException { @@ -496,23 +538,27 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { @Override public synchronized void force() { - synchronized (ourLock) { - try { - if (myKeyStorage != null) { - myKeyStorage.force(); - } - flush(); - } - catch (IOException e) { - throw new RuntimeException(e); + lockStorage(); + + try { + if (myKeyStorage != null) { + myKeyStorage.force(); } + flush(); + } + catch (IOException e) { + throw new RuntimeException(e); + } + finally { + unlockStorage(); } } protected final void markDirty(boolean dirty) throws IOException { //assert Thread.holdsLock(this) || Thread.holdsLock(ourLock); // we hold one lock or another so can access myDirty if (dirty && myDirty && !myDirtyStatusUpdateInProgress) return; - synchronized (ourLock) { + lockStorage(); + try { if (myDirty) { if (!dirty) { myDirtyStatusUpdateInProgress = true; @@ -533,6 +579,9 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { } } } + finally { + unlockStorage(); + } } protected synchronized void markCorrupted() { diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMap.java b/platform/util/src/com/intellij/util/io/PersistentHashMap.java index f1bd5d06bf37..61daaf1f6147 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMap.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMap.java @@ -100,24 +100,26 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< @Override protected void onDropFromCache(final Key key, @NotNull final AppendStream value) { - synchronized (PersistentEnumerator.ourLock) { - try { - final BufferExposingByteArrayOutputStream bytes = value.getInternalBuffer(); - final int id = enumerate(key); - long oldHeaderRecord = readValueId(id); + myEnumerator.lockStorage(); + try { + final BufferExposingByteArrayOutputStream bytes = value.getInternalBuffer(); + final int id = enumerate(key); + long oldHeaderRecord = readValueId(id); - long headerRecord = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), oldHeaderRecord); + long headerRecord = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), oldHeaderRecord); - updateValueId(id, headerRecord, oldHeaderRecord, key, 0); - if (oldHeaderRecord == NULL_ADDR) { - myLiveAndGarbageKeysCounter += LIVE_KEY_MASK; - } - - myStreamPool.recycle(value); - } - catch (IOException e) { - throw new RuntimeException(e); + updateValueId(id, headerRecord, oldHeaderRecord, key, 0); + if (oldHeaderRecord == NULL_ADDR) { + myLiveAndGarbageKeysCounter += LIVE_KEY_MASK; } + + myStreamPool.recycle(value); + } + catch (IOException e) { + throw new RuntimeException(e); + } + finally { + myEnumerator.unlockStorage(); } } }; @@ -213,9 +215,13 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< public void dropMemoryCaches() { synchronized (myEnumerator) { - synchronized (PersistentEnumerator.ourLock) { + myEnumerator.lockStorage(); + try { clearAppenderCaches(); } + finally { + myEnumerator.unlockStorage(); + } } } @@ -283,7 +289,8 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } protected void doPut(Key key, Value value) throws IOException { - synchronized (PersistentEnumerator.ourLock) { + myEnumerator.lockStorage(); + try { myEnumerator.markDirty(true); myAppendCache.remove(key); @@ -304,6 +311,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< updateValueId(id, header, oldheader, key, 0); } + finally { + myEnumerator.unlockStorage(); + } } @Override @@ -371,7 +381,8 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< @Nullable protected Value doGet(Key key) throws IOException { - synchronized (PersistentEnumerator.ourLock) { + myEnumerator.lockStorage(); + try { myAppendCache.remove(key); final int id = tryEnumerate(key); if (id == PersistentEnumerator.NULL_ID) { @@ -399,6 +410,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< input.close(); } } + finally { + myEnumerator.unlockStorage(); + } } public final boolean containsMapping(Key key) throws IOException { @@ -408,7 +422,8 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } protected boolean doContainsMapping(Key key) throws IOException { - synchronized (PersistentEnumerator.ourLock) { + myEnumerator.lockStorage(); + try { myAppendCache.remove(key); final int id = tryEnumerate(key); if (id == PersistentEnumerator.NULL_ID) { @@ -416,6 +431,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } return readValueId(id) != NULL_ADDR; } + finally { + myEnumerator.unlockStorage(); + } } public final void remove(Key key) throws IOException { @@ -425,7 +443,8 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } protected void doRemove(Key key) throws IOException { - synchronized (PersistentEnumerator.ourLock) { + myEnumerator.lockStorage(); + try { myAppendCache.remove(key); final int id = tryEnumerate(key); if (id == PersistentEnumerator.NULL_ID) { @@ -440,6 +459,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< updateValueId(id, NULL_ADDR, record, key, 0); } + finally { + myEnumerator.unlockStorage(); + } } @Override @@ -457,7 +479,8 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } protected void doForce() { - synchronized (PersistentEnumerator.ourLock) { + myEnumerator.lockStorage(); + try { try { clearAppenderCaches(); } @@ -465,6 +488,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< super.force(); } } + finally { + myEnumerator.unlockStorage(); + } } private void clearAppenderCaches() { @@ -480,7 +506,8 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } protected void doClose() throws IOException { - synchronized (PersistentEnumerator.ourLock) { + myEnumerator.lockStorage(); + try { try { myAppendCacheFlusher.stop(); myAppendCache.clear(); @@ -493,6 +520,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< super.close(); } } + finally { + myEnumerator.unlockStorage(); + } } // made public for tests diff --git a/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java b/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java index fe2a2e12436d..dc2129daf2e3 100644 --- a/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java +++ b/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java @@ -31,8 +31,8 @@ public class ResizeableMappedFile implements Forceable { private long myLogicalSize; private final PagedFileStorage myStorage; - public ResizeableMappedFile(final File file, int initialSize, PagedFileStorage.StorageLock lock, int pageSize, boolean valuesAreBufferAligned) throws IOException { - myStorage = new PagedFileStorage(file, lock, pageSize, valuesAreBufferAligned); + public ResizeableMappedFile(final File file, int initialSize, PagedFileStorage.StorageLockContext lockContext, int pageSize, boolean valuesAreBufferAligned) throws IOException { + myStorage = new PagedFileStorage(file, lockContext, pageSize, valuesAreBufferAligned); boolean exists = file.exists(); if (!exists || file.length() == 0) { if (!exists) FileUtil.createParentDirs(file); @@ -41,12 +41,20 @@ public class ResizeableMappedFile implements Forceable { myLogicalSize = readLength(); if (myLogicalSize == 0) { - synchronized (lock) { + try { + getPagedFileStorage().lock(); resize(initialSize); } + finally { + getPagedFileStorage().unlock(); + } } } + public ResizeableMappedFile(final File file, int initialSize, PagedFileStorage.StorageLock lock, int pageSize, boolean valuesAreBufferAligned) throws IOException { + this(file, initialSize, lock.myDefaultStorageLockContext, pageSize, valuesAreBufferAligned); + } + public ResizeableMappedFile(final File file, int initialSize, PagedFileStorage.StorageLock lock) throws IOException { this(file, initialSize, lock, -1, false); }