Revert "index: do not copy prebuilt indexes; attempt #2 WEB-45822"

This reverts commit a676a327

GitOrigin-RevId: 750251d21e6b6f4b0d3a4c0c5737d68ac4347d16
This commit is contained in:
Dmitry Batkovich
2020-06-10 16:49:20 +03:00
committed by intellij-monorepo-bot
parent 28781682ba
commit f7d00e0193
4 changed files with 100 additions and 95 deletions
@@ -6,6 +6,7 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.stubs.FileContentHashing
import com.intellij.psi.stubs.HashCodeDescriptor
@@ -15,6 +16,7 @@ import com.intellij.util.indexing.FileContent
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.PersistentHashMap
import java.io.File
import java.io.FileFilter
import java.io.IOException
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.withLock
@@ -46,10 +48,15 @@ abstract class PrebuiltIndexProvider<Value>: Disposable {
internal fun init() {
myOpenCloseLock.writeLock().withLock {
if (USE_PREBUILT_INDEX) {
val indexesRoot = findPrebuiltIndicesRoot()
var indexesRoot = findPrebuiltIndicesRoot()
try {
if (indexesRoot != null && indexesRoot.exists()) {
// we should copy prebuilt indexes to a writable folder
indexesRoot = copyPrebuiltIndicesToIndexRoot(indexesRoot)
// otherwise we can get access denied error, because persistent hash map opens file for read and write
myPrebuiltIndexStorage = openIndexStorage(indexesRoot)
LOG.info("Using prebuilt $indexName from " + myPrebuiltIndexStorage?.baseFile?.toAbsolutePath())
}
else {
@@ -103,6 +110,15 @@ abstract class PrebuiltIndexProvider<Value>: Disposable {
protected abstract fun getIndexRoot(): File
@Throws(IOException::class)
private fun copyPrebuiltIndicesToIndexRoot(prebuiltIndicesRoot: File): File {
val indexRoot = getIndexRoot()
FileUtil.copyDir(prebuiltIndicesRoot, indexRoot, FileFilter { f -> f.name.startsWith(indexName) })
return indexRoot
}
private fun findPrebuiltIndicesRoot(): File? {
val path: String? = System.getProperty(PrebuiltStubsProviderBase.PREBUILT_INDICES_PATH_PROPERTY)
if (path != null && File(path).exists()) {
@@ -106,7 +106,7 @@ abstract class PrebuiltStubsProviderBase : PrebuiltIndexProvider<SerializedStubT
}
else {
mySerializationManager = SerializationManagerImpl(File(indexesRoot, "$indexName.names").toPath(), true)
Disposer.register(ApplicationManager.getApplication(), mySerializationManager)
Disposer.register(ApplicationManager.getApplication(), mySerializationManager!!)
return super.openIndexStorage(indexesRoot)
}
}
@@ -160,104 +160,91 @@ public class PersistentHashMap<Key, Value> implements AppendablePersistentMap<Ke
@NotNull PersistentHashMapValueStorage.CreationTimeOptions options) throws IOException {
// it's important to initialize it as early as possible
myIsReadOnly = isReadOnly();
Boolean oldThreadLocalReadOnlyStatus = null;
if (myIsReadOnly) {
options = options.setReadOnly();
oldThreadLocalReadOnlyStatus = PersistentHashMapValueStorage.CreationTimeOptions.READONLY.get();
PersistentHashMapValueStorage.CreationTimeOptions.READONLY.set(Boolean.TRUE);
}
if (myIsReadOnly) options = options.setReadOnly();
myEnumerator = PersistentEnumeratorDelegate.createDefaultEnumerator(checkDataFiles(file),
keyDescriptor,
initialSize,
lockContext,
modifyVersionDependingOnOptions(version, options));
myStorageFile = file;
myKeyDescriptor = keyDescriptor;
final PersistentEnumeratorBase.@NotNull RecordBufferHandler<PersistentEnumeratorBase<?>> recordHandler = myEnumerator.getRecordHandler();
myParentValueRefOffset = recordHandler.getRecordBuffer(myEnumerator).length;
myIntMapping = valueExternalizer instanceof IntInlineKeyDescriptor && wantNonNegativeIntegralValues();
myDirectlyStoreLongFileOffsetMode = keyDescriptor instanceof InlineKeyDescriptor && myEnumerator instanceof PersistentBTreeEnumerator;
myRecordBuffer = ThreadLocal
.withInitial(() -> myDirectlyStoreLongFileOffsetMode ? ArrayUtilRt.EMPTY_BYTE_ARRAY : new byte[myParentValueRefOffset + 8]);
mySmallRecordBuffer = ThreadLocal
.withInitial(() -> myDirectlyStoreLongFileOffsetMode ? ArrayUtilRt.EMPTY_BYTE_ARRAY : new byte[myParentValueRefOffset + 4]);
myEnumerator.setRecordHandler(new PersistentEnumeratorBase.RecordBufferHandler<PersistentEnumeratorBase<?>>() {
@Override
int recordWriteOffset(PersistentEnumeratorBase<?> enumerator, byte[] buf) {
return recordHandler.recordWriteOffset(enumerator, buf);
}
@Override
byte @NotNull [] getRecordBuffer(PersistentEnumeratorBase<?> enumerator) {
return myIntAddressForNewRecord ? mySmallRecordBuffer.get() : myRecordBuffer.get();
}
@Override
void setupRecord(PersistentEnumeratorBase enumerator, int hashCode, int dataOffset, byte @NotNull [] buf) {
recordHandler.setupRecord(enumerator, hashCode, dataOffset, buf);
for (int i = myParentValueRefOffset; i < buf.length; i++) {
buf[i] = 0;
}
}
});
myEnumerator.setMarkCleanCallback(
new Flushable() {
@Override
public void flush() {
myEnumerator.putMetaData(myLiveAndGarbageKeysCounter);
myEnumerator.putMetaData2(myLargeIndexWatermarkId | ((long)myReadCompactionGarbageSize << 32));
}
}
);
if (myDoTrace) LOG.info("Opened " + file);
try {
myEnumerator = PersistentEnumeratorDelegate.createDefaultEnumerator(checkDataFiles(file),
keyDescriptor,
initialSize,
lockContext,
modifyVersionDependingOnOptions(version, options));
myValueExternalizer = valueExternalizer;
myValueStorage = myIntMapping ? null : new PersistentHashMapValueStorage(getDataFile(file), options);
myAppendCache = myIntMapping ? null : createAppendCache(keyDescriptor);
myAppendCacheFlusher = myIntMapping ? null : LowMemoryWatcher.register(this::dropMemoryCaches);
myLiveAndGarbageKeysCounter = myEnumerator.getMetaData();
long data2 = myEnumerator.getMetaData2();
myLargeIndexWatermarkId = (int)(data2 & DEAD_KEY_NUMBER_MASK);
myReadCompactionGarbageSize = (int)(data2 >>> 32);
myCanReEnumerate = myEnumerator.canReEnumerate();
myStorageFile = file;
myKeyDescriptor = keyDescriptor;
final PersistentEnumeratorBase.@NotNull RecordBufferHandler<PersistentEnumeratorBase<?>> recordHandler =
myEnumerator.getRecordHandler();
myParentValueRefOffset = recordHandler.getRecordBuffer(myEnumerator).length;
myIntMapping = valueExternalizer instanceof IntInlineKeyDescriptor && wantNonNegativeIntegralValues();
myDirectlyStoreLongFileOffsetMode = keyDescriptor instanceof InlineKeyDescriptor && myEnumerator instanceof PersistentBTreeEnumerator;
myRecordBuffer = ThreadLocal
.withInitial(() -> myDirectlyStoreLongFileOffsetMode ? ArrayUtilRt.EMPTY_BYTE_ARRAY : new byte[myParentValueRefOffset + 8]);
mySmallRecordBuffer = ThreadLocal
.withInitial(() -> myDirectlyStoreLongFileOffsetMode ? ArrayUtilRt.EMPTY_BYTE_ARRAY : new byte[myParentValueRefOffset + 4]);
myEnumerator.setRecordHandler(new PersistentEnumeratorBase.RecordBufferHandler<PersistentEnumeratorBase<?>>() {
@Override
int recordWriteOffset(PersistentEnumeratorBase<?> enumerator, byte[] buf) {
return recordHandler.recordWriteOffset(enumerator, buf);
}
@Override
byte @NotNull [] getRecordBuffer(PersistentEnumeratorBase<?> enumerator) {
return myIntAddressForNewRecord ? mySmallRecordBuffer.get() : myRecordBuffer.get();
}
@Override
void setupRecord(PersistentEnumeratorBase enumerator, int hashCode, int dataOffset, byte @NotNull [] buf) {
recordHandler.setupRecord(enumerator, hashCode, dataOffset, buf);
for (int i = myParentValueRefOffset; i < buf.length; i++) {
buf[i] = 0;
}
}
});
myEnumerator.setMarkCleanCallback(
new Flushable() {
@Override
public void flush() {
myEnumerator.putMetaData(myLiveAndGarbageKeysCounter);
myEnumerator.putMetaData2(myLargeIndexWatermarkId | ((long)myReadCompactionGarbageSize << 32));
}
}
);
if (myDoTrace) LOG.info("Opened " + file);
try {
myValueExternalizer = valueExternalizer;
myValueStorage = myIntMapping ? null : new PersistentHashMapValueStorage(getDataFile(file), options);
myAppendCache = myIntMapping ? null : createAppendCache(keyDescriptor);
myAppendCacheFlusher = myIntMapping ? null : LowMemoryWatcher.register(this::dropMemoryCaches);
myLiveAndGarbageKeysCounter = myEnumerator.getMetaData();
long data2 = myEnumerator.getMetaData2();
myLargeIndexWatermarkId = (int)(data2 & DEAD_KEY_NUMBER_MASK);
myReadCompactionGarbageSize = (int)(data2 >>> 32);
myCanReEnumerate = myEnumerator.canReEnumerate();
if (!options.isReadOnly() && makesSenseToCompact()) {
compact();
}
}
catch (IOException e) {
try {
// attempt to close already opened resources
close();
}
catch (Throwable ignored) {
}
throw e; // rethrow
}
catch (Throwable t) {
LOG.error(t);
try {
// attempt to close already opened resources
close();
}
catch (Throwable ignored) {
}
throw new PersistentEnumerator.CorruptedException(file);
if (!options.isReadOnly() && makesSenseToCompact()) {
compact();
}
}
finally {
if (myIsReadOnly) {
PersistentHashMapValueStorage.CreationTimeOptions.READONLY.set(oldThreadLocalReadOnlyStatus);
catch (IOException e) {
try {
// attempt to close already opened resources
close();
}
catch (Throwable ignored) {
}
throw e; // rethrow
}
catch (Throwable t) {
LOG.error(t);
try {
// attempt to close already opened resources
close();
}
catch (Throwable ignored) {
}
throw new PersistentEnumerator.CorruptedException(file);
}
}
@@ -43,6 +43,7 @@ public class ReadWriteDirectBufferWrapper extends DirectBufferWrapper {
static class FileContext implements AutoCloseable {
private final FileChannel myFile;
private final boolean myReadOnly;
FileContext(Path path, boolean readOnly) throws IOException {
myFile = FileUtilRt.doIOOperation(new FileUtilRt.RepeatableIOOperation<FileChannel, IOException>() {
@@ -52,7 +53,7 @@ public class ReadWriteDirectBufferWrapper extends DirectBufferWrapper {
@Override
public FileChannel execute(boolean finalAttempt) throws IOException {
try {
Set<StandardOpenOption> options = readOnly
Set<StandardOpenOption> options = myReadOnly
? EnumSet.of(StandardOpenOption.READ)
: EnumSet.of(StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
return unInterruptible(FileChannel.open(path, options));
@@ -73,6 +74,7 @@ public class ReadWriteDirectBufferWrapper extends DirectBufferWrapper {
}
}
});
myReadOnly = readOnly;
}
@Override