asterixdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wangs...@apache.org
Subject asterixdb git commit: Index-Only Plan Patch Set 4: Index SearchCursor adjustment
Date Tue, 25 Apr 2017 06:10:29 GMT
Repository: asterixdb
Updated Branches:
  refs/heads/master 2d6136dee -> d98c4c768


Index-Only Plan Patch Set 4: Index SearchCursor adjustment

 - Modify the search cursors to maintain the result of proceed()
   since the result will be required to check whether the given tuple
   is qualified to be part of an index-only plan result or not.
   More details will be followed in the next patch set.
 - Fix the search cursors to call cancel() correctly.

Change-Id: I299b1858b7875ffc116f8f3115d319fe7b53a537
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1630
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
BAD: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Yingyi Bu <buyingyi@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/d98c4c76
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/d98c4c76
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/d98c4c76

Branch: refs/heads/master
Commit: d98c4c768688e82d0d0906eeca958bc415fd78da
Parents: 2d6136d
Author: Taewoo Kim <wangsaeu@yahoo.com>
Authored: Sun Apr 23 17:29:52 2017 -0700
Committer: Taewoo Kim <wangsaeu@gmail.com>
Committed: Mon Apr 24 23:09:52 2017 -0700

----------------------------------------------------------------------
 ...maryIndexInstantSearchOperationCallback.java |  11 +-
 .../btree/impls/LSMBTreePointSearchCursor.java  |  10 +-
 .../btree/impls/LSMBTreeRangeSearchCursor.java  | 150 +++++++++++--------
 .../lsm/common/impls/LSMIndexSearchCursor.java  |  32 ++--
 .../impls/LSMInvertedIndexSearchCursor.java     |  21 ++-
 ...SMRTreeWithAntiMatterTuplesSearchCursor.java |  44 ++++--
 6 files changed, 170 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d98c4c76/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/opcallbacks/PrimaryIndexInstantSearchOperationCallback.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/opcallbacks/PrimaryIndexInstantSearchOperationCallback.java
b/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/opcallbacks/PrimaryIndexInstantSearchOperationCallback.java
index 890823c..c319b64 100644
--- a/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/opcallbacks/PrimaryIndexInstantSearchOperationCallback.java
+++ b/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/opcallbacks/PrimaryIndexInstantSearchOperationCallback.java
@@ -60,9 +60,18 @@ public class PrimaryIndexInstantSearchOperationCallback extends AbstractOperatio
         }
     }
 
+    /**
+     * Cancels the reconcile() operation. Since reconcile() gets a lock, this lock
+     * needs to be unlocked to reverse the effect of reconcile().
+     */
     @Override
     public void cancel(ITupleReference tuple) throws HyracksDataException {
-        //no op
+        int pkHash = computePrimaryKeyHashValue(tuple, primaryKeyFields);
+        try {
+            lockManager.unlock(datasetId, pkHash, LockMode.S, txnCtx);
+        } catch (ACIDException e) {
+            throw new HyracksDataException(e);
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d98c4c76/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreePointSearchCursor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreePointSearchCursor.java
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreePointSearchCursor.java
index 77c3573..99c3e3f 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreePointSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreePointSearchCursor.java
@@ -73,11 +73,14 @@ public class LSMBTreePointSearchCursor implements ITreeIndexCursor {
             btreeAccessors[i].search(rangeCursors[i], predicate);
             if (rangeCursors[i].hasNext()) {
                 rangeCursors[i].next();
-                // We use the predicate's to lock the key instead of the tuple that we get
from cursor to avoid copying the tuple when we do the "unlatch dance"
+                // We use the predicate's to lock the key instead of the tuple that we get
from cursor
+                // to avoid copying the tuple when we do the "unlatch dance".
                 if (reconciled || searchCallback.proceed(predicate.getLowKey())) {
                     // if proceed is successful, then there's no need for doing the "unlatch
dance"
                     if (((ILSMTreeTupleReference) rangeCursors[i].getTuple()).isAntimatter())
{
-                        searchCallback.cancel(predicate.getLowKey());
+                        if (reconciled) {
+                            searchCallback.cancel(predicate.getLowKey());
+                        }
                         rangeCursors[i].close();
                         return false;
                     } else {
@@ -94,7 +97,6 @@ public class LSMBTreePointSearchCursor implements ITreeIndexCursor {
 
                     // retraverse
                     btreeAccessors[0].search(rangeCursors[i], predicate);
-                    searchCallback.complete(predicate.getLowKey());
                     if (rangeCursors[i].hasNext()) {
                         rangeCursors[i].next();
                         if (((ILSMTreeTupleReference) rangeCursors[i].getTuple()).isAntimatter())
{
@@ -104,9 +106,11 @@ public class LSMBTreePointSearchCursor implements ITreeIndexCursor {
                         } else {
                             frameTuple = rangeCursors[i].getTuple();
                             foundTuple = true;
+                            searchCallback.complete(predicate.getLowKey());
                             return true;
                         }
                     } else {
+                        searchCallback.cancel(predicate.getLowKey());
                         rangeCursors[i].close();
                     }
                 } else {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d98c4c76/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreeRangeSearchCursor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreeRangeSearchCursor.java
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreeRangeSearchCursor.java
index 1b8c151..3199cb6 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreeRangeSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree/src/main/java/org/apache/hyracks/storage/am/lsm/btree/impls/LSMBTreeRangeSearchCursor.java
@@ -48,7 +48,8 @@ public class LSMBTreeRangeSearchCursor extends LSMIndexSearchCursor {
     private RangePredicate predicate;
     private BTreeAccessor[] btreeAccessors;
     private ArrayTupleBuilder tupleBuilder;
-    private boolean proceed = true;
+    private boolean canCallProceed = true;
+    private boolean resultOfSearchCallBackProceed = false;
 
     public LSMBTreeRangeSearchCursor(ILSMIndexOperationContext opCtx) {
         this(opCtx, false);
@@ -63,84 +64,115 @@ public class LSMBTreeRangeSearchCursor extends LSMIndexSearchCursor {
     @Override
     public void reset() throws HyracksDataException {
         super.reset();
-        proceed = true;
+        canCallProceed = true;
     }
 
     @Override
     public void next() throws HyracksDataException {
         outputElement = outputPriorityQueue.poll();
-        needPush = true;
-        proceed = false;
+        needPushElementIntoQueue = true;
+        canCallProceed = false;
     }
 
+    /**
+     * Checks the priority queue and resets and the top element if required.
+     * PriorityQueue can hold one element from each cursor.
+     * The boolean variable canCallProceedMethod controls whether we can call proceed() method
for this element.
+     * i.e. it can return this element if proceed() succeeds.
+     * If proceed fails, that is most-likely that there is ongoing operations in the in-memory
component.
+     * After resolving in-memory component issue, it progresses again.
+     * Also, in order to not release the same element again, it keeps the previous output
and checks it
+     * against the current head in the queue.
+     */
     @Override
     protected void checkPriorityQueue() throws HyracksDataException {
-        while (!outputPriorityQueue.isEmpty() || needPush == true) {
+        while (!outputPriorityQueue.isEmpty() || needPushElementIntoQueue == true) {
             if (!outputPriorityQueue.isEmpty()) {
                 PriorityQueueElement checkElement = outputPriorityQueue.peek();
-                if (proceed && !searchCallback.proceed(checkElement.getTuple()))
{
-                    if (includeMutableComponent) {
-                        PriorityQueueElement mutableElement = null;
-                        boolean mutableElementFound = false;
-                        // scan the PQ for the mutable component's element
-                        Iterator<PriorityQueueElement> it = outputPriorityQueue.iterator();
-                        while (it.hasNext()) {
-                            mutableElement = it.next();
-                            if (mutableElement.getCursorIndex() == 0) {
-                                mutableElementFound = true;
-                                it.remove();
-                                break;
-                            }
-                        }
-                        if (mutableElementFound) {
-                            // copy the in-mem tuple
-                            if (tupleBuilder == null) {
-                                tupleBuilder = new ArrayTupleBuilder(cmp.getKeyFieldCount());
+                if (canCallProceed) {
+                    resultOfSearchCallBackProceed = searchCallback.proceed(checkElement.getTuple());
+                    if (!resultOfSearchCallBackProceed) {
+                        // In case proceed() fails and there is an in-memory component,
+                        // we can't simply use this element since there might be a change.
+                        if (includeMutableComponent) {
+                            PriorityQueueElement mutableElement = null;
+                            boolean mutableElementFound = false;
+                            // Scans the PQ for the mutable component's element and delete
it
+                            // since it can be changed.
+                            // (i.e. we can't ensure that the element is the most current
one.)
+                            Iterator<PriorityQueueElement> it = outputPriorityQueue.iterator();
+                            while (it.hasNext()) {
+                                mutableElement = it.next();
+                                if (mutableElement.getCursorIndex() == 0) {
+                                    mutableElementFound = true;
+                                    it.remove();
+                                    break;
+                                }
                             }
-                            TupleUtils.copyTuple(tupleBuilder, mutableElement.getTuple(),
cmp.getKeyFieldCount());
-                            copyTuple.reset(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray());
+                            if (mutableElementFound) {
+                                // Copies the in-memory tuple.
+                                if (tupleBuilder == null) {
+                                    tupleBuilder = new ArrayTupleBuilder(cmp.getKeyFieldCount());
+                                }
+                                TupleUtils.copyTuple(tupleBuilder, mutableElement.getTuple(),
cmp.getKeyFieldCount());
+                                copyTuple.reset(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray());
 
-                            // unlatch/unpin
-                            rangeCursors[0].reset();
+                                // Unlatches/unpins the leaf page of the index.
+                                rangeCursors[0].reset();
 
-                            // reconcile
-                            if (checkElement.getCursorIndex() == 0) {
-                                searchCallback.reconcile(copyTuple);
-                            } else {
-                                searchCallback.reconcile(checkElement.getTuple());
-                                searchCallback.complete(checkElement.getTuple());
-                            }
-                            // retraverse
-                            reusablePred.setLowKey(copyTuple, true);
-                            btreeAccessors[0].search(rangeCursors[0], reusablePred);
-                            boolean isNotExhaustedCursor = pushIntoPriorityQueue(mutableElement);
+                                // Tries to reconcile.
+                                if (checkElement.getCursorIndex() == 0) {
+                                    searchCallback.reconcile(copyTuple);
+                                } else {
+                                    // If this element is from the disk component, we can
call complete()
+                                    // after reconcile() since we can guarantee that there
is no change.
+                                    searchCallback.reconcile(checkElement.getTuple());
+                                    searchCallback.complete(checkElement.getTuple());
+                                }
+                                // Re-traverses the index.
+                                reusablePred.setLowKey(copyTuple, true);
+                                btreeAccessors[0].search(rangeCursors[0], reusablePred);
+                                boolean isNotExhaustedCursor =
+                                        pushIntoQueueFromCursorAndReplaceThisElement(mutableElement);
 
-                            if (checkElement.getCursorIndex() == 0) {
-                                if (!isNotExhaustedCursor || cmp.compare(copyTuple, mutableElement.getTuple())
!= 0) {
+                                if (checkElement.getCursorIndex() == 0) {
+                                    if (!isNotExhaustedCursor
+                                            || cmp.compare(copyTuple, mutableElement.getTuple())
!= 0) {
+                                        // The searched key no longer exists. We call cancel()
to
+                                        // reverse the effect of reconcile() method.
+                                        searchCallback.cancel(copyTuple);
+                                        continue;
+                                    }
+                                    // The searched key is still there.
+                                    // TODO: do we need to call or not call complete() in
this case?
                                     searchCallback.complete(copyTuple);
-                                    searchCallback.cancel(copyTuple);
-                                    continue;
                                 }
-                                searchCallback.complete(copyTuple);
+                            } else {
+                                // The mutable cursor is exhausted and it couldn't find the
element.
+                                // The failed element did not come from the in-memory component.
+                                searchCallback.reconcile(checkElement.getTuple());
                             }
                         } else {
-                            // the mutable cursor is exhausted
+                            // proceed() failed. However, there is no in-memory component.
+                            // So just call reconcile.
                             searchCallback.reconcile(checkElement.getTuple());
                         }
-                    } else {
-                        searchCallback.reconcile(checkElement.getTuple());
                     }
                 }
-                // If there is no previous tuple or the previous tuple can be ignored
+
+                // If there is no previous tuple or the previous tuple can be ignored.
+                // This check is needed not to release the same tuple again.
                 if (outputElement == null) {
                     if (isDeleted(checkElement) && !returnDeletedTuples) {
                         // If the key has been deleted then pop it and set needPush to true.
                         // We cannot push immediately because the tuple may be
                         // modified if hasNext() is called
                         outputElement = outputPriorityQueue.poll();
-                        searchCallback.cancel(checkElement.getTuple());
-                        needPush = true;
-                        proceed = false;
+                        if (!resultOfSearchCallBackProceed) {
+                            searchCallback.cancel(checkElement.getTuple());
+                        }
+                        needPushElementIntoQueue = true;
+                        canCallProceed = false;
                     } else {
                         break;
                     }
@@ -154,24 +186,24 @@ public class LSMBTreeRangeSearchCursor extends LSMIndexSearchCursor
{
 
                         // the head element of PQ is useless now
                         PriorityQueueElement e = outputPriorityQueue.poll();
-                        pushIntoPriorityQueue(e);
+                        pushIntoQueueFromCursorAndReplaceThisElement(e);
                     } else {
                         // If the previous tuple and the head tuple are different
                         // the info of previous tuple is useless
-                        if (needPush == true) {
-                            pushIntoPriorityQueue(outputElement);
-                            needPush = false;
+                        if (needPushElementIntoQueue == true) {
+                            pushIntoQueueFromCursorAndReplaceThisElement(outputElement);
+                            needPushElementIntoQueue = false;
                         }
-                        proceed = true;
+                        canCallProceed = true;
                         outputElement = null;
                     }
                 }
             } else {
                 // the priority queue is empty and needPush
-                pushIntoPriorityQueue(outputElement);
-                needPush = false;
+                pushIntoQueueFromCursorAndReplaceThisElement(outputElement);
+                needPushElementIntoQueue = false;
                 outputElement = null;
-                proceed = true;
+                canCallProceed = true;
             }
         }
     }
@@ -224,6 +256,6 @@ public class LSMBTreeRangeSearchCursor extends LSMIndexSearchCursor {
         }
         setPriorityQueueComparator();
         initPriorityQueue();
-        proceed = true;
+        canCallProceed = true;
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d98c4c76/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/LSMIndexSearchCursor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/LSMIndexSearchCursor.java
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/LSMIndexSearchCursor.java
index 4c3a577..b8d21e4 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/LSMIndexSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/LSMIndexSearchCursor.java
@@ -44,7 +44,7 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor {
     protected PriorityQueue<PriorityQueueElement> outputPriorityQueue;
     protected PriorityQueueComparator pqCmp;
     protected MultiComparator cmp;
-    protected boolean needPush;
+    protected boolean needPushElementIntoQueue;
     protected boolean includeMutableComponent;
     protected ILSMHarness lsmHarness;
 
@@ -54,7 +54,7 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor {
         this.opCtx = opCtx;
         this.returnDeletedTuples = returnDeletedTuples;
         outputElement = null;
-        needPush = false;
+        needPushElementIntoQueue = false;
     }
 
     public ILSMIndexOperationContext getOpCtx() {
@@ -70,7 +70,7 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor {
                 pqes[i] = new PriorityQueueElement(i);
             }
             for (int i = 0; i < rangeCursors.length; i++) {
-                pushIntoPriorityQueue(pqes[i]);
+                pushIntoQueueFromCursorAndReplaceThisElement(pqes[i]);
             }
         } else {
             outputPriorityQueue.clear();
@@ -79,14 +79,14 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor
{
                 // size is the same -> re-use
                 for (int i = 0; i < rangeCursors.length; i++) {
                     pqes[i].reset(null);
-                    pushIntoPriorityQueue(pqes[i]);
+                    pushIntoQueueFromCursorAndReplaceThisElement(pqes[i]);
                 }
             } else {
                 // size changed (due to flushes, merges, etc) -> re-create
                 pqes = new PriorityQueueElement[pqInitSize];
                 for (int i = 0; i < rangeCursors.length; i++) {
                     pqes[i] = new PriorityQueueElement(i);
-                    pushIntoPriorityQueue(pqes[i]);
+                    pushIntoQueueFromCursorAndReplaceThisElement(pqes[i]);
                 }
             }
         }
@@ -99,7 +99,7 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor {
     @Override
     public void reset() throws HyracksDataException {
         outputElement = null;
-        needPush = false;
+        needPushElementIntoQueue = false;
 
         try {
             if (outputPriorityQueue != null) {
@@ -128,7 +128,7 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor
{
     @Override
     public void next() throws HyracksDataException {
         outputElement = outputPriorityQueue.poll();
-        needPush = true;
+        needPushElementIntoQueue = true;
     }
 
     @Override
@@ -169,7 +169,7 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor
{
         return outputElement.getTuple();
     }
 
-    protected boolean pushIntoPriorityQueue(PriorityQueueElement e) throws HyracksDataException
{
+    protected boolean pushIntoQueueFromCursorAndReplaceThisElement(PriorityQueueElement e)
throws HyracksDataException {
         int cursorIndex = e.getCursorIndex();
         if (rangeCursors[cursorIndex].hasNext()) {
             rangeCursors[cursorIndex].next();
@@ -186,7 +186,7 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor
{
     }
 
     protected void checkPriorityQueue() throws HyracksDataException {
-        while (!outputPriorityQueue.isEmpty() || (needPush == true)) {
+        while (!outputPriorityQueue.isEmpty() || (needPushElementIntoQueue == true)) {
             if (!outputPriorityQueue.isEmpty()) {
                 PriorityQueueElement checkElement = outputPriorityQueue.peek();
                 // If there is no previous tuple or the previous tuple can be ignored
@@ -196,7 +196,7 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor
{
                         // We cannot push immediately because the tuple may be
                         // modified if hasNext() is called
                         outputElement = outputPriorityQueue.poll();
-                        needPush = true;
+                        needPushElementIntoQueue = true;
                     } else {
                         break;
                     }
@@ -210,21 +210,21 @@ public abstract class LSMIndexSearchCursor implements ITreeIndexCursor
{
 
                         // the head element of PQ is useless now
                         PriorityQueueElement e = outputPriorityQueue.poll();
-                        pushIntoPriorityQueue(e);
+                        pushIntoQueueFromCursorAndReplaceThisElement(e);
                     } else {
                         // If the previous tuple and the head tuple are different
                         // the info of previous tuple is useless
-                        if (needPush == true) {
-                            pushIntoPriorityQueue(outputElement);
-                            needPush = false;
+                        if (needPushElementIntoQueue == true) {
+                            pushIntoQueueFromCursorAndReplaceThisElement(outputElement);
+                            needPushElementIntoQueue = false;
                         }
                         outputElement = null;
                     }
                 }
             } else {
                 // the priority queue is empty and needPush
-                pushIntoPriorityQueue(outputElement);
-                needPush = false;
+                pushIntoQueueFromCursorAndReplaceThisElement(outputElement);
+                needPushElementIntoQueue = false;
                 outputElement = null;
             }
         }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d98c4c76/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndexSearchCursor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndexSearchCursor.java
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndexSearchCursor.java
index 607f957..9352fbb 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndexSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-invertedindex/src/main/java/org/apache/hyracks/storage/am/lsm/invertedindex/impls/LSMInvertedIndexSearchCursor.java
@@ -58,6 +58,8 @@ public class LSMInvertedIndexSearchCursor implements IIndexCursor {
     private ILSMIndexOperationContext opCtx;
 
     private List<ILSMComponent> operationalComponents;
+    private ITupleReference currentTuple = null;
+    private boolean resultOfSearchCallBackProceed = false;
 
     @Override
     public void open(ICursorInitialState initialState, ISearchPredicate searchPred) throws
HyracksDataException {
@@ -111,9 +113,21 @@ public class LSMInvertedIndexSearchCursor implements IIndexCursor {
     private boolean nextValidTuple() throws HyracksDataException {
         while (currentCursor.hasNext()) {
             currentCursor.next();
-            if (!isDeleted(currentCursor.getTuple())) {
+            currentTuple = currentCursor.getTuple();
+            resultOfSearchCallBackProceed = searchCallback.proceed(currentTuple);
+
+            if (!resultOfSearchCallBackProceed) {
+                // We assume that the underlying cursors materialize their results such that
+                // there is no need to reposition the result cursor after reconciliation.
+                searchCallback.reconcile(currentTuple);
+            }
+
+            if (!isDeleted(currentTuple)) {
                 tupleConsumed = false;
                 return true;
+            } else if (!resultOfSearchCallBackProceed) {
+                // reconcile & tuple deleted case: needs to cancel the effect of reconcile().
+                searchCallback.cancel(currentTuple);
             }
         }
         return false;
@@ -150,11 +164,6 @@ public class LSMInvertedIndexSearchCursor implements IIndexCursor {
     public void next() throws HyracksDataException {
         // Mark the tuple as consumed, so hasNext() can move on.
         tupleConsumed = true;
-        // We assume that the underlying cursors materialize their results such that
-        // there is no need to reposition the result cursor after reconciliation.
-        if (!searchCallback.proceed(currentCursor.getTuple())) {
-            searchCallback.reconcile(currentCursor.getTuple());
-        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d98c4c76/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuplesSearchCursor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuplesSearchCursor.java
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuplesSearchCursor.java
index 98ab803..21c099b 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuplesSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-rtree/src/main/java/org/apache/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuplesSearchCursor.java
@@ -26,6 +26,7 @@ import org.apache.hyracks.storage.am.btree.impls.BTree;
 import org.apache.hyracks.storage.am.btree.impls.BTreeRangeSearchCursor;
 import org.apache.hyracks.storage.am.btree.impls.RangePredicate;
 import org.apache.hyracks.storage.am.common.api.ICursorInitialState;
+import org.apache.hyracks.storage.am.common.api.ISearchOperationCallback;
 import org.apache.hyracks.storage.am.common.api.ISearchPredicate;
 import org.apache.hyracks.storage.am.common.api.ITreeIndexAccessor;
 import org.apache.hyracks.storage.am.common.api.ITreeIndexCursor;
@@ -56,6 +57,7 @@ public class LSMRTreeWithAntiMatterTuplesSearchCursor extends LSMIndexSearchCurs
     private SearchPredicate rtreeSearchPredicate;
     private int numMutableComponents;
     private boolean open;
+    protected ISearchOperationCallback searchCallback;
 
     public LSMRTreeWithAntiMatterTuplesSearchCursor(ILSMIndexOperationContext opCtx) {
         this(opCtx, false);
@@ -75,6 +77,7 @@ public class LSMRTreeWithAntiMatterTuplesSearchCursor extends LSMIndexSearchCurs
         comparatorFields = lsmInitialState.getComparatorFields();
         operationalComponents = lsmInitialState.getOperationalComponents();
         rtreeSearchPredicate = (SearchPredicate) searchPred;
+        searchCallback = lsmInitialState.getSearchOperationCallback();
 
         includeMutableComponent = false;
         numMutableComponents = 0;
@@ -147,7 +150,13 @@ public class LSMRTreeWithAntiMatterTuplesSearchCursor extends LSMIndexSearchCurs
                 while (mutableRTreeCursors[currentCursor].hasNext()) {
                     mutableRTreeCursors[currentCursor].next();
                     ITupleReference currentTuple = mutableRTreeCursors[currentCursor].getTuple();
+                    // TODO: at this time, we only add proceed() part.
+                    // reconcile() and complete() can be added later after considering the
semantics.
+
+                    // Call proceed() to do necessary operations before returning this tuple.
+                    searchCallback.proceed(currentTuple);
                     if (searchMemBTrees(currentTuple, currentCursor)) {
+                        // anti-matter tuple is NOT found
                         foundNext = true;
                         frameTuple = currentTuple;
                         return true;
@@ -160,14 +169,33 @@ public class LSMRTreeWithAntiMatterTuplesSearchCursor extends LSMIndexSearchCurs
             while (super.hasNext()) {
                 super.next();
                 ITupleReference diskRTreeTuple = super.getTuple();
+                // TODO: at this time, we only add proceed().
+                // reconcile() and complete() can be added later after considering the semantics.
+
+                // Call proceed() to do necessary operations before returning this tuple.
+                searchCallback.proceed(diskRTreeTuple);
                 if (searchMemBTrees(diskRTreeTuple, numMutableComponents)) {
+                    // anti-matter tuple is NOT found
                     foundNext = true;
                     frameTuple = diskRTreeTuple;
                     return true;
                 }
             }
         } else {
-            return super.hasNext();
+            if (super.hasNext()) {
+                super.next();
+                ITupleReference diskRTreeTuple = super.getTuple();
+
+                // TODO: at this time, we only add proceed() part.
+                // reconcile() and complete() can be added later after considering the semantics.
+
+                // Call proceed() to do necessary operations before returning this tuple.
+                // Since in-memory components don't exist, we can skip searching in-memory
B-Trees.
+                searchCallback.proceed(diskRTreeTuple);
+                foundNext = true;
+                frameTuple = diskRTreeTuple;
+                return true;
+            }
         }
 
         return false;
@@ -175,22 +203,12 @@ public class LSMRTreeWithAntiMatterTuplesSearchCursor extends LSMIndexSearchCurs
 
     @Override
     public void next() throws HyracksDataException {
-        if (includeMutableComponent) {
-            foundNext = false;
-        } else {
-            super.next();
-        }
-
+        foundNext = false;
     }
 
     @Override
     public ITupleReference getTuple() {
-        if (includeMutableComponent) {
-            return frameTuple;
-        } else {
-            return super.getTuple();
-        }
-
+        return frameTuple;
     }
 
     @Override


Mime
View raw message