[Joafip-svn] SF.net SVN: joafip:[3030] trunk
Brought to you by:
luc_peuvrier
|
From: <luc...@us...> - 2012-04-25 04:28:36
|
Revision: 3030
http://joafip.svn.sourceforge.net/joafip/?rev=3030&view=rev
Author: luc_peuvrier
Date: 2012-04-25 04:28:28 +0000 (Wed, 25 Apr 2012)
Log Message:
-----------
WIP btree plus, tests in progress. NonTerminalPage tests ok
Modified Paths:
--------------
trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/LeafPage.java
trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/NonTerminalPage.java
trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/service/BtreePlusDataManager.java
trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/service/BtreePlusElementMgr.java
trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/LeafPageTest.java
trunk/joafip-testsuite/src/main/java/net/sf/joafip/btreeplus/entity/BtreePlusEntityTests.java
Added Paths:
-----------
trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/ILeafPage.java
trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/INonTerminalPage.java
trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/NonTerminalPageTest.java
trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/mock/MockLeafPage.java
trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/mock/MockNonTerminalPage.java
trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/service/
Added: trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/ILeafPage.java
===================================================================
--- trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/ILeafPage.java (rev 0)
+++ trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/ILeafPage.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 Luc Peuvrier
+ * All rights reserved.
+ *
+ * This file is a part of JOAFIP.
+ *
+ * JOAFIP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE
+ * Licensed under the LGPL License, Version 3, 29 June 2007 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * JOAFIP is distributed in the hope that it will be useful, but
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.joafip.btreeplus.entity;
+
+import net.sf.joafip.kvstore.record.entity.DataRecordIdentifier;
+
+/**
+ *
+ * @author luc peuvrier
+ *
+ */
+public interface ILeafPage extends IPageRecordable {
+
+ DataRecordIdentifier getLastKey();
+
+ long getPositionInFile();
+
+}
Added: trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/INonTerminalPage.java
===================================================================
--- trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/INonTerminalPage.java (rev 0)
+++ trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/INonTerminalPage.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012 Luc Peuvrier
+ * All rights reserved.
+ *
+ * This file is a part of JOAFIP.
+ *
+ * JOAFIP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE
+ * Licensed under the LGPL License, Version 3, 29 June 2007 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * JOAFIP is distributed in the hope that it will be useful, but
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.joafip.btreeplus.entity;
+
+import net.sf.joafip.kvstore.service.HeapException;
+
+/**
+ *
+ * @author luc peuvrier
+ *
+ */
+public interface INonTerminalPage extends IPageRecordable {
+
+ @Override
+ int getInParentIndex() throws HeapException;
+
+ long getPositionInFile();
+
+}
Modified: trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/LeafPage.java
===================================================================
--- trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/LeafPage.java 2012-04-24 04:44:11 UTC (rev 3029)
+++ trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/LeafPage.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -33,7 +33,7 @@
* @author luc peuvrier
*
*/
-public class LeafPage extends AbstractElement {
+public class LeafPage extends AbstractElement implements ILeafPage {
private long[] dataBlockPosition;
@@ -122,6 +122,7 @@
final DataRecordIdentifier key) {
dataBlockPosition[index] = pagePointer;
keys[index] = key;
+ byteSize = 0;// unknown size because key size change
}
@Override
@@ -141,6 +142,7 @@
/**/4/* int size for number of entries */+
/**/4/* int size for crc32 */+
/**/8/* for next */;
+ // FIXMELUC ______speedup if long value key
for (int index = 0; index < numberOfKeyEntries; index++) {
xbyteSize += entrySize(keys[index]);
}
@@ -258,7 +260,7 @@
return index;
}
- public DataRecordIdentifier lastKey() {
+ public DataRecordIdentifier getLastKey() {
return keys[numberOfKeyEntries - 1];
}
}
Modified: trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/NonTerminalPage.java
===================================================================
--- trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/NonTerminalPage.java 2012-04-24 04:44:11 UTC (rev 3029)
+++ trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/entity/NonTerminalPage.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -33,7 +33,8 @@
* @author luc peuvrier
*
*/
-public class NonTerminalPage extends AbstractElement {
+public class NonTerminalPage extends AbstractElement implements
+ INonTerminalPage {
private long[] pagePositions;
@@ -123,6 +124,7 @@
/**/4/* int size for number of entries */+
/**/4/* int size for crc32 */+
/**/8/* last pointer long size */;
+ // FIXMELUC ______speedup if long value key
for (int index = 0; index < numberOfKeyEntries; index++) {
xbyteSize += entrySize(keys[index]);
}
@@ -149,39 +151,42 @@
public int getIndex(final DataRecordIdentifier dataRecordIdentifier) {
// FIXMELUC _______dichotomic search
int index;
- boolean found = false;
- for (index = 0; !found && index < numberOfKeyEntries; index++) {
- found = keys[index].compareTo(dataRecordIdentifier) <= 0;
+ for (index = 0; index < numberOfKeyEntries; index++) {
+ if (keys[index].compareTo(dataRecordIdentifier) >= 0) {
+ return index;
+ }
}
return index;
}
/**
*
- * @param existingLeftLeafPage
- * @param newRightLeafPage
+ * @param existingLeftILeafPage
+ * @param newRightILeafPage
* @return true if add not need split
* @throws HeapException
*/
- public boolean add(final LeafPage existingLeftLeafPage,
- final LeafPage newRightLeafPage) throws HeapException {
- final int index = existingLeftLeafPage.getInParentIndex();
- final DataRecordIdentifier key = existingLeftLeafPage.lastKey();
+ public boolean add(final ILeafPage existingLeftILeafPage,
+ final ILeafPage newRightILeafPage) throws HeapException {
+ final int index = existingLeftILeafPage.getInParentIndex();
+ final DataRecordIdentifier key = existingLeftILeafPage.getLastKey();
final int entrySize = entrySize(key);
- final int afterLength = numberOfKeyEntries - (index + 1);
+ final int afterLength = numberOfKeyEntries - index;
numberOfKeyEntries++;
DataRecordIdentifier[] newKeys = new DataRecordIdentifier[numberOfKeyEntries];
long[] newPagePosition = new long[numberOfKeyEntries + 1];
if (index != 0) {
System.arraycopy(keys, 0, newKeys, 0, index);
- System.arraycopy(pagePositions, 0, newPagePosition, 0, index);
}
+ System.arraycopy(pagePositions, 0, newPagePosition, 0, index + 1);
+
newKeys[index] = key;
- newPagePosition[index + 1] = newRightLeafPage.getPositionInFile();
- newKeys[index + 1] = newRightLeafPage.lastKey();
+ newPagePosition[index + 1] = newRightILeafPage.getPositionInFile();
System.arraycopy(pagePositions, index + 1, newPagePosition, index + 2,
- afterLength + 1);
- System.arraycopy(keys, index + 1, newKeys, index + 2, afterLength);
+ afterLength);
+ if (afterLength != 0) {
+ System.arraycopy(keys, index, newKeys, index + 1, afterLength);
+ }
keys = newKeys;
pagePositions = newPagePosition;
// ASSERTX
@@ -192,34 +197,48 @@
return byteSize < PageConstant.PAGE_SIZE;
}
- public boolean add(final NonTerminalPage leftSonNonTerminalPage,
+ /**
+ *
+ * @param leftSonNonTerminalPage
+ * @param middleKey
+ * @param rightSonNonTerminalPage
+ * @return true if add not need split
+ * @throws HeapException
+ */
+ public boolean add(final INonTerminalPage leftSonNonTerminalPage,
final DataRecordIdentifier middleKey,
- final NonTerminalPage rightSonNonTerminalPage) throws HeapException {
+ final INonTerminalPage rightSonNonTerminalPage)
+ throws HeapException {
final int index = leftSonNonTerminalPage.getInParentIndex();
final int entrySize = entrySize(middleKey);
- final int afterLength = numberOfKeyEntries - (index + 1);
+ final int afterLength = numberOfKeyEntries - index;
numberOfKeyEntries++;
DataRecordIdentifier[] newKeys = new DataRecordIdentifier[numberOfKeyEntries];
- long[] newPagePosition = new long[numberOfKeyEntries + 1];
- System.arraycopy(pagePositions, 0, newPagePosition, 0, index + 1);
+ long[] newPagePositions = new long[numberOfKeyEntries + 1];
if (index != 0) {
System.arraycopy(keys, 0, newKeys, 0, index);
}
- DataRecordIdentifier k = keys[index];
+ System.arraycopy(pagePositions, 0, newPagePositions, 0, index + 1);
newKeys[index] = middleKey;
- newKeys[index + 1] = k;
- System.arraycopy(pagePositions, index + 1, newPagePosition, index + 2,
- afterLength + 1);
- System.arraycopy(keys, index + 2, newKeys, index + 2, afterLength);
+ newPagePositions[index + 1] = rightSonNonTerminalPage
+ .getPositionInFile();
+
+ if (afterLength != 0) {
+ System.arraycopy(keys, index, newKeys, index + 1, afterLength);
+ System.arraycopy(pagePositions, index + 1, newPagePositions,
+ index + 2, afterLength);
+ }
+ keys = newKeys;
+ pagePositions = newPagePositions;
// ASSERTX
assert byteSize != 0 : "unknow current byte size";
- byteSize += entrySize + 8;
+ byteSize += entrySize;
// ASSERTX
assert byteSize == computeByteSize();
return byteSize < PageConstant.PAGE_SIZE;
}
- public NonTerminalPage split() {
+ public INonTerminalPage split() {
final int splitIndex = numberOfKeyEntries / 2;
middleKey = keys[splitIndex];
final int newNumberOfKeyEntries = splitIndex;
@@ -233,7 +252,7 @@
keys, splitIndex + 1, numberOfKeyEntries);
final long[] newNonTerminalPagePosition = Arrays.copyOfRange(
pagePositions, splitIndex + 1, numberOfKeyEntries + 1);
- final NonTerminalPage nonTerminalPage = new NonTerminalPage(
+ final INonTerminalPage nonTerminalPage = new NonTerminalPage(
newNonTerminalPageNumberOfKeyEntries, newNonTerminalKeys,
newNonTerminalPagePosition);
keys = newKeys;
@@ -243,7 +262,14 @@
return nonTerminalPage;
}
- public DataRecordIdentifier getMiddleKey() {
- return middleKey;
+ /**
+ * get and clear middle key computed by {@link #split()}
+ *
+ * @return middle key computed by {@link #split()}
+ */
+ public DataRecordIdentifier getAndClearMiddleKey() {
+ final DataRecordIdentifier result = middleKey;
+ middleKey = null;
+ return result;
}
}
Modified: trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/service/BtreePlusDataManager.java
===================================================================
--- trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/service/BtreePlusDataManager.java 2012-04-24 04:44:11 UTC (rev 3029)
+++ trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/service/BtreePlusDataManager.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -30,6 +30,7 @@
import net.sf.joafip.Fortest;
import net.sf.joafip.btreeplus.entity.EnumRecordType;
import net.sf.joafip.btreeplus.entity.IDataBlock;
+import net.sf.joafip.btreeplus.entity.INonTerminalPage;
import net.sf.joafip.btreeplus.entity.IPageRecordable;
import net.sf.joafip.btreeplus.entity.LeafPage;
import net.sf.joafip.btreeplus.entity.NonTerminalPage;
@@ -263,13 +264,13 @@
newLeafPage);
} else {
if (!nonTerminalPage.add(leafPage, newLeafPage)) {
- NonTerminalPage newNonTerminalPage = nonTerminalPage
+ INonTerminalPage newNonTerminalPage = nonTerminalPage
.split();
do {
btreePlusElementMgr
.appendPageRecordable(newNonTerminalPage);
DataRecordIdentifier middleKey = nonTerminalPage
- .getMiddleKey();
+ .getAndClearMiddleKey();
NonTerminalPage parent = (NonTerminalPage) nonTerminalPage
.getParentPage();
if (parent == null) {
Modified: trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/service/BtreePlusElementMgr.java
===================================================================
--- trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/service/BtreePlusElementMgr.java 2012-04-24 04:44:11 UTC (rev 3029)
+++ trunk/joafip-btreeplus/src/main/java/net/sf/joafip/btreeplus/service/BtreePlusElementMgr.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -27,6 +27,7 @@
import net.sf.joafip.btreeplus.entity.DataBlockPage;
import net.sf.joafip.btreeplus.entity.HeaderPage;
import net.sf.joafip.btreeplus.entity.IDataBlock;
+import net.sf.joafip.btreeplus.entity.INonTerminalPage;
import net.sf.joafip.btreeplus.entity.IPageRecord;
import net.sf.joafip.btreeplus.entity.IPageRecordable;
import net.sf.joafip.btreeplus.entity.LeafPage;
@@ -239,7 +240,7 @@
final LeafPage rightLeafPage) throws HeapException {
final NonTerminalPage nonTerminalPage = new NonTerminalPage(1);
nonTerminalPage.setEntry(0, leftLeafPage.getPositionInFile(),
- leftLeafPage.lastKey());
+ leftLeafPage.getLastKey());
nonTerminalPage.setEntry(1, rightLeafPage.getPositionInFile(), null);
appendPageRecordable(nonTerminalPage);
nonTerminalPage.updateByteSize();
@@ -247,9 +248,9 @@
}
public void newRootNonTerminalPage(
- final NonTerminalPage leftNonTerminalPage,
+ final INonTerminalPage leftNonTerminalPage,
final DataRecordIdentifier middleKey,
- final NonTerminalPage rightNonTerminalPage) throws HeapException {
+ final INonTerminalPage rightNonTerminalPage) throws HeapException {
final NonTerminalPage nonTerminalPage = new NonTerminalPage(1);
nonTerminalPage.setEntry(0, leftNonTerminalPage.getPositionInFile(),
middleKey);
Modified: trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/LeafPageTest.java
===================================================================
--- trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/LeafPageTest.java 2012-04-24 04:44:11 UTC (rev 3029)
+++ trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/LeafPageTest.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -25,7 +25,6 @@
import net.sf.joafip.AbstractJoafipCommonTestCase;
import net.sf.joafip.NotStorableClass;
-import net.sf.joafip.StorableAccess;
import net.sf.joafip.TestException;
import net.sf.joafip.btreeplus.entity.mock.MockDataBlock;
import net.sf.joafip.btreeplus.entity.mock.MockPageRecordable;
@@ -38,7 +37,6 @@
*
*/
@NotStorableClass
-@StorableAccess
public class LeafPageTest extends AbstractJoafipCommonTestCase {
public LeafPageTest() throws TestException {
@@ -108,7 +106,7 @@
assertEquals("must not find", -1L,
leafPage.getDataBlockPosition(new DataRecordIdentifier(0)));
assertEquals("bad last key", new DataRecordIdentifier(lastKeyValue),
- leafPage.lastKey());
+ leafPage.getLastKey());
}
public void testSetDataBlock() throws HeapException {
Added: trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/NonTerminalPageTest.java
===================================================================
--- trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/NonTerminalPageTest.java (rev 0)
+++ trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/NonTerminalPageTest.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2012 Luc Peuvrier
+ * All rights reserved.
+ *
+ * This file is a part of JOAFIP.
+ *
+ * JOAFIP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE
+ * Licensed under the LGPL License, Version 3, 29 June 2007 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * JOAFIP is distributed in the hope that it will be useful, but
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.joafip.btreeplus.entity;
+
+import net.sf.joafip.AbstractJoafipCommonTestCase;
+import net.sf.joafip.NotStorableClass;
+import net.sf.joafip.StorableAccess;
+import net.sf.joafip.TestException;
+import net.sf.joafip.btreeplus.entity.mock.MockLeafPage;
+import net.sf.joafip.btreeplus.entity.mock.MockNonTerminalPage;
+import net.sf.joafip.kvstore.record.entity.DataRecordIdentifier;
+import net.sf.joafip.kvstore.service.HeapException;
+
+/**
+ *
+ * @author luc peuvrier
+ *
+ */
+@NotStorableClass
+@StorableAccess
+public class NonTerminalPageTest extends AbstractJoafipCommonTestCase {
+
+ public NonTerminalPageTest() throws TestException {
+ super();
+ }
+
+ public NonTerminalPageTest(final String name) throws TestException {
+ super(name);
+ }
+
+ public void testCreation() {
+ final NonTerminalPage nonTerminalPage = new NonTerminalPage();
+ assertEquals("must be empty", 0,
+ nonTerminalPage.getNumberOfKeyEntries());
+ assertEquals("must be one page", 1, nonTerminalPage.getNumberOfPage());
+ assertEquals("bad record type", EnumRecordType.NON_TERMINAL_PAGE,
+ nonTerminalPage.getRecordType());
+ assertEquals("bad byte size", byteSize(0),
+ nonTerminalPage.getByteSize());
+ }
+
+ public void testAddLeafPage() throws HeapException {
+ // A 10 B
+ final NonTerminalPage nonTerminalPage = new NonTerminalPage(1);
+ final MockLeafPage leafPageA = new MockLeafPage();
+ final long pageAPositionInFile = 1000;
+ leafPageA.setPositionInFile(pageAPositionInFile);
+ final MockLeafPage leafPageB = new MockLeafPage();
+ final long pageBPositionInFile = 2000;
+ leafPageB.setPositionInFile(pageBPositionInFile);
+ final DataRecordIdentifier key10 = new DataRecordIdentifier(10);
+ nonTerminalPage.setEntry(0, leafPageA.getPositionInFile(), key10);
+ nonTerminalPage.setEntry(1, leafPageB.getPositionInFile(), null);
+ nonTerminalPage.updateByteSize();
+
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key10 },
+ new long[] { pageAPositionInFile, pageBPositionInFile });
+ assertEquals("bad key 9 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+
+ // A 10 B -> A 5 C 10 B
+ final MockLeafPage leafPageC = new MockLeafPage();
+ final long pageCPositionInFile = 3000;
+ leafPageC.setPositionInFile(pageCPositionInFile);
+ final DataRecordIdentifier key5 = new DataRecordIdentifier(5);
+ leafPageA.setLastKey(key5);
+ leafPageA.setInParentIndex(0);
+
+ nonTerminalPage.add(leafPageA, leafPageC);
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key5, key10 },
+ new long[] { pageAPositionInFile, pageCPositionInFile,
+ pageBPositionInFile });
+ assertEquals("bad key 4 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(4)));
+ assertEquals("bad key 9 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 2,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+
+ // A 5 C 10 B -> A 5 C 10 B 15 D
+ final MockLeafPage leafPageD = new MockLeafPage();
+ final long pageDPositionInFile = 4000;
+ leafPageD.setPositionInFile(pageDPositionInFile);
+ final DataRecordIdentifier key15 = new DataRecordIdentifier(15);
+ leafPageB.setLastKey(key15);
+ leafPageB.setInParentIndex(2);
+ nonTerminalPage.add(leafPageB, leafPageD);
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key5, key10,
+ key15 }, new long[] { pageAPositionInFile, pageCPositionInFile,
+ pageBPositionInFile, pageDPositionInFile });
+ assertEquals("bad key 4 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(4)));
+ assertEquals("bad key 9 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 2,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+ assertEquals("bad key 16 index", 3,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(16)));
+
+ // A 5 C 10 B 15 D -> A 5 C 7 E 10 B 15 D
+ final MockLeafPage leafPageE = new MockLeafPage();
+ final long pageEPositionInFile = 5000;
+ leafPageE.setPositionInFile(pageEPositionInFile);
+ final DataRecordIdentifier key7 = new DataRecordIdentifier(7);
+ leafPageC.setLastKey(key7);
+ leafPageC.setInParentIndex(1);
+ nonTerminalPage.add(leafPageC, leafPageE);
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key5, key7,
+ key10, key15 }, new long[] { pageAPositionInFile,
+ pageCPositionInFile, pageEPositionInFile, pageBPositionInFile,
+ pageDPositionInFile });
+ assertEquals("bad key 4 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(4)));
+ assertEquals("bad key 6 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(6)));
+ assertEquals("bad key 9 index", 2,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 3,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+ assertEquals("bad key 16 index", 4,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(16)));
+
+ // A 5 C 7 E 10 B 15 D -> A 5 C 7 E 10 B 15 D 17 F
+ final MockLeafPage leafPageF = new MockLeafPage();
+ final long pageFPositionInFile = 6000;
+ leafPageF.setPositionInFile(pageFPositionInFile);
+ final DataRecordIdentifier key17 = new DataRecordIdentifier(17);
+ leafPageD.setLastKey(key17);
+ leafPageD.setInParentIndex(4);
+ nonTerminalPage.add(leafPageD, leafPageF);
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key5, key7,
+ key10, key15, key17 }, new long[] { pageAPositionInFile,
+ pageCPositionInFile, pageEPositionInFile, pageBPositionInFile,
+ pageDPositionInFile, pageFPositionInFile });
+ assertEquals("bad key 4 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(4)));
+ assertEquals("bad key 6 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(6)));
+ assertEquals("bad key 9 index", 2,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 3,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+ assertEquals("bad key 16 index", 4,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(16)));
+ assertEquals("bad key 18 index", 5,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(18)));
+ }
+
+ public void testAddLeafPageNeedSplit() throws HeapException {
+ // A 10 B
+ final NonTerminalPage nonTerminalPage = new NonTerminalPage(1);
+ final MockLeafPage leafPageA = new MockLeafPage();
+ final long pageAPositionInFile = 1000;
+ leafPageA.setPositionInFile(pageAPositionInFile);
+ final MockLeafPage leafPageB = new MockLeafPage();
+ final long pageBPositionInFile = 2000;
+ leafPageB.setPositionInFile(pageBPositionInFile);
+ final DataRecordIdentifier key10 = new DataRecordIdentifier(10);
+ nonTerminalPage.setEntry(0, leafPageA.getPositionInFile(), key10);
+ nonTerminalPage.setEntry(1, leafPageB.getPositionInFile(), null);
+ nonTerminalPage.updateByteSize();
+
+ MockLeafPage leftPage = leafPageB;
+ final int maxNumberOfEntries = maxNumberOfEntries();
+ while (nonTerminalPage.getNumberOfKeyEntries() < maxNumberOfEntries) {
+ final MockLeafPage rightPage = new MockLeafPage();
+ leftPage.setInParentIndex(nonTerminalPage.getNumberOfKeyEntries() - 1);
+ leftPage.setLastKey(key10);
+ assertTrue("must not need split",
+ nonTerminalPage.add(leftPage, rightPage));
+ leftPage = rightPage;
+ }
+ final MockLeafPage rightPage = new MockLeafPage();
+ leftPage.setInParentIndex(nonTerminalPage.getNumberOfKeyEntries() - 1);
+ leftPage.setLastKey(key10);
+ assertFalse("must need split", nonTerminalPage.add(leftPage, rightPage));
+ }
+
+ public void testAddNonTerminalPage() throws HeapException {
+ // A 10 B
+ final NonTerminalPage nonTerminalPage = new NonTerminalPage(1);
+ final MockNonTerminalPage pageA = new MockNonTerminalPage();
+ final long pageAPositionInFile = 1000;
+ pageA.setPositionInFile(pageAPositionInFile);
+ final MockNonTerminalPage pageB = new MockNonTerminalPage();
+ final long pageBPositionInFile = 2000;
+ pageB.setPositionInFile(pageBPositionInFile);
+ final DataRecordIdentifier key10 = new DataRecordIdentifier(10);
+ nonTerminalPage.setEntry(0, pageA.getPositionInFile(), key10);
+ nonTerminalPage.setEntry(1, pageB.getPositionInFile(), null);
+ nonTerminalPage.updateByteSize();
+
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key10 },
+ new long[] { pageAPositionInFile, pageBPositionInFile });
+ assertEquals("bad key 9 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+
+ // A 10 B -> A 5 C 10 B
+ final MockNonTerminalPage pageC = new MockNonTerminalPage();
+ final long pageCPositionInFile = 3000;
+ pageC.setPositionInFile(pageCPositionInFile);
+ final DataRecordIdentifier key5 = new DataRecordIdentifier(5);
+ pageA.setInParentIndex(0);
+ nonTerminalPage.add(pageA, key5, pageC);
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key5, key10 },
+ new long[] { pageAPositionInFile, pageCPositionInFile,
+ pageBPositionInFile });
+ assertEquals("bad key 4 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(4)));
+ assertEquals("bad key 9 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 2,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+
+ // ------------
+ // A 5 C 10 B -> A 5 C 10 B 15 D
+ final MockNonTerminalPage pageD = new MockNonTerminalPage();
+ final long pageDPositionInFile = 4000;
+ pageD.setPositionInFile(pageDPositionInFile);
+ final DataRecordIdentifier key15 = new DataRecordIdentifier(15);
+ pageB.setInParentIndex(2);
+ nonTerminalPage.add(pageB, key15, pageD);
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key5, key10,
+ key15 }, new long[] { pageAPositionInFile, pageCPositionInFile,
+ pageBPositionInFile, pageDPositionInFile });
+ assertEquals("bad key 4 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(4)));
+ assertEquals("bad key 9 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 2,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+ assertEquals("bad key 16 index", 3,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(16)));
+
+ // A 5 C 10 B 15 D -> A 5 C 7 E 10 B 15 D
+ final MockNonTerminalPage pageE = new MockNonTerminalPage();
+ final long pageEPositionInFile = 5000;
+ pageE.setPositionInFile(pageEPositionInFile);
+ final DataRecordIdentifier key7 = new DataRecordIdentifier(7);
+ pageC.setInParentIndex(1);
+ nonTerminalPage.add(pageC, key7, pageE);
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key5, key7,
+ key10, key15 }, new long[] { pageAPositionInFile,
+ pageCPositionInFile, pageEPositionInFile, pageBPositionInFile,
+ pageDPositionInFile });
+ assertEquals("bad key 4 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(4)));
+ assertEquals("bad key 6 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(6)));
+ assertEquals("bad key 9 index", 2,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 3,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+ assertEquals("bad key 16 index", 4,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(16)));
+
+ // A 5 C 7 E 10 B 15 D -> A 5 C 7 E 10 B 15 D 17 F
+ final MockNonTerminalPage pageF = new MockNonTerminalPage();
+ final long pageFPositionInFile = 6000;
+ pageF.setPositionInFile(pageFPositionInFile);
+ final DataRecordIdentifier key17 = new DataRecordIdentifier(17);
+ pageD.setInParentIndex(4);
+ nonTerminalPage.add(pageD, key17, pageF);
+ checkState(nonTerminalPage, new DataRecordIdentifier[] { key5, key7,
+ key10, key15, key17 }, new long[] { pageAPositionInFile,
+ pageCPositionInFile, pageEPositionInFile, pageBPositionInFile,
+ pageDPositionInFile, pageFPositionInFile });
+ assertEquals("bad key 4 index", 0,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(4)));
+ assertEquals("bad key 6 index", 1,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(6)));
+ assertEquals("bad key 9 index", 2,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(9)));
+ assertEquals("bad key 11 index", 3,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(11)));
+ assertEquals("bad key 16 index", 4,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(16)));
+ assertEquals("bad key 18 index", 5,
+ nonTerminalPage.getIndex(new DataRecordIdentifier(18)));
+
+ }
+
+ public void testAddNonTerminalPageNeedSplit() throws HeapException {
+ // A 10 B
+ final NonTerminalPage nonTerminalPage = new NonTerminalPage(1);
+ final MockNonTerminalPage pageA = new MockNonTerminalPage();
+ final long pageAPositionInFile = 1000;
+ pageA.setPositionInFile(pageAPositionInFile);
+ final MockNonTerminalPage pageB = new MockNonTerminalPage();
+ final long pageBPositionInFile = 2000;
+ pageB.setPositionInFile(pageBPositionInFile);
+ final DataRecordIdentifier key10 = new DataRecordIdentifier(10);
+ nonTerminalPage.setEntry(0, pageA.getPositionInFile(), key10);
+ nonTerminalPage.setEntry(1, pageB.getPositionInFile(), null);
+ nonTerminalPage.updateByteSize();
+
+ MockNonTerminalPage leftPage = pageB;
+ final int maxNumberOfEntries = maxNumberOfEntries();
+ while (nonTerminalPage.getNumberOfKeyEntries() < maxNumberOfEntries) {
+ final MockNonTerminalPage rightPage = new MockNonTerminalPage();
+ leftPage.setInParentIndex(nonTerminalPage.getNumberOfKeyEntries() - 1);
+ assertTrue("must not need split",
+ nonTerminalPage.add(leftPage, key10, rightPage));
+ leftPage = rightPage;
+ }
+ final MockNonTerminalPage rightPage = new MockNonTerminalPage();
+ leftPage.setInParentIndex(nonTerminalPage.getNumberOfKeyEntries() - 1);
+ assertFalse("must need split",
+ nonTerminalPage.add(leftPage, key10, rightPage));
+ }
+
+ public void testSplit() {
+
+ }
+
+ public void testSetEntry() {
+
+ }
+
+ public void testSetParentPage() {
+
+ }
+
+ private void checkState(final NonTerminalPage nonTerminalPage,
+ final DataRecordIdentifier[] keys, final long[] pointers) {
+ final int numberOfEntries = keys.length;
+ assertEquals("bad byte size", byteSize(numberOfEntries),
+ nonTerminalPage.getByteSize());
+ assertEquals("must has " + numberOfEntries + " entries",
+ numberOfEntries, nonTerminalPage.getNumberOfKeyEntries());
+ for (int index = 0; index < numberOfEntries; index++) {
+ assertEquals("bad index", index,
+ nonTerminalPage.getIndex(keys[index]));
+ assertEquals("bad key #0", keys[index],
+ nonTerminalPage.getKey(index));
+ assertEquals("bad #" + index + " page pointer", pointers[index],
+ nonTerminalPage.getPagePointer(index));
+ }
+ assertEquals("bad #" + numberOfEntries + " page pointer",
+ pointers[numberOfEntries],
+ nonTerminalPage.getPagePointer(numberOfEntries));
+ }
+
+ private int byteSize(final int numberOfKeyEntries) {
+ int xbyteSize = 1/* byte size for record type */+
+ /**/4/* int size for number of entries */+
+ /**/4/* int size for crc32 */+
+ /**/numberOfKeyEntries * 8/* key entries */+
+ /**/(numberOfKeyEntries + 1) * 8/* pointers entries */;
+ // FIXMELUC ______speedup if long value key
+ return xbyteSize;
+ }
+
+ private int maxNumberOfEntries() {
+ return (int) ((PageConstant.PAGE_SIZE - (1 + 4 + 4 + 8)) / (8 * 2));
+ }
+}
Added: trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/mock/MockLeafPage.java
===================================================================
--- trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/mock/MockLeafPage.java (rev 0)
+++ trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/mock/MockLeafPage.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2012 Luc Peuvrier
+ * All rights reserved.
+ *
+ * This file is a part of JOAFIP.
+ *
+ * JOAFIP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE
+ * Licensed under the LGPL License, Version 3, 29 June 2007 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * JOAFIP is distributed in the hope that it will be useful, but
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.joafip.btreeplus.entity.mock;
+
+import net.sf.joafip.btreeplus.entity.EnumRecordType;
+import net.sf.joafip.btreeplus.entity.ILeafPage;
+import net.sf.joafip.btreeplus.entity.IPageRecord;
+import net.sf.joafip.btreeplus.entity.IPageRecordable;
+import net.sf.joafip.kvstore.record.entity.DataRecordIdentifier;
+import net.sf.joafip.kvstore.service.HeapException;
+
+/**
+ *
+ * @author luc peuvrier
+ *
+ */
+public class MockLeafPage implements ILeafPage {
+
+ private long positionInFile;
+ private DataRecordIdentifier lastKey;
+ private int inParentIndex;
+
+ @Override
+ public EnumRecordType getRecordType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getNumberOfPage() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getByteSize() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void updateByteSize() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public IPageRecord getPageRecord() throws HeapException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setPageRecord(IPageRecord pageRecord) throws HeapException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setParentPage(IPageRecordable parentPage, int inParentIndex)
+ throws HeapException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public IPageRecordable getParentPage() throws HeapException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setInParentIndex(final int inParentIndex) {
+ this.inParentIndex = inParentIndex;
+ }
+
+ @Override
+ public int getInParentIndex() throws HeapException {
+ return inParentIndex;
+ }
+
+ @Override
+ public void setValueIsChangedValueToSave() throws HeapException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setValueIsNotChanged() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setLastKey(final DataRecordIdentifier lastKey) {
+ this.lastKey = lastKey;
+ }
+
+ @Override
+ public DataRecordIdentifier getLastKey() {
+ return lastKey;
+ }
+
+ public void setPositionInFile(final long positionInFile) {
+ this.positionInFile = positionInFile;
+ }
+
+ @Override
+ public long getPositionInFile() {
+ return positionInFile;
+ }
+}
Added: trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/mock/MockNonTerminalPage.java
===================================================================
--- trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/mock/MockNonTerminalPage.java (rev 0)
+++ trunk/joafip-btreeplus/src/test/java/net/sf/joafip/btreeplus/entity/mock/MockNonTerminalPage.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012 Luc Peuvrier
+ * All rights reserved.
+ *
+ * This file is a part of JOAFIP.
+ *
+ * JOAFIP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE
+ * Licensed under the LGPL License, Version 3, 29 June 2007 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * JOAFIP is distributed in the hope that it will be useful, but
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.joafip.btreeplus.entity.mock;
+
+import net.sf.joafip.btreeplus.entity.EnumRecordType;
+import net.sf.joafip.btreeplus.entity.INonTerminalPage;
+import net.sf.joafip.btreeplus.entity.IPageRecord;
+import net.sf.joafip.btreeplus.entity.IPageRecordable;
+import net.sf.joafip.kvstore.service.HeapException;
+
+/**
+ *
+ * @author luc peuvrier
+ *
+ */
+public class MockNonTerminalPage implements INonTerminalPage {
+
+ private long positionInFile;
+ private int inParentIndex;
+
+ @Override
+ public EnumRecordType getRecordType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getNumberOfPage() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getByteSize() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void updateByteSize() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public IPageRecord getPageRecord() throws HeapException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setPageRecord(IPageRecord pageRecord) throws HeapException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setParentPage(IPageRecordable parentPage, int inParentIndex)
+ throws HeapException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public IPageRecordable getParentPage() throws HeapException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setValueIsChangedValueToSave() throws HeapException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setValueIsNotChanged() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setInParentIndex(final int inParentIndex) {
+ this.inParentIndex = inParentIndex;
+ }
+
+ @Override
+ public int getInParentIndex() throws HeapException {
+ return inParentIndex;
+ }
+
+ public void setPositionInFile(final long positionInFile) {
+ this.positionInFile = positionInFile;
+ }
+
+ @Override
+ public long getPositionInFile() {
+ return positionInFile;
+ }
+
+}
Modified: trunk/joafip-testsuite/src/main/java/net/sf/joafip/btreeplus/entity/BtreePlusEntityTests.java
===================================================================
--- trunk/joafip-testsuite/src/main/java/net/sf/joafip/btreeplus/entity/BtreePlusEntityTests.java 2012-04-24 04:44:11 UTC (rev 3029)
+++ trunk/joafip-testsuite/src/main/java/net/sf/joafip/btreeplus/entity/BtreePlusEntityTests.java 2012-04-25 04:28:28 UTC (rev 3030)
@@ -43,8 +43,7 @@
final TestSuite suite = new TestSuite("Test for btree plus entity");
// $JUnit-BEGIN$
suite.addTestSuite(LeafPageTest.class);
- // suite.addTestSuite(RandomAccessFileReadWriteCacheTest.class);
- // suite.addTestSuite(TestRandomAccessFileCache.class);
+ suite.addTestSuite(NonTerminalPageTest.class);
// $JUnit-END$
return suite;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|