http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/TreeTupleSorter.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/TreeTupleSorter.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/TreeTupleSorter.java index 6fe6b60..9ef305c 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/TreeTupleSorter.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/TreeTupleSorter.java @@ -25,6 +25,7 @@ import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; import org.apache.hyracks.storage.am.common.api.ITreeIndexCursor; import org.apache.hyracks.storage.am.common.api.ITreeIndexFrame; import org.apache.hyracks.storage.am.common.api.ITreeIndexTupleReference; +import org.apache.hyracks.storage.common.EnforcedIndexCursor; import org.apache.hyracks.storage.common.ICursorInitialState; import org.apache.hyracks.storage.common.ISearchPredicate; import org.apache.hyracks.storage.common.MultiComparator; @@ -32,7 +33,7 @@ import org.apache.hyracks.storage.common.buffercache.IBufferCache; import org.apache.hyracks.storage.common.buffercache.ICachedPage; import org.apache.hyracks.storage.common.file.BufferedFileHandle; -public class TreeTupleSorter implements ITreeIndexCursor { +public class TreeTupleSorter extends EnforcedIndexCursor implements ITreeIndexCursor { private final static int INITIAL_SIZE = 1000000; private int numTuples; private int currentTupleIndex; @@ -62,13 +63,13 @@ public class TreeTupleSorter implements ITreeIndexCursor { } @Override - public void close() { + public void doClose() { numTuples = 0; currentTupleIndex = 0; } @Override - public boolean hasNext() throws HyracksDataException { + public boolean doHasNext() throws HyracksDataException { if (numTuples <= currentTupleIndex) { return false; } @@ -87,12 +88,12 @@ public class TreeTupleSorter implements ITreeIndexCursor { } @Override - public void next() { + public void doNext() { currentTupleIndex++; } @Override - public ITupleReference getTuple() { + public ITupleReference doGetTuple() { return frameTuple1; } @@ -180,34 +181,32 @@ public class TreeTupleSorter implements ITreeIndexCursor { private int compare(int[] tPointers, int tp1, int tp2i, int tp2j) throws HyracksDataException { int i1 = tPointers[tp1 * 2]; int j1 = tPointers[tp1 * 2 + 1]; - int i2 = tp2i; int j2 = tp2j; - ICachedPage node1 = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, i1), false); - leafFrame1.setPage(node1); - ICachedPage node2 = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, i2), false); - leafFrame2.setPage(node2); - try { - frameTuple1.resetByTupleOffset(leafFrame1.getBuffer().array(), j1); - frameTuple2.resetByTupleOffset(leafFrame2.getBuffer().array(), j2); - - return cmp.selectiveFieldCompare(frameTuple1, frameTuple2, comparatorFields); - + leafFrame1.setPage(node1); + ICachedPage node2 = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, i2), false); + try { + leafFrame2.setPage(node2); + frameTuple1.resetByTupleOffset(leafFrame1.getBuffer().array(), j1); + frameTuple2.resetByTupleOffset(leafFrame2.getBuffer().array(), j2); + return cmp.selectiveFieldCompare(frameTuple1, frameTuple2, comparatorFields); + } finally { + bufferCache.unpin(node2); + } } finally { bufferCache.unpin(node1); - bufferCache.unpin(node2); } } @Override - public void open(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException { + public void doOpen(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException { // do nothing } @Override - public void destroy() throws HyracksDataException { + public void doDestroy() throws HyracksDataException { // do nothing }
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTree.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTree.java b/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTree.java index 1e71b7f..5582075 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTree.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTree.java @@ -769,6 +769,7 @@ public class RTree extends AbstractTreeIndex { public class RTreeAccessor implements ITreeIndexAccessor { private RTree rtree; private RTreeOpContext ctx; + private boolean destroyed = false; public RTreeAccessor(RTree rtree, IModificationOperationCallback modificationCallback, ISearchOperationCallback searchCallback) { @@ -895,6 +896,15 @@ public class RTree extends AbstractTreeIndex { } } } + + @Override + public void destroy() throws HyracksDataException { + if (destroyed) { + return; + } + destroyed = true; + ctx.destroy(); + } } @Override http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeOpContext.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeOpContext.java b/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeOpContext.java index dc2e83b..46e6b22 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeOpContext.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeOpContext.java @@ -62,6 +62,7 @@ public class RTreeOpContext implements IIndexOperationContext, IExtraPageBlockHe private IModificationOperationCallback modificationCallback; private PermutingTupleReference tupleWithNonIndexFields; + private boolean destroyed = false; public RTreeOpContext(IRTreeLeafFrame leafFrame, IRTreeInteriorFrame interiorFrame, IPageManager freePageManager, IBinaryComparatorFactory[] cmpFactories, IModificationOperationCallback modificationCallback) { @@ -207,4 +208,15 @@ public class RTreeOpContext implements IIndexOperationContext, IExtraPageBlockHe public void resetNonIndexFieldsTuple(ITupleReference newValue) { tupleWithNonIndexFields.reset(newValue); } + + @Override + public void destroy() throws HyracksDataException { + if (destroyed) { + return; + } + destroyed = true; + if (cursor != null) { + cursor.destroy(); + } + } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeSearchCursor.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeSearchCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeSearchCursor.java index 3f4e00a..f85c044 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeSearchCursor.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTreeSearchCursor.java @@ -25,6 +25,7 @@ import org.apache.hyracks.storage.am.common.api.ITreeIndexCursor; import org.apache.hyracks.storage.am.common.api.ITreeIndexTupleReference; import org.apache.hyracks.storage.am.rtree.api.IRTreeInteriorFrame; import org.apache.hyracks.storage.am.rtree.api.IRTreeLeafFrame; +import org.apache.hyracks.storage.common.EnforcedIndexCursor; import org.apache.hyracks.storage.common.ICursorInitialState; import org.apache.hyracks.storage.common.ISearchPredicate; import org.apache.hyracks.storage.common.MultiComparator; @@ -32,7 +33,7 @@ import org.apache.hyracks.storage.common.buffercache.IBufferCache; import org.apache.hyracks.storage.common.buffercache.ICachedPage; import org.apache.hyracks.storage.common.file.BufferedFileHandle; -public class RTreeSearchCursor implements ITreeIndexCursor { +public class RTreeSearchCursor extends EnforcedIndexCursor implements ITreeIndexCursor { private int fileId = -1; private ICachedPage page = null; @@ -62,7 +63,7 @@ public class RTreeSearchCursor implements ITreeIndexCursor { } @Override - public void destroy() throws HyracksDataException { + public void doDestroy() throws HyracksDataException { if (readLatched) { page.releaseReadLatch(); bufferCache.unpin(page); @@ -75,7 +76,7 @@ public class RTreeSearchCursor implements ITreeIndexCursor { } @Override - public ITupleReference getTuple() { + public ITupleReference doGetTuple() { return frameTuple; } @@ -163,7 +164,7 @@ public class RTreeSearchCursor implements ITreeIndexCursor { } @Override - public boolean hasNext() throws HyracksDataException { + public boolean doHasNext() throws HyracksDataException { if (page == null) { return false; } @@ -198,12 +199,12 @@ public class RTreeSearchCursor implements ITreeIndexCursor { } @Override - public void next() throws HyracksDataException { + public void doNext() throws HyracksDataException { tupleIndex = tupleIndexInc; } @Override - public void open(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException { + public void doOpen(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException { // in case open is called multiple times without closing if (this.page != null) { this.page.releaseReadLatch(); @@ -239,8 +240,8 @@ public class RTreeSearchCursor implements ITreeIndexCursor { } @Override - public void close() throws HyracksDataException { - destroy(); + public void doClose() throws HyracksDataException { + doDestroy(); } @Override http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/EnforcedIndexCursor.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/EnforcedIndexCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/EnforcedIndexCursor.java index 19dfbab..929faff 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/EnforcedIndexCursor.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/EnforcedIndexCursor.java @@ -19,83 +19,117 @@ package org.apache.hyracks.storage.common; +import java.util.Arrays; + import org.apache.hyracks.api.exceptions.HyracksDataException; import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; -public class EnforcedIndexCursor implements IIndexCursor { +public abstract class EnforcedIndexCursor implements IIndexCursor { enum State { CLOSED, OPENED, DESTROYED } + private static final boolean STORE_TRACES = false; + private static final boolean ENFORCE_NEXT_HAS_NEXT = true; + private static final boolean ENFORCE_OPEN_CLOSE_DESTROY = true; + private static final Logger LOGGER = LogManager.getLogger(); + private State state = State.CLOSED; + private StackTraceElement[] openCallStack; + private StackTraceElement[] destroyCallStack; @Override - public void open(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException { - if (state != State.CLOSED) { + public final void open(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException { + if (ENFORCE_OPEN_CLOSE_DESTROY && state != State.CLOSED) { + if (STORE_TRACES && destroyCallStack != null) { + LOGGER.log(Level.WARN, "The cursor was destroyed in " + Arrays.toString(destroyCallStack)); + } throw new IllegalStateException("Cannot open a cursor in the state " + state); } doOpen(initialState, searchPred); state = State.OPENED; + if (STORE_TRACES) { + openCallStack = new Throwable().getStackTrace(); + } } - protected void doOpen(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException { - // Do nothing - } + protected abstract void doOpen(ICursorInitialState initialState, ISearchPredicate searchPred) + throws HyracksDataException; @Override - public boolean hasNext() throws HyracksDataException { - if (state != State.OPENED) { + public final boolean hasNext() throws HyracksDataException { + if (ENFORCE_NEXT_HAS_NEXT && state != State.OPENED) { throw new IllegalStateException("Cannot call hasNext() on a cursor in the state " + state); } return doHasNext(); } - protected boolean doHasNext() throws HyracksDataException { - return false; - } + protected abstract boolean doHasNext() throws HyracksDataException; @Override - public void next() throws HyracksDataException { - if (state != State.OPENED) { + public final void next() throws HyracksDataException { + if (ENFORCE_NEXT_HAS_NEXT && state != State.OPENED) { throw new IllegalStateException("Cannot call next() on a cursor in the state " + state); } doNext(); } - protected void doNext() throws HyracksDataException { - // Do nothing - } + protected abstract void doNext() throws HyracksDataException; @Override - public void destroy() throws HyracksDataException { - if (state != State.CLOSED) { - throw new IllegalStateException("Cannot destroy a cursor in the state " + state); + public final void destroy() throws HyracksDataException { + if (ENFORCE_OPEN_CLOSE_DESTROY) { + if (state == State.DESTROYED) { + LOGGER.log(Level.WARN, + "multiple cursor.destroy() call in " + Arrays.toString(new Throwable().getStackTrace())); + return; + } else if (state != State.CLOSED) { + if (STORE_TRACES && openCallStack != null) { + LOGGER.log(Level.WARN, "The cursor was opened in " + Arrays.toString(openCallStack)); + } + throw new IllegalStateException("Cannot destroy a cursor in the state " + state); + } } - doDestroy(); state = State.DESTROYED; + try { + doDestroy(); + } finally { + if (ENFORCE_OPEN_CLOSE_DESTROY && STORE_TRACES) { + destroyCallStack = new Throwable().getStackTrace(); + } + } } - protected void doDestroy() throws HyracksDataException { - // Do nothing - } + protected abstract void doDestroy() throws HyracksDataException; @Override - public void close() throws HyracksDataException { - if (state != State.OPENED) { - throw new IllegalStateException("Cannot close a cursor in the state " + state); + public final void close() throws HyracksDataException { + if (ENFORCE_OPEN_CLOSE_DESTROY) { + if (state == State.CLOSED) { + return; + } else if (state == State.DESTROYED) { + throw new IllegalStateException("Cannot close a cursor in the state " + state); + } } - doClose(); state = State.CLOSED; + doClose(); } - private void doClose() throws HyracksDataException { - // Do nothing - } + protected abstract void doClose() throws HyracksDataException; @Override - public ITupleReference getTuple() { - return null; + public final ITupleReference getTuple() { + if (state == State.OPENED) { + return doGetTuple(); + } else { + return null; + } } + + protected abstract ITupleReference doGetTuple(); } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndex.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndex.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndex.java index 19b4856..4c0012d 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndex.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndex.java @@ -134,7 +134,7 @@ public interface IIndex { /** * @param fillFactor * @param verifyInput - * @throws IndexException + * @throws HyracksDataException */ public IIndexBulkLoader createBulkLoader(float fillFactor, boolean verifyInput, long numElementsHint, boolean checkIfEmptyIndex) throws HyracksDataException; http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexAccessor.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexAccessor.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexAccessor.java index 27ca8c8..382aea2 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexAccessor.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexAccessor.java @@ -19,6 +19,7 @@ package org.apache.hyracks.storage.common; +import org.apache.hyracks.api.dataflow.IDestroyable; import org.apache.hyracks.api.exceptions.HyracksDataException; import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; @@ -28,7 +29,7 @@ import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; * can concurrently operate on the same IIndex (i.e., the IIndex must allow * concurrent operations). */ -public interface IIndexAccessor { +public interface IIndexAccessor extends IDestroyable { /** * Inserts the given tuple. * @@ -36,11 +37,10 @@ public interface IIndexAccessor { * Tuple to be inserted. * @throws HyracksDataException * If the BufferCache throws while un/pinning or un/latching. - * @throws IndexException * If an index-specific constraint is violated, e.g., the key * already exists. */ - public void insert(ITupleReference tuple) throws HyracksDataException; + void insert(ITupleReference tuple) throws HyracksDataException; /** * Updates the tuple in the index matching the given tuple with the new @@ -51,10 +51,9 @@ public interface IIndexAccessor { * tuples contents. * @throws HyracksDataException * If the BufferCache throws while un/pinning or un/latching. - * @throws IndexException * If there is no matching tuple in the index. */ - public void update(ITupleReference tuple) throws HyracksDataException; + void update(ITupleReference tuple) throws HyracksDataException; /** * Deletes the tuple in the index matching the given tuple. @@ -63,10 +62,9 @@ public interface IIndexAccessor { * Tuple to be deleted. * @throws HyracksDataException * If the BufferCache throws while un/pinning or un/latching. - * @throws IndexException * If there is no matching tuple in the index. */ - public void delete(ITupleReference tuple) throws HyracksDataException; + void delete(ITupleReference tuple) throws HyracksDataException; /** * This operation is only supported by indexes with the notion of a unique key. @@ -77,29 +75,29 @@ public interface IIndexAccessor { * Tuple to be deleted. * @throws HyracksDataException * If the BufferCache throws while un/pinning or un/latching. - * @throws IndexException * If there is no matching tuple in the index. * */ - public void upsert(ITupleReference tuple) throws HyracksDataException; + void upsert(ITupleReference tuple) throws HyracksDataException; /** * Creates a cursor appropriate for passing into search(). * */ - public IIndexCursor createSearchCursor(boolean exclusive); + IIndexCursor createSearchCursor(boolean exclusive); /** * Open the given cursor for an index search using the given predicate as * search condition. * - * @param icursor + * Note: if this call returns successfully, then the cursor is open, otherwise it is not. + * + * @param cursor * Cursor over the index entries satisfying searchPred. * @param searchPred * Search condition. * @throws HyracksDataException * If the BufferCache throws while un/pinning or un/latching. - * @throws IndexException */ - public void search(IIndexCursor cursor, ISearchPredicate searchPred) throws HyracksDataException; + void search(IIndexCursor cursor, ISearchPredicate searchPred) throws HyracksDataException; } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexBulkLoader.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexBulkLoader.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexBulkLoader.java index 5c4d3c0..fc54903 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexBulkLoader.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexBulkLoader.java @@ -37,7 +37,6 @@ public interface IIndexBulkLoader { /** * Finalize the bulk loading operation in the given context. * - * @throws IndexException * @throws HyracksDataException * If the BufferCache throws while un/pinning or un/latching. */ @@ -46,6 +45,9 @@ public interface IIndexBulkLoader { /** * Release all resources held by this bulkloader, with no guarantee of * persisted content. + * + * @throws HyracksDataException + * If the operation was completed through end() invocation before abort is called */ void abort() throws HyracksDataException; } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexCursor.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexCursor.java index b561e25..f704921 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexCursor.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/IIndexCursor.java @@ -19,6 +19,7 @@ package org.apache.hyracks.storage.common; +import org.apache.hyracks.api.dataflow.IDestroyable; import org.apache.hyracks.api.exceptions.HyracksDataException; import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; @@ -44,12 +45,12 @@ import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; * <li>DESTROYED</li> * </ul> * When a cursor object is created, it is in the CLOSED state. - * CLOSED: The only legal calls are open() --> OPENED, or destroy() --> DESTROYED + * CLOSED: Legal calls are open() --> OPENED, or destroy() --> DESTROYED, close() --> no effect * OPENED: The only legal calls are hasNext(), next(), or close() --> CLOSED. * DESTROYED: All calls are illegal. * Cursors must enforce the cursor state machine */ -public interface IIndexCursor { +public interface IIndexCursor extends IDestroyable { /** * Opens the cursor * if open succeeds, close must be called. @@ -76,15 +77,8 @@ public interface IIndexCursor { void next() throws HyracksDataException; /** - * Destroys the cursor allowing for release of resources. - * The cursor can't be used anymore after this call. - * - * @throws HyracksDataException - */ - void destroy() throws HyracksDataException; - - /** - * Close the cursor when done with it after a successful open + * Close the cursor. If the cursor is already closed then invoking this + * method has no effect. * * @throws HyracksDataException */ http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/VirtualPage.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/VirtualPage.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/VirtualPage.java index be384e0..d7ec4e9 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/VirtualPage.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/VirtualPage.java @@ -141,8 +141,9 @@ public class VirtualPage implements ICachedPage { @Override public String toString() { StringBuilder str = new StringBuilder(); - str.append("{\"class\":\"" + getClass().getSimpleName() + "\", \"readers\":" + getReadLatchCount() - + ",\"writers\":" + (isWriteLatched())); + str.append("{\"class\":\"").append(getClass().getSimpleName()).append("\", \"readers\":") + .append(getReadLatchCount()).append(",\"writers\":").append(isWriteLatched()); + str.append(",\"next\":").append(next); str.append("}"); return str.toString(); } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/AbstractSearchOperationCallbackTest.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/AbstractSearchOperationCallbackTest.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/AbstractSearchOperationCallbackTest.java index 368430c..6e7717d 100644 --- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/AbstractSearchOperationCallbackTest.java +++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/AbstractSearchOperationCallbackTest.java @@ -110,24 +110,27 @@ public abstract class AbstractSearchOperationCallbackTest extends AbstractOperat public Boolean call() throws Exception { lock.lock(); try { - if (!insertTaskStarted) { - condition.await(); + try { + while (!insertTaskStarted) { + condition.await(); + } + // begin a search on [101, +inf), blocking on 101 + TupleUtils.createIntegerTuple(builder, tuple, 101); + predicate.setLowKey(tuple, true); + predicate.setHighKey(null, true); + accessor.search(cursor, predicate); + try { + consumeIntTupleRange(101, 101, true, 101); + // consume tuples [102, 152], blocking on 151 + consumeIntTupleRange(102, 151, true, 152); + // consume tuples [153, 300] + consumeIntTupleRange(153, 300, false, -1); + } finally { + cursor.close(); + } + } finally { + cursor.destroy(); } - - // begin a search on [101, +inf), blocking on 101 - TupleUtils.createIntegerTuple(builder, tuple, 101); - predicate.setLowKey(tuple, true); - predicate.setHighKey(null, true); - accessor.search(cursor, predicate); - consumeIntTupleRange(101, 101, true, 101); - - // consume tuples [102, 152], blocking on 151 - consumeIntTupleRange(102, 151, true, 152); - - // consume tuples [153, 300] - consumeIntTupleRange(153, 300, false, -1); - - cursor.destroy(); } finally { lock.unlock(); } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexExamplesTest.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexExamplesTest.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexExamplesTest.java index 9ca3b59..80e443d 100644 --- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexExamplesTest.java +++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexExamplesTest.java @@ -760,16 +760,20 @@ public abstract class OrderedIndexExamplesTest { LOGGER.info("Ordered Scan:"); } IIndexCursor scanCursor = indexAccessor.createSearchCursor(false); - RangePredicate nullPred = new RangePredicate(null, null, true, true, null, null); - indexAccessor.search(scanCursor, nullPred); try { - while (scanCursor.hasNext()) { - scanCursor.next(); - ITupleReference frameTuple = scanCursor.getTuple(); - String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); - if (LOGGER.isInfoEnabled()) { - LOGGER.info(rec); + RangePredicate nullPred = new RangePredicate(null, null, true, true, null, null); + indexAccessor.search(scanCursor, nullPred); + try { + while (scanCursor.hasNext()) { + scanCursor.next(); + ITupleReference frameTuple = scanCursor.getTuple(); + String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); + if (LOGGER.isInfoEnabled()) { + LOGGER.info(rec); + } } + } finally { + scanCursor.close(); } } finally { scanCursor.destroy(); @@ -784,15 +788,17 @@ public abstract class OrderedIndexExamplesTest { ITreeIndexAccessor treeIndexAccessor = (ITreeIndexAccessor) indexAccessor; TreeIndexDiskOrderScanCursor diskOrderCursor = (TreeIndexDiskOrderScanCursor) treeIndexAccessor.createDiskOrderScanCursor(); - treeIndexAccessor.diskOrderScan(diskOrderCursor); try { - while (diskOrderCursor.hasNext()) { - diskOrderCursor.next(); - ITupleReference frameTuple = diskOrderCursor.getTuple(); - String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); - if (LOGGER.isInfoEnabled()) { + treeIndexAccessor.diskOrderScan(diskOrderCursor); + try { + while (diskOrderCursor.hasNext()) { + diskOrderCursor.next(); + ITupleReference frameTuple = diskOrderCursor.getTuple(); + String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); LOGGER.info(rec); } + } finally { + diskOrderCursor.close(); } } finally { diskOrderCursor.destroy(); @@ -821,24 +827,28 @@ public abstract class OrderedIndexExamplesTest { LOGGER.info("Range-Search in: [ " + lowKeyString + ", " + highKeyString + "]"); } IIndexCursor rangeCursor = indexAccessor.createSearchCursor(false); - MultiComparator lowKeySearchCmp = BTreeUtils.getSearchMultiComparator(cmpFactories, lowKey); - MultiComparator highKeySearchCmp = BTreeUtils.getSearchMultiComparator(cmpFactories, highKey); - RangePredicate rangePred; - if (minFilterTuple != null && maxFilterTuple != null) { - rangePred = new RangePredicate(lowKey, highKey, true, true, lowKeySearchCmp, highKeySearchCmp, - minFilterTuple, maxFilterTuple); - } else { - rangePred = new RangePredicate(lowKey, highKey, true, true, lowKeySearchCmp, highKeySearchCmp); - } - indexAccessor.search(rangeCursor, rangePred); try { - while (rangeCursor.hasNext()) { - rangeCursor.next(); - ITupleReference frameTuple = rangeCursor.getTuple(); - String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); - if (LOGGER.isInfoEnabled()) { - LOGGER.info(rec); + MultiComparator lowKeySearchCmp = BTreeUtils.getSearchMultiComparator(cmpFactories, lowKey); + MultiComparator highKeySearchCmp = BTreeUtils.getSearchMultiComparator(cmpFactories, highKey); + RangePredicate rangePred; + if (minFilterTuple != null && maxFilterTuple != null) { + rangePred = new RangePredicate(lowKey, highKey, true, true, lowKeySearchCmp, highKeySearchCmp, + minFilterTuple, maxFilterTuple); + } else { + rangePred = new RangePredicate(lowKey, highKey, true, true, lowKeySearchCmp, highKeySearchCmp); + } + indexAccessor.search(rangeCursor, rangePred); + try { + while (rangeCursor.hasNext()) { + rangeCursor.next(); + ITupleReference frameTuple = rangeCursor.getTuple(); + String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); + if (LOGGER.isInfoEnabled()) { + LOGGER.info(rec); + } } + } finally { + rangeCursor.close(); } } finally { rangeCursor.destroy(); http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexTestUtils.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexTestUtils.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexTestUtils.java index bf3c8e5..d3dac3e 100644 --- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexTestUtils.java +++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/btree/OrderedIndexTestUtils.java @@ -99,37 +99,42 @@ public class OrderedIndexTestUtils extends TreeIndexTestUtils { MultiComparator lowKeyCmp = BTreeUtils.getSearchMultiComparator(ctx.getComparatorFactories(), lowKey); MultiComparator highKeyCmp = BTreeUtils.getSearchMultiComparator(ctx.getComparatorFactories(), highKey); IIndexCursor searchCursor = ctx.getIndexAccessor().createSearchCursor(false); - RangePredicate rangePred = - new RangePredicate(lowKey, highKey, lowKeyInclusive, highKeyInclusive, lowKeyCmp, highKeyCmp); - ctx.getIndexAccessor().search(searchCursor, rangePred); - // Get the subset of elements from the expected set within given key - // range. - CheckTuple lowKeyCheck = createCheckTupleFromTuple(lowKey, ctx.getFieldSerdes(), lowKeyCmp.getKeyFieldCount()); - CheckTuple highKeyCheck = - createCheckTupleFromTuple(highKey, ctx.getFieldSerdes(), highKeyCmp.getKeyFieldCount()); - SortedSet<CheckTuple> expectedSubset = null; - if (lowKeyCmp.getKeyFieldCount() < ctx.getKeyFieldCount() - || highKeyCmp.getKeyFieldCount() < ctx.getKeyFieldCount()) { - // Searching on a key prefix (low key or high key or both). - expectedSubset = - getPrefixExpectedSubset((TreeSet<CheckTuple>) ctx.getCheckTuples(), lowKeyCheck, highKeyCheck); - } else { - // Searching on all key fields. - expectedSubset = ((TreeSet<CheckTuple>) ctx.getCheckTuples()).subSet(lowKeyCheck, lowKeyInclusive, - highKeyCheck, highKeyInclusive); - } - Iterator<CheckTuple> checkIter = expectedSubset.iterator(); - int actualCount = 0; try { - while (searchCursor.hasNext()) { - if (!checkIter.hasNext()) { - fail("Range search returned more answers than expected.\nExpected: " + expectedSubset.size()); + RangePredicate rangePred = + new RangePredicate(lowKey, highKey, lowKeyInclusive, highKeyInclusive, lowKeyCmp, highKeyCmp); + int actualCount = 0; + SortedSet<CheckTuple> expectedSubset = null; + ctx.getIndexAccessor().search(searchCursor, rangePred); + try { + // Get the subset of elements from the expected set within given key + // range. + CheckTuple lowKeyCheck = + createCheckTupleFromTuple(lowKey, ctx.getFieldSerdes(), lowKeyCmp.getKeyFieldCount()); + CheckTuple highKeyCheck = + createCheckTupleFromTuple(highKey, ctx.getFieldSerdes(), highKeyCmp.getKeyFieldCount()); + if (lowKeyCmp.getKeyFieldCount() < ctx.getKeyFieldCount() + || highKeyCmp.getKeyFieldCount() < ctx.getKeyFieldCount()) { + // Searching on a key prefix (low key or high key or both). + expectedSubset = getPrefixExpectedSubset((TreeSet<CheckTuple>) ctx.getCheckTuples(), lowKeyCheck, + highKeyCheck); + } else { + // Searching on all key fields. + expectedSubset = ((TreeSet<CheckTuple>) ctx.getCheckTuples()).subSet(lowKeyCheck, lowKeyInclusive, + highKeyCheck, highKeyInclusive); } - searchCursor.next(); - CheckTuple expectedTuple = checkIter.next(); - ITupleReference tuple = searchCursor.getTuple(); - compareActualAndExpected(tuple, expectedTuple, ctx.getFieldSerdes()); - actualCount++; + Iterator<CheckTuple> checkIter = expectedSubset.iterator(); + while (searchCursor.hasNext()) { + if (!checkIter.hasNext()) { + fail("Range search returned more answers than expected.\nExpected: " + expectedSubset.size()); + } + searchCursor.next(); + CheckTuple expectedTuple = checkIter.next(); + ITupleReference tuple = searchCursor.getTuple(); + compareActualAndExpected(tuple, expectedTuple, ctx.getFieldSerdes()); + actualCount++; + } + } finally { + searchCursor.close(); } if (actualCount < expectedSubset.size()) { fail("Range search returned fewer answers than expected.\nExpected: " + expectedSubset.size() @@ -146,41 +151,43 @@ public class OrderedIndexTestUtils extends TreeIndexTestUtils { } OrderedIndexTestContext ctx = (OrderedIndexTestContext) ictx; IIndexCursor searchCursor = ctx.getIndexAccessor().createSearchCursor(false); - - ArrayTupleBuilder lowKeyBuilder = new ArrayTupleBuilder(ctx.getKeyFieldCount()); - ArrayTupleReference lowKey = new ArrayTupleReference(); - ArrayTupleBuilder highKeyBuilder = new ArrayTupleBuilder(ctx.getKeyFieldCount()); - ArrayTupleReference highKey = new ArrayTupleReference(); - RangePredicate rangePred = new RangePredicate(lowKey, highKey, true, true, null, null); - - // Iterate through expected tuples, and perform a point search in the - // BTree to verify the tuple can be reached. - for (CheckTuple checkTuple : ctx.getCheckTuples()) { - createTupleFromCheckTuple(checkTuple, lowKeyBuilder, lowKey, ctx.getFieldSerdes()); - createTupleFromCheckTuple(checkTuple, highKeyBuilder, highKey, ctx.getFieldSerdes()); - MultiComparator lowKeyCmp = BTreeUtils.getSearchMultiComparator(ctx.getComparatorFactories(), lowKey); - MultiComparator highKeyCmp = BTreeUtils.getSearchMultiComparator(ctx.getComparatorFactories(), highKey); - - rangePred.setLowKey(lowKey, true); - rangePred.setHighKey(highKey, true); - rangePred.setLowKeyComparator(lowKeyCmp); - rangePred.setHighKeyComparator(highKeyCmp); - - ctx.getIndexAccessor().search(searchCursor, rangePred); - - try { - // We expect exactly one answer. - if (searchCursor.hasNext()) { - searchCursor.next(); - ITupleReference tuple = searchCursor.getTuple(); - compareActualAndExpected(tuple, checkTuple, ctx.getFieldSerdes()); - } - if (searchCursor.hasNext()) { - fail("Point search returned more than one answer."); + try { + ArrayTupleBuilder lowKeyBuilder = new ArrayTupleBuilder(ctx.getKeyFieldCount()); + ArrayTupleReference lowKey = new ArrayTupleReference(); + ArrayTupleBuilder highKeyBuilder = new ArrayTupleBuilder(ctx.getKeyFieldCount()); + ArrayTupleReference highKey = new ArrayTupleReference(); + RangePredicate rangePred = new RangePredicate(lowKey, highKey, true, true, null, null); + + // Iterate through expected tuples, and perform a point search in the + // BTree to verify the tuple can be reached. + for (CheckTuple checkTuple : ctx.getCheckTuples()) { + createTupleFromCheckTuple(checkTuple, lowKeyBuilder, lowKey, ctx.getFieldSerdes()); + createTupleFromCheckTuple(checkTuple, highKeyBuilder, highKey, ctx.getFieldSerdes()); + MultiComparator lowKeyCmp = BTreeUtils.getSearchMultiComparator(ctx.getComparatorFactories(), lowKey); + MultiComparator highKeyCmp = BTreeUtils.getSearchMultiComparator(ctx.getComparatorFactories(), highKey); + + rangePred.setLowKey(lowKey, true); + rangePred.setHighKey(highKey, true); + rangePred.setLowKeyComparator(lowKeyCmp); + rangePred.setHighKeyComparator(highKeyCmp); + + ctx.getIndexAccessor().search(searchCursor, rangePred); + try { + // We expect exactly one answer. + if (searchCursor.hasNext()) { + searchCursor.next(); + ITupleReference tuple = searchCursor.getTuple(); + compareActualAndExpected(tuple, checkTuple, ctx.getFieldSerdes()); + } + if (searchCursor.hasNext()) { + fail("Point search returned more than one answer."); + } + } finally { + searchCursor.close(); } - } finally { - searchCursor.destroy(); } + } finally { + searchCursor.destroy(); } } @@ -479,25 +486,20 @@ public class OrderedIndexTestUtils extends TreeIndexTestUtils { public void checkExpectedResults(IIndexCursor cursor, Collection checkTuples, ISerializerDeserializer[] fieldSerdes, int keyFieldCount, Iterator<CheckTuple> checkIter) throws Exception { int actualCount = 0; - try { - while (cursor.hasNext()) { - if (!checkIter.hasNext()) { - fail("Ordered scan returned more answers than expected.\nExpected: " + checkTuples.size()); - } - cursor.next(); - CheckTuple expectedTuple = checkIter.next(); - ITupleReference tuple = cursor.getTuple(); - compareActualAndExpected(tuple, expectedTuple, fieldSerdes); - actualCount++; - } - if (actualCount < checkTuples.size()) { - fail("Ordered scan returned fewer answers than expected.\nExpected: " + checkTuples.size() - + "\nActual : " + actualCount); + while (cursor.hasNext()) { + if (!checkIter.hasNext()) { + fail("Ordered scan returned more answers than expected.\nExpected: " + checkTuples.size()); } - } finally { - cursor.destroy(); + cursor.next(); + CheckTuple expectedTuple = checkIter.next(); + ITupleReference tuple = cursor.getTuple(); + compareActualAndExpected(tuple, expectedTuple, fieldSerdes); + actualCount++; + } + if (actualCount < checkTuples.size()) { + fail("Ordered scan returned fewer answers than expected.\nExpected: " + checkTuples.size() + "\nActual : " + + actualCount); } - } @Override http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexTestWorker.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexTestWorker.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexTestWorker.java index 5248a22..b9123a5 100644 --- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexTestWorker.java +++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexTestWorker.java @@ -68,12 +68,8 @@ public abstract class AbstractIndexTestWorker extends Thread implements ITreeInd } protected void consumeCursorTuples(IIndexCursor cursor) throws HyracksDataException { - try { - while (cursor.hasNext()) { - cursor.next(); - } - } finally { - cursor.destroy(); + while (cursor.hasNext()) { + cursor.next(); } } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/TreeIndexTestUtils.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/TreeIndexTestUtils.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/TreeIndexTestUtils.java index f0b01a2..a703b0b 100644 --- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/TreeIndexTestUtils.java +++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/TreeIndexTestUtils.java @@ -44,7 +44,6 @@ import org.apache.hyracks.storage.am.common.api.ITreeIndexCursor; import org.apache.hyracks.storage.common.IIndexBulkLoader; import org.apache.hyracks.storage.common.IIndexCursor; import org.apache.hyracks.storage.common.ISearchPredicate; -import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -123,10 +122,19 @@ public abstract class TreeIndexTestUtils { LOGGER.info("Testing Scan."); } IIndexCursor scanCursor = ctx.getIndexAccessor().createSearchCursor(false); - ISearchPredicate nullPred = createNullSearchPredicate(); - ctx.getIndexAccessor().search(scanCursor, nullPred); - Iterator<CheckTuple> checkIter = ctx.getCheckTuples().iterator(); - checkExpectedResults(scanCursor, ctx.getCheckTuples(), ctx.getFieldSerdes(), ctx.getKeyFieldCount(), checkIter); + try { + ISearchPredicate nullPred = createNullSearchPredicate(); + ctx.getIndexAccessor().search(scanCursor, nullPred); + try { + Iterator<CheckTuple> checkIter = ctx.getCheckTuples().iterator(); + checkExpectedResults(scanCursor, ctx.getCheckTuples(), ctx.getFieldSerdes(), ctx.getKeyFieldCount(), + checkIter); + } finally { + scanCursor.close(); + } + } finally { + scanCursor.destroy(); + } } public void checkDiskOrderScan(IIndexTestContext ctx) throws Exception { @@ -135,34 +143,29 @@ public abstract class TreeIndexTestUtils { LOGGER.info("Testing Disk-Order Scan."); } ITreeIndexAccessor treeIndexAccessor = (ITreeIndexAccessor) ctx.getIndexAccessor(); - ITreeIndexCursor diskOrderCursor = treeIndexAccessor.createDiskOrderScanCursor(); - treeIndexAccessor.diskOrderScan(diskOrderCursor); - int actualCount = 0; try { - while (diskOrderCursor.hasNext()) { - diskOrderCursor.next(); - ITupleReference tuple = diskOrderCursor.getTuple(); - CheckTuple checkTuple = - createCheckTupleFromTuple(tuple, ctx.getFieldSerdes(), ctx.getKeyFieldCount()); - if (!checkDiskOrderScanResult(tuple, checkTuple, ctx)) { - fail("Disk-order scan returned unexpected answer: " + checkTuple.toString()); - } - actualCount++; - } - if (actualCount < ctx.getCheckTuples().size()) { - fail("Disk-order scan returned fewer answers than expected.\nExpected: " - + ctx.getCheckTuples().size() + "\nActual : " + actualCount); - } - if (actualCount > ctx.getCheckTuples().size()) { - fail("Disk-order scan returned more answers than expected.\nExpected: " - + ctx.getCheckTuples().size() + "\nActual : " + actualCount); - } - } finally { + ITreeIndexCursor diskOrderCursor = treeIndexAccessor.createDiskOrderScanCursor(); try { + int actualCount = 0; + treeIndexAccessor.diskOrderScan(diskOrderCursor); + try { + actualCount = scan(ctx, diskOrderCursor); + } finally { + diskOrderCursor.close(); + } + if (actualCount < ctx.getCheckTuples().size()) { + fail("Disk-order scan returned fewer answers than expected.\nExpected: " + + ctx.getCheckTuples().size() + "\nActual : " + actualCount); + } + if (actualCount > ctx.getCheckTuples().size()) { + fail("Disk-order scan returned more answers than expected.\nExpected: " + + ctx.getCheckTuples().size() + "\nActual : " + actualCount); + } + } finally { diskOrderCursor.destroy(); - } catch (Exception ex) { - LOGGER.log(Level.WARN, "Error during scan cursor close", ex); } + } finally { + treeIndexAccessor.destroy(); } } catch (UnsupportedOperationException e) { // Ignore exception because some indexes, e.g. the LSMTrees, don't @@ -179,7 +182,19 @@ public abstract class TreeIndexTestUtils { } } - @SuppressWarnings("unchecked") + private int scan(IIndexTestContext ctx, ITreeIndexCursor diskOrderCursor) throws HyracksDataException { + int actualCount = 0; + while (diskOrderCursor.hasNext()) { + diskOrderCursor.next(); + ITupleReference tuple = diskOrderCursor.getTuple(); + CheckTuple checkTuple = createCheckTupleFromTuple(tuple, ctx.getFieldSerdes(), ctx.getKeyFieldCount()); + if (!checkDiskOrderScanResult(tuple, checkTuple, ctx)) { + fail("Disk-order scan returned unexpected answer: " + checkTuple.toString()); + } + actualCount++; + } + return actualCount; + } public Pair<ITupleReference, ITupleReference> insertIntTuples(IIndexTestContext ctx, int numTuples, Random rnd) throws Exception { http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java index a36acf0..6505675 100644 --- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java +++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java @@ -846,16 +846,20 @@ public abstract class AbstractRTreeExamplesTest { LOGGER.info("Scan:"); } IIndexCursor scanCursor = indexAccessor.createSearchCursor(false); - SearchPredicate nullPred = new SearchPredicate(null, null); - indexAccessor.search(scanCursor, nullPred); try { - while (scanCursor.hasNext()) { - scanCursor.next(); - ITupleReference frameTuple = scanCursor.getTuple(); - String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); - if (LOGGER.isInfoEnabled()) { - LOGGER.info(rec); + SearchPredicate nullPred = new SearchPredicate(null, null); + indexAccessor.search(scanCursor, nullPred); + try { + while (scanCursor.hasNext()) { + scanCursor.next(); + ITupleReference frameTuple = scanCursor.getTuple(); + String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); + if (LOGGER.isInfoEnabled()) { + LOGGER.info(rec); + } } + } finally { + scanCursor.close(); } } finally { scanCursor.destroy(); @@ -870,15 +874,17 @@ public abstract class AbstractRTreeExamplesTest { ITreeIndexAccessor treeIndexAccessor = (ITreeIndexAccessor) indexAccessor; TreeIndexDiskOrderScanCursor diskOrderCursor = (TreeIndexDiskOrderScanCursor) treeIndexAccessor.createDiskOrderScanCursor(); - treeIndexAccessor.diskOrderScan(diskOrderCursor); try { - while (diskOrderCursor.hasNext()) { - diskOrderCursor.next(); - ITupleReference frameTuple = diskOrderCursor.getTuple(); - String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); - if (LOGGER.isInfoEnabled()) { + treeIndexAccessor.diskOrderScan(diskOrderCursor); + try { + while (diskOrderCursor.hasNext()) { + diskOrderCursor.next(); + ITupleReference frameTuple = diskOrderCursor.getTuple(); + String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); LOGGER.info(rec); } + } finally { + diskOrderCursor.close(); } } finally { diskOrderCursor.destroy(); @@ -905,25 +911,27 @@ public abstract class AbstractRTreeExamplesTest { String kString = TupleUtils.printTuple(key, fieldSerdes); LOGGER.info("Range-Search using key: " + kString); } - IIndexCursor rangeCursor = indexAccessor.createSearchCursor(false); MultiComparator cmp = RTreeUtils.getSearchMultiComparator(cmpFactories, key); - SearchPredicate rangePred; if (minFilterTuple != null && maxFilterTuple != null) { rangePred = new SearchPredicate(key, cmp, minFilterTuple, maxFilterTuple); } else { rangePred = new SearchPredicate(key, cmp); } - - indexAccessor.search(rangeCursor, rangePred); + IIndexCursor rangeCursor = indexAccessor.createSearchCursor(false); try { - while (rangeCursor.hasNext()) { - rangeCursor.next(); - ITupleReference frameTuple = rangeCursor.getTuple(); - String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); - if (LOGGER.isInfoEnabled()) { - LOGGER.info(rec); + indexAccessor.search(rangeCursor, rangePred); + try { + while (rangeCursor.hasNext()) { + rangeCursor.next(); + ITupleReference frameTuple = rangeCursor.getTuple(); + String rec = TupleUtils.printTuple(frameTuple, fieldSerdes); + if (LOGGER.isInfoEnabled()) { + LOGGER.info(rec); + } } + } finally { + rangeCursor.close(); } } finally { rangeCursor.destroy(); http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/RTreeTestUtils.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/RTreeTestUtils.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/RTreeTestUtils.java index f48da3a..165bf43 100644 --- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/RTreeTestUtils.java +++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/rtree/RTreeTestUtils.java @@ -72,18 +72,25 @@ public class RTreeTestUtils extends TreeIndexTestUtils { MultiComparator cmp = RTreeUtils.getSearchMultiComparator(ctx.getComparatorFactories(), key); IIndexCursor searchCursor = ctx.getIndexAccessor().createSearchCursor(false); - SearchPredicate searchPred = new SearchPredicate(key, cmp); - ctx.getIndexAccessor().search(searchCursor, searchPred); - - // Get the subset of elements from the expected set within given key - // range. - RTreeCheckTuple keyCheck = - (RTreeCheckTuple) createCheckTupleFromTuple(key, ctx.getFieldSerdes(), cmp.getKeyFieldCount()); + try { + SearchPredicate searchPred = new SearchPredicate(key, cmp); + ctx.getIndexAccessor().search(searchCursor, searchPred); + try { + // Get the subset of elements from the expected set within given key + // range. + RTreeCheckTuple keyCheck = + (RTreeCheckTuple) createCheckTupleFromTuple(key, ctx.getFieldSerdes(), cmp.getKeyFieldCount()); - HashMultiSet<RTreeCheckTuple> expectedResult = null; + HashMultiSet<RTreeCheckTuple> expectedResult = null; - expectedResult = getRangeSearchExpectedResults(ctx.getCheckTuples(), keyCheck); - checkExpectedResults(searchCursor, expectedResult, ctx.getFieldSerdes(), ctx.getKeyFieldCount(), null); + expectedResult = getRangeSearchExpectedResults(ctx.getCheckTuples(), keyCheck); + checkExpectedResults(searchCursor, expectedResult, ctx.getFieldSerdes(), ctx.getKeyFieldCount(), null); + } finally { + searchCursor.close(); + } + } finally { + searchCursor.destroy(); + } } @SuppressWarnings("unchecked") @@ -176,27 +183,22 @@ public class RTreeTestUtils extends TreeIndexTestUtils { public void checkExpectedResults(IIndexCursor cursor, Collection checkTuples, ISerializerDeserializer[] fieldSerdes, int keyFieldCount, Iterator<CheckTuple> checkIter) throws Exception { int actualCount = 0; - try { - while (cursor.hasNext()) { - cursor.next(); - ITupleReference tuple = cursor.getTuple(); - RTreeCheckTuple checkTuple = - (RTreeCheckTuple) createCheckTupleFromTuple(tuple, fieldSerdes, keyFieldCount); - if (!checkTuples.contains(checkTuple)) { - fail("Scan or range search returned unexpected answer: " + checkTuple.toString()); - } - actualCount++; - } - if (actualCount < checkTuples.size()) { - fail("Scan or range search returned fewer answers than expected.\nExpected: " + checkTuples.size() - + "\nActual : " + actualCount); - } - if (actualCount > checkTuples.size()) { - fail("Scan or range search returned more answers than expected.\nExpected: " + checkTuples.size() - + "\nActual : " + actualCount); + while (cursor.hasNext()) { + cursor.next(); + ITupleReference tuple = cursor.getTuple(); + RTreeCheckTuple checkTuple = (RTreeCheckTuple) createCheckTupleFromTuple(tuple, fieldSerdes, keyFieldCount); + if (!checkTuples.contains(checkTuple)) { + fail("Scan or range search returned unexpected answer: " + checkTuple.toString()); } - } finally { - cursor.destroy(); + actualCount++; + } + if (actualCount < checkTuples.size()) { + fail("Scan or range search returned fewer answers than expected.\nExpected: " + checkTuples.size() + + "\nActual : " + actualCount); + } + if (actualCount > checkTuples.size()) { + fail("Scan or range search returned more answers than expected.\nExpected: " + checkTuples.size() + + "\nActual : " + actualCount); } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/pom.xml ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/pom.xml b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/pom.xml index b618834..45d6989 100644 --- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/pom.xml +++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/pom.xml @@ -67,6 +67,13 @@ </dependency> <dependency> <groupId>org.apache.hyracks</groupId> + <artifactId>hyracks-storage-am-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.hyracks</groupId> <artifactId>hyracks-api</artifactId> <version>${project.version}</version> </dependency> http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeCountingCursorTest.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeCountingCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeCountingCursorTest.java new file mode 100644 index 0000000..291ab8a --- /dev/null +++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeCountingCursorTest.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 at + * + * 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 org.apache.hyracks.storage.am.btree; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.storage.am.btree.impls.BTree; +import org.apache.hyracks.storage.am.btree.impls.BTree.BTreeAccessor; +import org.apache.hyracks.storage.am.btree.util.BTreeTestHarness; +import org.apache.hyracks.storage.am.common.TestOperationCallback; +import org.apache.hyracks.storage.am.common.api.IMetadataPageManager; +import org.apache.hyracks.storage.am.common.freepage.LinkedMetaDataPageManager; +import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters; +import org.apache.hyracks.storage.am.common.test.IIndexCursorTest; +import org.apache.hyracks.storage.common.IIndexAccessor; +import org.apache.hyracks.storage.common.IIndexCursor; +import org.apache.hyracks.storage.common.ISearchPredicate; +import org.apache.hyracks.storage.common.buffercache.IBufferCache; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +public class BTreeCountingCursorTest extends IIndexCursorTest { + private static final BTreeTestHarness harness = new BTreeTestHarness(); + private static BTree btree; + + @BeforeClass + public static void setup() throws HyracksDataException { + harness.setUp(); + IBufferCache bufferCache = harness.getBufferCache(); + IMetadataPageManager freePageManager = + new LinkedMetaDataPageManager(bufferCache, BTreeSearchCursorTest.META_FRAME_FACTORY); + btree = new BTree(bufferCache, freePageManager, BTreeSearchCursorTest.INTERIOR_FRAME_FACTORY, + BTreeSearchCursorTest.LEAF_FRAME_FACTORY, BTreeSearchCursorTest.CMP_FACTORIES, + BTreeSearchCursorTest.FIELD_COUNT, harness.getFileReference()); + btree.create(); + btree.activate(); + // generate keys + int numKeys = 50; + int maxKey = 1000; + TreeSet<Integer> uniqueKeys = new TreeSet<>(); + ArrayList<Integer> keys = new ArrayList<>(); + while (uniqueKeys.size() < numKeys) { + int key = BTreeSearchCursorTest.RANDOM.nextInt() % maxKey; + uniqueKeys.add(key); + } + for (Integer i : uniqueKeys) { + keys.add(i); + } + BTreeSearchCursorTest.staticInsertBTree(keys, btree); + } + + @AfterClass + public static void tearDown() throws HyracksDataException { + try { + btree.deactivate(); + btree.destroy(); + } finally { + harness.tearDown(); + } + } + + @Override + protected List<ISearchPredicate> createSearchPredicates() throws HyracksDataException { + List<ISearchPredicate> predicates = new ArrayList<>(); + int minKey = -10; + int maxKey = 10; + for (int i = minKey; i < maxKey; i++) { + for (int j = minKey; j < maxKey; j++) { + int lowKey = i; + int highKey = j; + predicates.add(BTreeSearchCursorTest.createRangePredicate(lowKey, highKey, true, true)); + } + } + return predicates; + } + + @Override + protected IIndexAccessor createAccessor() throws Exception { + return btree.createAccessor( + new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE)); + } + + @Override + protected IIndexCursor createCursor(IIndexAccessor accessor) { + return ((BTreeAccessor) accessor).createCountingSearchCursor(); + } +} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeRangeSearchCursorTest.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeRangeSearchCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeRangeSearchCursorTest.java new file mode 100644 index 0000000..73a9bb6 --- /dev/null +++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeRangeSearchCursorTest.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 at + * + * 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 org.apache.hyracks.storage.am.btree; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.storage.am.btree.impls.BTree; +import org.apache.hyracks.storage.am.btree.util.BTreeTestHarness; +import org.apache.hyracks.storage.am.common.TestOperationCallback; +import org.apache.hyracks.storage.am.common.api.IMetadataPageManager; +import org.apache.hyracks.storage.am.common.freepage.LinkedMetaDataPageManager; +import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters; +import org.apache.hyracks.storage.am.common.test.IIndexCursorTest; +import org.apache.hyracks.storage.common.IIndexAccessor; +import org.apache.hyracks.storage.common.ISearchPredicate; +import org.apache.hyracks.storage.common.buffercache.IBufferCache; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +public class BTreeRangeSearchCursorTest extends IIndexCursorTest { + private static final BTreeTestHarness harness = new BTreeTestHarness(); + private static BTree btree; + + @BeforeClass + public static void setup() throws HyracksDataException { + harness.setUp(); + IBufferCache bufferCache = harness.getBufferCache(); + IMetadataPageManager freePageManager = + new LinkedMetaDataPageManager(bufferCache, BTreeSearchCursorTest.META_FRAME_FACTORY); + btree = new BTree(bufferCache, freePageManager, BTreeSearchCursorTest.INTERIOR_FRAME_FACTORY, + BTreeSearchCursorTest.LEAF_FRAME_FACTORY, BTreeSearchCursorTest.CMP_FACTORIES, + BTreeSearchCursorTest.FIELD_COUNT, harness.getFileReference()); + btree.create(); + btree.activate(); + // generate keys + int numKeys = 50; + int maxKey = 1000; + TreeSet<Integer> uniqueKeys = new TreeSet<>(); + ArrayList<Integer> keys = new ArrayList<>(); + while (uniqueKeys.size() < numKeys) { + int key = BTreeSearchCursorTest.RANDOM.nextInt() % maxKey; + uniqueKeys.add(key); + } + for (Integer i : uniqueKeys) { + keys.add(i); + } + BTreeSearchCursorTest.staticInsertBTree(keys, btree); + } + + @AfterClass + public static void tearDown() throws HyracksDataException { + try { + btree.deactivate(); + btree.destroy(); + } finally { + harness.tearDown(); + } + } + + @Override + protected List<ISearchPredicate> createSearchPredicates() throws HyracksDataException { + List<ISearchPredicate> predicates = new ArrayList<>(); + int minKey = -10; + int maxKey = 10; + for (int i = minKey; i < maxKey; i++) { + for (int j = minKey; j < maxKey; j++) { + int lowKey = i; + int highKey = j; + predicates.add(BTreeSearchCursorTest.createRangePredicate(lowKey, highKey, true, true)); + } + } + return predicates; + } + + @Override + protected IIndexAccessor createAccessor() throws Exception { + IndexAccessParameters actx = + new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE); + return btree.createAccessor(actx); + } +}