mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
(instead of numerous stub index locks) use stub_updating_index's lock for processing stubs, flushing, clearing, disposing
as side effect accessing stub indices during processing other stub indices is allowed
This commit is contained in:
@@ -536,7 +536,7 @@ class IndexTest extends JavaCodeInsightFixtureTestCase {
|
||||
}
|
||||
|
||||
assertTrue(foundClass[0])
|
||||
assertTrue(!foundMethod[0])
|
||||
assertTrue(foundMethod[0]) // allow access stub index processing other index
|
||||
|
||||
def foundClassProcessAll = [false]
|
||||
def foundClassStub = [false]
|
||||
|
||||
@@ -39,10 +39,7 @@ import com.intellij.util.Processors;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.indexing.impl.IndexStorage;
|
||||
import com.intellij.util.indexing.impl.InputDataDiffBuilder;
|
||||
import com.intellij.util.indexing.impl.MapInputDataDiffBuilder;
|
||||
import com.intellij.util.indexing.impl.UpdateData;
|
||||
import com.intellij.util.indexing.impl.*;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.DataInputOutputUtil;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
@@ -59,7 +56,7 @@ import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@State(name = "FileBasedIndex", storages = @Storage(value = "stubIndex.xml", roamingType = RoamingType.DISABLED))
|
||||
public class StubIndexImpl extends StubIndex implements PersistentStateComponent<StubIndexState>, ApplicationComponent {
|
||||
@@ -214,9 +211,7 @@ public class StubIndexImpl extends StubIndex implements PersistentStateComponent
|
||||
if (!myInitialized) {
|
||||
return;
|
||||
}
|
||||
AsyncState state = getAsyncState();
|
||||
for (StubIndexKey key : getAllStubIndexKeys()) {
|
||||
final MyIndex<?> index = state.myIndices.get(key);
|
||||
for (MyIndex<?> index : getAsyncState().myIndices.values()) {
|
||||
index.flush();
|
||||
}
|
||||
}
|
||||
@@ -344,27 +339,29 @@ public class StubIndexImpl extends StubIndex implements PersistentStateComponent
|
||||
@Nullable final GlobalSearchScope scope,
|
||||
@NotNull StubIdListContainerAction action) {
|
||||
final FileBasedIndexImpl fileBasedIndex = (FileBasedIndexImpl)FileBasedIndex.getInstance();
|
||||
myAccessValidator.checkAccessingIndexDuringOtherIndexProcessing(StubUpdatingIndex.INDEX_ID);
|
||||
fileBasedIndex.ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, scope);
|
||||
ID<Integer, SerializedStubTree> stubUpdatingIndexId = StubUpdatingIndex.INDEX_ID;
|
||||
myAccessValidator.checkAccessingIndexDuringOtherIndexProcessing(stubUpdatingIndexId);
|
||||
fileBasedIndex.ensureUpToDate(stubUpdatingIndexId, project, scope);
|
||||
|
||||
final MyIndex<Key> index = (MyIndex<Key>)getAsyncState().myIndices.get(indexKey);
|
||||
|
||||
UpdatableIndex<Integer, SerializedStubTree, FileContent> stubUpdatingIndex = fileBasedIndex.getIndex(stubUpdatingIndexId);
|
||||
try {
|
||||
myAccessValidator.checkAccessingIndexDuringOtherIndexProcessing(indexKey);
|
||||
myAccessValidator.checkAccessingIndexDuringOtherIndexProcessing(stubUpdatingIndexId);
|
||||
|
||||
try {
|
||||
// disable up-to-date check to avoid locks on attempt to acquire index write lock while holding at the same time the readLock for this index
|
||||
FileBasedIndexImpl.disableUpToDateCheckForCurrentThread();
|
||||
|
||||
index.getReadLock().lock();
|
||||
stubUpdatingIndex.getReadLock().lock();
|
||||
|
||||
myAccessValidator.startedProcessingActivityForIndex(indexKey);
|
||||
myAccessValidator.startedProcessingActivityForIndex(stubUpdatingIndexId);
|
||||
|
||||
return index.getData(key).forEach(action);
|
||||
}
|
||||
finally {
|
||||
myAccessValidator.stoppedProcessingActivityForIndex(indexKey);
|
||||
index.getReadLock().unlock();
|
||||
myAccessValidator.stoppedProcessingActivityForIndex(stubUpdatingIndexId);
|
||||
stubUpdatingIndex.getReadLock().unlock();
|
||||
FileBasedIndexImpl.enableUpToDateCheckForCurrentThread();
|
||||
}
|
||||
}
|
||||
@@ -505,19 +502,21 @@ public class StubIndexImpl extends StubIndex implements PersistentStateComponent
|
||||
}
|
||||
|
||||
public void cleanupMemoryStorage() {
|
||||
for (UpdatableIndex index : getAsyncState().myIndices.values()) {
|
||||
final IndexStorage indexStorage = ((VfsAwareMapReduceIndex)index).getStorage();
|
||||
index.getWriteLock().lock();
|
||||
try {
|
||||
UpdatableIndex<Integer, SerializedStubTree, FileContent> stubUpdatingIndex =
|
||||
((FileBasedIndexImpl)FileBasedIndex.getInstance()).getIndex(StubUpdatingIndex.INDEX_ID);
|
||||
stubUpdatingIndex.getWriteLock().lock();
|
||||
|
||||
try {
|
||||
for (UpdatableIndex index : getAsyncState().myIndices.values()) {
|
||||
final IndexStorage indexStorage = ((VfsAwareMapReduceIndex)index).getStorage();
|
||||
((MemoryIndexStorage)indexStorage).clearMemoryMap();
|
||||
}
|
||||
finally {
|
||||
index.getWriteLock().unlock();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stubUpdatingIndex.getWriteLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clearAllIndices() {
|
||||
for (UpdatableIndex index : getAsyncState().myIndices.values()) {
|
||||
try {
|
||||
@@ -561,14 +560,6 @@ public class StubIndexImpl extends StubIndex implements PersistentStateComponent
|
||||
myPreviouslyRegistered = state;
|
||||
}
|
||||
|
||||
public final Lock getWriteLock(StubIndexKey indexKey) {
|
||||
return getAsyncState().myIndices.get(indexKey).getWriteLock();
|
||||
}
|
||||
|
||||
Collection<StubIndexKey> getAllStubIndexKeys() {
|
||||
return Collections.unmodifiableCollection(getAsyncState().myIndices.keySet());
|
||||
}
|
||||
|
||||
public <K> void updateIndex(@NotNull StubIndexKey key,
|
||||
int fileId,
|
||||
@NotNull final Map<K, StubIdList> oldValues,
|
||||
@@ -586,6 +577,12 @@ public class StubIndexImpl extends StubIndex implements PersistentStateComponent
|
||||
}
|
||||
|
||||
private static class MyIndex<K> extends VfsAwareMapReduceIndex<K, StubIdList, Void> {
|
||||
@NotNull
|
||||
@Override
|
||||
protected ReentrantReadWriteLock createLock() {
|
||||
UpdatableIndex<?, ?, FileContent> index = ((FileBasedIndexImpl)FileBasedIndex.getInstance()).getIndex(StubUpdatingIndex.INDEX_ID);
|
||||
return ((MapReduceIndex)index).getLock();
|
||||
}
|
||||
|
||||
public MyIndex(IndexExtension<K, StubIdList, Void> extension, IndexStorage<K, StubIdList> storage) throws IOException {
|
||||
super(extension, storage);
|
||||
|
||||
@@ -441,13 +441,13 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws StorageException {
|
||||
protected void doFlush() throws IOException, StorageException {
|
||||
final StubIndexImpl stubIndex = getStubIndex();
|
||||
try {
|
||||
stubIndex.flush();
|
||||
}
|
||||
finally {
|
||||
super.flush();
|
||||
super.doFlush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,36 +458,22 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
|
||||
StubUpdatingData stubUpdatingData = (StubUpdatingData)updateData;
|
||||
final Map<StubIndexKey, Map<Object, StubIdList>> newStubIndicesValueMap = stubUpdatingData.getNewStubIndicesValueMap();
|
||||
|
||||
final StubIndexImpl stubIndex = getStubIndex();
|
||||
final Collection<StubIndexKey> allStubIndices = stubIndex.getAllStubIndexKeys();
|
||||
try {
|
||||
// first write-lock affected stub indices to avoid deadlocks
|
||||
for (StubIndexKey key : allStubIndices) {
|
||||
stubIndex.getWriteLock(key).lock();
|
||||
}
|
||||
getWriteLock().lock();
|
||||
|
||||
try {
|
||||
getWriteLock().lock();
|
||||
super.updateWithMap(inputId, updateData);
|
||||
|
||||
super.updateWithMap(inputId, updateData);
|
||||
final Map<StubIndexKey, Map<Object, StubIdList>> previousStubIndicesValueMap = stubUpdatingData.getOldStubIndicesValueMap();
|
||||
|
||||
final Map<StubIndexKey, Map<Object, StubIdList>> previousStubIndicesValueMap = stubUpdatingData.getOldStubIndicesValueMap();
|
||||
|
||||
updateStubIndices(
|
||||
getAffectedIndices(previousStubIndicesValueMap, newStubIndicesValueMap),
|
||||
inputId,
|
||||
previousStubIndicesValueMap,
|
||||
newStubIndicesValueMap
|
||||
);
|
||||
}
|
||||
finally {
|
||||
getWriteLock().unlock();
|
||||
}
|
||||
updateStubIndices(
|
||||
getAffectedIndices(previousStubIndicesValueMap, newStubIndicesValueMap),
|
||||
inputId,
|
||||
previousStubIndicesValueMap,
|
||||
newStubIndicesValueMap
|
||||
);
|
||||
}
|
||||
finally {
|
||||
for (StubIndexKey key : allStubIndices) {
|
||||
stubIndex.getWriteLock(key).unlock();
|
||||
}
|
||||
getWriteLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,34 +495,19 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() throws StorageException {
|
||||
protected void doClear() throws StorageException, IOException {
|
||||
final StubIndexImpl stubIndex = StubIndexImpl.getInstanceOrInvalidate();
|
||||
final Collection<StubIndexKey> allStubIndexKeys = stubIndex != null? stubIndex.getAllStubIndexKeys() : Collections.emptyList();
|
||||
try {
|
||||
for (StubIndexKey key : allStubIndexKeys) {
|
||||
//noinspection ConstantConditions
|
||||
stubIndex.getWriteLock(key).lock();
|
||||
}
|
||||
getWriteLock().lock();
|
||||
if (stubIndex != null) {
|
||||
stubIndex.clearAllIndices();
|
||||
}
|
||||
myStubVersionMap.clear();
|
||||
super.clear();
|
||||
}
|
||||
finally {
|
||||
getWriteLock().unlock();
|
||||
for (StubIndexKey key : allStubIndexKeys) {
|
||||
//noinspection ConstantConditions
|
||||
stubIndex.getWriteLock(key).unlock();
|
||||
}
|
||||
if (stubIndex != null) {
|
||||
stubIndex.clearAllIndices();
|
||||
}
|
||||
myStubVersionMap.clear();
|
||||
super.doClear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
protected void doDispose() throws StorageException {
|
||||
try {
|
||||
super.dispose();
|
||||
super.doDispose();
|
||||
}
|
||||
finally {
|
||||
getStubIndex().dispose();
|
||||
|
||||
@@ -57,7 +57,7 @@ public class VfsAwareMapReduceIndex<Key, Value, Input> extends MapReduceIndex<Ke
|
||||
}
|
||||
|
||||
private final AtomicBoolean myInMemoryMode = new AtomicBoolean();
|
||||
private final TIntObjectHashMap<Collection<Key>> myInMemoryKeys = new TIntObjectHashMap<Collection<Key>>();
|
||||
private final TIntObjectHashMap<Collection<Key>> myInMemoryKeys = new TIntObjectHashMap<>();
|
||||
private final SnapshotInputMappings<Key, Value, Input> mySnapshotInputMappings;
|
||||
|
||||
public VfsAwareMapReduceIndex(@NotNull IndexExtension<Key, Value, Input> extension,
|
||||
@@ -179,30 +179,35 @@ public class VfsAwareMapReduceIndex<Key, Value, Input> extends MapReduceIndex<Ke
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() throws StorageException {
|
||||
super.clear();
|
||||
if (mySnapshotInputMappings != null) try {
|
||||
mySnapshotInputMappings.clear();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
protected void doClear() throws StorageException, IOException {
|
||||
super.doClear();
|
||||
if (mySnapshotInputMappings != null) {
|
||||
try {
|
||||
mySnapshotInputMappings.clear();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws StorageException {
|
||||
super.flush();
|
||||
protected void doFlush() throws IOException, StorageException {
|
||||
super.doFlush();
|
||||
if (mySnapshotInputMappings != null) mySnapshotInputMappings.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
if (mySnapshotInputMappings != null) try {
|
||||
mySnapshotInputMappings.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
protected void doDispose() throws StorageException {
|
||||
super.doDispose();
|
||||
|
||||
if (mySnapshotInputMappings != null) {
|
||||
try {
|
||||
mySnapshotInputMappings.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public abstract class MapReduceIndex<Key,Value, Input> implements InvertedIndex<
|
||||
|
||||
protected final ForwardIndex<Key, Value> myForwardIndex;
|
||||
|
||||
private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock();
|
||||
private final ReentrantReadWriteLock myLock = createLock();
|
||||
private volatile boolean myDisposed;
|
||||
|
||||
private final LowMemoryWatcher myLowMemoryFlusher = LowMemoryWatcher.register(new Runnable() {
|
||||
@@ -91,12 +91,20 @@ public abstract class MapReduceIndex<Key,Value, Input> implements InvertedIndex<
|
||||
return myStorage;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ReentrantReadWriteLock createLock() {
|
||||
return new ReentrantReadWriteLock();
|
||||
}
|
||||
|
||||
public final ReentrantReadWriteLock getLock() {
|
||||
return myLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() throws StorageException {
|
||||
try {
|
||||
getWriteLock().lock();
|
||||
myStorage.clear();
|
||||
if (myForwardIndex != null) myForwardIndex.clear();
|
||||
doClear();
|
||||
}
|
||||
catch (StorageException e) {
|
||||
LOG.error(e);
|
||||
@@ -109,12 +117,16 @@ public abstract class MapReduceIndex<Key,Value, Input> implements InvertedIndex<
|
||||
}
|
||||
}
|
||||
|
||||
protected void doClear() throws StorageException, IOException {
|
||||
myStorage.clear();
|
||||
if (myForwardIndex != null) myForwardIndex.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws StorageException{
|
||||
try {
|
||||
getReadLock().lock();
|
||||
if (myForwardIndex != null) myForwardIndex.flush();
|
||||
myStorage.flush();
|
||||
doFlush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new StorageException(e);
|
||||
@@ -133,23 +145,18 @@ public abstract class MapReduceIndex<Key,Value, Input> implements InvertedIndex<
|
||||
}
|
||||
}
|
||||
|
||||
protected void doFlush() throws IOException, StorageException {
|
||||
if (myForwardIndex != null) myForwardIndex.flush();
|
||||
myStorage.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
myLowMemoryFlusher.stop();
|
||||
final Lock lock = getWriteLock();
|
||||
try {
|
||||
lock.lock();
|
||||
try {
|
||||
myStorage.close();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (myForwardIndex != null) myForwardIndex.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
doDispose();
|
||||
}
|
||||
catch (StorageException e) {
|
||||
LOG.error(e);
|
||||
@@ -160,6 +167,20 @@ public abstract class MapReduceIndex<Key,Value, Input> implements InvertedIndex<
|
||||
}
|
||||
}
|
||||
|
||||
protected void doDispose() throws StorageException {
|
||||
try {
|
||||
myStorage.close();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (myForwardIndex != null) myForwardIndex.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public final Lock getReadLock() {
|
||||
return myLock.readLock();
|
||||
|
||||
Reference in New Issue
Block a user