@Override
 public CompactionPolicy getMetadataEntityFromTuple(ITupleReference tuple) throws IOException {
   byte[] serRecord = tuple.getFieldData(COMPACTION_POLICY_PAYLOAD_TUPLE_FIELD_INDEX);
   int recordStartOffset = tuple.getFieldStart(COMPACTION_POLICY_PAYLOAD_TUPLE_FIELD_INDEX);
   int recordLength = tuple.getFieldLength(COMPACTION_POLICY_PAYLOAD_TUPLE_FIELD_INDEX);
   ByteArrayInputStream stream =
       new ByteArrayInputStream(serRecord, recordStartOffset, recordLength);
   DataInput in = new DataInputStream(stream);
   ARecord compactionPolicyRecord = (ARecord) recordSerDes.deserialize(in);
   return createCompactionPolicyFromARecord(compactionPolicyRecord);
 }
  @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.");
    }
  }