public LSMBTreeTestWorker(
     DataGenThread dataGen, TestOperationSelector opSelector, IIndex index, int numBatches)
     throws HyracksDataException {
   super(dataGen, opSelector, index, numBatches);
   lsmBTree = (LSMBTree) index;
   numKeyFields = lsmBTree.getComparatorFactories().length;
   deleteTb = new ArrayTupleBuilder(numKeyFields);
 }
  @Override
  public void performOp(ITupleReference tuple, TestOperation op)
      throws HyracksDataException, IndexException {
    LSMBTreeAccessor accessor = (LSMBTreeAccessor) indexAccessor;
    IIndexCursor searchCursor = accessor.createSearchCursor(false);
    MultiComparator cmp = accessor.getMultiComparator();
    RangePredicate rangePred = new RangePredicate(tuple, tuple, true, true, cmp, cmp);

    switch (op) {
      case INSERT:
        try {
          accessor.insert(tuple);
        } catch (TreeIndexDuplicateKeyException e) {
          // Ignore duplicate keys, since we get random tuples.
        }
        break;

      case DELETE:
        // Create a tuple reference with only key fields.
        deleteTb.reset();
        for (int i = 0; i < numKeyFields; i++) {
          deleteTb.addField(tuple.getFieldData(i), tuple.getFieldStart(i), tuple.getFieldLength(i));
        }
        deleteTuple.reset(deleteTb.getFieldEndOffsets(), deleteTb.getByteArray());
        try {
          accessor.delete(deleteTuple);
        } catch (TreeIndexNonExistentKeyException e) {
          // Ignore non-existant keys, since we get random tuples.
        }
        break;

      case UPDATE:
        try {
          accessor.update(tuple);
        } catch (TreeIndexNonExistentKeyException e) {
          // Ignore non-existant keys, since we get random tuples.
        } catch (BTreeNotUpdateableException e) {
          // Ignore not updateable exception due to numKeys == numFields.
        }
        break;

      case POINT_SEARCH:
        searchCursor.reset();
        rangePred.setLowKey(tuple, true);
        rangePred.setHighKey(tuple, true);
        accessor.search(searchCursor, rangePred);
        consumeCursorTuples(searchCursor);
        break;

      case SCAN:
        searchCursor.reset();
        rangePred.setLowKey(null, true);
        rangePred.setHighKey(null, true);
        accessor.search(searchCursor, rangePred);
        consumeCursorTuples(searchCursor);
        break;

      case MERGE:
        accessor.scheduleMerge(NoOpIOOperationCallback.INSTANCE, lsmBTree.getImmutableComponents());
        break;

      default:
        throw new HyracksDataException("Op " + op.toString() + " not supported.");
    }
  }