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

/*----------------------------------------------------
 * dqs_c_qsub.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_c_qsub.c,v $
 * Revision 1.1.1.1  1998/08/18 14:39:11  green
 * DQS 3.2.0.5 WIP Import
 *
 * Revision 1.3  1998/02/03 19:49:28  decker
 * Added note to log, concerning queue in alarm mode
 * Few minor changes for new revision 3.2 s
 *
 * Revision 1.2  1997/08/11 18:11:33  decker
 * Patch from John Rowe for Memory leak.
 *
 * Revision 1.1.1.1  1997/04/10 15:10:32  green
 * DQS 3.1.3.4.1 Distribution
 *
 * Revision 3.14  1996/11/19 21:03:08  nrl
 * added tid update to DEFAULT path also.
 *
 * Revision 3.13  1996/11/19 16:54:25  nrl
 * failed to setup reply head with tid for missing resources
 * error path.
 *
 * Revision 3.12  1996/07/19  12:04:04  nrl
 * Changes to fix "non existent resources"
 *
 * Revision 3.11  1996/07/10  11:20:10  nrl
 * fixed crash in resource pre-scan. Strcat sometimes was
 * invoked with a NULL pointer.
 *
 * Revision 3.10  1996/06/27  01:55:47  nrl
 * changes to accomodate osf gcc
 *
 * Revision 3.9  1996/03/22  04:20:12  nrl
 * Added error cataloguing number to all routines
 *
 * Revision 3.8  1996/03/21  17:06:40  nrl
 * added fortran and "c" syntax to resource requests
 *
 * Revision 3.7  1996/03/17  00:57:33  nrl
 * merge in qsub prevalidation scheme and consumable restoration
 *
 * Revision 3.6  1996/03/12  17:11:53  nrl
 * removed aborts and replaced with an error messaging scheme
 * to send email to the dqs adminsitrator and wait for
 * actions by that administrator
 *
 * Revision 3.4  1995/06/21  16:57:34  nrl
 * Major scheduling changes... added a subpriority field to manage
 * things within the user submitted priority. Added priority info to the
 * accounting file.
 *
 * Revision 3.3  1995/03/05  03:47:10  nrl
 * Included Axel Brandes job scheduling mechanism to keep one
 * user from hawging the queue.
 *
 * Revision 3.2  1995/01/30  15:21:48  nrl
 * added "tid" verification between execd and qmaster to prevent
 * "ghost" jobs from persisting in visible queue. Changed ERROR messages
 * which were for information only to DEBUG messages.
 *
 * Revision 3.1  1994/04/20  23:25:53  green
 * added qhold.c qrls.c
 *
 * Revision 3.0  1994/03/07  04:13:30  green
 * 3.0 freeze
 *
 * Revision 1.2  1994/02/10  18:24:12  green
 * removed the following options from "qsub"
 *
 * 	-k
 * 	-p
 * 	-u
 * 	-z
 *
 * fixed the following options in "qsub"
 *
 * 	-e
 * 	-o
 * 	-N
 * 	-v
 *
 * synced with docs
 *
 * Revision 1.1.1.1  1994/02/01  17:57:38  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_c_qsub(sfd,request_head)
     int           sfd;
     dqs_list_type **request_head;
     
     /*
       dqs_c_qsub - is used solely by the qmaster and provides services
       to the qsub ancillary.
     */
     
{
  
  char               *cp;
  u_long32           i;
  string             str;
  dqs_hash_type      *hashel_ptr;
  dqs_list_type      *listel_ptr;
  dqs_list_type      listel;
  dqs_list_type      *lp;
  dqs_list_type      *request_list;
  dqs_list_type      *missing_resources;
  dqs_list_type      *reply_head=NULL;
  dqs_queue_type     *queue_ptr;
  struct sockaddr_in cli_addr;
  
  DENTER((DQS_EVENT,"dqs_c_qsub"));
  
  request_list= *request_head;
  
  if ((reply_head=dqs_locate_tid(request_list->tid)))
    {  /* this transaction has already occurred */ 
      INFO((DQS_EVENT,"DQS_ERROR_0200 TRANSACTION ALREADY OCCURRED"));
      *request_head=dqs_free_list(*request_head);
      if ((sfd=dqs_send_list(NULL,NULL,sfd,reply_head))<0)
	{
	  DEXITE;
	  return;
	}
      dqs_close_sfd(sfd);
      DEXIT;
      return;
    }
  
  DPRINTF((DQS_EVENT,"------------------------------------------------------"));
  bzero((char *)&listel,sizeof(listel));
  
  switch(request_list->int0)
    {
    case QSUB:
      DPRINTF((DQS_EVENT,"===>QSUB:"));
      
      if(!request_list->job->force_submission){
	missing_resources= (dqs_list_type *)dqs_malloc(sizeof(dqs_list_type) );
	bzero((char *)missing_resources, sizeof(dqs_list_type) );
	if(!dqs_validate_resources(request_list->job, missing_resources) ){
	  listel.status=DQS_NAK;
	  lp= missing_resources;
	  sprintf(str,"Non existent resources: ");
	  while(lp){
	    if(lp->str0){
	      strcat(str, lp->str0);
	      strcat(str," ");
	    }
	    lp=lp->next;
	  }
          missing_resources= dqs_free_list(missing_resources);	      
	  DPRINTF((DQS_EVENT,"%s",str));
	  listel.str0=dqs_string_insert(NULL,str);
	  reply_head=dqs_insert(DQS_STR0,TAIL,reply_head,&listel);
	  /*Patch*/
	  request_list->tid=NULL;
	  reply_head->tid=request_list->tid;
	  missing_resources=dqs_free_list(missing_resources); 
	  break;
	}
      }
      request_list->job->job_number=dqs_get_job_number();
      
      request_list->job->scheduling_flags  =  NEWCOMER_FLAG;   /*  one-time flag*/
      
      request_list->job->submission_time=dqs_get_gmt();
      request_list->job->status=IDLE;
      request_list->job->state=(QUEUED|WAITING);
      if (request_list->job->hold)
	{
	  CLEARBIT(NO_HOLD,request_list->job->state);
	  request_list->job->state=(request_list->job->state|HELD);
	}
      sprintf(str,"%s/%d",JOB_DIR,request_list->job->job_number);
      request_list->job->job_file=dqs_string_insert(NULL,str);
      sprintf(str,"%s/%d",EXEC_DIR,request_list->job->job_number);
      request_list->job->exec_file=dqs_string_insert(NULL,str);
      
      sprintf(str,"%d",request_list->job->job_number);
      
      /*request_list->job->dqs_job_name=dqs_string_insert(NULL,str);*/
      /*Fix possible leak by jdg*/
      request_list->job->dqs_job_name=dqs_string_insert(request_list->job->dqs_job_name,str);
      /*End Patch*/
      DPRINTF((DQS_EVENT,"just subed \"%s\" \"%s\"",
	       request_list->job->dqs_job_name,request_list->job->job_name));
      
      
      bzero((char *)&listel,sizeof(listel));
      listel.status=DQS_ACK;
      sprintf(str,"your job %d has been submitted",request_list->job->job_number);
      listel.str0=dqs_string_insert(NULL,str);
      reply_head=dqs_insert(DQS_STR0,TAIL,reply_head,&listel);
      reply_head->tid=request_list->tid;
      request_list->tid=NULL;
      dqs_add_job(request_list->job);/* do eeror cking???*/
      request_list->job=NULL;
      jobs_to_start=TRUE;
      break;
      
      /*------------------------------------------------------*/
    default:
      INFO((DQS_EVENT,"DQS_ERROR_0201 CASE unknown list type %d",request_list->type));
      listel.status=DQS_NAK;
      sprintf(str,"error: unknown list type %d",request_list->type);
      DPRINTF((DQS_EVENT,"%s",str));
      listel.str0=dqs_string_insert(NULL,str);
      request_list->tid=NULL;
      reply_head=dqs_insert(DQS_STR0,TAIL,reply_head,&listel);
      reply_head->tid=request_list->tid;	  
      break;
    }
  
  *request_head=dqs_free_list(*request_head);
  dqs_save_tid(reply_head,QSUB);
  
  if ((sfd=dqs_send_list(NULL,NULL,sfd,reply_head))<0)
    {
      DEXITE;
      return;
    }
  
  dqs_close_sfd(sfd);
  
  DEXIT;
  return;
  
}
