https://issues.apache.org/jira/browse/AMQ-3956 - KahaDB pagefile (db.data) steady growth - BTreeIndex page leak. release the clild page when empty branch is promoted, additional tests

git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1367924 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gary Tully 2012-08-01 11:22:48 +00:00
parent 6f92d5f8b9
commit 8e60ca9a90
3 changed files with 55 additions and 6 deletions

View File

@ -762,15 +762,14 @@ public class DurableSubscriptionOfflineTest extends org.apache.activemq.TestSupp
return;
}
// fails for numMessages > 3000
final int numMessages = 100;
final int numMessages = 2750;
KahaDBPersistenceAdapter kahaDBPersistenceAdapter = (KahaDBPersistenceAdapter)broker.getPersistenceAdapter();
PageFile pageFile = kahaDBPersistenceAdapter.getStore().getPageFile();
LOG.info("PageCount " + pageFile.getPageCount() + " f:" + pageFile.getFreePageCount() + ", fileSize:" + pageFile.getFile().length());
long lastDiff = 0;
for (int repeats=0; repeats<4; repeats++) {
for (int repeats=0; repeats<2; repeats++) {
LOG.info("Iteration: "+ repeats + " Count:" + pageFile.getPageCount() + " f:" + pageFile.getFreePageCount());
@ -801,7 +800,7 @@ public class DurableSubscriptionOfflineTest extends org.apache.activemq.TestSupp
LOG.info("PageCount " + pageFile.getPageCount() + " f:" + pageFile.getFreePageCount() + " diff: " + (pageFile.getPageCount() - pageFile.getFreePageCount()) + " fileSize:" + pageFile.getFile().length());
if (lastDiff != 0) {
assertEquals("Only use X pages per iteration", lastDiff, pageFile.getPageCount() - pageFile.getFreePageCount());
assertEquals("Only use X pages per iteration: " + repeats, lastDiff, pageFile.getPageCount() - pageFile.getFreePageCount());
}
lastDiff = pageFile.getPageCount() - pageFile.getFreePageCount();
}

View File

@ -282,7 +282,7 @@ public final class BTreeNode<Key,Value> {
idx = idx < 0 ? -(idx + 1) : idx + 1;
BTreeNode<Key, Value> child = getChild(tx, idx);
if( child.getPageId() == index.getPageId() ) {
throw new IOException("BTree corrupted: Cylce detected.");
throw new IOException("BTree corrupted: Cycle detected.");
}
Value rc = child.remove(tx, key);
@ -293,6 +293,7 @@ public final class BTreeNode<Key,Value> {
if( child.isBranch() ) {
// This is cause branches are never really empty.. they just go down to 1 child..
children[idx] = child.children[0];
tx.free(child.getPage());
} else {
// The child was a leaf. Then we need to actually remove it from this branch node..
@ -508,7 +509,10 @@ public final class BTreeNode<Key,Value> {
if( prefix.length()>0 && parent == null ) {
throw new IllegalStateException("Cycle back to root node detected.");
}
if (parent == null) {
prefix += "|";
out.println(prefix + getPageId());
}
if( isBranch() ) {
for(int i=0 ; i < children.length; i++) {
BTreeNode<Key, Value> child = getChild(tx, i);

View File

@ -25,6 +25,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@ -421,6 +422,51 @@ public class BTreeIndexTest extends IndexTestSupport {
tx.commit();
}
public void testIndexRepeatFillClearIncrementingPageReuse() throws Exception {
pf = new PageFile(directory, getClass().getName());
pf.setPageSize(4*1024);
pf.load();
tx = pf.tx();
long id = tx.allocate().getPageId();
BTreeIndex<Long, String> test = new BTreeIndex<Long, String>(pf, id);
test.setKeyMarshaller(LongMarshaller.INSTANCE);
test.setValueMarshaller(StringMarshaller.INSTANCE);
test.load(tx);
tx.commit();
final int count = 5000;
final int reps = 2;
final long[] diffs = new long[reps];
long keyVal = 0;
final String payload = new String(new byte[50]);
LOG.info("PF diff:" + (pf.getPageCount() - pf.getFreePageCount()) + " pc:" + pf.getPageCount() + " f:" + pf.getFreePageCount() );
for (int i=0; i<reps; i++) {
for (int j = 0; j < count; j++) {
tx = pf.tx();
test.put(tx, keyVal++, payload);
tx.commit();
}
tx = pf.tx();
for (long k = keyVal - count; k < keyVal; k++) {
test.remove(tx, k);
}
test.clear(tx);
tx.commit();
diffs[i] = pf.getPageCount() - pf.getFreePageCount();
LOG.info("PF diff:" + (pf.getPageCount() - pf.getFreePageCount()) + " pc:" + pf.getPageCount() + " f:" + pf.getFreePageCount());
}
for (int i=1; i<diffs.length; i++) {
assertEquals("diff is constant:" + Arrays.toString(diffs), diffs[0],diffs[i]);
}
}
public void testListIndexConsistancyOverTime() throws Exception {
final int NUM_ITERATIONS = 50;