[indexes][refactoring] combine add/remove/update processors into single UpdatedEntryProcessor

+ 3 different processors were used during diff(old,new) calculation, to report added/updated/removed entries -> actual processing of all 3 categories is quite similar, so I replace 3 processors with 1 `UpdatedEntryProcessor` with an additional `UpdateKind` enum arg.

GitOrigin-RevId: 53b1121ee1cb0899c87de17a9148b0b51029dd45
This commit is contained in:
Ruslan Cheremin
2024-08-22 15:28:28 +02:00
committed by intellij-monorepo-bot
parent bb7fd0b10c
commit 13dfa850c0
16 changed files with 97 additions and 187 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.stubs; package com.intellij.psi.stubs;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
@@ -10,8 +10,7 @@ import com.intellij.util.indexing.FileBasedIndexEx;
import com.intellij.util.indexing.StorageException; import com.intellij.util.indexing.StorageException;
import com.intellij.util.indexing.impl.DirectInputDataDiffBuilder; import com.intellij.util.indexing.impl.DirectInputDataDiffBuilder;
import com.intellij.util.indexing.impl.IndexDebugProperties; import com.intellij.util.indexing.impl.IndexDebugProperties;
import com.intellij.util.indexing.impl.KeyValueUpdateProcessor; import com.intellij.util.indexing.impl.UpdatedEntryProcessor;
import com.intellij.util.indexing.impl.RemovedKeyProcessor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -28,20 +27,15 @@ final class StubCumulativeInputDiffBuilder extends DirectInputDataDiffBuilder<In
@Override @Override
public boolean differentiate(@NotNull Map<Integer, SerializedStubTree> newData, public boolean differentiate(@NotNull Map<Integer, SerializedStubTree> newData,
@NotNull KeyValueUpdateProcessor<? super Integer, ? super SerializedStubTree> addProcessor, @NotNull UpdatedEntryProcessor<? super Integer, ? super SerializedStubTree> changesProcessor) throws StorageException {
@NotNull KeyValueUpdateProcessor<? super Integer, ? super SerializedStubTree> updateProcessor, return differentiate(newData, changesProcessor, false);
@NotNull RemovedKeyProcessor<? super Integer> removeProcessor) throws StorageException
{
return differentiate(newData, addProcessor, updateProcessor, removeProcessor, false);
} }
/** /**
* @param dryRun if true, won't update the stub indices * @param dryRun if true, won't update the stub indices
*/ */
public boolean differentiate(@NotNull Map<Integer, SerializedStubTree> newData, public boolean differentiate(@NotNull Map<Integer, SerializedStubTree> newData,
@NotNull KeyValueUpdateProcessor<? super Integer, ? super SerializedStubTree> addProcessor, @NotNull UpdatedEntryProcessor<? super Integer, ? super SerializedStubTree> changesProcessor,
@NotNull KeyValueUpdateProcessor<? super Integer, ? super SerializedStubTree> updateProcessor,
@NotNull RemovedKeyProcessor<? super Integer> removeProcessor,
boolean dryRun) throws StorageException { boolean dryRun) throws StorageException {
if (FileBasedIndexEx.TRACE_STUB_INDEX_UPDATES) { if (FileBasedIndexEx.TRACE_STUB_INDEX_UPDATES) {
LOG.info((dryRun ? "[dry run]" : "") + "differentiate: inputId=" + myInputId + LOG.info((dryRun ? "[dry run]" : "") + "differentiate: inputId=" + myInputId +
@@ -69,9 +63,9 @@ final class StubCumulativeInputDiffBuilder extends DirectInputDataDiffBuilder<In
",newStubLen=" + newSerializedStubTree.myIndexedStubByteLength); ",newStubLen=" + newSerializedStubTree.myIndexedStubByteLength);
} }
} }
removeProcessor.process(myInputId, myInputId); changesProcessor.removed(myInputId, myInputId);
} }
addProcessor.process(myInputId, newSerializedStubTree, myInputId); changesProcessor.added(myInputId, newSerializedStubTree, myInputId);
if (!dryRun) updateStubIndices(newSerializedStubTree); if (!dryRun) updateStubIndices(newSerializedStubTree);
} }
else { else {
@@ -81,7 +75,7 @@ final class StubCumulativeInputDiffBuilder extends DirectInputDataDiffBuilder<In
} }
return false; // ????????? return false; // ?????????
} }
removeProcessor.process(myInputId, myInputId); changesProcessor.removed(myInputId, myInputId);
if (!dryRun) updateStubIndices(null); if (!dryRun) updateStubIndices(null);
} }
return true; return true;

View File

@@ -92,19 +92,19 @@ public abstract class StubIndexEx extends StubIndex {
fileId, fileId,
index.getExtension().getName(), index.getExtension().getName(),
(addedEntriesProcessor, updatedEntriesProcessor, removedEntriesProcessor) -> { (changedEntriesProcessor) -> {
boolean modified = false; boolean modified = false;
for (K oldKey : oldKeys) { for (K oldKey : oldKeys) {
if (!newKeys.contains(oldKey)) { if (!newKeys.contains(oldKey)) {
removedEntriesProcessor.process(oldKey, fileId); changedEntriesProcessor.removed(oldKey, fileId);
if (!modified) modified = true; if (!modified) modified = true;
} }
} }
for (K newKey : newKeys) { for (K newKey : newKeys) {
if (!oldKeys.contains(newKey)) { if (!oldKeys.contains(newKey)) {
addedEntriesProcessor.process(newKey, null, fileId); changedEntriesProcessor.added(newKey, null, fileId);
if (!modified) modified = true; if (!modified) modified = true;
} }
} }

View File

@@ -99,27 +99,25 @@ public class SingleEntryIndexForwardIndexAccessor<V> extends AbstractMapForwardI
@Override @Override
public boolean differentiate(@NotNull Map<Integer, V> newData, public boolean differentiate(@NotNull Map<Integer, V> newData,
@NotNull KeyValueUpdateProcessor<? super Integer, ? super V> addProcessor, @NotNull UpdatedEntryProcessor<? super Integer, ? super V> changesProcessor) throws StorageException {
@NotNull KeyValueUpdateProcessor<? super Integer, ? super V> updateProcessor,
@NotNull RemovedKeyProcessor<? super Integer> removeProcessor) throws StorageException {
boolean newValueExists = !newData.isEmpty(); boolean newValueExists = !newData.isEmpty();
V newValue = ContainerUtil.getFirstItem(newData.values()); V newValue = ContainerUtil.getFirstItem(newData.values());
if (myContainsValue) { if (myContainsValue) {
if (!newValueExists) { if (!newValueExists) {
removeProcessor.process(myInputId, myInputId); changesProcessor.removed(myInputId, myInputId);
return true; return true;
} }
else if (Comparing.equal(myCurrentValue, newValue)) { else if (Comparing.equal(myCurrentValue, newValue)) {
return false; return false;
} }
else { else {
updateProcessor.process(myInputId, newValue, myInputId); changesProcessor.updated(myInputId, newValue, myInputId);
return true; return true;
} }
} }
else { else {
if (newValueExists) { if (newValueExists) {
addProcessor.process(myInputId, newValue, myInputId); changesProcessor.added(myInputId, newValue, myInputId);
return true; return true;
} }
else { else {

View File

@@ -223,7 +223,7 @@ final class PerFileElementTypeStubModificationTracker implements StubIndexImpl.F
} }
final Stub stub = StubTreeBuilder.buildStubTree(fileContent); final Stub stub = StubTreeBuilder.buildStubTree(fileContent);
Map<Integer, SerializedStubTree> serializedStub = stub == null ? Collections.emptyMap() : stubIndexer.map(fileContent); Map<Integer, SerializedStubTree> serializedStub = stub == null ? Collections.emptyMap() : stubIndexer.map(fileContent);
if (diffBuilder.differentiate(serializedStub, (__, ___, ____) -> { }, (__, ___, ____) -> { }, (__, ___) -> { }, true)) { if (diffBuilder.differentiate(serializedStub, (__, ___, ____, _____) -> { }, true)) {
registerModificationFor(info.type); registerModificationFor(info.type);
} }
} }

View File

@@ -4306,12 +4306,6 @@ f:com.intellij.util.indexing.impl.CollectionDataExternalizer
- <init>(com.intellij.util.io.DataExternalizer):V - <init>(com.intellij.util.io.DataExternalizer):V
- read(java.io.DataInput):java.util.Collection - read(java.io.DataInput):java.util.Collection
- save(java.io.DataOutput,java.util.Collection):V - save(java.io.DataOutput,java.util.Collection):V
f:com.intellij.util.indexing.impl.EmptyInputDataDiffBuilder
- <init>(I):V
- differentiate(java.util.Map,com.intellij.util.indexing.impl.KeyValueUpdateProcessor,com.intellij.util.indexing.impl.KeyValueUpdateProcessor,com.intellij.util.indexing.impl.RemovedKeyProcessor):Z
- getKeys():java.util.Collection
- s:processAllKeyValuesAsAdded(I,java.util.Map,com.intellij.util.indexing.impl.KeyValueUpdateProcessor):Z
- s:processAllKeyValuesAsRemoved(I,java.util.Map,com.intellij.util.indexing.impl.RemovedKeyProcessor):Z
com.intellij.util.indexing.impl.IndexStorage com.intellij.util.indexing.impl.IndexStorage
- java.io.Closeable - java.io.Closeable
- java.io.Flushable - java.io.Flushable
@@ -4336,18 +4330,10 @@ f:com.intellij.util.indexing.impl.InputIndexDataExternalizer
- <init>(com.intellij.util.io.KeyDescriptor,com.intellij.util.indexing.IndexId):V - <init>(com.intellij.util.io.KeyDescriptor,com.intellij.util.indexing.IndexId):V
- read(java.io.DataInput):java.util.Collection - read(java.io.DataInput):java.util.Collection
- save(java.io.DataOutput,java.util.Collection):V - save(java.io.DataOutput,java.util.Collection):V
com.intellij.util.indexing.impl.KeyValueUpdateProcessor
- a:process(java.lang.Object,java.lang.Object,I):V
c:com.intellij.util.indexing.impl.MapInputDataDiffBuilder
- <init>(I,java.util.Map):V
- differentiate(java.util.Map,com.intellij.util.indexing.impl.KeyValueUpdateProcessor,com.intellij.util.indexing.impl.KeyValueUpdateProcessor,com.intellij.util.indexing.impl.RemovedKeyProcessor):Z
- getKeys():java.util.Collection
*f:com.intellij.util.indexing.impl.MapReduceIndexMappingException *f:com.intellij.util.indexing.impl.MapReduceIndexMappingException
- java.lang.RuntimeException - java.lang.RuntimeException
- <init>(java.lang.Throwable,java.lang.Class):V - <init>(java.lang.Throwable,java.lang.Class):V
- getClassToBlame():java.lang.Class - getClassToBlame():java.lang.Class
com.intellij.util.indexing.impl.RemovedKeyProcessor
- a:process(java.lang.Object,I):V
com.intellij.util.indexing.impl.ValueSerializationProblemReporter com.intellij.util.indexing.impl.ValueSerializationProblemReporter
- a:reportProblem(java.lang.Exception):V - a:reportProblem(java.lang.Exception):V
com.intellij.util.indexing.impl.forward.ForwardIndex com.intellij.util.indexing.impl.forward.ForwardIndex

View File

@@ -2,12 +2,14 @@
package com.intellij.util.indexing.impl; package com.intellij.util.indexing.impl;
import com.intellij.util.indexing.StorageException; import com.intellij.util.indexing.StorageException;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
@ApiStatus.Internal
public final class EmptyInputDataDiffBuilder<Key, Value> extends DirectInputDataDiffBuilder<Key, Value> { public final class EmptyInputDataDiffBuilder<Key, Value> extends DirectInputDataDiffBuilder<Key, Value> {
public EmptyInputDataDiffBuilder(int inputId) { public EmptyInputDataDiffBuilder(int inputId) {
super(inputId); super(inputId);
@@ -20,21 +22,19 @@ public final class EmptyInputDataDiffBuilder<Key, Value> extends DirectInputData
@Override @Override
public boolean differentiate(@NotNull Map<Key, Value> newData, public boolean differentiate(@NotNull Map<Key, Value> newData,
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> addProcessor, @NotNull UpdatedEntryProcessor<? super Key, ? super Value> changesProcessor) throws StorageException {
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> updateProcessor, return processAllKeyValuesAsAdded(myInputId, newData, changesProcessor);
@NotNull RemovedKeyProcessor<? super Key> removeProcessor) throws StorageException {
return processAllKeyValuesAsAdded(myInputId, newData, addProcessor);
} }
public static <Key, Value> boolean processAllKeyValuesAsAdded(int inputId, public static <Key, Value> boolean processAllKeyValuesAsAdded(int inputId,
@NotNull Map<Key, Value> addedData, @NotNull Map<Key, Value> addedData,
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> addProcessor) @NotNull UpdatedEntryProcessor<? super Key, ? super Value> changesProcessor)
throws StorageException { throws StorageException {
boolean[] anyAdded = {false}; boolean[] anyAdded = {false};
try { try {
addedData.forEach((key, value) -> { addedData.forEach((key, value) -> {
try { try {
addProcessor.process(key, value, inputId); changesProcessor.added(key, value, inputId);
} }
catch (StorageException e) { catch (StorageException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -54,10 +54,11 @@ public final class EmptyInputDataDiffBuilder<Key, Value> extends DirectInputData
public static <Key, Value> boolean processAllKeyValuesAsRemoved(int inputId, public static <Key, Value> boolean processAllKeyValuesAsRemoved(int inputId,
@NotNull Map<Key, Value> removedData, @NotNull Map<Key, Value> removedData,
@NotNull RemovedKeyProcessor<? super Key> removedProcessor) throws StorageException { @NotNull UpdatedEntryProcessor<? super Key, ? super Value> changesProcessor)
throws StorageException {
boolean anyRemoved = false; boolean anyRemoved = false;
for (Key key : removedData.keySet()) { for (Key key : removedData.keySet()) {
removedProcessor.process(key, inputId); changesProcessor.removed(key, inputId);
anyRemoved = true; anyRemoved = true;
} }
return anyRemoved; return anyRemoved;

View File

@@ -1,18 +1,4 @@
/* // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.indexing.impl; package com.intellij.util.indexing.impl;
import com.intellij.util.indexing.StorageException; import com.intellij.util.indexing.StorageException;
@@ -34,7 +20,5 @@ public abstract class InputDataDiffBuilder<Key, Value> {
* @return false if there is no difference and true otherwise * @return false if there is no difference and true otherwise
*/ */
public abstract boolean differentiate(@NotNull Map<Key, Value> newData, public abstract boolean differentiate(@NotNull Map<Key, Value> newData,
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> addProcessor, @NotNull UpdatedEntryProcessor<? super Key, ? super Value> changesProcessor) throws StorageException;
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> updateProcessor,
@NotNull RemovedKeyProcessor<? super Key> removeProcessor) throws StorageException;
} }

View File

@@ -1,22 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.indexing.impl;
import com.intellij.util.indexing.StorageException;
public interface KeyValueUpdateProcessor<Key, Value> {
void process(Key key, Value value, int inputId) throws StorageException;
}

View File

@@ -1,9 +1,10 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.indexing.impl; package com.intellij.util.indexing.impl;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Comparing;
import com.intellij.util.indexing.StorageException; import com.intellij.util.indexing.StorageException;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -12,6 +13,7 @@ import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ApiStatus.Internal
public class MapInputDataDiffBuilder<Key, Value> extends DirectInputDataDiffBuilder<Key, Value> { public class MapInputDataDiffBuilder<Key, Value> extends DirectInputDataDiffBuilder<Key, Value> {
private final @NotNull Map<Key, Value> myMap; private final @NotNull Map<Key, Value> myMap;
@@ -22,14 +24,12 @@ public class MapInputDataDiffBuilder<Key, Value> extends DirectInputDataDiffBuil
@Override @Override
public boolean differentiate(@NotNull Map<Key, Value> newData, public boolean differentiate(@NotNull Map<Key, Value> newData,
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> addProcessor, @NotNull UpdatedEntryProcessor<? super Key, ? super Value> changesProcessor) throws StorageException {
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> updateProcessor,
@NotNull RemovedKeyProcessor<? super Key> removeProcessor) throws StorageException {
if (myMap.isEmpty()) { if (myMap.isEmpty()) {
return EmptyInputDataDiffBuilder.processAllKeyValuesAsAdded(myInputId, newData, addProcessor); return EmptyInputDataDiffBuilder.processAllKeyValuesAsAdded(myInputId, newData, changesProcessor);
} }
if (newData.isEmpty()) { if (newData.isEmpty()) {
return EmptyInputDataDiffBuilder.processAllKeyValuesAsRemoved(myInputId, myMap, removeProcessor); return EmptyInputDataDiffBuilder.processAllKeyValuesAsRemoved(myInputId, myMap, changesProcessor);
} }
int added = 0; int added = 0;
@@ -42,11 +42,11 @@ public class MapInputDataDiffBuilder<Key, Value> extends DirectInputDataDiffBuil
Value newValue = newData.get(key); Value newValue = newData.get(key);
if (!Comparing.equal(oldValue, newValue) || (newValue == null && !newData.containsKey(key))) { if (!Comparing.equal(oldValue, newValue) || (newValue == null && !newData.containsKey(key))) {
if (newData.containsKey(key)) { if (newData.containsKey(key)) {
updateProcessor.process(key, newValue, myInputId); changesProcessor.updated(key, newValue, myInputId);
updated++; updated++;
} }
else { else {
removeProcessor.process(key, myInputId); changesProcessor.removed(key, myInputId);
removed++; removed++;
} }
} }
@@ -55,7 +55,7 @@ public class MapInputDataDiffBuilder<Key, Value> extends DirectInputDataDiffBuil
for (Map.Entry<Key, Value> e : newData.entrySet()) { for (Map.Entry<Key, Value> e : newData.entrySet()) {
final Key newKey = e.getKey(); final Key newKey = e.getKey();
if (!myMap.containsKey(newKey)) { if (!myMap.containsKey(newKey)) {
addProcessor.process(newKey, e.getValue(), myInputId); changesProcessor.added(newKey, e.getValue(), myInputId);
added++; added++;
} }
} }

View File

@@ -313,16 +313,11 @@ public abstract class MapReduceIndex<Key, Value, Input> implements InvertedIndex
inputId, inputId,
indexId(), indexId(),
(addedEntriesProcessor, updatedEntriesProcessor, removedEntriesProcessor) -> { (changedEntriesProcessor) -> {
try { try {
InputDataDiffBuilder<Key, Value> diffBuilder = getKeysDiffBuilder(inputId); InputDataDiffBuilder<Key, Value> diffBuilder = getKeysDiffBuilder(inputId);
Map<Key, Value> newData = inputData.getKeyValues(); Map<Key, Value> newData = inputData.getKeyValues();
return diffBuilder.differentiate( return diffBuilder.differentiate(newData, changedEntriesProcessor);
newData,
addedEntriesProcessor,
updatedEntriesProcessor,
removedEntriesProcessor
);
} }
catch (IOException e) { catch (IOException e) {
throw new StorageException("Error while applying " + this, e); throw new StorageException("Error while applying " + this, e);
@@ -391,27 +386,21 @@ public abstract class MapReduceIndex<Key, Value, Input> implements InvertedIndex
protected abstract void requestRebuild(@NotNull Throwable e); protected abstract void requestRebuild(@NotNull Throwable e);
private final RemovedKeyProcessor<Key> myRemovedKeyProcessor = new RemovedKeyProcessor<Key>() { private final UpdatedEntryProcessor<Key, Value> changedEntriesProcessor = new UpdatedEntryProcessor<Key, Value>() {
@Override @Override
public void process(Key key, int inputId) throws StorageException { public void process(@NotNull UpdateKind kind, Key key, Value value, int inputId) throws StorageException {
incrementModificationStamp(); incrementModificationStamp();
myStorage.removeAllValues(key, inputId); switch (kind) {
} case ADDED:
}; myStorage.addValue(key, inputId, value);
break;
private final KeyValueUpdateProcessor<Key, Value> myAddedKeyProcessor = new KeyValueUpdateProcessor<Key, Value>() { case UPDATED:
@Override myStorage.updateValue(key, inputId, value);
public void process(Key key, Value value, int inputId) throws StorageException { break;
incrementModificationStamp(); case REMOVED:
myStorage.addValue(key, inputId, value); myStorage.removeAllValues(key, inputId);
} break;
}; }
private final KeyValueUpdateProcessor<Key, Value> myUpdatedKeyProcessor = new KeyValueUpdateProcessor<Key, Value>() {
@Override
public void process(Key key, Value value, int inputId) throws StorageException {
incrementModificationStamp();
myStorage.updateValue(key, inputId, value);
} }
}; };
@@ -425,11 +414,8 @@ public abstract class MapReduceIndex<Key, Value, Input> implements InvertedIndex
IndexId<?, ?> oldIndexId = IndexDebugProperties.DEBUG_INDEX_ID.get(); IndexId<?, ?> oldIndexId = IndexDebugProperties.DEBUG_INDEX_ID.get();
try { try {
IndexDebugProperties.DEBUG_INDEX_ID.set(myIndexId); IndexDebugProperties.DEBUG_INDEX_ID.set(myIndexId);
boolean hasDifference = updateData.iterateChanges( boolean hasDifference = updateData.iterateChanges(changedEntriesProcessor);
myAddedKeyProcessor,
myUpdatedKeyProcessor,
myRemovedKeyProcessor
);
//TODO RC: separate lock for forwardIndex? -- it seems it is used only in updates (?), i.e. only in one place, //TODO RC: separate lock for forwardIndex? -- it seems it is used only in updates (?), i.e. only in one place,
// so if it is out-of-sync with inverted index it is not a big deal since nobody able to see it? // so if it is out-of-sync with inverted index it is not a big deal since nobody able to see it?
// ...but it is important to not allow same fileId data to be applied by different threads, because // ...but it is important to not allow same fileId data to be applied by different threads, because

View File

@@ -1,22 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.indexing.impl;
import com.intellij.util.indexing.StorageException;
public interface RemovedKeyProcessor<Key> {
void process(Key key, int inputId) throws StorageException;
}

View File

@@ -15,7 +15,7 @@ import java.io.IOException;
* <p> * <p>
* The update as a whole is going to the forward index, while the changes are going to the inverted index. * The update as a whole is going to the forward index, while the changes are going to the inverted index.
* So the {@link #updateForwardIndex()} is to update the forward index with the new data, and * So the {@link #updateForwardIndex()} is to update the forward index with the new data, and
* {@link #iterateChanges(KeyValueUpdateProcessor, KeyValueUpdateProcessor, RemovedKeyProcessor)} is to stream * {@link #iterateChanges(UpdatedEntryProcessor)} is to stream
* the changes against current data to apply on the inverted index. * the changes against current data to apply on the inverted index.
* <p> * <p>
* The 2 sides are separated to allow indexes to skip forward index update, and/or to provide an optimized version * The 2 sides are separated to allow indexes to skip forward index update, and/or to provide an optimized version
@@ -47,14 +47,8 @@ public final class UpdateData<Key, Value> {
//MAYBE RC: move ChangesProducer to the upper level, and make UpdateData implement ChangesProducer, so this //MAYBE RC: move ChangesProducer to the upper level, and make UpdateData implement ChangesProducer, so this
// method become .forEachChange()? // method become .forEachChange()?
/** @return true if new data is different from current data -- which means at least one processor _was_ called */ /** @return true if new data is different from current data -- which means at least one processor _was_ called */
boolean iterateChanges(@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> addedEntriesProcessor, boolean iterateChanges(@NotNull UpdatedEntryProcessor<? super Key, ? super Value> changedEntriesProcessor) throws StorageException {
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> updatedEntriesProcessor, return changesProducer.forEachChange(changedEntriesProcessor);
@NotNull RemovedKeyProcessor<? super Key> removedEntriesProcessor) throws StorageException {
return changesProducer.forEachChange(
addedEntriesProcessor,
updatedEntriesProcessor,
removedEntriesProcessor
);
} }
void updateForwardIndex() throws IOException { void updateForwardIndex() throws IOException {
@@ -90,8 +84,6 @@ public final class UpdateData<Key, Value> {
@ApiStatus.Internal @ApiStatus.Internal
@FunctionalInterface @FunctionalInterface
public interface ChangesProducer<Key, Value> { public interface ChangesProducer<Key, Value> {
boolean forEachChange(@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> addedEntriesProcessor, boolean forEachChange(@NotNull UpdatedEntryProcessor<? super Key, ? super Value> changedEntriesProcessor) throws StorageException;
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> updatedEntriesProcessor,
@NotNull RemovedKeyProcessor<? super Key> removedEntriesProcessor) throws StorageException;
} }
} }

View File

@@ -0,0 +1,27 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.indexing.impl;
import com.intellij.util.indexing.StorageException;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@ApiStatus.Internal
@FunctionalInterface
public interface UpdatedEntryProcessor<Key, Value> {
enum UpdateKind {ADDED, UPDATED, REMOVED}
default void added(Key key, Value value, int inputId) throws StorageException {
process(UpdateKind.ADDED, key, value, inputId);
}
default void updated(Key key, Value value, int inputId) throws StorageException {
process(UpdateKind.UPDATED, key, value, inputId);
}
default void removed(Key key, int inputId) throws StorageException {
process(UpdateKind.REMOVED, key, /*value: */ null, inputId);
}
void process(@NotNull UpdateKind kind, Key key, Value value, int inputId) throws StorageException;
}

View File

@@ -4,8 +4,7 @@ package com.intellij.util.indexing.impl.forward;
import com.intellij.openapi.util.io.ByteArraySequence; import com.intellij.openapi.util.io.ByteArraySequence;
import com.intellij.util.indexing.impl.InputData; import com.intellij.util.indexing.impl.InputData;
import com.intellij.util.indexing.impl.InputDataDiffBuilder; import com.intellij.util.indexing.impl.InputDataDiffBuilder;
import com.intellij.util.indexing.impl.KeyValueUpdateProcessor; import com.intellij.util.indexing.impl.UpdatedEntryProcessor;
import com.intellij.util.indexing.impl.RemovedKeyProcessor;
import org.jetbrains.annotations.ApiStatus.Internal; import org.jetbrains.annotations.ApiStatus.Internal;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -19,7 +18,7 @@ public interface ForwardIndexAccessor<Key, Value> {
* Method deserializes sequence bytes back into a {@link InputData}, and creates a diff-builder from this input * Method deserializes sequence bytes back into a {@link InputData}, and creates a diff-builder from this input
* (with id=inputId). * (with id=inputId).
* The diff-builder could be used later to calculate a diff between that inputData, and any other inputData * The diff-builder could be used later to calculate a diff between that inputData, and any other inputData
* (see {@link InputDataDiffBuilder#differentiate(Map, KeyValueUpdateProcessor, KeyValueUpdateProcessor, RemovedKeyProcessor)}) * (see {@link InputDataDiffBuilder#differentiate(Map, UpdatedEntryProcessor)})
*/ */
@NotNull @NotNull
InputDataDiffBuilder<Key, Value> getDiffBuilder(int inputId, @Nullable ByteArraySequence sequence) throws IOException; InputDataDiffBuilder<Key, Value> getDiffBuilder(int inputId, @Nullable ByteArraySequence sequence) throws IOException;

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.indexing.impl.forward; package com.intellij.util.indexing.impl.forward;
import com.intellij.util.indexing.IndexExtension; import com.intellij.util.indexing.IndexExtension;
@@ -51,13 +51,11 @@ public final class KeyCollectionForwardIndexAccessor<Key, Value> extends Abstrac
@Override @Override
public boolean differentiate(@NotNull Map<Key, Value> newData, public boolean differentiate(@NotNull Map<Key, Value> newData,
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> addProcessor, @NotNull UpdatedEntryProcessor<? super Key, ? super Value> changesProcessor) throws StorageException {
@NotNull KeyValueUpdateProcessor<? super Key, ? super Value> updateProcessor,
@NotNull RemovedKeyProcessor<? super Key> removeProcessor) throws StorageException {
for (Key key : myKeys) { for (Key key : myKeys) {
removeProcessor.process(key, myInputId); changesProcessor.removed(key, myInputId);
} }
boolean anyAdded = EmptyInputDataDiffBuilder.processAllKeyValuesAsAdded(myInputId, newData, addProcessor); boolean anyAdded = EmptyInputDataDiffBuilder.processAllKeyValuesAsAdded(myInputId, newData, changesProcessor);
boolean anyRemoved = !myKeys.isEmpty(); boolean anyRemoved = !myKeys.isEmpty();
return anyAdded || anyRemoved; return anyAdded || anyRemoved;
} }

View File

@@ -285,14 +285,8 @@ public abstract class IndexStorageLayoutProviderTestBase {
ByteArraySequence serializedData = forwardIndex.get(inputId); ByteArraySequence serializedData = forwardIndex.get(inputId);
forwardIndexAccessor.getDiffBuilder(inputId, serializedData).differentiate( forwardIndexAccessor.getDiffBuilder(inputId, serializedData).differentiate(
expectedInputData, expectedInputData,
(k, v, _inputId) -> { (kind, k, v, _inputId) -> {
inconsistencies.add("add(" + k + ", " + v + ")[" + _inputId + "]"); inconsistencies.add(kind + "(" + k + ", " + v + ")[" + _inputId + "]");
},
(k, v, _inputId) -> {
inconsistencies.add("update(" + k + ", " + v + ")[" + _inputId + "]");
},
(k, _inputId) -> {
inconsistencies.add("remove(" + k + ")[" + _inputId + "]");
} }
); );
} }
@@ -351,16 +345,11 @@ public abstract class IndexStorageLayoutProviderTestBase {
inputId, inputId,
serializedData serializedData
); );
diffBuilder.differentiate(expectedInputData, diffBuilder.differentiate(
(k, v, _inputId) -> { expectedInputData,
fail(); (kind, key, value, _inputId) -> {
}, fail("Shouldn't be any difference, but: " + kind + "(" + key + ", " + value + ")[" + _inputId + "]");
(k, v, _inputId) -> { });
fail();
},
(k, _inputId) -> {
fail();
});
} }
assertTrue( assertTrue(