don't use forward index for single entry indexes

GitOrigin-RevId: 6dc4afce26f0a7dde9a6183a797f26d1dc45e0a1
This commit is contained in:
Dmitry Batkovich
2019-10-10 15:31:26 +00:00
committed by intellij-monorepo-bot
parent 56c486c0ac
commit f8151e8af1
6 changed files with 165 additions and 8 deletions
+2
View File
@@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
@@ -12,5 +13,6 @@
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
<orderEntry type="library" name="commons-imaging" level="project" />
<orderEntry type="module" module-name="intellij.xml.psi.impl" />
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
</component>
</module>
@@ -0,0 +1,43 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.intellij.images.index;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.fixtures.BasePlatformTestCase;
import com.intellij.util.indexing.FileBasedIndex;
import org.intellij.images.util.ImageInfo;
import java.io.IOException;
import static org.junit.Assert.assertNotEquals;
public class ImageInfoIndexTest extends BasePlatformTestCase {
public void testIndexModification() throws IOException {
VirtualFile file = myFixture.addFileToProject("image.svg", "<svg width='300' height='300' xmlns='http://www.w3.org/2000/svg'></svg>").getVirtualFile();
long stamp = getIndexStamp();
ImageInfo value = getIndexValue(file);
VfsUtil.saveText(file, "<svg width='500' height='300' xmlns='http://www.w3.org/2000/svg'></svg>");
assertNotEquals(stamp, getIndexStamp());
assertNotEquals(value, getIndexValue(file));
stamp = getIndexStamp();
value = getIndexValue(file);
VfsUtil.saveText(file, "<svg width='500' height='300' xmlns='http://www.w3.org/2000/svg'><path d=\"M10 10\"/></svg>");
assertEquals(stamp, getIndexStamp());
assertEquals(value, getIndexValue(file));
}
private long getIndexStamp() {
return FileBasedIndex.getInstance().getIndexModificationStamp(ImageInfoIndex.INDEX_ID, myFixture.getProject());
}
private ImageInfo getIndexValue(VirtualFile file) {
return FileBasedIndex.getInstance().getFileData(ImageInfoIndex.INDEX_ID, file, myFixture.getProject()).values().iterator().next();
}
@Override
protected boolean isWriteActionRequired() {
return true;
}
}
@@ -34,6 +34,7 @@ import com.intellij.psi.tree.IStubFileElementType;
import com.intellij.util.BitUtil;
import com.intellij.util.indexing.*;
import com.intellij.util.indexing.impl.*;
import com.intellij.util.indexing.impl.forward.EmptyForwardIndex;
import com.intellij.util.io.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -16,11 +16,7 @@ import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.impl.*;
import com.intellij.util.indexing.impl.forward.AbstractMapForwardIndexAccessor;
import com.intellij.util.indexing.impl.forward.ForwardIndex;
import com.intellij.util.indexing.impl.forward.ForwardIndexAccessor;
import com.intellij.util.indexing.impl.forward.MapForwardIndexAccessor;
import com.intellij.util.indexing.impl.forward.PersistentMapBasedForwardIndex;
import com.intellij.util.indexing.impl.forward.*;
import gnu.trove.THashSet;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
@@ -51,6 +47,7 @@ public class VfsAwareMapReduceIndex<Key, Value, Input> extends MapReduceIndex<Ke
private final SnapshotInputMappingIndex<Key, Value, Input> mySnapshotInputMappings;
private final boolean myUpdateMappings;
private final boolean mySingleEntryIndex;
public VfsAwareMapReduceIndex(@NotNull IndexExtension<Key, Value, Input> extension,
@NotNull IndexStorage<Key, Value> storage) throws IOException {
@@ -85,6 +82,7 @@ public class VfsAwareMapReduceIndex<Key, Value, Input> extends MapReduceIndex<Ke
}
mySnapshotInputMappings = IndexImporterMappingIndex.wrap(snapshotInputMappings, extension);
myUpdateMappings = snapshotInputMappings instanceof UpdatableSnapshotInputMappingIndex;
mySingleEntryIndex = extension instanceof SingleEntryFileBasedIndexExtension;
installMemoryModeListener();
}
@@ -143,7 +141,8 @@ public class VfsAwareMapReduceIndex<Key, Value, Input> extends MapReduceIndex<Ke
@NotNull
protected InputDataDiffBuilder<Key, Value> getKeysDiffBuilderInMemoryMode(int inputId, @NotNull Map<Key, Value> keysAndValues) {
return new MapInputDataDiffBuilder<>(inputId, keysAndValues);
return mySingleEntryIndex ? new SingleEntryIndexForwardIndexAccessor.SingleValueDiffBuilder(inputId, keysAndValues)
: new MapInputDataDiffBuilder<>(inputId, keysAndValues);
}
@Override
@@ -355,6 +354,7 @@ public class VfsAwareMapReduceIndex<Key, Value, Input> extends MapReduceIndex<Ke
@Nullable
private static <Key, Value> ForwardIndexAccessor<Key, Value> getForwardIndexAccessor(@NotNull IndexExtension<Key, Value, ?> indexExtension) {
if (!shouldCreateForwardIndex(indexExtension)) return null;
if (indexExtension instanceof SingleEntryFileBasedIndexExtension) return new SingleEntryIndexForwardIndexAccessor(indexExtension);
return new MapForwardIndexAccessor<>(new InputMapExternalizer<>(indexExtension));
}
@@ -362,6 +362,7 @@ public class VfsAwareMapReduceIndex<Key, Value, Input> extends MapReduceIndex<Ke
private static ForwardIndex getForwardIndexMap(@NotNull IndexExtension<?, ?, ?> indexExtension)
throws IOException {
if (!shouldCreateForwardIndex(indexExtension)) return null;
if (indexExtension instanceof SingleEntryFileBasedIndexExtension<?>) return new EmptyForwardIndex(); // indexStorage and forwardIndex are same here
File indexStorageFile = IndexInfrastructure.getInputIndexStorageFile((ID<?, ?>)indexExtension.getName());
return new PersistentMapBasedForwardIndex(indexStorageFile, false);
}
@@ -0,0 +1,110 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.indexing.impl.forward;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.VolatileNotNullLazyValue;
import com.intellij.openapi.util.io.ByteArraySequence;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.*;
import com.intellij.util.indexing.impl.InputData;
import com.intellij.util.indexing.impl.InputDataDiffBuilder;
import com.intellij.util.indexing.impl.KeyValueUpdateProcessor;
import com.intellij.util.indexing.impl.RemovedKeyProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Map;
public class SingleEntryIndexForwardIndexAccessor<V> implements ForwardIndexAccessor<Integer, V> {
private static final Logger LOG = Logger.getInstance(SingleEntryIndexForwardIndexAccessor.class);
private final ID<Integer, V> myIndexId;
private final VolatileNotNullLazyValue<UpdatableIndex<Integer, V, ?>> myIndex = new VolatileNotNullLazyValue<UpdatableIndex<Integer, V, ?>>() {
@NotNull
@Override
protected UpdatableIndex<Integer, V, ?> compute() {
return ((FileBasedIndexImpl)FileBasedIndex.getInstance()).getIndex(myIndexId);
}
};
@SuppressWarnings("unchecked")
public SingleEntryIndexForwardIndexAccessor(IndexExtension<?, ?, V> extension) {
LOG.assertTrue(extension instanceof SingleEntryFileBasedIndexExtension);
myIndexId = (ID<Integer, V>)extension.getName();
}
@NotNull
@Override
public InputDataDiffBuilder<Integer, V> getDiffBuilder(int inputId, @Nullable ByteArraySequence sequence) throws IOException {
Ref<Map<Integer, V>> dataRef = Ref.create();
StorageException[] ex = {null};
ProgressManager.getInstance().executeNonCancelableSection(() -> {
try {
dataRef.set(myIndex.getValue().getIndexedFileData(inputId));
}
catch (StorageException e) {
ex[0] = e;
}
});
if (ex[0] != null) {
throw new IOException(ex[0]);
}
Map<Integer, V> currentData = dataRef.get();
return new SingleValueDiffBuilder<>(inputId, currentData);
}
@Nullable
@Override
public ByteArraySequence serializeIndexedData(@NotNull InputData<Integer, V> data) {
return null;
}
public static class SingleValueDiffBuilder<V> extends InputDataDiffBuilder<Integer, V> {
private final int myInputId;
private final boolean myContainsValue;
@Nullable
private final V myCurrentValue;
public SingleValueDiffBuilder(int inputId, @NotNull Map<Integer, V> currentData) {
this(inputId, !currentData.isEmpty(), ContainerUtil.getFirstItem(currentData.values()));
}
private SingleValueDiffBuilder(int inputId, boolean containsValue, @Nullable V currentValue) {
super(inputId);
myInputId = inputId;
myContainsValue = containsValue;
myCurrentValue = currentValue;
}
@Override
public boolean differentiate(@NotNull Map<Integer, V> newData,
@NotNull KeyValueUpdateProcessor<? super Integer, ? super V> addProcessor,
@NotNull KeyValueUpdateProcessor<? super Integer, ? super V> updateProcessor,
@NotNull RemovedKeyProcessor<? super Integer> removeProcessor) throws StorageException {
boolean newValueExists = !newData.isEmpty();
V newValue = ContainerUtil.getFirstItem(newData.values());
if (myContainsValue) {
if (!newValueExists) {
removeProcessor.process(myInputId, myInputId);
return true;
} else if (Comparing.equal(myCurrentValue, newValue)) {
return false;
} else {
updateProcessor.process(myInputId, newValue, myInputId);
return true;
}
} else {
if (newValueExists) {
addProcessor.process(myInputId, newValue, myInputId);
return true;
} else {
return false;
}
}
}
}
}
@@ -1,12 +1,12 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.stubs;
package com.intellij.util.indexing.impl.forward;
import com.intellij.openapi.util.io.ByteArraySequence;
import com.intellij.util.indexing.impl.forward.ForwardIndex;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class EmptyForwardIndex implements ForwardIndex {
public class EmptyForwardIndex implements ForwardIndex {
@Nullable
@Override
public ByteArraySequence get(@NotNull Integer key) {