From f8151e8af1bb9db7ac35e76ab01b02a3c5d14f7a Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 9 Oct 2019 08:45:25 +0300 Subject: [PATCH] don't use forward index for single entry indexes GitOrigin-RevId: 6dc4afce26f0a7dde9a6183a797f26d1dc45e0a1 --- images/intellij.platform.images.iml | 2 + .../images/index/ImageInfoIndexTest.java | 43 +++++++ .../intellij/psi/stubs/StubUpdatingIndex.java | 1 + .../util/indexing/VfsAwareMapReduceIndex.java | 13 ++- .../SingleEntryIndexForwardIndexAccessor.java | 110 ++++++++++++++++++ .../impl/forward}/EmptyForwardIndex.java | 4 +- 6 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 images/test/org/intellij/images/index/ImageInfoIndexTest.java create mode 100644 platform/lang-impl/src/com/intellij/util/indexing/impl/forward/SingleEntryIndexForwardIndexAccessor.java rename platform/{lang-impl/src/com/intellij/psi/stubs => util/src/com/intellij/util/indexing/impl/forward}/EmptyForwardIndex.java (86%) diff --git a/images/intellij.platform.images.iml b/images/intellij.platform.images.iml index 4ccd82898b87..626e6e4930c7 100644 --- a/images/intellij.platform.images.iml +++ b/images/intellij.platform.images.iml @@ -5,6 +5,7 @@ + @@ -12,5 +13,6 @@ + \ No newline at end of file diff --git a/images/test/org/intellij/images/index/ImageInfoIndexTest.java b/images/test/org/intellij/images/index/ImageInfoIndexTest.java new file mode 100644 index 000000000000..95c5ca52c7cf --- /dev/null +++ b/images/test/org/intellij/images/index/ImageInfoIndexTest.java @@ -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", "").getVirtualFile(); + long stamp = getIndexStamp(); + ImageInfo value = getIndexValue(file); + + VfsUtil.saveText(file, ""); + assertNotEquals(stamp, getIndexStamp()); + assertNotEquals(value, getIndexValue(file)); + stamp = getIndexStamp(); + value = getIndexValue(file); + + VfsUtil.saveText(file, ""); + 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; + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index f650cef48353..8cabb4a0a936 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -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; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java index 31b7546f9825..68d3808e128f 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java @@ -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 extends MapReduceIndex mySnapshotInputMappings; private final boolean myUpdateMappings; + private final boolean mySingleEntryIndex; public VfsAwareMapReduceIndex(@NotNull IndexExtension extension, @NotNull IndexStorage storage) throws IOException { @@ -85,6 +82,7 @@ public class VfsAwareMapReduceIndex extends MapReduceIndex extends MapReduceIndex getKeysDiffBuilderInMemoryMode(int inputId, @NotNull Map 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 extends MapReduceIndex ForwardIndexAccessor getForwardIndexAccessor(@NotNull IndexExtension 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 extends MapReduceIndex 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); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/impl/forward/SingleEntryIndexForwardIndexAccessor.java b/platform/lang-impl/src/com/intellij/util/indexing/impl/forward/SingleEntryIndexForwardIndexAccessor.java new file mode 100644 index 000000000000..6efa0cd968cb --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/indexing/impl/forward/SingleEntryIndexForwardIndexAccessor.java @@ -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 implements ForwardIndexAccessor { + private static final Logger LOG = Logger.getInstance(SingleEntryIndexForwardIndexAccessor.class); + private final ID myIndexId; + private final VolatileNotNullLazyValue> myIndex = new VolatileNotNullLazyValue>() { + @NotNull + @Override + protected UpdatableIndex compute() { + return ((FileBasedIndexImpl)FileBasedIndex.getInstance()).getIndex(myIndexId); + } + }; + + @SuppressWarnings("unchecked") + public SingleEntryIndexForwardIndexAccessor(IndexExtension extension) { + LOG.assertTrue(extension instanceof SingleEntryFileBasedIndexExtension); + myIndexId = (ID)extension.getName(); + } + + @NotNull + @Override + public InputDataDiffBuilder getDiffBuilder(int inputId, @Nullable ByteArraySequence sequence) throws IOException { + Ref> 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 currentData = dataRef.get(); + + return new SingleValueDiffBuilder<>(inputId, currentData); + } + + @Nullable + @Override + public ByteArraySequence serializeIndexedData(@NotNull InputData data) { + return null; + } + + public static class SingleValueDiffBuilder extends InputDataDiffBuilder { + private final int myInputId; + private final boolean myContainsValue; + @Nullable + private final V myCurrentValue; + + public SingleValueDiffBuilder(int inputId, @NotNull Map 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 newData, + @NotNull KeyValueUpdateProcessor addProcessor, + @NotNull KeyValueUpdateProcessor updateProcessor, + @NotNull RemovedKeyProcessor 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; + } + } + } + } +} diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/EmptyForwardIndex.java b/platform/util/src/com/intellij/util/indexing/impl/forward/EmptyForwardIndex.java similarity index 86% rename from platform/lang-impl/src/com/intellij/psi/stubs/EmptyForwardIndex.java rename to platform/util/src/com/intellij/util/indexing/impl/forward/EmptyForwardIndex.java index 3e4e6fa3dbc8..916050da880c 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/EmptyForwardIndex.java +++ b/platform/util/src/com/intellij/util/indexing/impl/forward/EmptyForwardIndex.java @@ -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) {