static char dqs_ck_to_do_list_rcsid[]="$Id: dqs_ck_to_do_list.c,v 1.1.1.1 1998/08/18 14:39:11 green Exp $";

/*----------------------------------------------------
 * dqs_ck_to_do_list.c Tom Green Mon Jan 31 10:42:40 1994
 *
 * Copyright 1993
 *
 * SUPER COMPUTER COMPUTATIONS RESEARCH INSTITUTE
 *            FLORIDA STATE UNIVERSITY
 *
 *
 * SCRI representatives make no claims about the
 * suitability of this software for any purpose.
 * It is provided "as is" without express or
 * implied warranty.
 *
 * $Log: dqs_ck_to_do_list.c,v $
 * Revision 1.1.1.1  1998/08/18 14:39:11  green
 * DQS 3.2.0.5 WIP Import
 *
 * Revision 1.1.1.1  1997/04/10 15:10:32  green
 * DQS 3.1.3.4.1 Distribution
 *
 * Revision 3.18  1996/11/20 23:03:28  nrl
 * Several fixes submitted by or as a result of investigations by
 * Ron Lee, Bodo Bechenback, Guntram Wolski and Frank Dwyyer.
 *
 * Revision 3.17  1996/03/22  04:20:14  nrl
 * Added error cataloguing number to all routines
 *
 * Revision 3.16  1996/02/07  13:07:50  nrl
 * Added "process leader" and TMP_FILES link capability
 *
 * Revision 3.15  1995/06/27  23:46:43  nrl
 * removed typo for SIGUSR1 (thanks to Ron lee )
 *
 * Revision 3.14  1995/06/16  15:35:24  nrl
 * eliminated the need to have a "qty.eq.1" in the default cases
 * fixed the "-notify" option when used with suspend queue function
 *
 * Revision 3.13  1995/05/26  19:07:32  nrl
 * Cleaned up signal handling and the notify option with the
 * help of Ron Lee.
 *
 * Revision 3.12  1995/05/04  18:58:42  nrl
 * Made notify option consistent with documentation, including
 * hard-wallclock overrun case
 *
 * Revision 3.11  1994/06/23  20:01:39  green
 * Solaris porting mods...
 *
 * Revision 3.10  1994/06/12  23:29:15  green
 * ignore
 *
 * Revision 3.9  1994/06/12  23:19:40  green
 * send a SIGQUIT rather than a SIGUSR1 to processes which go over their
 * soft wallclock
 *
 * Revision 3.8  1994/06/12  04:00:14  green
 * minor function relocation mods
 *
 * Revision 3.7  1994/06/12  03:57:44  green
 * added Kings's dqs_read_stats() and dqs_stats_type
 *
 * Revision 3.6  1994/06/08  17:48:03  green
 * added P4 support(with the help of Ralph Butler - Thanks Ralph!)
 *
 * backed down to Rev. 3.3 of dqs_check_to_do_list.c
 *
 * Revision 3.3  1994/03/26  12:24:09  green
 * bug in dqs_ck_to_do_list.c:dqs_ck_to_do_list() allowed garbage in
 * "lp2" to be forwarded to dqs_build_complex_str();
 *
 * dqs_job_exit.c:dqs_build_complex_str() modified - changed line 460
 * from strcat() to strcpy()
 *
 * added additional error logging to dqs_sec.c:dqs_qmaster() and
 * dqs_sec.c:dqs_trusted_host() to aid in tracking of bougus
 * configurations.
 *
 * Revision 3.2  1994/03/24  19:17:36  green
 * patched dqs_job_exit.c:dqs_build_qcomplex_str() - this routine still
 * needs more work...
 *
 * modified dqs_ck_to_do_list.c accordingly.
 *
 * Revision 3.1  1994/03/17  18:36:23  green
 * added support for "STAT_FILE"
 *
 * fixed memory leak in dqs_job_exit.c
 *
 * Revision 3.0  1994/03/07  04:13:34  green
 * 3.0 freeze
 *
 * Revision 1.1.1.1  1994/02/01  17:57:39  green
 * DQS 3.0 ALPHA
 *
 *--------------------------------------------------*/


#include "h.h"
#include "def.h"
#include "dqs.h"
#include "struct.h"
#include "func.h"
#include "globals.h"
#include "dqs_errno.h"

/******************************************************************************/
void dqs_ck_to_do_list()
     
     /*
       This module is used by the qmaster and dqs_execd.
       
       If the invoker is the qmaster, this function provides self reauthentication
       services - if so configured.
       
       If invoked by the dqs_execd, this routine also checks for jobs which
       have surpassed there wall clock time limits, and job reauthentication.
     */
     
{
  
  FILE            *fp;
  u_long32        now;
  char            *qcomplex_str;
  string          str;
  static u_long32 next_stat_log_time=0;
  struct stat statbuf;
  dqs_list_type   *lp;
  dqs_list_type   *lp2;
  
  DENTER((DQS_EVENT,"dqs_ck_to_do_list"));
  
  now=dqs_get_gmt();
  
  if (now>next_stat_log_time)
    {
      if (stat(STAT_FILE,&statbuf))
	{
	  close(creat(STAT_FILE,0755));
	}
      fp = fopen(STAT_FILE,"a");
      if (fp)
	{
	  lp=Queue_head;
	  while (lp)
	    {
	      bzero(str,sizeof(str));
	      fprintf(fp,"%d:%s:%s:%d:%d:%d:",now,
		      lp->queue->hostname,lp->queue->qname,
		      lp->queue->load_avg,lp->queue->qty,
		      lp->queue->qty_active);
	      dqs_get_states(str,lp->queue->state);
	      if (lp->queue->complex_list)
		lp2=dqs_locate_complex(lp->queue->complex_list->str0);
	      else
		lp2=NULL;
	      qcomplex_str=dqs_build_qcomplex_str(lp2);
	      if (qcomplex_str)
		fprintf(fp,"%s:%s\n",qcomplex_str,str);
	      else
		fprintf(fp,"%s:%s\n","NULL_qcomplex_str",str);
	      dqs_free(qcomplex_str);
	      lp=lp->next;
	    }
	  fclose(fp);
	}
      else
	{
	  ERROR((DQS_EVENT,"DQS_ERROR_0202 error: could not open \"%s\" for appending",
		 STAT_FILE));
	}
      next_stat_log_time=now+conf.stat_log_time;
    }
  
  if (me.who==DQS_EXECD)
    {
      dqs_reauth(options);  
      lp=Job_head;
      
      while (lp)
	{
	  DPRINTF((DQS_EVENT,"pending %d now= %d time=%d",lp->job->pending_signal,
		   now,lp->job->pending_signal_delivery_time));	       
	  
	  if (!lp->job->hard_wallclock_gmt)
	    { /* initialize everything */
	      if (lp->queue->s_rt != 0x7fffffff) { 
		lp->job->soft_wallclock_gmt=now+lp->queue->s_rt;
	      }
	      else{
		lp->job->soft_wallclock_gmt=lp->queue->s_rt;
	      }
	      if (lp->queue->h_rt != 0x7fffffff) {
		lp->job->hard_wallclock_gmt=now+lp->queue->h_rt;
	      }
	      else{
		lp->job->hard_wallclock_gmt=lp->queue->h_rt;
	      }
	      
	      if ((lp->job->passwd_list)||(lp->job->Passwd))
		{
		  if (!lp->job->reauth_time)
		    lp->job->reauth_gmt=now+conf.reauth_time;
		  else
		    lp->job->reauth_gmt=now+lp->job->reauth_time;
		}
	    }
	  dqs_reauth(lp->job);
	  if ((now>=lp->job->pending_signal_delivery_time)
	      &&(lp->job->pending_signal))
	    {
	      ERROR((DQS_EVENT,"DQS_ERROR_0203 ###PENDING SIGNAL delivering %d to %s",
		     lp->job->pending_signal,lp->job->dqs_job_name));
	      dqs_kill(-(int)lp->job->pid,lp->job->pending_signal);
	      lp->job->pending_signal_delivery_time=now+lp->queue->notify;
	      
	      lp->job->pending_signal=0;   /* don't keep hammering the poor fellow */
	      
	      lp=lp->next;
	      continue;
	    }
	  
	  if (now>=lp->job->hard_wallclock_gmt)
	    {
	      ERROR((DQS_EVENT,"DQS_ERROR_0204 ###now %d lp->job->hard_wallclock_gmt %d",now,
		     lp->job->hard_wallclock_gmt));
	      ERROR((DQS_EVENT,"DQS_ERROR_0205 ###%s exceeded hard_wallclock",lp->job->dqs_job_name));
	      ERROR((DQS_EVENT,"DQS_ERROR_0206 ###delivering %d to %s pid %d",
		     SIGKILL,lp->job->dqs_job_name,lp->job->pid));
	      dqs_execd_deliver_signal(DQS_SIGKILL,lp);
	      lp=lp->next;
	      continue;
	    }
	  if (now>=lp->job->soft_wallclock_gmt)
	    {
	      ERROR((DQS_EVENT,"DQS_ERROR_0207 ###%s exceeded soft_wallclock",lp->job->dqs_job_name));
	      dqs_kill(-(int)lp->job->pid,DQS_SIGUSR1);
	      
	    }
	  lp=lp->next;
	}
      
    }
  else if (me.who==QMASTER)
    {
      dqs_tid_garbage_collector();
      dqs_reauth(options);
    }
  
  DEXIT;
  return;
  
}

