# include "pcontrol.h"

static FILE *logfile = NULL;

/* the supplied host is not on a stack: it cannot be taken by the other thread */
int CheckIdleHost (Host *host, int Stage) {

  int i;
  Stack *stack;
  Job *job;
  struct timeval now;
  float dtime;

  if (logfile == NULL) { 
    logfile = fopen ("pcontrol.log", "w");
  }

  ASSERT (host, "host not set");

  /* if this host has been marked to be turned off, do that and return */
  if (host[0].markoff) {
    host[0].markoff = FALSE;
    StopHost (host);
    return (TRUE);
  }
    
  /* search the JOB_PENDING stack for an appropriate job */
  stack = GetJobStack (PCONTROL_JOB_PENDING);
  LockStack (stack);
  
  /* look for first NEEDHOST matching this host */
  for (i = 0; (Stage == PCONTROL_JOB_STAGE_NEEDHOST) && (i < stack[0].Nobject); i++) {
    job = (Job *) stack[0].object[i];
    if (job[0].mode != PCONTROL_JOB_NEEDHOST) continue;
    ASSERT (job[0].hostname != NULL, "NEEDHOST hostname missing");
    if (strcasecmp (job[0].hostname, host[0].hostname)) continue;

    /* we have found an appropriate job; link it to the host and send to StartJob */
    job[0].host = (struct Host *) host;
    host[0].job = (struct Job *) job;

    // if (logfile) fprintf (logfile, "start needhost %s (job host %s) : %s\n", host[0].hostname, job[0].hostname, job[0].argv[0]);

    /* take the job off the stack and unlock the stack */
    RemoveStackEntry (stack, i);
    UnlockStack (stack);
    StartJob (job, host);
    return (TRUE);
  }

  /* no NEEDHOST entry, look for first WANTHOST matching this host */
  for (i = 0; (Stage == PCONTROL_JOB_STAGE_WANTHOST) && (i < stack[0].Nobject); i++) {
    job = (Job *) stack[0].object[i];
    if (job[0].mode != PCONTROL_JOB_WANTHOST) continue;
    ASSERT (job[0].hostname != NULL, "WANTHOST hostname missing");
    if (strcasecmp (job[0].hostname, host[0].hostname)) continue;

    /* we have found an appropriate job; link it to the host and send to StartJob */
    job[0].host = (struct Host *) host;
    host[0].job = (struct Job *) job;

    // if (logfile) fprintf (logfile, "start wanthost %s (job host %s) : %s\n", host[0].hostname, job[0].hostname, job[0].argv[0]);

    /* take the job off the stack and unlock the stack */
    RemoveStackEntry (stack, i);
    UnlockStack (stack);
    StartJob (job, host);
    return (TRUE);
  }

  /* no WANTHOST entry, look for first ANYHOST matching this host */
  for (i = 0; (Stage == PCONTROL_JOB_STAGE_ANYHOST) && (i < stack[0].Nobject); i++) {
    job = (Job *) stack[0].object[i];
    if (job[0].mode != PCONTROL_JOB_ANYHOST) continue;

    /* we have found an appropriate job; link it to the host and send to StartJob */
    job[0].host = (struct Host *) host;
    host[0].job = (struct Job *) job;

    // if (logfile) fprintf (logfile, "start  anyhost %s (job host %s) : %s\n", host[0].hostname, job[0].hostname, job[0].argv[0]);

    /* take the job off the stack and unlock the stack */
    RemoveStackEntry (stack, i);
    UnlockStack (stack);
    StartJob (job, host);
    return (TRUE);
  }

  /* no ANYHOST entry, look for first WANTHOST with old time */
  for (i = 0; (Stage == PCONTROL_JOB_STAGE_OLDWANT) && (i < stack[0].Nobject); i++) {
    job = (Job *) stack[0].object[i];
    if (job[0].mode != PCONTROL_JOB_WANTHOST) continue;

    // allow WANT jobs to wait up to 10.0 sec for the host to be free before giving up
    gettimeofday (&now, (void *) NULL);
    dtime = DTIME (now, job[0].start);
    if (dtime < 10.0) continue;

    if (logfile) fprintf (logfile, "start wanthost(2) %s (job host %s) : %s\n", host[0].hostname, job[0].hostname, job[0].argv[0]);

    /* we have found an appropriate job; link it to the host and send to StartJob */
    job[0].host = (struct Host *) host;
    host[0].job = (struct Job *) job;

    /* take the job off the stack and unlock the stack */
    RemoveStackEntry (stack, i);
    UnlockStack (stack);
    StartJob (job, host);
    return (TRUE);
  }
  UnlockStack (stack);

  /* no jobs for host, put it back on IDLE stack */
  PutHost (host, PCONTROL_HOST_IDLE, STACK_BOTTOM);
  return (TRUE);
}

/** note : host and job popped off IDLE and PENDING stacks, 
    unless no job is available **/
