# include "pcontrol.h"

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

  int i;
  Stack *stack;
  Job *job;

  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);
    OffHost (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; 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;

    /* 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; 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;

    /* 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; 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;

    /* 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 */
  /* XXX perhaps I should add this to the conditions for ANYHOST instead of
     running a separate loop?  ie, WANTHOST && time > X == ANYHOST */
  for (i = 0; i < stack[0].Nobject; i++) {
    job = (Job *) stack[0].object[i];
    if (job[0].mode != PCONTROL_JOB_WANTHOST) continue;
    // XXX test the job age and skip if too young

    /* 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 **/
