mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
memory index storage reworked:
1. unneccesary synchronization removed 2. clear memory map on document save rather than on myBufferingEnabled flag change
This commit is contained in:
@@ -351,6 +351,19 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanupMemoryStorage() {
|
||||
for (UpdatableIndex index : myIndices.values()) {
|
||||
final IndexStorage indexStorage = ((MapReduceIndex)index).getStorage();
|
||||
index.getWriteLock().lock();
|
||||
try {
|
||||
((MemoryIndexStorage)indexStorage).clearMemoryMap();
|
||||
}
|
||||
finally {
|
||||
index.getWriteLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clearAllIndices() {
|
||||
for (UpdatableIndex index : myIndices.values()) {
|
||||
|
||||
@@ -217,6 +217,10 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
|
||||
public void bufferingStateChanged(final boolean newState) {
|
||||
((StubIndexImpl)StubIndexImpl.getInstance()).setDataBufferingEnabled(newState);
|
||||
}
|
||||
|
||||
public void memoryStorageCleared() {
|
||||
((StubIndexImpl)StubIndexImpl.getInstance()).cleanupMemoryStorage();
|
||||
}
|
||||
});
|
||||
}
|
||||
return new MyIndex(indexId, owner, storage, getIndexer());
|
||||
|
||||
@@ -42,8 +42,10 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.ManagingFS;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
@@ -200,6 +202,20 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
}
|
||||
});
|
||||
|
||||
connection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
|
||||
public void before(List<? extends VFileEvent> events) {
|
||||
for (VFileEvent event : events) {
|
||||
if (event.getRequestor() instanceof FileDocumentManager) {
|
||||
cleanupMemoryStorage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void after(List<? extends VFileEvent> events) {
|
||||
}
|
||||
});
|
||||
|
||||
ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() {
|
||||
public void writeActionStarted(Object action) {
|
||||
myUpToDateIndices.clear();
|
||||
@@ -257,7 +273,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private String calcConfigPath(final String path) {
|
||||
private static String calcConfigPath(final String path) {
|
||||
try {
|
||||
final String _path = FileUtil.toSystemIndependentName(new File(path).getCanonicalPath());
|
||||
return _path.endsWith("/")? _path : _path + "/" ;
|
||||
@@ -1078,11 +1094,6 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
|
||||
private StorageGuard.Holder setDataBufferingEnabled(final boolean enabled) {
|
||||
final StorageGuard.Holder holder = myStorageLock.enter(enabled);
|
||||
if (!enabled) {
|
||||
synchronized (myLastIndexedDocStamps) {
|
||||
myLastIndexedDocStamps.clear();
|
||||
}
|
||||
}
|
||||
for (ID<?, ?> indexId : myIndices.keySet()) {
|
||||
final MapReduceIndex index = (MapReduceIndex)getIndex(indexId);
|
||||
assert index != null;
|
||||
@@ -1092,6 +1103,25 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
return holder;
|
||||
}
|
||||
|
||||
private void cleanupMemoryStorage() {
|
||||
synchronized (myLastIndexedDocStamps) {
|
||||
myLastIndexedDocStamps.clear();
|
||||
}
|
||||
for (ID<?, ?> indexId : myIndices.keySet()) {
|
||||
final MapReduceIndex index = (MapReduceIndex)getIndex(indexId);
|
||||
assert index != null;
|
||||
final MemoryIndexStorage memStorage = (MemoryIndexStorage)index.getStorage();
|
||||
index.getWriteLock().lock();
|
||||
try {
|
||||
memStorage.clearMemoryMap();
|
||||
}
|
||||
finally {
|
||||
index.getWriteLock().unlock();
|
||||
}
|
||||
memStorage.fireMemoryStorageCleared();
|
||||
}
|
||||
}
|
||||
|
||||
private void dropUnregisteredIndices() {
|
||||
final Set<String> indicesToDrop = readRegistsredIndexNames();
|
||||
for (ID<?, ?> key : myIndices.keySet()) {
|
||||
|
||||
@@ -20,13 +20,14 @@ import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: Dec 10, 2007
|
||||
*/
|
||||
public interface IndexStorage<Key, Value> extends Flushable{
|
||||
public interface IndexStorage<Key, Value> extends Flushable {
|
||||
|
||||
void addValue(Key key, int inputId, Value value) throws StorageException;
|
||||
|
||||
@@ -44,4 +45,6 @@ public interface IndexStorage<Key, Value> extends Flushable{
|
||||
Collection<Key> getKeys() throws StorageException;
|
||||
|
||||
void close() throws StorageException;
|
||||
|
||||
void flush() throws IOException;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Valu
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void close() throws StorageException {
|
||||
public void close() throws StorageException {
|
||||
try {
|
||||
flush();
|
||||
myMap.close();
|
||||
@@ -157,7 +157,7 @@ public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Valu
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void clear() throws StorageException{
|
||||
public void clear() throws StorageException{
|
||||
try {
|
||||
myMap.close();
|
||||
}
|
||||
|
||||
@@ -18,14 +18,12 @@ package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.concurrency.JBLock;
|
||||
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
|
||||
import com.intellij.util.concurrency.LockFactory;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* This storage is needed for indexing yet unsaved data without saving those changes to 'main' backend storage
|
||||
@@ -36,14 +34,12 @@ import java.util.*;
|
||||
public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value> {
|
||||
private final Map<Key, UpdatableValueContainer<Value>> myMap = new HashMap<Key,UpdatableValueContainer<Value>>();
|
||||
private final IndexStorage<Key, Value> myBackendStorage;
|
||||
private boolean myBufferingEnabled = false;
|
||||
private final List<BufferingStateListener> myListeners = ContainerUtil.createEmptyCOWList();
|
||||
private final JBReentrantReadWriteLock myLock = LockFactory.createReadWriteLock();
|
||||
private final JBLock r = myLock.readLock();
|
||||
private final JBLock w = myLock.writeLock();
|
||||
|
||||
private final AtomicBoolean myBufferingEnabled = new AtomicBoolean(false);
|
||||
|
||||
public interface BufferingStateListener {
|
||||
void bufferingStateChanged(boolean newState);
|
||||
void memoryStorageCleared();
|
||||
}
|
||||
|
||||
public MemoryIndexStorage(IndexStorage<Key, Value> backend) {
|
||||
@@ -59,21 +55,21 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
}
|
||||
|
||||
public void setBufferingEnabled(boolean enabled) {
|
||||
w.lock();
|
||||
try {
|
||||
final boolean wasEnabled = myBufferingEnabled;
|
||||
myBufferingEnabled = enabled;
|
||||
if (wasEnabled && !enabled) {
|
||||
myMap.clear();
|
||||
}
|
||||
if (wasEnabled != enabled) {
|
||||
for (BufferingStateListener listener : myListeners) {
|
||||
listener.bufferingStateChanged(enabled);
|
||||
}
|
||||
final boolean wasEnabled = myBufferingEnabled.getAndSet(enabled);
|
||||
if (wasEnabled != enabled) {
|
||||
for (BufferingStateListener listener : myListeners) {
|
||||
listener.bufferingStateChanged(enabled);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
w.unlock();
|
||||
}
|
||||
|
||||
public void clearMemoryMap() {
|
||||
myMap.clear();
|
||||
}
|
||||
|
||||
public void fireMemoryStorageCleared() {
|
||||
for (BufferingStateListener listener : myListeners) {
|
||||
listener.memoryStorageCleared();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,14 +78,8 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
}
|
||||
|
||||
public void clear() throws StorageException {
|
||||
w.lock();
|
||||
try {
|
||||
myMap.clear();
|
||||
myBackendStorage.clear();
|
||||
}
|
||||
finally {
|
||||
w.unlock();
|
||||
}
|
||||
clearMemoryMap();
|
||||
myBackendStorage.clear();
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
@@ -103,75 +93,60 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
}
|
||||
|
||||
public boolean processKeys(final Processor<Key> processor) throws StorageException {
|
||||
r.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
final Set<Key> stopList = new HashSet<Key>();
|
||||
final Set<Key> stopList = new HashSet<Key>();
|
||||
|
||||
Processor<Key> decoratingProcessor = new Processor<Key>() {
|
||||
public boolean process(final Key key) {
|
||||
if (stopList.contains(key)) return true;
|
||||
Processor<Key> decoratingProcessor = new Processor<Key>() {
|
||||
public boolean process(final Key key) {
|
||||
if (stopList.contains(key)) return true;
|
||||
|
||||
final UpdatableValueContainer<Value> container = myMap.get(key);
|
||||
if (container != null && container.size() == 0) return true;
|
||||
return processor.process(key);
|
||||
}
|
||||
};
|
||||
|
||||
for (Key key : myMap.keySet()) {
|
||||
if (!decoratingProcessor.process(key)) return false;
|
||||
stopList.add(key);
|
||||
}
|
||||
return myBackendStorage.processKeys(decoratingProcessor);
|
||||
final UpdatableValueContainer<Value> container = myMap.get(key);
|
||||
if (container != null && container.size() == 0) return true;
|
||||
return processor.process(key);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
r.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
return myBackendStorage.processKeys(processor);
|
||||
for (Key key : myMap.keySet()) {
|
||||
if (!decoratingProcessor.process(key)) return false;
|
||||
stopList.add(key);
|
||||
}
|
||||
return myBackendStorage.processKeys(decoratingProcessor);
|
||||
}
|
||||
|
||||
public void addValue(final Key key, final int inputId, final Value value) throws StorageException {
|
||||
w.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
getMemValueContainer(key).addValue(inputId, value);
|
||||
return;
|
||||
}
|
||||
if (myBufferingEnabled.get()) {
|
||||
getMemValueContainer(key).addValue(inputId, value);
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
w.unlock();
|
||||
final UpdatableValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
valueContainer.addValue(inputId, value);
|
||||
}
|
||||
|
||||
myBackendStorage.addValue(key, inputId, value);
|
||||
}
|
||||
|
||||
public void removeValue(final Key key, final int inputId, final Value value) throws StorageException {
|
||||
w.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
getMemValueContainer(key).removeValue(inputId, value);
|
||||
return;
|
||||
}
|
||||
if (myBufferingEnabled.get()) {
|
||||
getMemValueContainer(key).removeValue(inputId, value);
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
w.unlock();
|
||||
final UpdatableValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
valueContainer.removeValue(inputId, value);
|
||||
}
|
||||
myBackendStorage.removeValue(key, inputId, value);
|
||||
}
|
||||
|
||||
public void removeAllValues(Key key, int inputId) throws StorageException {
|
||||
w.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
getMemValueContainer(key).removeAllValues(inputId);
|
||||
return;
|
||||
}
|
||||
if (myBufferingEnabled.get()) {
|
||||
getMemValueContainer(key).removeAllValues(inputId);
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
w.unlock();
|
||||
final UpdatableValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
valueContainer.removeAllValues(inputId);
|
||||
}
|
||||
|
||||
myBackendStorage.removeAllValues(key, inputId);
|
||||
}
|
||||
|
||||
@@ -199,18 +174,9 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
|
||||
@NotNull
|
||||
public ValueContainer<Value> read(final Key key) throws StorageException {
|
||||
r.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
final ValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
return valueContainer;
|
||||
}
|
||||
return myBackendStorage.read(key);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
r.unlock();
|
||||
final ValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
return valueContainer;
|
||||
}
|
||||
|
||||
return myBackendStorage.read(key);
|
||||
|
||||
Reference in New Issue
Block a user