diff --git a/java/compiler/impl/src/com/intellij/compiler/make/CachedPersistentHashMap.java b/java/compiler/impl/src/com/intellij/compiler/make/CachedPersistentHashMap.java index 12eb05e551e3..08ed18da40c0 100644 --- a/java/compiler/impl/src/com/intellij/compiler/make/CachedPersistentHashMap.java +++ b/java/compiler/impl/src/com/intellij/compiler/make/CachedPersistentHashMap.java @@ -53,21 +53,23 @@ public class CachedPersistentHashMap extends PersistentHashMap extends PersistentHashMap get(Integer integer) throws IOException { + protected Collection doGet(Integer integer) throws IOException { if (isBufferingMode.get()) { final Collection collection = tempMap.get(integer); if (collection != null) { return collection; } } - return super.get(integer); + return super.doGet(integer); } @Override - public synchronized void put(Integer integer, Collection ks) throws IOException { + protected void doPut(Integer integer, Collection ks) throws IOException { if (isBufferingMode.get()) { tempMap.put(integer, ks == null? Collections.emptySet() : ks); } else { - super.put(integer, ks); + super.doPut(integer, ks); } } @Override - public synchronized void remove(Integer integer) throws IOException { + protected void doRemove(Integer integer) throws IOException { if (isBufferingMode.get()) { tempMap.put(integer, Collections.emptySet()); } else { - super.remove(integer); + super.doRemove(integer); } } }; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java index da356061ab0d..6b83f5eca610 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java @@ -27,37 +27,39 @@ public class ValueContainerMap extends PersistentHashMap container) throws IOException { - ChangeTrackingValueContainer valueContainer = (ChangeTrackingValueContainer)container; - if (!valueContainer.needsCompacting()) { - final BufferExposingByteArrayOutputStream bytes = new BufferExposingByteArrayOutputStream(); - //noinspection IOResourceOpenedButNotSafelyClosed - final DataOutputStream _out = new DataOutputStream(bytes); - final TIntHashSet set = valueContainer.getInvalidated(); - if (set.size() > 0) { - for (int inputId : set.toArray()) { - ValueContainerExternalizer.saveInvalidateCommand(_out, inputId); + protected void doPut(Key key, ValueContainer container) throws IOException { + synchronized (myEnumerator) { + ChangeTrackingValueContainer valueContainer = (ChangeTrackingValueContainer)container; + if (!valueContainer.needsCompacting()) { + final BufferExposingByteArrayOutputStream bytes = new BufferExposingByteArrayOutputStream(); + //noinspection IOResourceOpenedButNotSafelyClosed + final DataOutputStream _out = new DataOutputStream(bytes); + final TIntHashSet set = valueContainer.getInvalidated(); + if (set.size() > 0) { + for (int inputId : set.toArray()) { + ValueContainerExternalizer.saveInvalidateCommand(_out, inputId); + } } - } - final ValueContainer toRemove = valueContainer.getRemovedDelta(); - if (toRemove.size() > 0) { - myValueContainerExternalizer.saveAsRemoved(_out, toRemove); - } - - final ValueContainer toAppend = valueContainer.getAddedDelta(); - if (toAppend.size() > 0) { - myValueContainerExternalizer.save(_out, toAppend); - } - - appendData(key, new PersistentHashMap.ValueDataAppender() { - public void append(final DataOutput out) throws IOException { - out.write(bytes.getInternalBuffer(), 0, bytes.size()); + final ValueContainer toRemove = valueContainer.getRemovedDelta(); + if (toRemove.size() > 0) { + myValueContainerExternalizer.saveAsRemoved(_out, toRemove); } - }); - } - else { - // rewrite the value container for defragmentation - super.put(key, valueContainer); + + final ValueContainer toAppend = valueContainer.getAddedDelta(); + if (toAppend.size() > 0) { + myValueContainerExternalizer.save(_out, toAppend); + } + + appendData(key, new PersistentHashMap.ValueDataAppender() { + public void append(final DataOutput out) throws IOException { + out.write(bytes.getInternalBuffer(), 0, bytes.size()); + } + }); + } + else { + // rewrite the value container for defragmentation + super.doPut(key, valueContainer); + } } } diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMap.java b/platform/util/src/com/intellij/util/io/PersistentHashMap.java index ae60e05fa38c..bbffefd7e465 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMap.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMap.java @@ -139,7 +139,7 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< private final LowMemoryWatcher myAppendCacheFlusher = LowMemoryWatcher.register(new LowMemoryWatcher.ForceableAdapter() { public void force() { //System.out.println("Flushing caches: " + myFile.getPath()); - synchronized (PersistentHashMap.this) { + synchronized (myEnumerator) { synchronized (PersistentEnumerator.ourLock) { clearAppenderCaches(); } @@ -253,7 +253,13 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< return new File(file.getParentFile(), file.getName() + DATA_FILE_EXTENSION); } - public synchronized void put(Key key, Value value) throws IOException { + public final void put(Key key, Value value) throws IOException { + synchronized (myEnumerator) { + doPut(key, value); + } + } + + protected void doPut(Key key, Value value) throws IOException { synchronized (PersistentEnumerator.ourLock) { myEnumerator.markDirty(true); myAppendCache.remove(key); @@ -278,16 +284,24 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } @Override - public synchronized int enumerate(Key name) throws IOException { - myIntAddressForNewRecord = canUseIntAddressForNewRecord(myValueStorage.getSize()); - return super.enumerate(name); + public final int enumerate(Key name) throws IOException { + synchronized (myEnumerator) { + myIntAddressForNewRecord = canUseIntAddressForNewRecord(myValueStorage.getSize()); + return super.enumerate(name); + } } public interface ValueDataAppender { void append(DataOutput out) throws IOException; } - public synchronized void appendData(Key key, ValueDataAppender appender) throws IOException { + public final void appendData(Key key, ValueDataAppender appender) throws IOException { + synchronized (myEnumerator) { + doAppendData(key, appender); + } + } + + protected void doAppendData(Key key, ValueDataAppender appender) throws IOException { myEnumerator.markDirty(true); final AppendStream stream = myAppendCache.get(key); @@ -298,9 +312,11 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< * Process all keys registered in the map. Note that keys which were removed after {@link #compact()} call will be processed as well. Use * {@link #processKeysWithExistingMapping(com.intellij.util.Processor)} to process only keys with existing mappings */ - public synchronized boolean processKeys(Processor processor) throws IOException { - myAppendCache.clear(); - return myEnumerator.iterateData(processor); + public final boolean processKeys(Processor processor) throws IOException { + synchronized (myEnumerator) { + myAppendCache.clear(); + return myEnumerator.iterateData(processor); + } } public Collection getAllKeysWithExistingMapping() throws IOException { @@ -309,8 +325,8 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< return values; } - public synchronized boolean processKeysWithExistingMapping(Processor processor) throws IOException { - synchronized (PersistentEnumerator.ourLock) { + public final boolean processKeysWithExistingMapping(Processor processor) throws IOException { + synchronized (myEnumerator) { return myEnumerator.processAllDataObject(processor, new PersistentEnumerator.DataFilter() { public boolean accept(final int id) { return readValueId(id).address != NULL_ADDR; @@ -319,7 +335,13 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } } - public synchronized Value get(Key key) throws IOException { + public final Value get(Key key) throws IOException { + synchronized (myEnumerator) { + return doGet(key); + } + } + + protected Value doGet(Key key) throws IOException { synchronized (PersistentEnumerator.ourLock) { myAppendCache.remove(key); final int id = tryEnumerate(key); @@ -330,7 +352,7 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< if (oldHeader.address == PersistentEnumerator.NULL_ID) { return null; } - + Pair readResult = myValueStorage.readBytes(oldHeader.address); if (readResult.first != null && readResult.first != oldHeader.address) { myEnumerator.markDirty(true); @@ -351,7 +373,13 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } } - public synchronized boolean containsMapping(Key key) throws IOException { + public final boolean containsMapping(Key key) throws IOException { + synchronized (myEnumerator) { + return doContainsMapping(key); + } + } + + protected boolean doContainsMapping(Key key) throws IOException { synchronized (PersistentEnumerator.ourLock) { myAppendCache.remove(key); final int id = tryEnumerate(key); @@ -362,7 +390,13 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } } - public synchronized void remove(Key key) throws IOException { + public final void remove(Key key) throws IOException { + synchronized (myEnumerator) { + doRemove(key); + } + } + + protected void doRemove(Key key) throws IOException { synchronized (PersistentEnumerator.ourLock) { myAppendCache.remove(key); final int id = tryEnumerate(key); @@ -380,11 +414,19 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } } - public final synchronized void markDirty() throws IOException { - myEnumerator.markDirty(true); + public final void markDirty() throws IOException { + synchronized (myEnumerator) { + myEnumerator.markDirty(true); + } } - public synchronized void force() { + public final void force() { + synchronized (myEnumerator) { + doForce(); + } + } + + protected void doForce() { synchronized (PersistentEnumerator.ourLock) { try { clearAppenderCaches(); @@ -400,7 +442,13 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< myValueStorage.force(); } - public synchronized void close() throws IOException { + public final void close() throws IOException { + synchronized (myEnumerator) { + doClose(); + } + } + + protected void doClose() throws IOException { synchronized (PersistentEnumerator.ourLock) { try { myAppendCacheFlusher.stop(); @@ -412,10 +460,10 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } } } - + // made public for tests - public synchronized void compact() throws IOException { - synchronized (PersistentEnumerator.ourLock) { + public void compact() throws IOException { + synchronized (myEnumerator) { final long now = System.currentTimeMillis(); final String newPath = getDataFile(myEnumerator.myFile).getPath() + ".new"; final PersistentHashMapValueStorage newStorage = PersistentHashMapValueStorage.create(newPath);