Merge branch 'master' into yingyi/fullstack_fix
diff --git a/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java b/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java
index 2a0f6c3..756e0f3 100644
--- a/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java
+++ b/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java
@@ -48,8 +48,7 @@
throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
- if (op.getOperatorTag() != LogicalOperatorTag.INNERJOIN
- && op.getOperatorTag() != LogicalOperatorTag.LEFTOUTERJOIN) {
+ if (op.getOperatorTag() != LogicalOperatorTag.INNERJOIN) {
return false;
}
AbstractBinaryJoinOperator join = (AbstractBinaryJoinOperator) op;
diff --git a/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMInteriorFrame.java b/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMInteriorFrame.java
index 67392ac..3f651df 100644
--- a/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMInteriorFrame.java
+++ b/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMInteriorFrame.java
@@ -185,45 +185,54 @@
ByteBuffer right = rightFrame.getBuffer();
int tupleCount = getTupleCount();
- // Find split point, and determine into which frame the new tuple should be inserted into.
- int tuplesToLeft;
+ // Find split point, and determine into which frame the new tuple should be inserted into.
ITreeIndexFrame targetFrame = null;
-
- int totalSize = 0;
- int halfPageSize = (buf.capacity() - getPageHeaderSize()) / 2;
- int i;
- for (i = 0; i < tupleCount; ++i) {
- frameTuple.resetByTupleIndex(this, i);
- totalSize += tupleWriter.bytesRequired(frameTuple) + childPtrSize + slotManager.getSlotSize();
- if (totalSize >= halfPageSize) {
- break;
- }
- }
-
+ frameTuple.resetByTupleIndex(this, tupleCount - 1);
+ int tuplesToLeft;
if (cmp.compare(tuple, frameTuple) > 0) {
- tuplesToLeft = i;
+ // This is a special optimization case when the tuple to be inserted is the largest key on the page.
targetFrame = rightFrame;
+ tuplesToLeft = tupleCount;
} else {
- tuplesToLeft = i + 1;
- targetFrame = this;
+ int totalSize = 0;
+ int halfPageSize = (buf.capacity() - getPageHeaderSize()) / 2;
+ int i;
+ for (i = 0; i < tupleCount; ++i) {
+ frameTuple.resetByTupleIndex(this, i);
+ totalSize += tupleWriter.bytesRequired(frameTuple) + childPtrSize + slotManager.getSlotSize();
+ if (totalSize >= halfPageSize) {
+ break;
+ }
+ }
+
+ if (cmp.compare(tuple, frameTuple) > 0) {
+ tuplesToLeft = i;
+ targetFrame = rightFrame;
+ } else {
+ tuplesToLeft = i + 1;
+ targetFrame = this;
+ }
+ int tuplesToRight = tupleCount - tuplesToLeft;
+
+ // Copy entire page.
+ System.arraycopy(buf.array(), 0, right.array(), 0, buf.capacity());
+
+ // On the right page we need to copy rightmost slots to left.
+ int src = rightFrame.getSlotManager().getSlotEndOff();
+ int dest = rightFrame.getSlotManager().getSlotEndOff() + tuplesToLeft
+ * rightFrame.getSlotManager().getSlotSize();
+ int length = rightFrame.getSlotManager().getSlotSize() * tuplesToRight;
+ System.arraycopy(right.array(), src, right.array(), dest, length);
+ right.putInt(tupleCountOff, tuplesToRight);
+
+ // On the left page, remove the highest key and make its child pointer
+ // the rightmost child pointer.
+ buf.putInt(tupleCountOff, tuplesToLeft);
+
+ // Compact both pages.
+ rightFrame.compact();
+ compact();
}
- int tuplesToRight = tupleCount - tuplesToLeft;
-
- // Copy entire page.
- System.arraycopy(buf.array(), 0, right.array(), 0, buf.capacity());
-
- // On the right page we need to copy rightmost slots to left.
- int src = rightFrame.getSlotManager().getSlotEndOff();
- int dest = rightFrame.getSlotManager().getSlotEndOff() + tuplesToLeft
- * rightFrame.getSlotManager().getSlotSize();
- int length = rightFrame.getSlotManager().getSlotSize() * tuplesToRight;
- System.arraycopy(right.array(), src, right.array(), dest, length);
- right.putInt(tupleCountOff, tuplesToRight);
-
- // On the left page, remove the highest key and make its child pointer
- // the rightmost child pointer.
- buf.putInt(tupleCountOff, tuplesToLeft);
-
// Copy the split key to be inserted.
// We must do so because setting the new split key will overwrite the
// old split key, and we cannot insert the existing split key at this point.
@@ -242,10 +251,6 @@
buf.putInt(rightLeafOff, buf.getInt(getLeftChildPageOff(frameTuple)));
buf.putInt(tupleCountOff, tuplesToLeft - 1);
- // Compact both pages.
- rightFrame.compact();
- compact();
-
// Insert the saved split key.
int targetTupleIndex;
// it's safe to catch this exception since it will have been caught before reaching here
diff --git a/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMLeafFrame.java b/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMLeafFrame.java
index 187cd52..995e8a7 100644
--- a/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMLeafFrame.java
+++ b/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMLeafFrame.java
@@ -49,7 +49,7 @@
public int getBytesRequriedToWriteTuple(ITupleReference tuple) {
return tupleWriter.bytesRequired(tuple) + slotManager.getSlotSize();
}
-
+
@Override
public void initBuffer(byte level) {
super.initBuffer(level);
@@ -148,45 +148,51 @@
// Find split point, and determine into which frame the new tuple should
// be inserted into.
- int tuplesToLeft;
ITreeIndexFrame targetFrame = null;
- int totalSize = 0;
- int halfPageSize = (buf.capacity() - getPageHeaderSize()) / 2;
- int i;
- for (i = 0; i < tupleCount; ++i) {
- frameTuple.resetByTupleIndex(this, i);
- totalSize += tupleWriter.getCopySpaceRequired(frameTuple) + slotManager.getSlotSize();
- if (totalSize >= halfPageSize) {
- break;
- }
- }
-
- if (cmp.compare(tuple, frameTuple) >= 0) {
- tuplesToLeft = i + 1;
+ frameTuple.resetByTupleIndex(this, tupleCount - 1);
+ if (cmp.compare(tuple, frameTuple) > 0) {
+ // This is a special optimization case when the tuple to be inserted is the largest key on the page.
targetFrame = rightFrame;
} else {
- tuplesToLeft = i;
- targetFrame = this;
+ int tuplesToLeft;
+ int totalSize = 0;
+ int halfPageSize = (buf.capacity() - getPageHeaderSize()) / 2;
+ int i;
+ for (i = 0; i < tupleCount; ++i) {
+ frameTuple.resetByTupleIndex(this, i);
+ totalSize += tupleWriter.getCopySpaceRequired(frameTuple) + slotManager.getSlotSize();
+ if (totalSize >= halfPageSize) {
+ break;
+ }
+ }
+
+ if (cmp.compare(tuple, frameTuple) >= 0) {
+ tuplesToLeft = i + 1;
+ targetFrame = rightFrame;
+ } else {
+ tuplesToLeft = i;
+ targetFrame = this;
+ }
+ int tuplesToRight = tupleCount - tuplesToLeft;
+
+ // Copy entire page.
+ System.arraycopy(buf.array(), 0, right.array(), 0, buf.capacity());
+
+ // On the right page we need to copy rightmost slots to the left.
+ int src = rightFrame.getSlotManager().getSlotEndOff();
+ int dest = rightFrame.getSlotManager().getSlotEndOff() + tuplesToLeft
+ * rightFrame.getSlotManager().getSlotSize();
+ int length = rightFrame.getSlotManager().getSlotSize() * tuplesToRight;
+ System.arraycopy(right.array(), src, right.array(), dest, length);
+ right.putInt(tupleCountOff, tuplesToRight);
+
+ // On left page only change the tupleCount indicator.
+ buf.putInt(tupleCountOff, tuplesToLeft);
+
+ // Compact both pages.
+ rightFrame.compact();
+ compact();
}
- int tuplesToRight = tupleCount - tuplesToLeft;
-
- // Copy entire page.
- System.arraycopy(buf.array(), 0, right.array(), 0, buf.capacity());
-
- // On the right page we need to copy rightmost slots to the left.
- int src = rightFrame.getSlotManager().getSlotEndOff();
- int dest = rightFrame.getSlotManager().getSlotEndOff() + tuplesToLeft
- * rightFrame.getSlotManager().getSlotSize();
- int length = rightFrame.getSlotManager().getSlotSize() * tuplesToRight;
- System.arraycopy(right.array(), src, right.array(), dest, length);
- right.putInt(tupleCountOff, tuplesToRight);
-
- // On left page only change the tupleCount indicator.
- buf.putInt(tupleCountOff, tuplesToLeft);
-
- // Compact both pages.
- rightFrame.compact();
- compact();
// Insert the new tuple.
int targetTupleIndex;
diff --git a/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/OrderedSlotManager.java b/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/OrderedSlotManager.java
index 2071a77..2316c6b 100644
--- a/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/OrderedSlotManager.java
+++ b/hyracks/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/OrderedSlotManager.java
@@ -27,19 +27,29 @@
@Override
public int findTupleIndex(ITupleReference searchKey, ITreeIndexTupleReference frameTuple, MultiComparator multiCmp,
FindTupleMode mode, FindTupleNoExactMatchPolicy matchPolicy) {
- if (frame.getTupleCount() <= 0) {
+ int tupleCount = frame.getTupleCount();
+ if (tupleCount <= 0) {
return GREATEST_KEY_INDICATOR;
}
int mid;
- int begin = 0;
- int end = frame.getTupleCount() - 1;
+ int begin;
+ int end = tupleCount - 1;
+
+ frameTuple.resetByTupleIndex(frame, end);
+ int cmp = multiCmp.compare(searchKey, frameTuple);
+ if (cmp > 0) {
+ // This is a special optimization case when the tuple to be searched is larger than all the keys on the page.
+ begin = tupleCount;
+ } else {
+ begin = 0;
+ }
while (begin <= end) {
mid = (begin + end) / 2;
frameTuple.resetByTupleIndex(frame, mid);
- int cmp = multiCmp.compare(searchKey, frameTuple);
+ cmp = multiCmp.compare(searchKey, frameTuple);
if (cmp < 0) {
end = mid - 1;
} else if (cmp > 0) {
@@ -66,7 +76,7 @@
}
if (matchPolicy == FindTupleNoExactMatchPolicy.HIGHER_KEY) {
- if (begin > frame.getTupleCount() - 1) {
+ if (begin > tupleCount - 1) {
return GREATEST_KEY_INDICATOR;
}
frameTuple.resetByTupleIndex(frame, begin);
diff --git a/hyracks/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexSortedInsertTest.java b/hyracks/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexSortedInsertTest.java
new file mode 100644
index 0000000..e8b83e8
--- /dev/null
+++ b/hyracks/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexSortedInsertTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2009-2013 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 edu.uci.ics.hyracks.storage.am.btree;
+
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.UTF8StringSerializerDeserializer;
+import edu.uci.ics.hyracks.storage.am.btree.frames.BTreeLeafFrameType;
+
+/**
+ * Tests the BTree insert operation with sorted stream of strings and integer fields using
+ * various numbers of key and payload fields.
+ * Each tests first fills a BTree with sorted generated tuples. We compare the
+ * following operations against expected results: 1. Point searches for all
+ * tuples. 2. Ordered scan. 3. Disk-order scan. 4. Range search (and prefix
+ * search for composite keys).
+ */
+@SuppressWarnings("rawtypes")
+public abstract class OrderedIndexSortedInsertTest extends OrderedIndexTestDriver {
+
+ private final OrderedIndexTestUtils orderedIndexTestUtils;
+
+ public OrderedIndexSortedInsertTest(BTreeLeafFrameType[] leafFrameTypesToTest) {
+ super(leafFrameTypesToTest);
+ this.orderedIndexTestUtils = new OrderedIndexTestUtils();
+ }
+
+ @Override
+ protected void runTest(ISerializerDeserializer[] fieldSerdes, int numKeys, BTreeLeafFrameType leafType,
+ ITupleReference lowKey, ITupleReference highKey, ITupleReference prefixLowKey, ITupleReference prefixHighKey)
+ throws Exception {
+ OrderedIndexTestContext ctx = createTestContext(fieldSerdes, numKeys, leafType);
+ ctx.getIndex().create();
+ ctx.getIndex().activate();
+ // We assume all fieldSerdes are of the same type. Check the first one
+ // to determine which field types to generate.
+ if (fieldSerdes[0] instanceof IntegerSerializerDeserializer) {
+ orderedIndexTestUtils.insertSortedIntTuples(ctx, numTuplesToInsert, getRandom());
+ } else if (fieldSerdes[0] instanceof UTF8StringSerializerDeserializer) {
+ orderedIndexTestUtils.insertSortedStringTuples(ctx, numTuplesToInsert, getRandom());
+ }
+
+ orderedIndexTestUtils.checkPointSearches(ctx);
+ orderedIndexTestUtils.checkScan(ctx);
+ orderedIndexTestUtils.checkDiskOrderScan(ctx);
+
+ orderedIndexTestUtils.checkRangeSearch(ctx, lowKey, highKey, true, true);
+ if (prefixLowKey != null && prefixHighKey != null) {
+ orderedIndexTestUtils.checkRangeSearch(ctx, prefixLowKey, prefixHighKey, true, true);
+ }
+
+ ctx.getIndex().validate();
+ ctx.getIndex().deactivate();
+ ctx.getIndex().destroy();
+ }
+
+ @Override
+ protected String getTestOpName() {
+ return "Insert-Sorted";
+ }
+}
diff --git a/hyracks/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexTestUtils.java b/hyracks/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexTestUtils.java
index 9de217b..bb614d4 100644
--- a/hyracks/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexTestUtils.java
+++ b/hyracks/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexTestUtils.java
@@ -43,6 +43,7 @@
import edu.uci.ics.hyracks.storage.am.common.api.IIndexCursor;
import edu.uci.ics.hyracks.storage.am.common.api.ISearchPredicate;
import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
+import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
import edu.uci.ics.hyracks.storage.am.common.exceptions.TreeIndexDuplicateKeyException;
import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
@@ -180,6 +181,79 @@
}
@SuppressWarnings("unchecked")
+ public void insertSortedIntTuples(IIndexTestContext ctx, int numTuples, Random rnd) throws Exception {
+ int fieldCount = ctx.getFieldCount();
+ int numKeyFields = ctx.getKeyFieldCount();
+ int[] fieldValues = new int[ctx.getFieldCount()];
+ int maxValue = (int) Math.ceil(Math.pow(numTuples, 1.0 / (double) numKeyFields));
+ Collection<CheckTuple> tmpCheckTuples = createCheckTuplesCollection();
+ for (int i = 0; i < numTuples; i++) {
+ // Set keys.
+ setIntKeyFields(fieldValues, numKeyFields, maxValue, rnd);
+ // Set values.
+ setIntPayloadFields(fieldValues, numKeyFields, fieldCount);
+
+ // Set expected values. (We also use these as the pre-sorted stream
+ // for ordered indexes bulk loading).
+ ctx.insertCheckTuple(createIntCheckTuple(fieldValues, ctx.getKeyFieldCount()), tmpCheckTuples);
+ }
+ insertCheckTuples(ctx, tmpCheckTuples);
+
+ // Add tmpCheckTuples to ctx check tuples for comparing searches.
+ for (CheckTuple checkTuple : tmpCheckTuples) {
+ ctx.insertCheckTuple(checkTuple, ctx.getCheckTuples());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void insertSortedStringTuples(IIndexTestContext ctx, int numTuples, Random rnd) throws Exception {
+ int fieldCount = ctx.getFieldCount();
+ int numKeyFields = ctx.getKeyFieldCount();
+ String[] fieldValues = new String[fieldCount];
+ TreeSet<CheckTuple> tmpCheckTuples = new TreeSet<CheckTuple>();
+ for (int i = 0; i < numTuples; i++) {
+ // Set keys.
+ for (int j = 0; j < numKeyFields; j++) {
+ int length = (Math.abs(rnd.nextInt()) % 10) + 1;
+ fieldValues[j] = getRandomString(length, rnd);
+ }
+ // Set values.
+ for (int j = numKeyFields; j < fieldCount; j++) {
+ fieldValues[j] = getRandomString(5, rnd);
+ }
+ // Set expected values. We also use these as the pre-sorted stream
+ // for bulk loading.
+ ctx.insertCheckTuple(createStringCheckTuple(fieldValues, ctx.getKeyFieldCount()), tmpCheckTuples);
+ }
+ insertCheckTuples(ctx, tmpCheckTuples);
+
+ // Add tmpCheckTuples to ctx check tuples for comparing searches.
+ for (CheckTuple checkTuple : tmpCheckTuples) {
+ ctx.insertCheckTuple(checkTuple, ctx.getCheckTuples());
+ }
+ }
+
+ public static void insertCheckTuples(IIndexTestContext ctx, Collection<CheckTuple> checkTuples)
+ throws HyracksDataException, IndexException {
+ int fieldCount = ctx.getFieldCount();
+ int numTuples = checkTuples.size();
+ ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(fieldCount);
+ ArrayTupleReference tuple = new ArrayTupleReference();
+
+ int c = 1;
+ for (CheckTuple checkTuple : checkTuples) {
+ if (LOGGER.isLoggable(Level.INFO)) {
+ if (c % (numTuples / 10) == 0) {
+ LOGGER.info("Inserting Tuple " + c + "/" + numTuples);
+ }
+ }
+ createTupleFromCheckTuple(checkTuple, tupleBuilder, tuple, ctx.getFieldSerdes());
+ ctx.getIndexAccessor().insert(tuple);
+ c++;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
public void insertStringTuples(IIndexTestContext ctx, int numTuples, Random rnd) throws Exception {
int fieldCount = ctx.getFieldCount();
int numKeyFields = ctx.getKeyFieldCount();
diff --git a/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeSortedInsertTest.java b/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeSortedInsertTest.java
new file mode 100644
index 0000000..5e24c52
--- /dev/null
+++ b/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeSortedInsertTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009-2013 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 edu.uci.ics.hyracks.storage.am.btree;
+
+import java.util.Random;
+
+import org.junit.After;
+import org.junit.Before;
+
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.storage.am.btree.frames.BTreeLeafFrameType;
+import edu.uci.ics.hyracks.storage.am.btree.util.BTreeTestContext;
+import edu.uci.ics.hyracks.storage.am.btree.util.BTreeTestHarness;
+
+/**
+ * Tests the BTree insert operation with sorted stream of strings and integer fields using
+ * various numbers of key and payload fields. Each tests first fills a BTree with
+ * randomly generated tuples. We compare the following operations against expected results:
+ * 1) Point searches for all tuples
+ * 2) Ordered scan
+ * 3) Disk-order scan
+ * 4) Range search (and prefix search for composite keys)
+ */
+public class BTreeSortedInsertTest extends OrderedIndexSortedInsertTest {
+
+ private final BTreeTestHarness harness = new BTreeTestHarness();
+
+ public BTreeSortedInsertTest() {
+ super(BTreeTestHarness.LEAF_FRAMES_TO_TEST);
+ }
+
+ @Before
+ public void setUp() throws HyracksDataException {
+ harness.setUp();
+ }
+
+ @After
+ public void tearDown() throws HyracksDataException {
+ harness.tearDown();
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected OrderedIndexTestContext createTestContext(ISerializerDeserializer[] fieldSerdes, int numKeys,
+ BTreeLeafFrameType leafType) throws Exception {
+ return BTreeTestContext.create(harness.getBufferCache(), harness.getFileMapProvider(),
+ harness.getFileReference(), fieldSerdes, numKeys, leafType);
+ }
+
+ @Override
+ protected Random getRandom() {
+ return harness.getRandom();
+ }
+}