[vcs-log] ensure that persistent storages are closed if exception occurs in VcsLogFullDetailsIndex constructor

Persistent storages are registered in the FilePageCache#registerPagedFileStorage on creation and deregistered on close, so if the storage is not closed properly, a new instance with the same path can't be created later.

IDEA-330343, EA-933249

GitOrigin-RevId: fbec9dc8a25ebbf52b8cc7bc203a55c723f18121
This commit is contained in:
Julia Beliaeva
2024-03-12 00:54:04 +00:00
committed by intellij-monorepo-bot
parent b31ab28504
commit 7da501ece2
3 changed files with 46 additions and 34 deletions
@@ -7,6 +7,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.indexing.*;
import com.intellij.util.indexing.impl.IndexStorage;
import com.intellij.util.indexing.impl.MapIndexStorage;
@@ -128,6 +129,18 @@ public class VcsLogFullDetailsIndex<T, D> implements Disposable {
if (myDisposed) throw new ProcessCanceledException();
}
protected static void catchAndWarn(@NotNull Logger logger, @NotNull ThrowableRunnable<IOException> runnable) {
try {
runnable.run();
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
logger.warn(e);
}
}
private static final class MyMapReduceIndex<T, D> extends MapReduceIndex<Integer, T, D> {
private final @NotNull VcsLogErrorHandler myErrorHandler;
@@ -3,6 +3,7 @@ package com.intellij.vcs.log.data.index;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
@@ -39,7 +40,7 @@ import java.util.function.Consumer;
import static java.nio.charset.StandardCharsets.UTF_8;
final class VcsLogPathsIndex extends VcsLogFullDetailsIndex<List<ChangeKind>, CompressedDetails> {
public final class VcsLogPathsIndex extends VcsLogFullDetailsIndex<List<ChangeKind>, CompressedDetails> {
private static final Logger LOG = Logger.getInstance(VcsLogPathsIndex.class);
public static final String PATHS = "paths";
public static final String INDEX_PATHS_IDS = "paths-ids";
@@ -95,17 +96,6 @@ final class VcsLogPathsIndex extends VcsLogFullDetailsIndex<List<ChangeKind>, Co
myPathsIndexer.myPathsEnumerator.force();
}
@Override
public void dispose() {
super.dispose();
try {
myPathsIndexer.myPathsEnumerator.close();
}
catch (IOException e) {
LOG.warn(e);
}
}
@Contract("null,_ -> null; !null,_ -> !null")
static @Nullable FilePath toFilePath(@Nullable LightFilePath lightFilePath, boolean isDirectory) {
if (lightFilePath == null) return null;
@@ -117,11 +107,20 @@ final class VcsLogPathsIndex extends VcsLogFullDetailsIndex<List<ChangeKind>, Co
@NotNull PersistentHashMap<int[], int[]> renamesMap,
boolean useDurableEnumerator, @NotNull VcsLogErrorHandler errorHandler,
@NotNull Disposable disposableParent) throws IOException {
DurableDataEnumerator<LightFilePath> pathsEnumerator = createPathsEnumerator(roots, storageId, storageLockContext,
useDurableEnumerator);
PathIndexer pathsIndex = new PathIndexer(storage, pathsEnumerator, renamesMap,
e -> errorHandler.handleError(VcsLogErrorHandler.Source.Index, e));
return new VcsLogPathsIndex(storageId, storageLockContext, pathsIndex, errorHandler, disposableParent);
Disposable disposable = Disposer.newDisposable(disposableParent);
try {
DurableDataEnumerator<LightFilePath> pathsEnumerator = createPathsEnumerator(roots, storageId, storageLockContext,
useDurableEnumerator);
Disposer.register(disposable, () -> catchAndWarn(LOG, pathsEnumerator::close));
PathIndexer pathsIndex = new PathIndexer(storage, pathsEnumerator, renamesMap,
e -> errorHandler.handleError(VcsLogErrorHandler.Source.Index, e));
return new VcsLogPathsIndex(storageId, storageLockContext, pathsIndex, errorHandler, disposable);
}
catch (Throwable t) {
Disposer.dispose(disposable);
throw t;
}
}
static final class PathIndexer implements DataIndexer<Integer, List<ChangeKind>, CompressedDetails> {
@@ -3,9 +3,9 @@ package com.intellij.vcs.log.data.index;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.indexing.DataIndexer;
import com.intellij.util.indexing.StorageException;
import com.intellij.util.indexing.impl.MapReduceIndex;
import com.intellij.util.indexing.impl.forward.KeyCollectionForwardIndexAccessor;
import com.intellij.util.indexing.impl.forward.PersistentMapBasedForwardIndex;
import com.intellij.util.io.IntCollectionDataExternalizer;
@@ -112,27 +112,27 @@ final class VcsLogUserIndex extends VcsLogFullDetailsIndex<Void, VcsShortCommitD
myUserIndexer.flush();
}
@Override
public void dispose() {
super.dispose();
try {
myUserIndexer.close();
}
catch (IOException e) {
LOG.warn(e);
}
}
static @NotNull VcsLogUserIndex create(@NotNull StorageId.Directory storageId,
@Nullable StorageLockContext storageLockContext,
@NotNull VcsUserRegistry userRegistry,
@NotNull VcsLogErrorHandler errorHandler,
@NotNull Disposable disposableParent) throws IOException {
PersistentMapBasedForwardIndex forwardIndex = new PersistentMapBasedForwardIndex(storageId.getStorageFile(USERS + ".idx"),
true, false, storageLockContext);
PersistentEnumerator<VcsUser> enumerator = createUserEnumerator(storageId, storageLockContext, userRegistry);
UserIndexer userIndexer = new UserIndexer(enumerator, e -> errorHandler.handleError(VcsLogErrorHandler.Source.Index, e));
return new VcsLogUserIndex(storageId, userIndexer, forwardIndex, storageLockContext, errorHandler, disposableParent);
Disposable disposable = Disposer.newDisposable(disposableParent);
try {
PersistentMapBasedForwardIndex forwardIndex = new PersistentMapBasedForwardIndex(storageId.getStorageFile(USERS + ".idx"),
true, false, storageLockContext);
Disposer.register(disposable, () -> catchAndWarn(LOG, forwardIndex::close));
PersistentEnumerator<VcsUser> userEnumerator = createUserEnumerator(storageId, storageLockContext, userRegistry);
Disposer.register(disposable, () -> catchAndWarn(LOG, userEnumerator::close));
UserIndexer userIndexer = new UserIndexer(userEnumerator, e -> errorHandler.handleError(VcsLogErrorHandler.Source.Index, e));
return new VcsLogUserIndex(storageId, userIndexer, forwardIndex, storageLockContext, errorHandler, disposable);
}
catch (Throwable t) {
Disposer.dispose(disposable);
throw t;
}
}
private static final class UserIndexer implements DataIndexer<Integer, Void, VcsShortCommitDetails> {