diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java index 913f57ee14d3..913faaeefe79 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java @@ -18,6 +18,7 @@ package com.intellij.util.indexing; import com.intellij.openapi.util.Computable; import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.DataInputOutputUtil; import gnu.trove.TIntHashSet; import gnu.trove.TIntProcedure; import org.jetbrains.annotations.NotNull; @@ -88,11 +89,6 @@ class ChangeTrackingValueContainer extends UpdatableValueContainer return getMergedData().toValueList(); } - @Override - public boolean isAssociated(final Value value, final int inputId) { - return getMergedData().isAssociated(value, inputId); - } - @NotNull @Override public IntPredicate getValueAssociationPredicate(Value value) { @@ -168,10 +164,6 @@ class ChangeTrackingValueContainer extends UpdatableValueContainer return myAdded; } - public @Nullable TIntHashSet getInvalidated() { - return myInvalidated; - } - @Override public void saveTo(DataOutput out, DataExternalizer externalizer) throws IOException { if (needsCompacting()) { @@ -180,7 +172,7 @@ class ChangeTrackingValueContainer extends UpdatableValueContainer final TIntHashSet set = myInvalidated; if (set != null && set.size() > 0) { for (int inputId : set.toArray()) { - ValueContainerImpl.saveInvalidateCommand(out, inputId); + DataInputOutputUtil.writeINT(out, -inputId); // mark inputId as invalid, to be processed on load in ValueContainerImpl.readFrom } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index f357f2bec8aa..bd8282e1e173 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -965,7 +965,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { final int restrictedFileId = getFileId(restrictToFile); for (final Iterator valueIt = container.getValueIterator(); valueIt.hasNext(); ) { final V value = valueIt.next(); - if (container.isAssociated(value, restrictedFileId)) { + if (container.getValueAssociationPredicate(value).contains(restrictedFileId)) { shouldContinue = processor.process(restrictToFile, value); if (!shouldContinue) { break; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java index 3a5864d1c908..14234ad3b785 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java @@ -29,23 +29,23 @@ import java.util.List; * Date: Dec 14, 2007 */ public abstract class ValueContainer { - interface IntIterator { + public interface IntIterator { boolean hasNext(); int next(); int size(); + + boolean hasAscendingOrder(); } - abstract static class IntPredicate { - abstract boolean contains(int id); + public interface IntPredicate { + boolean contains(int id); } @NotNull public abstract IntIterator getInputIdsIterator(Value value); - public abstract boolean isAssociated(Value value, int inputId); - @NotNull public abstract IntPredicate getValueAssociationPredicate(Value value); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java index 8fb895ba7e00..4944b949053e 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java @@ -19,7 +19,6 @@ package com.intellij.util.indexing; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.ThreadLocalCachedIntArray; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.SmartList; import com.intellij.util.containers.EmptyIterator; import com.intellij.util.io.DataExternalizer; @@ -30,7 +29,10 @@ import org.jetbrains.annotations.NotNull; import java.io.DataInputStream; import java.io.DataOutput; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; /** * @author Eugene Zhuravlev @@ -90,7 +92,7 @@ class ValueContainerImpl extends UpdatableValueContainer implement List toRemove = null; for (final Iterator valueIterator = getValueIterator(); valueIterator.hasNext();) { final Value value = valueIterator.next(); - if (isAssociated(value, inputId)) { + if (getValueAssociationPredicate(value).contains(inputId)) { if (toRemove == null) toRemove = new SmartList(); else if (ApplicationInfoImpl.getShadowInstance().isEAP()) { LOG.error("Expected only one value per-inputId", String.valueOf(toRemove.get(0)), String.valueOf(value)); @@ -211,21 +213,6 @@ class ValueContainerImpl extends UpdatableValueContainer implement } } - @Override - public boolean isAssociated(Value value, final int inputId) { - final Object input = getInput(value); - if (input instanceof TIntHashSet) { - return ((TIntHashSet)input).contains(inputId); - } - if (input instanceof Integer ){ - return inputId == ((Integer)input).intValue(); - } - if (input instanceof IdBitSet) { - return ((IdBitSet)input).get(inputId); - } - return false; - } - @NotNull @Override public IntPredicate getValueAssociationPredicate(Value value) { @@ -244,7 +231,7 @@ class ValueContainerImpl extends UpdatableValueContainer implement return new IntPredicate() { final IdBitSet myIdBitSet = (IdBitSet)input; @Override - boolean contains(int id) { + public boolean contains(int id) { return myIdBitSet.get(id); } }; @@ -252,7 +239,7 @@ class ValueContainerImpl extends UpdatableValueContainer implement return new IntPredicate() { final TIntHashSet mySet = (TIntHashSet)input; @Override - boolean contains(int id) { + public boolean contains(int id) { return mySet.contains(id); } }; @@ -261,8 +248,11 @@ class ValueContainerImpl extends UpdatableValueContainer implement @NotNull @Override public IntIterator getInputIdsIterator(Value value) { - final Object input = getInput(value); - final IntIterator it; + return getIntIteratorFromInput(getInput(value)); + } + + private IntIterator getIntIteratorFromInput(final Object input) { + IntIterator it; if (input instanceof TIntHashSet) { it = new IntSetIterator((TIntHashSet)input); } @@ -289,6 +279,11 @@ class ValueContainerImpl extends UpdatableValueContainer implement public int size() { return myIdBitSet.numberOfBitsSet(); } + + @Override + public boolean hasAscendingOrder() { + return true; + } }; } else { @@ -345,6 +340,11 @@ class ValueContainerImpl extends UpdatableValueContainer implement public int size() { return 0; } + + @Override + public boolean hasAscendingOrder() { + return false; + } }; @NotNull @@ -454,38 +454,39 @@ class ValueContainerImpl extends UpdatableValueContainer implement if (input instanceof Integer) { DataInputOutputUtil.writeINT(out, (Integer)input); // most common 90% case during index building } else { - // serialize positive file ids with delta encoding after sorting numbers via bitset + // serialize positive file ids with delta encoding + IntIterator inputIdIterator = getIntIteratorFromInput(input); + DataInputOutputUtil.writeINT(out, -inputIdIterator.size()); - if (input instanceof TIntHashSet) { - TIntHashSet set = (TIntHashSet)input; - DataInputOutputUtil.writeINT(out, -set.size()); - // todo it would be nice to have compressed random access serializable bitset or at least file ids sorted - final int[] max = {0}, min = {Integer.MAX_VALUE}; + if (inputIdIterator.hasAscendingOrder()) { + int prev = 0; + while(inputIdIterator.hasNext()) { + int inputId = inputIdIterator.next(); + DataInputOutputUtil.writeINT(out, inputId - prev); + prev = inputId; + } + } else { + // sorting numbers via bitset before writing deltas + int max = 0, min = Integer.MAX_VALUE; - set.forEach(new TIntProcedure() { - @Override - public boolean execute(int value) { - max[0] = Math.max(max[0], value); - min[0] = Math.min(min[0], value); - return true; - } - }); + while(inputIdIterator.hasNext()) { + int inputId = inputIdIterator.next(); + max = Math.max(max, inputId); + min = Math.min(min, inputId); + } - assert min[0] > 0; + assert min > 0; - final int offset = (min[0] >> INT_BITS_SHIFT) << INT_BITS_SHIFT; - final int bitsLength = ((max[0] - offset) >> INT_BITS_SHIFT) + 1; + final int offset = (min >> INT_BITS_SHIFT) << INT_BITS_SHIFT; + final int bitsLength = ((max - offset) >> INT_BITS_SHIFT) + 1; final int[] bits = ourSpareBuffer.getBuffer(bitsLength); for(int i = 0; i < bitsLength; ++i) bits[i] = 0; - set.forEach(new TIntProcedure() { - @Override - public boolean execute(int value) { - final int id = value - offset; - bits[id >> INT_BITS_SHIFT] |= (1 << (id)); - return true; - } - }); + inputIdIterator = getIntIteratorFromInput(input); + while(inputIdIterator.hasNext()) { + final int id = inputIdIterator.next() - offset; + bits[id >> INT_BITS_SHIFT] |= (1 << (id)); + } int pos = nextSetBit(0, bits, bitsLength); int prev = 0; @@ -495,35 +496,16 @@ class ValueContainerImpl extends UpdatableValueContainer implement prev = pos + offset; pos = nextSetBit(pos + 1, bits, bitsLength); } - } else if (input instanceof IdBitSet) { - IdBitSet idBitSet = (IdBitSet)input; - - DataInputOutputUtil.writeINT(out, -idBitSet.numberOfBitsSet()); - - int pos = idBitSet.nextSetBit(0); - int prev = 0; - - while (pos != -1) { - DataInputOutputUtil.writeINT(out, pos - prev); - prev = pos; - pos = idBitSet.nextSetBit(pos + 1); - } - } else { - throw new IncorrectOperationException("Unexpected else"); } } } } - static void saveInvalidateCommand(DataOutput out, int inputId) throws IOException { - DataInputOutputUtil.writeINT(out, -inputId); - } - public void readFrom(DataInputStream stream, DataExternalizer externalizer) throws IOException { while (stream.available() > 0) { final int valueCount = DataInputOutputUtil.readINT(stream); if (valueCount < 0) { - removeAssociatedValue(-valueCount); + removeAssociatedValue(-valueCount); // ChangeTrackingValueContainer marked inputId as invalidated, see ChangeTrackingValueContainer.saveTo setNeedsCompacting(true); } else { @@ -571,6 +553,11 @@ class ValueContainerImpl extends UpdatableValueContainer implement public int size() { return 1; } + + @Override + public boolean hasAscendingOrder() { + return true; + } } private static class IntSetIterator implements IntIterator { @@ -596,6 +583,11 @@ class ValueContainerImpl extends UpdatableValueContainer implement public int size() { return mySize; } + + @Override + public boolean hasAscendingOrder() { + return false; + } } private THashMap mapCopy(final THashMap map) {