/**
   * Submit the work for actual execution.
   *
   * @throws InvalidProtocolBufferException
   */
  public void submitWork(SubmitWorkRequestProto request, String llapHost, int llapPort) {
    // Register the pending events to be sent for this spec.
    VertexOrBinary vob = request.getWorkSpec();
    assert vob.hasVertexBinary() != vob.hasVertex();
    SignableVertexSpec vertex = null;
    try {
      vertex =
          vob.hasVertex() ? vob.getVertex() : SignableVertexSpec.parseFrom(vob.getVertexBinary());
    } catch (InvalidProtocolBufferException e) {
      throw new RuntimeException(e);
    }
    QueryIdentifierProto queryIdentifierProto = vertex.getQueryIdentifier();
    TezTaskAttemptID attemptId =
        Converters.createTaskAttemptId(
            queryIdentifierProto,
            vertex.getVertexIndex(),
            request.getFragmentNumber(),
            request.getAttemptNumber());
    final String fragmentId = attemptId.toString();

    pendingEvents.putIfAbsent(
        fragmentId,
        new PendingEventData(
            new TaskHeartbeatInfo(fragmentId, llapHost, llapPort), Lists.<TezEvent>newArrayList()));

    // Setup timer task to check for hearbeat timeouts
    timer.scheduleAtFixedRate(
        new HeartbeatCheckTask(), connectionTimeout, connectionTimeout, TimeUnit.MILLISECONDS);

    // Send out the actual SubmitWorkRequest
    communicator.sendSubmitWork(
        request,
        llapHost,
        llapPort,
        new LlapProtocolClientProxy.ExecuteRequestCallback<SubmitWorkResponseProto>() {

          @Override
          public void setResponse(SubmitWorkResponseProto response) {
            if (response.hasSubmissionState()) {
              if (response.getSubmissionState().equals(SubmissionStateProto.REJECTED)) {
                String msg = "Fragment: " + fragmentId + " rejected. Server Busy.";
                LOG.info(msg);
                if (responder != null) {
                  Throwable err = new RuntimeException(msg);
                  responder.submissionFailed(fragmentId, err);
                }
                return;
              }
            }
          }

          @Override
          public void indicateError(Throwable t) {
            String msg = "Failed to submit: " + fragmentId;
            LOG.error(msg, t);
            Throwable err = new RuntimeException(msg, t);
            responder.submissionFailed(fragmentId, err);
          }
        });
  }