summaryrefslogtreecommitdiff
path: root/platform/util/src/com/intellij/util/io
diff options
context:
space:
mode:
Diffstat (limited to 'platform/util/src/com/intellij/util/io')
-rw-r--r--platform/util/src/com/intellij/util/io/IntToIntBtree.java85
-rw-r--r--platform/util/src/com/intellij/util/io/PagedFileStorage.java23
-rw-r--r--platform/util/src/com/intellij/util/io/RandomAccessDataFile.java29
-rw-r--r--platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java46
4 files changed, 126 insertions, 57 deletions
diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java
index b17fc6cc5c6c..475f3cb67a94 100644
--- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java
+++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ import java.util.Arrays;
* Date: 7/12/11
* Time: 1:34 PM
*/
-class IntToIntBtree {
+public class IntToIntBtree {
public static int version() {
return 4 + (IOUtil.ourByteBuffersUseNativeByteOrder ? 0xFF : 0);
}
@@ -55,10 +55,10 @@ class IntToIntBtree {
private boolean hasZeroKey;
private int zeroKeyValue;
- private boolean isLarge = true;
+ private final boolean isLarge = true;
private final ResizeableMappedFile storage;
private final boolean offloadToSiblingsBeforeSplit = false;
- private boolean indexNodeIsHashTable = true;
+ private final boolean indexNodeIsHashTable = true;
final int metaDataLeafPageLength;
final int hashPageCapacity;
@@ -66,8 +66,8 @@ class IntToIntBtree {
private TIntIntHashMap myCachedMappings;
private final int myCachedMappingsSize;
- public IntToIntBtree(int _pageSize, File file, PagedFileStorage.StorageLockContext storageLockContext, boolean initial) throws IOException {
- pageSize = _pageSize;
+ public IntToIntBtree(int pageSize, @NotNull File file, @NotNull PagedFileStorage.StorageLockContext storageLockContext, boolean initial) throws IOException {
+ this.pageSize = pageSize;
if (initial) {
FileUtil.delete(file);
@@ -82,13 +82,12 @@ class IntToIntBtree {
root.setIndexLeaf(true);
}
- int i = (pageSize - BtreePage.RESERVED_META_PAGE_LEN) / BtreeIndexNodeView.INTERIOR_SIZE - 1;
+ int i = (this.pageSize - BtreePage.RESERVED_META_PAGE_LEN) / BtreeIndexNodeView.INTERIOR_SIZE - 1;
assert i < Short.MAX_VALUE && i % 2 == 0;
maxInteriorNodes = (short)i;
maxLeafNodes = (short)i;
- int metaPageLen = BtreePage.RESERVED_META_PAGE_LEN;
-
+ int metaPageLen;
if (indexNodeIsHashTable) {
++i;
while(!isPrime(i)) i -= 2;
@@ -97,8 +96,10 @@ class IntToIntBtree {
metaPageLen = BtreePage.RESERVED_META_PAGE_LEN;
i = (int)(hashPageCapacity * 0.9);
if ((i & 1) == 1) ++i;
- } else {
+ }
+ else {
hashPageCapacity = -1;
+ metaPageLen = BtreePage.RESERVED_META_PAGE_LEN;
}
metaDataLeafPageLength = metaPageLen;
@@ -108,20 +109,18 @@ class IntToIntBtree {
if (hasCachedMappings) {
myCachedMappings = new TIntIntHashMap(myCachedMappingsSize = 4 * maxLeafNodes);
- } else {
+ }
+ else {
myCachedMappings = null;
myCachedMappingsSize = -1;
}
}
- public void persistVars(BtreeDataStorage storage, boolean toDisk) {
- if (toDisk) {
- storage.persistInt(0, height | (hasZeroKey ? HAS_ZERO_KEY_MASK :0), true);
- } else {
- int i = storage.persistInt(0, 0, false);
- hasZeroKey = (i & HAS_ZERO_KEY_MASK) != 0;
- height = i & ~HAS_ZERO_KEY_MASK;
- }
+ // return total number of bytes needed for storing information
+ public int persistVars(@NotNull BtreeDataStorage storage, boolean toDisk) {
+ int i = storage.persistInt(0, height | (hasZeroKey ? HAS_ZERO_KEY_MASK :0), toDisk);
+ hasZeroKey = (i & HAS_ZERO_KEY_MASK) != 0;
+ height = i & ~HAS_ZERO_KEY_MASK;
pagesCount = storage.persistInt(4, pagesCount, toDisk);
movedMembersCount = storage.persistInt(8, movedMembersCount, toDisk);
@@ -132,9 +131,10 @@ class IntToIntBtree {
hashedPagesCount = storage.persistInt(28, hashedPagesCount, toDisk);
root.setAddress(storage.persistInt(32, root.address, toDisk));
zeroKeyValue = storage.persistInt(36, zeroKeyValue, toDisk);
+ return 40;
}
- interface BtreeDataStorage {
+ public interface BtreeDataStorage {
int persistInt(int offset, int value, boolean toDisk);
}
@@ -155,10 +155,11 @@ class IntToIntBtree {
}
private BtreeIndexNodeView myAccessNodeView;
- private int myLastGetKey, myOptimizedInserts;
+ private int myLastGetKey;
+ private int myOptimizedInserts;
private boolean myCanUseLastKey;
- public boolean get(int key, int[] result) {
+ public boolean get(int key, @NotNull int[] result) {
if (key == 0) {
if (hasZeroKey) {
result[0] = zeroKeyValue;
@@ -199,7 +200,8 @@ class IntToIntBtree {
if (hasCachedMappings) {
myCachedMappings.put(key, value);
if (myCachedMappings.size() == myCachedMappingsSize) flushCachedMappings();
- } else {
+ }
+ else {
boolean canUseLastKey = myCanUseLastKey;
if (canUseLastKey) {
myCanUseLastKey = false;
@@ -256,12 +258,12 @@ class IntToIntBtree {
}
}
- void doClose() throws IOException {
+ public void doClose() throws IOException {
myCachedMappings = null;
storage.close();
}
- void doFlush() {
+ public void doFlush() {
flushCachedMappings();
storage.force();
}
@@ -445,11 +447,11 @@ class IntToIntBtree {
putInt(offset, value);
}
- private final int indexToOffset(int i) {
+ private int indexToOffset(int i) {
return i * INTERIOR_SIZE + (isHashedLeaf() ? btree.metaDataLeafPageLength:RESERVED_META_PAGE_LEN);
}
- private final int keyAt(int i) {
+ private int keyAt(int i) {
if (doSanityCheck) {
if (isHashedLeaf()) myAssert(i < btree.hashPageCapacity);
else myAssert(i < getChildrenCount());
@@ -495,7 +497,7 @@ class IntToIntBtree {
setFlag(INDEX_LEAF_MASK, value);
}
- private final boolean isHashedLeaf() {
+ private boolean isHashedLeaf() {
return isHashedLeaf;
}
@@ -608,7 +610,8 @@ class IntToIntBtree {
if (hashedLeaf) {
hashLeafData = new HashLeafData(this, recordCount);
if (doOffloadToSiblingsWhenHashed(parent, hashLeafData)) return parentAddress;
- } else {
+ }
+ else {
if (doOffloadToSiblingsSorted(parent)) return parentAddress;
}
}
@@ -1074,16 +1077,14 @@ class IntToIntBtree {
private static final boolean useDoubleHash = true;
private int hashIndex(int value) {
- int hash, index;
-
final int length = btree.hashPageCapacity;
- hash = value & 0x7fffffff;
- index = hash % length;
+ int hash = value & 0x7fffffff;
+ int index = hash % length;
int keyAtIndex = keyAt(index);
- int total = 0;
btree.hashSearchRequests++;
+ int total = 0;
if (useDoubleHash) {
if (keyAtIndex != value && keyAtIndex != HASH_FREE) {
// see Knuth, p. 529
@@ -1148,11 +1149,21 @@ class IntToIntBtree {
if (childrenAddresses.length > 0) {
BtreeIndexNodeView child = new BtreeIndexNodeView(this);
- for(int i = 0; i < childrenAddresses.length; ++i) {
- child.setAddress(childrenAddresses[i]);
- if (!processLeafPages(child, processor)) return false;
+ for (int childrenAddress : childrenAddresses) {
+ child.setAddress(childrenAddress);
+ if (!processLeafPages(child, processor)) return false;
}
}
return true;
}
+
+ public void withStorageLock(@NotNull Runnable runnable) {
+ storage.getPagedFileStorage().lock();
+ try {
+ runnable.run();
+ }
+ finally {
+ storage.getPagedFileStorage().unlock();
+ }
+ }
}
diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java
index 69315f1b3764..1fca8e063394 100644
--- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java
+++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,11 +88,11 @@ public class PagedFileStorage implements Forceable {
private static final ByteOrder ourNativeByteOrder = ByteOrder.nativeOrder();
public void lock() {
- myStorageLockContext.myLock.lock();
+ myStorageLockContext.lock();
}
public void unlock() {
- myStorageLockContext.myLock.unlock();
+ myStorageLockContext.unlock();
}
public StorageLockContext getStorageLockContext() {
@@ -510,11 +510,11 @@ public class PagedFileStorage implements Forceable {
}
public void lock() {
- myDefaultStorageLockContext.myLock.lock();
+ myDefaultStorageLockContext.lock();
}
public void unlock() {
- myDefaultStorageLockContext.myLock.unlock();
+ myDefaultStorageLockContext.unlock();
}
private int registerPagedFileStorage(@NotNull PagedFileStorage storage) {
@@ -658,7 +658,9 @@ public class PagedFileStorage implements Forceable {
LOG.info("Max memory:"+maxMemory.get(null) + ", reserved memory:" + reservedMemory.get(null));
}
}
- catch (Throwable t) {}
+ catch (Throwable t) {
+
+ }
throw new MappingFailedException(
"Cannot recover from OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MB + "MB " +
"new size limit: " + mySizeLimit / MB + "MB " +
@@ -669,7 +671,7 @@ public class PagedFileStorage implements Forceable {
}
}
- private void checkThreadAccess(StorageLockContext storageLockContext) {
+ private static void checkThreadAccess(StorageLockContext storageLockContext) {
if (storageLockContext.myCheckThreadAccess && !storageLockContext.myLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Must hold StorageLock lock to access PagedFileStorage");
}
@@ -776,5 +778,12 @@ public class PagedFileStorage implements Forceable {
public StorageLockContext(boolean checkAccess) {
this(ourLock, checkAccess);
}
+
+ public void lock() {
+ myLock.lock();
+ }
+ public void unlock() {
+ myLock.unlock();
+ }
}
}
diff --git a/platform/util/src/com/intellij/util/io/RandomAccessDataFile.java b/platform/util/src/com/intellij/util/io/RandomAccessDataFile.java
index 9a297bcef6d1..d4383a55d03e 100644
--- a/platform/util/src/com/intellij/util/io/RandomAccessDataFile.java
+++ b/platform/util/src/com/intellij/util/io/RandomAccessDataFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,11 +47,11 @@ public class RandomAccessDataFile implements Forceable, Closeable {
private static final boolean DEBUG = false;
- public RandomAccessDataFile(final File file) throws IOException {
+ public RandomAccessDataFile(@NotNull File file) throws IOException {
this(file, PagePool.SHARED);
}
- public RandomAccessDataFile(final File file, final PagePool pool) throws IOException {
+ public RandomAccessDataFile(@NotNull File file, @NotNull PagePool pool) throws IOException {
myPool = pool;
myFile = file;
if (!file.exists()) {
@@ -201,6 +201,9 @@ public class RandomAccessDataFile implements Forceable, Closeable {
dispose();
}
+ /**
+ * Flushes dirty pages to underlying buffers
+ */
@Override
public void force() {
assertNotDisposed();
@@ -210,6 +213,23 @@ public class RandomAccessDataFile implements Forceable, Closeable {
}
}
+ /**
+ * Flushes dirty pages to buffers and saves them to disk
+ */
+ public void sync() {
+ force();
+ try {
+ RandomAccessFile file = getRandomAccessFile();
+ file.getChannel().force(true);
+ }
+ catch (IOException ignored) {
+
+ }
+ finally {
+ releaseFile();
+ }
+ }
+
public void flushSomePages(int maxPagesToFlush) {
assertNotDisposed();
if (isDirty()) {
@@ -229,7 +249,7 @@ public class RandomAccessDataFile implements Forceable, Closeable {
private void assertNotDisposed() {
if (myIsDisposed) {
- LOG.assertTrue(false, "storage file is disposed: " + myFile);
+ LOG.error("storage file is disposed: " + myFile);
}
}
@@ -316,6 +336,7 @@ public class RandomAccessDataFile implements Forceable, Closeable {
file.seek(fileOffset);
}
+ @Override
public int hashCode() {
return myCount;
}
diff --git a/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java b/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java
index e0d349c0c7ad..663cd215cfbe 100644
--- a/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java
+++ b/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,19 +19,47 @@
*/
package com.intellij.util.io.storage;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.util.EventDispatcher;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EventListener;
+import java.util.concurrent.atomic.AtomicInteger;
+
public class HeavyProcessLatch {
public static final HeavyProcessLatch INSTANCE = new HeavyProcessLatch();
- private int myHeavyProcessCounter = 0;
-
- public synchronized void processStarted() {
- myHeavyProcessCounter++;
+
+ private final AtomicInteger myHeavyProcessCounter = new AtomicInteger();
+ private final EventDispatcher<HeavyProcessListener> myEventDispatcher = EventDispatcher.create(HeavyProcessListener.class);
+
+ private HeavyProcessLatch() {
+ }
+
+ public void processStarted() {
+ myHeavyProcessCounter.incrementAndGet();
+ myEventDispatcher.getMulticaster().processStarted();
}
- public synchronized void processFinished() {
- myHeavyProcessCounter--;
+ public void processFinished() {
+ myHeavyProcessCounter.decrementAndGet();
+ myEventDispatcher.getMulticaster().processFinished();
+ }
+
+ public boolean isRunning() {
+ return myHeavyProcessCounter.get() != 0;
+ }
+
+ public interface HeavyProcessListener extends EventListener {
+ public void processStarted();
+
+ public void processFinished();
}
- public synchronized boolean isRunning() {
- return myHeavyProcessCounter != 0;
+ @NotNull
+ public Disposable addListener(@NotNull HeavyProcessListener listener) {
+ Disposable disposable = Disposer.newDisposable();
+ myEventDispatcher.addListener(listener, disposable);
+ return disposable;
}
} \ No newline at end of file