From d837340f54638bb2b68bce0361061ab7a3357fee Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 4 Jun 2012 18:12:51 +0400 Subject: [PATCH] track dirty status for btree structures --- .../com/intellij/util/io/IntToIntBtree.java | 16 ++++++++--- .../intellij/util/io/PagedFileStorage.java | 28 ++++++++++++++----- .../util/io/PersistentBTreeEnumerator.java | 11 ++++++-- .../util/io/PersistentEnumeratorBase.java | 4 +-- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 32de16aba15f..555c5ba6585c 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -182,10 +182,11 @@ class IntToIntBtree { int index = myAccessNodeView.locate(key, true); if (index < 0) { + ++count; myAccessNodeView.insert(key, value); } else { - ++count; myAccessNodeView.setAddressAt(index, value); + if (!myAccessNodeView.myIsDirty) myAccessNodeView.markDirty(); } } @@ -243,6 +244,7 @@ class IntToIntBtree { protected int myAddressInBuffer; protected ByteBuffer myBuffer; protected boolean myHasFullPagesAlongPath; + protected boolean myIsDirty; public BtreePage(IntToIntBtree btree) { this.btree = btree; @@ -259,7 +261,8 @@ class IntToIntBtree { protected void syncWithStore() { PagedFileStorage pagedFileStorage = btree.storage.getPagedFileStorage(); myAddressInBuffer = pagedFileStorage.getOffsetInPage(address); - myBuffer = pagedFileStorage.getByteBuffer(address); + myBuffer = pagedFileStorage.getByteBuffer(address, false); + myIsDirty = false; // we will mark dirty on child count change, attrs change or existing key put doInitFlags(myBuffer.getInt(myAddressInBuffer)); } @@ -272,6 +275,12 @@ class IntToIntBtree { if (flag) b |= mask; else b &= ~mask; myBuffer.put(myAddressInBuffer, b); + if (!myIsDirty) markDirty(); + } + + void markDirty() { + btree.storage.getPagedFileStorage().getByteBuffer(address, true); + myIsDirty = true; } protected final short getChildrenCount() { @@ -281,6 +290,7 @@ class IntToIntBtree { protected final void setChildrenCount(short value) { myChildrenCount = value; myBuffer.putShort(myAddressInBuffer + 1, value); + if (!myIsDirty) markDirty(); } protected final void setNextPage(int nextPage) { @@ -686,7 +696,6 @@ class IntToIntBtree { btree.root.setAddressAt(0, -address); btree.root.setAddressAt(1, -newIndexNode.address); - if (doSanityCheck) { btree.root.dump("New root"); dump("First child"); @@ -952,7 +961,6 @@ class IntToIntBtree { hashSetState(index, HASH_FULL); setAddressAt(index, newValueId); setChildrenCount((short)(recordCount + 1)); - return; } } diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index 1d14f6e54295..0539b85804ca 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -73,10 +73,13 @@ public class PagedFileStorage implements Forceable { private final StorageLockContext myStorageLockContext; private int myLastPage = UNKNOWN_PAGE; private int myLastPage2 = UNKNOWN_PAGE; + private int myLastPage3 = UNKNOWN_PAGE; private ByteBufferWrapper myLastBuffer; private ByteBufferWrapper myLastBuffer2; + private ByteBufferWrapper myLastBuffer3; private int myLastChangeCount; private int myLastChangeCount2; + private int myLastChangeCount3; private int myStorageIndex; private static final int MAX_PAGES_COUNT = 0xFFFF; @@ -160,9 +163,9 @@ public class PagedFileStorage implements Forceable { int getOffsetInPage(int addr) { return addr % myPageSize; } - - ByteBuffer getByteBuffer(int address) { - return getBuffer(address / myPageSize); + + ByteBuffer getByteBuffer(int address, boolean modify) { + return getBuffer(address / myPageSize, modify); } public final short getShort(int addr) { @@ -294,8 +297,10 @@ public class PagedFileStorage implements Forceable { myLastPage = UNKNOWN_PAGE; myLastPage2 = UNKNOWN_PAGE; + myLastPage3 = UNKNOWN_PAGE; myLastBuffer = null; myLastBuffer2 = null; + myLastBuffer3 = null; } public void resize(int newSize) throws IOException { @@ -364,14 +369,18 @@ public class PagedFileStorage implements Forceable { if (modify) myLastBuffer.markDirty(); return buf; } - } - - if (myLastPage2 == page) { + } else if (myLastPage2 == page) { ByteBuffer buf = myLastBuffer2.getCachedBuffer(); if (buf != null && myLastChangeCount2 == myStorageLockContext.myStorageLock.myMappingChangeCount) { if (modify) myLastBuffer2.markDirty(); return buf; } + } else if (myLastPage3 == page) { + ByteBuffer buf = myLastBuffer3.getCachedBuffer(); + if (buf != null && myLastChangeCount3 == myStorageLockContext.myStorageLock.myMappingChangeCount) { + if (modify) myLastBuffer3.markDirty(); + return buf; + } } try { @@ -385,9 +394,14 @@ public class PagedFileStorage implements Forceable { ByteBuffer buf = byteBufferWrapper.getBuffer(); if (myLastPage != page) { + myLastPage3 = myLastPage2; + myLastBuffer3 = myLastBuffer2; + myLastChangeCount3 = myLastChangeCount2; + myLastPage2 = myLastPage; myLastBuffer2 = myLastBuffer; myLastChangeCount2 = myLastChangeCount; + myLastBuffer = byteBufferWrapper; myLastPage = page; } else { @@ -443,7 +457,7 @@ public class PagedFileStorage implements Forceable { myDefaultStorageLockContext = new StorageLockContext(this); mySizeLimit = UPPER_LIMIT; - myMap = new LinkedHashMap(10) { + myMap = new LinkedHashMap(10, 0.75f) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return mySize > mySizeLimit; diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java index 7e57f9af80a8..bd4b389a0667 100644 --- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java @@ -132,7 +132,7 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorBase extends PersistentEnumeratorBase extends PersistentEnumeratorBase implements Forceable, Closeable { protected void putMetaData(long data) throws IOException { lockStorage(); try { - myStorage.putLong(META_DATA_OFFSET, data); + if (myStorage.length() < META_DATA_OFFSET + 8 || getMetaData() != data) myStorage.putLong(META_DATA_OFFSET, data); } finally { unlockStorage(); @@ -317,7 +317,7 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { protected void putMetaData2(long data) throws IOException { lockStorage(); try { - myStorage.putLong(META_DATA_OFFSET + 8, data); + if (myStorage.length() < META_DATA_OFFSET + 16 || getMetaData2() != data) myStorage.putLong(META_DATA_OFFSET + 8, data); } finally { unlockStorage();