public static FragmentWritableBatch getEmptyLastWithSchema(
      QueryId queryId,
      int sendMajorFragmentId,
      int sendMinorFragmentId,
      int receiveMajorFragmentId,
      int receiveMinorFragmentId,
      BatchSchema schema) {

    List<SerializedField> fields = Lists.newArrayList();
    for (MaterializedField field : schema) {
      fields.add(field.getAsBuilder().build());
    }
    RecordBatchDef def = RecordBatchDef.newBuilder().addAllField(fields).build();
    return new FragmentWritableBatch(
        true,
        queryId,
        sendMajorFragmentId,
        sendMinorFragmentId,
        receiveMajorFragmentId,
        receiveMinorFragmentId,
        def);
  }
public class FragmentWritableBatch {
  static final org.slf4j.Logger logger =
      org.slf4j.LoggerFactory.getLogger(FragmentWritableBatch.class);

  private static RecordBatchDef EMPTY_DEF = RecordBatchDef.newBuilder().setRecordCount(0).build();

  private final ByteBuf[] buffers;
  private final FragmentRecordBatch header;

  public FragmentWritableBatch(
      boolean isLast,
      QueryId queryId,
      int sendMajorFragmentId,
      int sendMinorFragmentId,
      int receiveMajorFragmentId,
      int receiveMinorFragmentId,
      WritableBatch batch) {
    this(
        isLast,
        queryId,
        sendMajorFragmentId,
        sendMinorFragmentId,
        receiveMajorFragmentId,
        receiveMinorFragmentId,
        batch.getDef(),
        batch.getBuffers());
  }

  private FragmentWritableBatch(
      boolean isLast,
      QueryId queryId,
      int sendMajorFragmentId,
      int sendMinorFragmentId,
      int receiveMajorFragmentId,
      int receiveMinorFragmentId,
      RecordBatchDef def,
      ByteBuf... buffers) {
    this.buffers = buffers;
    FragmentHandle handle =
        FragmentHandle //
            .newBuilder() //
            .setMajorFragmentId(receiveMajorFragmentId) //
            .setMinorFragmentId(receiveMinorFragmentId) //
            .setQueryId(queryId) //
            .build();
    this.header =
        FragmentRecordBatch //
            .newBuilder() //
            .setIsLastBatch(isLast) //
            .setDef(def) //
            .setHandle(handle) //
            .setSendingMajorFragmentId(sendMajorFragmentId) //
            .setSendingMinorFragmentId(sendMinorFragmentId) //
            .build();
  }

  public static FragmentWritableBatch getEmptyLast(
      QueryId queryId,
      int sendMajorFragmentId,
      int sendMinorFragmentId,
      int receiveMajorFragmentId,
      int receiveMinorFragmentId) {
    return new FragmentWritableBatch(
        true,
        queryId,
        sendMajorFragmentId,
        sendMinorFragmentId,
        receiveMajorFragmentId,
        receiveMinorFragmentId,
        EMPTY_DEF);
  }

  public static FragmentWritableBatch getEmptyLastWithSchema(
      QueryId queryId,
      int sendMajorFragmentId,
      int sendMinorFragmentId,
      int receiveMajorFragmentId,
      int receiveMinorFragmentId,
      BatchSchema schema) {

    List<SerializedField> fields = Lists.newArrayList();
    for (MaterializedField field : schema) {
      fields.add(field.getAsBuilder().build());
    }
    RecordBatchDef def = RecordBatchDef.newBuilder().addAllField(fields).build();
    return new FragmentWritableBatch(
        true,
        queryId,
        sendMajorFragmentId,
        sendMinorFragmentId,
        receiveMajorFragmentId,
        receiveMinorFragmentId,
        def);
  }

  public ByteBuf[] getBuffers() {
    return buffers;
  }

  public long getByteCount() {
    long n = 0;
    for (ByteBuf buf : buffers) {
      n += buf.readableBytes();
    }
    return n;
  }

  public FragmentRecordBatch getHeader() {
    return header;
  }
}