diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java index cf4de2562378..6eb9fc8c789d 100644 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java +++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java @@ -149,7 +149,7 @@ public abstract class CompilerOutputBaseIndex { } public final void update(final int id, final ClassNode inputData) { - final Boolean result = myIndex.update(id, inputData).compute(); + final Boolean result = myIndex.update(id, inputData, true).compute(); if (result == Boolean.FALSE) throw new RuntimeException(); } diff --git a/java/java-tests/testSrc/com/intellij/index/StringIndex.java b/java/java-tests/testSrc/com/intellij/index/StringIndex.java index a12f58fbf137..cc9e7001a446 100644 --- a/java/java-tests/testSrc/com/intellij/index/StringIndex.java +++ b/java/java-tests/testSrc/com/intellij/index/StringIndex.java @@ -33,7 +33,7 @@ public class StringIndex { } public void update(final String path, @Nullable String content, @Nullable String oldContent) throws StorageException { - myIndex.update(path.hashCode(), toInput(path, content)).compute(); + myIndex.update(path.hashCode(), toInput(path, content), true).compute(); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index 8ae32826414d..06f4e2703252 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -429,7 +429,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe public Collection call() throws Exception { return oldValues.keySet(); } - }); + }, true); } catch (StorageException e) { LOG.info(e); @@ -443,8 +443,11 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe } @Override - public void updateWithMap(final int inputId, @NotNull final Map newData, @NotNull Callable> oldKeysGetter) throws StorageException { - super.updateWithMap(inputId, newData, oldKeysGetter); + public void updateWithMap(final int inputId, + @NotNull final Map newData, + @NotNull Callable> oldKeysGetter, + boolean merge) throws StorageException { + super.updateWithMap(inputId, newData, oldKeysGetter, merge); } } 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 10b088935885..22730e2cfdc9 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -89,7 +89,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi return true; } final ID indexId = IndexInfrastructure.getStubId(INDEX_ID, fileType); - if (IndexingStamp.isFileIndexed(file, indexId, IndexInfrastructure.getIndexCreationStamp(indexId))) { + if (IndexingStamp.getIndexingState(file, indexId) == IndexingStamp.State.INDEXED) { return true; } } @@ -298,7 +298,10 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi } @Override - protected void updateWithMap(final int inputId, @NotNull final Map newData, @NotNull Callable> oldKeysGetter) + protected void updateWithMap(final int inputId, + @NotNull final Map newData, + @NotNull Callable> oldKeysGetter, + boolean merge) throws StorageException { checkNameStorage(); @@ -321,7 +324,8 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi try { getWriteLock().lock(); - final Map oldData = readOldData(inputId); + final Map oldData = + merge ? readOldData(inputId) : Collections.emptyMap(); final Map> oldStubTree; try { oldStubTree = getStubTree(oldData); @@ -330,7 +334,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi throw new StorageException(e); } - super.updateWithMap(inputId, newData, oldKeysGetter); + super.updateWithMap(inputId, newData, oldKeysGetter, merge); updateStubIndices(getAffectedIndices(oldStubTree, newStubTree), inputId, oldStubTree, newStubTree); } 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 15d4fdf9a089..f6a857483d5a 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1573,7 +1573,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { final int inputId = Math.abs(getFileId(vFile)); try { - getIndex(requestedIndexId).update(inputId, newFc).compute(); + getIndex(requestedIndexId).update(inputId, newFc, true).compute(); } catch (ProcessCanceledException pce) { myLastIndexedDocStamps.getAndSet(document, requestedIndexId, previousDocStamp); throw pce; @@ -1709,7 +1709,9 @@ public class FileBasedIndexImpl extends FileBasedIndex { //noinspection ForLoopReplaceableByForEach for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) { final ID indexId = affectedIndexCandidates.get(i); - if (shouldIndexFile(file, indexId)) { + if (!getInputFilter(indexId).acceptInput(file)) continue; + IndexingStamp.State state = isMock(file) ? IndexingStamp.State.FILE_CONTENT_CHANGED : getIndexingState(file, indexId); + if (state != IndexingStamp.State.INDEXED) { if (fc == null) { byte[] currentBytes; try { @@ -1729,7 +1731,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { try { ProgressManager.checkCanceled(); - updateSingleIndex(indexId, file, fc); + updateSingleIndex(indexId, file, fc, state == IndexingStamp.State.FILE_CONTENT_CHANGED); } catch (ProcessCanceledException e) { cleanFileContent(fc, psiFile); @@ -1777,7 +1779,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { fc.putUserData(IndexingDataKeys.PROJECT, project); } - private void updateSingleIndex(final ID indexId, @NotNull final VirtualFile file, @Nullable FileContent currentFC) + private void updateSingleIndex(final ID indexId, @NotNull final VirtualFile file, @Nullable FileContent currentFC, boolean merge) throws StorageException { if (ourRebuildStatus.get(indexId).get() == REQUIRES_REBUILD) { return; // the index is scheduled for rebuild, no need to update @@ -1789,7 +1791,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { assert index != null; // important: no hard referencing currentFC to avoid OOME, the methods introduced for this purpose! - final Computable update = index.update(inputId, currentFC); + final Computable update = index.update(inputId, currentFC, merge); final FileType fileType = file.getFileType(); scheduleUpdate(indexId, @@ -1975,7 +1977,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { if (fileContent == null) { fileContent = new FileContentImpl(file); } - updateSingleIndex(indexId, file, fileContent); + updateSingleIndex(indexId, file, fileContent, true); } catch (StorageException e) { LOG.info(e); @@ -1998,7 +2000,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { final ID indexId = candidates.get(i); if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) { ID id = IndexInfrastructure.getStubId(indexId, fileType); - if (IndexingStamp.isFileIndexed(file, id, IndexInfrastructure.getIndexCreationStamp(id))) { + if (IndexingStamp.getIndexingState(file, id) != IndexingStamp.State.INDEXED) { IndexingStamp.update(file, id, IndexInfrastructure.INVALID_STAMP2); resetStamp = true; } @@ -2066,7 +2068,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { try { if (!needsFileContentLoading(indexId)) { if (shouldUpdateIndex(file, indexId)) { - updateSingleIndex(indexId, file, null); + updateSingleIndex(indexId, file, null, true); // todo: set merge to false? } } else { // the index requires file content @@ -2130,7 +2132,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { Throwable unexpectedError = null; for (ID indexId : affectedIndices) { try { - updateSingleIndex(indexId, file, null); + updateSingleIndex(indexId, file, null, true); // todo: set merge to false? } catch (StorageException e) { LOG.info(e); @@ -2398,7 +2400,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { if (fileContent == null) { fileContent = new FileContentImpl(file); } - updateSingleIndex(indexId, file, fileContent); + updateSingleIndex(indexId, file, fileContent, true); } catch (StorageException e) { LOG.info(e); @@ -2425,6 +2427,11 @@ public class FileBasedIndexImpl extends FileBasedIndex { } } + private static IndexingStamp.State getIndexingState(VirtualFile file, ID indexId) { + ID id = IndexInfrastructure.getStubId(indexId, file.getFileType()); + return IndexingStamp.getIndexingState(file, id); + } + private boolean shouldUpdateIndex(final VirtualFile file, final ID indexId) { return getInputFilter(indexId).acceptInput(file) && (isMock(file) || isFileIndexed(file, indexId)); @@ -2436,8 +2443,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { } private static boolean isFileIndexed(VirtualFile file, ID indexId) { - ID id = IndexInfrastructure.getStubId(indexId, file.getFileType()); - return IndexingStamp.isFileIndexed(file, id, IndexInfrastructure.getIndexCreationStamp(id)); + return getIndexingState(file, indexId) == IndexingStamp.State.INDEXED; } private static long getIndexCreationStamp(ID indexId, FileType fileType) { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java index 8531bcf688eb..27170ce020e2 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java @@ -18,7 +18,6 @@ package com.intellij.util.indexing; import com.intellij.openapi.vfs.InvalidVirtualFileAccessException; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileWithId; import com.intellij.openapi.vfs.newvfs.FileAttribute; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.util.containers.ConcurrentHashMap; @@ -58,7 +57,7 @@ public class IndexingStamp { if (id != null) { long stamp = IndexInfrastructure.getIndexCreationStamp(id); if (myIndexStamps == null) myIndexStamps = new TObjectLongHashMap>(5, 0.98f); - if (stamp <= dominatingIndexStamp) myIndexStamps.put(id, stamp); + myIndexStamps.put(id, stamp <= dominatingIndexStamp ? stamp : INDEX_VERSION_CHANGED_STAMP); } } } @@ -126,10 +125,20 @@ public class IndexingStamp { private static final ConcurrentHashMap myTimestampsCache = new ConcurrentHashMap(); private static final int CAPACITY = 100; private static final ArrayBlockingQueue myFinishedFiles = new ArrayBlockingQueue(CAPACITY); + private static final long INDEX_VERSION_CHANGED_STAMP = 1l; - public static boolean isFileIndexed(VirtualFile file, ID indexName, final long indexCreationStamp) { + public enum State { + INDEXED, INDEX_VERSION_CHANGED, FILE_CONTENT_CHANGED + } + + public static State getIndexingState(VirtualFile file, ID indexName) { try { - return getIndexStamp(file, indexName) == indexCreationStamp; + long stamp = getIndexStamp(file, indexName); + if (stamp == INDEX_VERSION_CHANGED_STAMP) { + return State.INDEX_VERSION_CHANGED; + } + long indexCreationStamp = IndexInfrastructure.getIndexCreationStamp(indexName); + return stamp == indexCreationStamp ? State.INDEXED : State.FILE_CONTENT_CHANGED; } catch (RuntimeException e) { final Throwable cause = e.getCause(); @@ -138,7 +147,7 @@ public class IndexingStamp { } } - return false; + return State.FILE_CONTENT_CHANGED; } public static long getIndexStamp(VirtualFile file, ID indexName) { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java index 98b62a5b3ffc..008aa3fd43a0 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java @@ -202,7 +202,7 @@ public class MapReduceIndex implements UpdatableIndex update(final int inputId, @Nullable Input content) { + public final Computable update(final int inputId, @Nullable final Input content, final boolean merge) { assert myInputsIndex != null; final Map data = content != null ? myIndexer.map(content) : Collections.emptyMap(); @@ -224,7 +224,7 @@ public class MapReduceIndex implements UpdatableIndex oldKeys = myInputsIndex.get(inputId); return oldKeys == null? Collections.emptyList() : oldKeys; } - }); + }, merge); } catch (StorageException ex) { exRef.set(ex); } @@ -242,7 +242,10 @@ public class MapReduceIndex implements UpdatableIndex newData, @NotNull Callable> oldKeysGetter) throws StorageException { + protected void updateWithMap(final int inputId, + @NotNull Map newData, + @NotNull Callable> oldKeysGetter, + boolean merge) throws StorageException { getWriteLock().lock(); try { try { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java index 51b2330ca36f..78704703a0d1 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java @@ -17,10 +17,8 @@ package com.intellij.util.indexing; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.ThrowableComputable; import org.jetbrains.annotations.Nullable; -import java.util.concurrent.Callable; import java.util.concurrent.locks.Lock; /** @@ -33,7 +31,10 @@ public interface UpdatableIndex extends AbstractIndex update(int inputId, @Nullable Input content); + /** + * @param merge true if merge with old data needed (e.g. file content changed), false if not needed (e.g. index version changed) + */ + Computable update(int inputId, @Nullable Input content, boolean merge); Lock getReadLock();