api for (re)creating PHM that rewrites it if it is broken (IDEA-115334)

This commit is contained in:
Maxim.Mossienko
2013-11-03 12:52:52 +01:00
parent 8353b38f9e
commit 49e112c23c
4 changed files with 91 additions and 48 deletions
@@ -5,10 +5,11 @@ import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.IOUtil;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.io.PersistentHashMap;
import org.jetbrains.asm4.tree.ClassNode;
@@ -51,24 +52,32 @@ public abstract class CompilerOutputBaseIndex<K, V> {
if (!IndexInfrastructure.getIndexRootDir(indexId).exists()) {
rewriteIndex.set(true);
}
final File storageFile = IndexInfrastructure.getStorageFile(indexId);
final File storageFile = getStorageFile(indexId);
final MapIndexStorage<K, V> indexStorage = new MapIndexStorage<K, V>(storageFile, myKeyDescriptor, myValueExternalizer, 1024);
index = new MapReduceIndex<K, V, ClassNode>(indexId, getIndexer(), indexStorage);
index.setInputIdToDataKeysIndex(new Factory<PersistentHashMap<Integer, Collection<K>>>() {
@Override
public PersistentHashMap<Integer, Collection<K>> create() {
Exception failCause = null;
for (int attempts = 0; attempts < 2; attempts++) {
try {
return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage<K, V>(indexStorage));
}
catch (IOException e) {
failCause = e;
FileUtil.delete(IndexInfrastructure.getInputIndexStorageFile(getIndexId()));
rewriteIndex.set(true);
}
try {
return IOUtil.openCleanOrResetBroken(
new ThrowableComputable<PersistentHashMap<Integer, Collection<K>>, IOException>() {
@Override
public PersistentHashMap<Integer, Collection<K>> compute() throws IOException {
return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage<K, V>(indexStorage));
}
},
new Runnable() {
@Override
public void run() {
FileUtil.delete(getInputIndexStorageFile(getIndexId()));
rewriteIndex.set(true);
}
}
);
}
catch (IOException e) {
throw new RuntimeException("couldn't create index", e);
}
throw new RuntimeException("couldn't create index", failCause);
}
});
final File versionFile = getVersionFile(indexId);
@@ -144,9 +153,4 @@ public abstract class CompilerOutputBaseIndex<K, V> {
protected final ID<K, V> generateIndexId(final String indexName) {
return CompilerOutputIndexUtil.generateIndexId(indexName, myProject);
}
protected final ID<K, V> generateIndexId(final Class aClass) {
final String className = StringUtil.getShortName(aClass);
return generateIndexId(StringUtil.trimEnd(className, "Index"));
}
}
@@ -12,6 +12,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.RegistryValue;
import com.intellij.openapi.util.registry.RegistryValueListener;
@@ -153,16 +154,19 @@ public class CompilerOutputIndexer extends AbstractProjectComponent {
private void doEnable() {
if (myInitialized.compareAndSet(false, true)) {
initTimestampIndex();
File storageFile =
final File storageFile =
IndexInfrastructure.getStorageFile(CompilerOutputIndexUtil.generateIndexId("compilerOutputIndexFileId.enum", myProject));
for (int i = 0; i < 2; i++) {
try {
myFileEnumerator = new PersistentEnumeratorDelegate<String>(storageFile, new EnumeratorStringDescriptor(), 2048);
}
catch (IOException e) {
if (i == 1) throw new RuntimeException(e);
IOUtil.deleteAllFilesStartingWith(storageFile);
}
try {
myFileEnumerator = IOUtil.openCleanOrResetBroken(new ThrowableComputable<PersistentEnumeratorDelegate<String>, IOException>() {
@Override
public PersistentEnumeratorDelegate<String> compute() throws IOException {
return new PersistentEnumeratorDelegate<String>(storageFile, new EnumeratorStringDescriptor(), 2048);
}
}, storageFile);
}
catch (IOException e) {
throw new RuntimeException(e);
}
CompilerManager.getInstance(myProject).addCompilationStatusListener(new CompilationStatusAdapter() {
@Override
@@ -184,29 +188,35 @@ public class CompilerOutputIndexer extends AbstractProjectComponent {
}
private void initTimestampIndex() {
for (int attempts = 0; attempts < 2; attempts++) {
try {
myFileTimestampsIndex = new PersistentHashMap<String, Long>(IndexInfrastructure.getStorageFile(getFileTimestampsIndexId()),
new EnumeratorStringDescriptor(), new DataExternalizer<Long>() {
final File storageFile = IndexInfrastructure.getStorageFile(getFileTimestampsIndexId());
try {
myFileTimestampsIndex = IOUtil.openCleanOrResetBroken(
new ThrowableComputable<PersistentHashMap<String, Long>, IOException>() {
@Override
public void save(final DataOutput out, final Long value) throws IOException {
out.writeLong(value);
}
public PersistentHashMap<String, Long> compute() throws IOException {
return new PersistentHashMap<String, Long>(storageFile,
new EnumeratorStringDescriptor(), new DataExternalizer<Long>() {
@Override
public void save(final DataOutput out, final Long value) throws IOException {
out.writeLong(value);
}
@Override
public Long read(final DataInput in) throws IOException {
return in.readLong();
@Override
public Long read(final DataInput in) throws IOException {
return in.readLong();
}
});
}
});
}
catch (IOException e) {
FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
}
if (myFileTimestampsIndex != null) {
return;
}
},
new Runnable() {
public void run() {
FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
}
}
);
} catch (IOException ex) {
throw new RuntimeException("Timestamps index not initialized", ex);
}
throw new RuntimeException("Timestamps index not initialized");
}
public void reindex(final FileVisitorService visitorService, final @NotNull ProgressIndicator indicator) {
@@ -15,6 +15,7 @@
*/
package com.intellij.util.io;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.SystemProperties;
@@ -184,4 +185,26 @@ public class IOUtil {
throw new RuntimeException(e);
}
}
public static <T> T openCleanOrResetBroken(@NotNull ThrowableComputable<T, IOException> factoryComputable, final File file) throws IOException {
return openCleanOrResetBroken(factoryComputable, new Runnable() {
@Override
public void run() {
deleteAllFilesStartingWith(file);
}
});
}
public static <T> T openCleanOrResetBroken(@NotNull ThrowableComputable<T, IOException> factoryComputable, Runnable cleanupCallback) throws IOException {
for(int i = 0; i < 2; ++i) {
try {
return factoryComputable.compute();
} catch (IOException ex) {
if (i == 1) throw ex;
cleanupCallback.run();
}
}
return null;
}
}
@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.indices;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.*;
import gnu.trove.THashMap;
@@ -617,8 +618,13 @@ public class MavenIndex {
}
}
private PersistentHashMap<String, Set<String>> createPersistentMap(File f) throws IOException {
return new PersistentHashMap<String, Set<String>>(f, new EnumeratorStringDescriptor(), new SetDescriptor());
private PersistentHashMap<String, Set<String>> createPersistentMap(final File f) throws IOException {
return IOUtil.openCleanOrResetBroken(new ThrowableComputable<PersistentHashMap<String, Set<String>>, IOException>() {
@Override
public PersistentHashMap<String, Set<String>> compute() throws IOException {
return new PersistentHashMap<String, Set<String>>(f, new EnumeratorStringDescriptor(), new SetDescriptor());
}
}, f);
}
public void close(boolean releaseIndexContext) throws MavenIndexException {