remove all indexed state upon invalidateIndicesForFile (r=Eugene.Zhuravlev)

This commit is contained in:
Maxim.Mossienko
2013-12-02 19:59:14 +01:00
parent 5012a9b137
commit c5819e47f3
2 changed files with 59 additions and 46 deletions
@@ -2061,67 +2061,42 @@ public class FileBasedIndexImpl extends FileBasedIndex {
cleanProcessedFlag(file);
IndexingStamp.flushCache(file);
final List<ID<?, ?>> affectedIndexCandidates = getAffectedIndexCandidates(file);
final List<ID<?, ?>> affectedIndices = new ArrayList<ID<?, ?>>(affectedIndexCandidates.size());
Collection<ID<?, ?>> existingIndexedIds = IndexingStamp.getIndexedIds(file);
//noinspection ForLoopReplaceableByForEach
for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) {
final ID<?, ?> indexId = affectedIndexCandidates.get(i);
try {
if (!needsFileContentLoading(indexId)) {
if (shouldUpdateIndex(file, indexId)) {
updateSingleIndex(indexId, file, null, true); // todo: set merge to false?
}
for(ID<?, ?> indexId:existingIndexedIds) {
if (myNotRequiringContentIndices.contains(indexId)) {
try {
updateSingleIndex(indexId, file, null, true);
} catch (StorageException e) {
LOG.info(e);
requestRebuild(indexId);
}
else { // the index requires file content
if (shouldUpdateIndex(file, indexId)) {
affectedIndices.add(indexId);
}
}
}
catch (StorageException e) {
LOG.info(e);
requestRebuild(indexId);
}
}
if (!affectedIndices.isEmpty()) {
if (markForReindex && !isTooLarge(file)) {
// only mark the file as unindexed, reindex will be done lazily
final Collection<ID<?, ?>> indexedIdsToUpdate = ContainerUtil.intersection(existingIndexedIds, myRequiringContentIndices);
if (markForReindex) {
// only mark the file as unindexed, reindex will be done lazily
if (!indexedIdsToUpdate.isEmpty()) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
FileType fileType = file.getFileType();
for (ID<?, ?> indexId : affectedIndices) {
ID id = IndexInfrastructure.getStubId(indexId, fileType);
IndexingStamp.update(file, id, IndexInfrastructure.INVALID_STAMP2);
}
}
});
// the file is for sure not a dir and it was previously indexed by at least one index
scheduleForUpdate(file);
}
else {
myFutureInvalidations.offer(new InvalidationTask(file) {
@Override
public void run() {
removeFileDataFromIndices(affectedIndices, file);
IndexingStamp.removeAllIndexedState(file);
}
});
}
// the file is for sure not a dir and it was previously indexed by at least one index
scheduleForUpdate(file);
}
if (!markForReindex) {
final boolean removedFromUpdateQueue = myFilesToUpdate.remove(file);// no need to update it anymore
if (removedFromUpdateQueue && affectedIndices.isEmpty()) {
// Currently the file is about to be deleted and previously it was scheduled for update and not processed up to now.
// Because the file was scheduled for update, at the moment of scheduling it was marked as unindexed,
// so, to be on the safe side, we have to schedule data invalidation from all content-requiring indices for this file
else {
myFilesToUpdate.remove(file);
if (!indexedIdsToUpdate.isEmpty()) {
myFutureInvalidations.offer(new InvalidationTask(file) {
@Override
public void run() {
List<ID<?, ?>> candidates = new ArrayList<ID<?, ?>>(affectedIndexCandidates);
candidates.retainAll(myRequiringContentIndices);
removeFileDataFromIndices(candidates, file);
removeFileDataFromIndices(indexedIdsToUpdate, file);
}
});
}
@@ -20,15 +20,19 @@ import com.intellij.openapi.vfs.InvalidVirtualFileAccessException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.FileAttribute;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.io.DataInputOutputUtil;
import gnu.trove.TObjectLongHashMap;
import gnu.trove.TObjectLongProcedure;
import gnu.trove.TObjectProcedure;
import org.jetbrains.annotations.Nullable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ArrayBlockingQueue;
/**
@@ -72,6 +76,10 @@ public class IndexingStamp {
}
}
private Timestamps() {
myIsDirty = true;
}
private void writeToStream(final DataOutputStream stream) throws IOException {
if (myIndexStamps != null && !myIndexStamps.isEmpty()) {
final long[] dominatingIndexStamp = new long[1];
@@ -194,6 +202,36 @@ public class IndexingStamp {
}
}
public static void removeAllIndexedState(VirtualFile file) {
synchronized (getStripedLock(file)) {
if (file instanceof NewVirtualFile && file.isValid()) {
myTimestampsCache.put(file, new Timestamps());
}
}
}
public static Collection<ID<?,?>> getIndexedIds(final VirtualFile file) {
synchronized (getStripedLock(file)) {
try {
Timestamps stamp = createOrGetTimeStamp(file);
if (stamp != null && stamp.myIndexStamps != null && !stamp.myIndexStamps.isEmpty()) {
final SmartList<ID<?, ?>> retained = new SmartList<ID<?, ?>>();
stamp.myIndexStamps.forEach(new TObjectProcedure<ID<?, ?>>() {
@Override
public boolean execute(ID<?, ?> object) {
retained.add(object);
return true;
}
});
return retained;
}
}
catch (InvalidVirtualFileAccessException ignored /*ok to ignore it here*/) {
}
}
return Collections.emptyList();
}
public static void flushCaches() {
flushCache(null);
myTimestampsCache.clear();