@Override
  public void open(ICursorInitialState initialState, ISearchPredicate searchPred)
      throws HyracksDataException, IndexException {
    LSMBTreeCursorInitialState lsmInitialState = (LSMBTreeCursorInitialState) initialState;
    cmp = lsmInitialState.getOriginalKeyComparator();
    includeMemComponent = lsmInitialState.getIncludeMemComponent();
    operationalComponents = lsmInitialState.getOperationalComponents();
    lsmHarness = lsmInitialState.getLSMHarness();
    searchCallback = lsmInitialState.getSearchOperationCallback();
    memBTreeAccessor = lsmInitialState.getMemBTreeAccessor();
    predicate = (RangePredicate) lsmInitialState.getSearchPredicate();
    reusablePred.setLowKeyComparator(cmp);
    reusablePred.setHighKey(predicate.getHighKey(), predicate.isHighKeyInclusive());
    reusablePred.setHighKeyComparator(predicate.getHighKeyComparator());

    int numBTrees = lsmInitialState.getNumBTrees();
    rangeCursors = new IIndexCursor[numBTrees];
    for (int i = 0; i < numBTrees; i++) {
      IBTreeLeafFrame leafFrame =
          (IBTreeLeafFrame) lsmInitialState.getLeafFrameFactory().createFrame();
      rangeCursors[i] = new BTreeRangeSearchCursor(leafFrame, false);
    }
    setPriorityQueueComparator();

    int cursorIx = 0;
    ListIterator<ILSMComponent> btreesIter = operationalComponents.listIterator();
    if (includeMemComponent) {
      // Open cursor of in-memory BTree at index 0.
      memBTreeAccessor.search(rangeCursors[cursorIx], searchPred);
      // Skip 0 because it is the in-memory BTree.
      ++cursorIx;
      btreesIter.next();
    }

    // Open cursors of on-disk BTrees.
    int numDiskComponents = includeMemComponent ? numBTrees - 1 : numBTrees;
    ITreeIndexAccessor[] diskBTreeAccessors = new ITreeIndexAccessor[numDiskComponents];
    int diskBTreeIx = 0;
    while (btreesIter.hasNext()) {
      BTree diskBTree = (BTree) ((LSMBTreeImmutableComponent) btreesIter.next()).getBTree();
      diskBTreeAccessors[diskBTreeIx] =
          diskBTree.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
      diskBTreeAccessors[diskBTreeIx].search(rangeCursors[cursorIx], searchPred);
      cursorIx++;
      diskBTreeIx++;
    }
    initPriorityQueue();
    proceed = true;
  }
  @Override
  public void open(ICursorInitialState initialState, ISearchPredicate searchPred)
      throws HyracksDataException {
    LSMBTreeCursorInitialState lsmInitialState = (LSMBTreeCursorInitialState) initialState;
    operationalComponents = lsmInitialState.getOperationalComponents();
    lsmHarness = lsmInitialState.getLSMHarness();
    searchCallback = lsmInitialState.getSearchOperationCallback();
    predicate = (RangePredicate) lsmInitialState.getSearchPredicate();
    numBTrees = operationalComponents.size();
    if (rangeCursors == null || rangeCursors.length != numBTrees) {
      // object creation: should be relatively low
      rangeCursors = new BTreeRangeSearchCursor[numBTrees];
      btreeAccessors = new BTreeAccessor[numBTrees];
    }
    includeMutableComponent = false;

    for (int i = 0; i < numBTrees; i++) {
      ILSMComponent component = operationalComponents.get(i);
      BTree btree;
      if (component.getType() == LSMComponentType.MEMORY) {
        includeMutableComponent = true;
        // No need for a bloom filter for the in-memory BTree.
        if (rangeCursors[i] == null || rangeCursors[i].isBloomFilterAware()) {
          // create a new one
          IBTreeLeafFrame leafFrame =
              (IBTreeLeafFrame) lsmInitialState.getLeafFrameFactory().createFrame();
          rangeCursors[i] = new BTreeRangeSearchCursor(leafFrame, false);
        } else {
          // reset
          rangeCursors[i].reset();
        }
        btree = ((LSMBTreeMemoryComponent) component).getBTree();
      } else {
        if (rangeCursors[i] != null && rangeCursors[i].isBloomFilterAware()) {
          // can re-use cursor
          ((BloomFilterAwareBTreePointSearchCursor) rangeCursors[i])
              .resetBloomFilter(((LSMBTreeDiskComponent) component).getBloomFilter());
          rangeCursors[i].reset();
        } else {
          // create new cursor <should be relatively rare>
          IBTreeLeafFrame leafFrame =
              (IBTreeLeafFrame) lsmInitialState.getLeafFrameFactory().createFrame();
          rangeCursors[i] =
              new BloomFilterAwareBTreePointSearchCursor(
                  leafFrame, false, ((LSMBTreeDiskComponent) component).getBloomFilter());
        }
        btree = ((LSMBTreeDiskComponent) component).getBTree();
      }
      if (btreeAccessors[i] == null) {
        btreeAccessors[i] =
            (BTreeAccessor)
                btree.createAccessor(
                    NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
      } else {
        // re-use
        btreeAccessors[i].reset(
            btree, NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
      }
    }
    nextHasBeenCalled = false;
    foundTuple = false;
  }