@Override
  public void open() throws HyracksDataException {
    /** open the function */
    functionProxy.functionOpen();
    accessor = new FrameTupleAccessor(treeIndexHelper.getTaskContext().getFrameSize(), recDesc);

    try {
      treeIndexHelper.open();
      btree = (BTree) treeIndexHelper.getIndexInstance();
      cursorFrame = btree.getLeafFrameFactory().createFrame();
      setCursor();

      // Construct range predicate.
      lowKeySearchCmp = BTreeUtils.getSearchMultiComparator(btree.getComparatorFactories(), lowKey);
      highKeySearchCmp =
          BTreeUtils.getSearchMultiComparator(btree.getComparatorFactories(), highKey);
      rangePred =
          new RangePredicate(
              null, null, lowKeyInclusive, highKeyInclusive, lowKeySearchCmp, highKeySearchCmp);

      writeBuffer = treeIndexHelper.getTaskContext().allocateFrame();
      tb = new ArrayTupleBuilder(btree.getFieldCount());
      dos = tb.getDataOutput();
      appender = new FrameTupleAppender(treeIndexHelper.getTaskContext().getFrameSize());
      appender.reset(writeBuffer, true);
      indexAccessor =
          btree.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);

      cloneUpdateTb = new ArrayTupleBuilder(btree.getFieldCount());
      updateBuffer.setFieldCount(btree.getFieldCount());
    } catch (Exception e) {
      treeIndexHelper.close();
      throw new HyracksDataException(e);
    }
  }
  @Override
  public void close() throws HyracksDataException {
    try {
      try {
        cursor.close();
        // batch update
        updateBuffer.updateBTree(indexAccessor);
      } catch (Exception e) {
        throw new HyracksDataException(e);
      }

      /** close the update function */
      functionProxy.functionClose();
    } finally {
      treeIndexHelper.close();
    }
  }
  @Override
  public void close() throws HyracksDataException {
    try {
      while (currentTopTuple != null) {
        moveTreeCursor();
      }

      if (appender.getTupleCount() > 0) {
        FrameUtils.flushFrame(writeBuffer, writer);
      }
      writer.close();
      try {
        cursor.close();
      } catch (Exception e) {
        throw new HyracksDataException(e);
      }
    } catch (Exception e) {
      throw new HyracksDataException(e);
    } finally {
      treeIndexOpHelper.close();
    }
  }
  @Override
  public void open() throws HyracksDataException {
    accessor = new FrameTupleAccessor(treeIndexOpHelper.getTaskContext().getFrameSize(), recDesc);

    try {
      treeIndexOpHelper.open();
      btree = (BTree) treeIndexOpHelper.getIndexInstance();
      cursorFrame = btree.getLeafFrameFactory().createFrame();
      setCursor();
      writer.open();

      rangePred = new RangePredicate(null, null, true, true, null, null);
      int lowKeySearchFields = btree.getComparatorFactories().length;
      IBinaryComparator[] lowKeySearchComparators = new IBinaryComparator[lowKeySearchFields];
      for (int i = 0; i < lowKeySearchFields; i++) {
        lowKeySearchComparators[i] = btree.getComparatorFactories()[i].createBinaryComparator();
      }
      lowKeySearchCmp = new MultiComparator(lowKeySearchComparators);

      writeBuffer = treeIndexOpHelper.getTaskContext().allocateFrame();
      tb = new ArrayTupleBuilder(btree.getFieldCount());
      dos = tb.getDataOutput();
      appender = new FrameTupleAppender(treeIndexOpHelper.getTaskContext().getFrameSize());
      appender.reset(writeBuffer, true);

      indexAccessor =
          btree.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);

      /** set the search cursor */
      rangePred.setLowKey(null, true);
      rangePred.setHighKey(null, true);
      cursor.reset();
      indexAccessor.search(cursor, rangePred);

      /** set up current top tuple */
      if (cursor.hasNext()) {
        cursor.next();
        currentTopTuple = cursor.getTuple();
        match = false;
      }

    } catch (Exception e) {
      treeIndexOpHelper.close();
      throw new HyracksDataException(e);
    }
  }