# include "pcontrol.h"

int StartJob (Job *job, Host *host) {

  int  i, Nline, status;
  char *line, *p;
  IOBuffer buffer;

  InitIOBuffer (&buffer, 0x100);

  /* job must have assigned host */
  ASSERT (job != NULL, "missing job");
  ASSERT (host != NULL, "missing host");
  ASSERT (host == (Host *) job[0].host, "invalid host");
  ASSERT (job  == (Job *) host[0].job, "invalid job");

  /* construct command line : job arg0 arg1 ... argN\n */
  Nline = 10 + job[0].argc;
  for (i = 0; i < job[0].argc; i++) {
    Nline += strlen (job[0].argv[i]);
  }
  ALLOCATE (line, char, Nline);
  bzero (line, Nline);
  strcpy (line, "job");
  for (i = 0; i < job[0].argc; i++) {
    strcat (line, " ");
    strcat (line, job[0].argv[i]);
  }

  status = PclientCommand (host, line, PCLIENT_PROMPT, &buffer);
  free (line);

  /* check on success of pclient command */
  switch (status) {
    case PCLIENT_DOWN:
      if (VerboseMode()) gprint (GP_ERR, "host %s is down\n", host[0].hostname);
      goto failure;

    case PCLIENT_HUNG:
      // we need the job start to return a valid Job ID, 
      // give up on jobs which don't get started.
      // XXX we are sensitive here to the time it takes pclient
      // to fork the job.  if this is slow, the client may appear to hang.
      gprint (GP_ERR, "host %s is not responding (StartJob)\n", host[0].hostname);
      if (VerboseMode()) gprint (GP_ERR, "host %s is not responding\n", host[0].hostname);

      // unlink host & job
      job[0].host = NULL;
      host[0].job = NULL;
      if (job[0].realhost) free (job[0].realhost);
      job[0].realhost = NULL;
      PutHost (host, PCONTROL_HOST_DONE, STACK_BOTTOM);
      PutJob (job, PCONTROL_JOB_PENDING, STACK_BOTTOM);
      FreeIOBuffer (&buffer);
      return (FALSE);

    case PCLIENT_GOOD:
      if (VerboseMode()) gprint (GP_ERR, "message received (StartJob)\n");  
      break;

    default:
      ABORT ("unknown status for pclient command");  
  }

  /* check on result of pclient command */
  p = memstr (buffer.buffer, "STATUS", buffer.Nbuffer);
  ASSERT (p != NULL, "missing STATUS in pclient message");

  sscanf (p, "%*s %d", &status);
  switch (status) {
    case -1:
      if (VerboseMode()) gprint (GP_ERR, "error in pclient child\n");
      goto failure;

    case -2:
      ABORT ("syntax error in pclient command");

    case -3:
      ABORT ("existing child on pclient");

    default:
      job[0].realhost = strcreate (host[0].hostname);
      job[0].pid = status;
      PutHost (host, PCONTROL_HOST_BUSY, STACK_BOTTOM);
      PutJob (job, PCONTROL_JOB_BUSY, STACK_BOTTOM);
      FreeIOBuffer (&buffer);
      gettimeofday (&job[0].start, (void *) NULL);
      return (TRUE);
  }
  /* we should never reach here */
  ABORT ("should not reach here (StartJob)");

failure:
  // unlink host & job
  job[0].host = NULL;
  host[0].job = NULL;
  HarvestHost (host[0].pid);
  PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
  PutJob (job, PCONTROL_JOB_PENDING, STACK_BOTTOM);
  FreeIOBuffer (&buffer);
  return (FALSE);
}
