int sge_get_path(const char *qualified_hostname, lList *lp, const char *cwd, const char *owner, 
                 const char *job_name, u_long32 job_number, 
                 u_long32 ja_task_number, int type,
                 char *pathstr, size_t pathstr_len) 
{
   lListElem *ep = NULL;
   const char *path = NULL, *host = NULL;

   DENTER(TOP_LAYER, "sge_get_path");

   *pathstr = '\0';

   /*
    * check if there's a path for this host
    */
   ep = lGetElemHost(lp, PN_host, qualified_hostname);
   if (ep != NULL) {
      path = expand_path(lGetString(ep, PN_path), job_number, 
         ja_task_number, job_name, owner, qualified_hostname);
      host = lGetHost(ep, PN_host);
   } else {
      /* 
       * hostname: wasn't set, look for a default 
       */
      for_each(ep, lp) {
         path = expand_path(lGetString(ep, PN_path), job_number, 
                            ja_task_number, job_name, owner, 
                            qualified_hostname);
         host = lGetHost(ep, PN_host);
         if (host == NULL) {
            break;
         }
      }
   }
/****** sgeobj/href/href_list_find_references() *******************************
*  NAME
*     href_list_find_references() -- Find referenced hosts and groups 
*
*  SYNOPSIS
*     bool 
*     href_list_find_references(const lList *this_list, 
*                               lList **answer_list, 
*                               const lList *master_list, 
*                               lList **referenced_hosts, 
*                               lList **referenced_groups) 
*
*  FUNCTION
*     Finds hosts and hostgroups, which are directy referenced
*     in the hostgroups mentioned in 'this_list'. 'master_list' is
*     the list of all existing hostgroups. Directly referenced hosts
*     and hostgroups will be added to 'used_hosts' and 'used_groups'.
*     In case of any errors 'answer_list' will be filled.
*
*  INPUTS
*     const lList *this_list   - HR_Type 
*     lList **answer_list      - AN_Type 
*     const lList *master_list - HGRP_Type
*     lList **used_hosts       - HR_Type 
*     lList **used_groups      - HR_Type 
*
*  RESULT
*     bool - error state
*        true  - Success
*        false - Error
*******************************************************************************/
bool 
href_list_find_references(const lList *this_list, lList **answer_list,
                          const lList *master_list, lList **used_hosts,
                          lList **used_groups)
{
   bool ret = true;

   DENTER(HOSTREF_LAYER, "href_list_find_references");
   if (this_list != NULL && master_list != NULL) { 
      lListElem *href;  /* HR_Type */

      /*
       * Handle each reference which was given by the calling context
       */
      for_each(href, this_list) {
         const char *name = lGetHost(href, HR_name);
         bool is_group = is_hgroup_name(name);
         lListElem *hgroup = NULL;  /* HGRP_name */

         /*
          * Try to locate the concerned hgroup object
          * or add host
          */
         if (is_group) {
            hgroup = hgroup_list_locate(master_list, name);
         } else {
            if (used_hosts != NULL) {
               href_list_add(used_hosts, answer_list, name);
            }
         }

         if (hgroup != NULL) {
            lList *href_list2 = lGetList(hgroup, HGRP_host_list);
            lListElem *href2;    /* HR_Type */

            /* 
             * Add each element contained in the sublist of the hostgroup
             * we found previously to one of the result lists.
             */
            for_each(href2, href_list2) {
               const char *name2 = lGetHost(href2, HR_name);

               if (is_hgroup_name(name2)) {
                  if (used_groups != NULL) {
                     href_list_add(used_groups, answer_list, name2); 
                  }
               } else {
                  if (used_hosts != NULL) {
                     href_list_add(used_hosts, answer_list, name2); 
                  }
               }   
            }
         }
      } 
void
qinstance_add_event(lListElem *this_elem, ev_event type)
{
   DENTER(TOP_LAYER, "qinstance_add_event");
   sge_add_event(0, type, 0, 0,
                 lGetString(this_elem, QU_qname),
                 lGetHost(this_elem, QU_qhostname), NULL, this_elem);
   DRETURN_VOID;
}
Beispiel #4
0
/****** qmaster/setup_qmaster/sge_setup_job_resend() ***************************
*  NAME
*     sge_setup_job_resend() -- Setup job resend events.
*
*  SYNOPSIS
*     void sge_setup_job_resend(void)
*
*  FUNCTION
*     Register a job resend event for each job or array task which does have a
*     'JTRANSFERING' status.
*
*  INPUTS
*     void - none
*
*  RESULT
*     void - none
*
*  NOTES
*     MT-NOTE: sge_setup_job_resend() is not MT safe
*
*******************************************************************************/
void sge_setup_job_resend(void)
{
    lListElem *job = NULL;
    object_description *object_base = object_type_get_object_description();

    DENTER(TOP_LAYER, "sge_setup_job_resend");

    job = lFirst(*object_base[SGE_TYPE_JOB].list);

    while (NULL != job)
    {
        lListElem *task;
        u_long32 job_num;

        job_num = lGetUlong(job, JB_job_number);

        task = lFirst(lGetList(job, JB_ja_tasks));

        while (NULL != task)
        {
            if (lGetUlong(task, JAT_status) == JTRANSFERING)
            {
                lListElem *granted_queue, *qinstance, *host;
                const char *qname;
                u_long32 task_num, when;
                te_event_t ev;

                task_num = lGetUlong(task, JAT_task_number);

                granted_queue = lFirst(lGetList(task, JAT_granted_destin_identifier_list));

                qname = lGetString(granted_queue, JG_qname);

                qinstance = cqueue_list_locate_qinstance(*object_base[SGE_TYPE_CQUEUE].list, qname);

                host = host_list_locate(*object_base[SGE_TYPE_EXECHOST].list, lGetHost(qinstance, QU_qhostname));

                when = lGetUlong(task, JAT_start_time);

                when += MAX(load_report_interval(host), MAX_JOB_DELIVER_TIME);

                ev = te_new_event((time_t)when, TYPE_JOB_RESEND_EVENT, ONE_TIME_EVENT, job_num, task_num, "job-resend_event");
                te_add_event(ev);
                te_free_event(&ev);

                DPRINTF(("Did add job resend for "sge_u32"/"sge_u32" at %d\n", job_num, task_num, when));
            }

            task = lNext(task);
        }

        job = lNext(job);
    }

    DEXIT;
    return;
} /* sge_setup_job_resend() */
Beispiel #5
0
/**********************************************************************
 This is the function used by the scheduler to get a complete list of 
 complexes for a given queue.
 All templates are filled by actual values.
 With this list the scheduler can decide whether a request matches this
 queue.

 **********************************************************************/
int queue_complexes2scheduler(lList **new_centry_list, lListElem *queue, const lList *exechost_list,
                              const lList *centry_list)
{
   DENTER(BASIS_LAYER, "queue_complexes2scheduler");

   lFreeList(new_centry_list);
   *new_centry_list = get_attribute_list(host_list_locate(exechost_list, "global"), 
                                         queue ? host_list_locate(exechost_list, lGetHost(queue, QU_qhostname)) : NULL, 
                                         queue, centry_list);
   DRETURN(0);
}
Beispiel #6
0
/****** sgeobj/qinstance/qinstance_get_name() *********************************
*  NAME
*     qinstance_get_name() -- returns the fullname of a qinstance object 
*
*  SYNOPSIS
*     const char * 
*     qinstance_get_name(const lListElem *this_elem, 
*                        dstring *string_buffer) 
*
*  FUNCTION
*     Returns the fullname of a qinstance object 
*
*  INPUTS
*     const lListElem *this_elem - QU_Type 
*     dstring *string_buffer     - dynamic string buffer 
*
*  RESULT
*     const char * - pointer to the internal string buffer of "string_buffer"
*
*  NOTES
*     MT-NOTE: qinstance_get_name() is MT safe 
*******************************************************************************/
const char *
qinstance_get_name(const lListElem *this_elem, dstring *string_buffer)
{
   const char *ret = NULL;

   if (this_elem != NULL && string_buffer != NULL) {
      ret = sge_dstring_sprintf(string_buffer, SFN"@"SFN,
                                lGetString(this_elem, QU_qname),
                                lGetHost(this_elem, QU_qhostname));
   } 
   return ret;
}
static bool
cqueue_add_qinstances(sge_gdi_ctx_class_t *ctx, lListElem *cqueue, lList **answer_list, lList *add_hosts, monitoring_t *monitor)
{
   bool ret = true;

   DENTER(TOP_LAYER, "cqueue_add_qinstances");
   if (cqueue != NULL && add_hosts != NULL) {
      lListElem *href = NULL;

      for_each(href, add_hosts) {
         const char *hostname = lGetHost(href, HR_name);
         lList *list = lGetList(cqueue, CQ_qinstances);
         lListElem* qinstance = lGetElemHost(list, QU_qhostname, hostname);

         if (qinstance != NULL) {
            if (qinstance_state_is_orphaned(qinstance)) {
               sge_qmaster_qinstance_state_set_orphaned(qinstance, false);
               lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD);
            } else {
               /*
                * We might already have this QI if it is in orphaned state.
                * If this is not true, than there is a bug!
                */
               ERROR((SGE_EVENT, MSG_QINSTANCE_QIALREADYHERE_S, hostname));
               answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX,
                               ANSWER_QUALITY_ERROR);
            }
         } else {
            bool is_ambiguous = false;

            if (list == NULL) {
               list = lCreateList("", QU_Type);
               lSetList(cqueue, CQ_qinstances, list);
            }
            qinstance = qinstance_create(ctx,
                                         cqueue, answer_list,
                                         hostname, &is_ambiguous, monitor);
            if (is_ambiguous) {
               DPRINTF(("qinstance %s has ambiguous conf\n", hostname));
            }
            lSetUlong(qinstance, QU_tag, SGE_QI_TAG_ADD);
            lAppendElem(list, qinstance);
         }
      }
   }
Beispiel #8
0
/****** sgeobj/qinstance/qinstance_list_locate() ******************************
*  NAME
*     qinstance_list_locate() -- find a qinstance 
*
*  SYNOPSIS
*     lListElem * 
*     qinstance_list_locate(const lList *this_list, 
*                           const char *hostname, const char *cqueue_name) 
*
*  FUNCTION
*     Find a qinstance in "this_list" which is part of the cluster queue
*     with the name "cqueue_name" and resides on the host with the name 
*     "hostname".
*
*  INPUTS
*     const lList *this_list  - QU_Type list
*     const char *hostname    - hostname 
*     const char *cqueue_name - cluster queue name 
*
*  RESULT
*     lListElem * - QU_Type element
*
*  NOTES
*     MT-NOTE: qinstance_list_locate() is MT safe 
*******************************************************************************/
lListElem *
qinstance_list_locate(const lList *this_list, const char *hostname,
                      const char *cqueue_name) 
{
   lListElem *ret = NULL;

   if (cqueue_name == NULL) {
      ret = lGetElemHost(this_list, QU_qhostname, hostname);
   } else {
      for_each(ret, this_list) {
         const char *qname = lGetString(ret, QU_qname);
         const char *hname = lGetHost(ret, QU_qhostname);

         /* use qinstance expression */
         if (!sge_eval_expression(TYPE_CSTR, cqueue_name, qname, NULL)) { 
           if (!sge_eval_expression(TYPE_HOST, hostname, hname, NULL))  {
             break;
           }
         }
      }
   }
   return ret;
}
Beispiel #9
0
/****** sgeobj/host/host_is_referenced() **************************************
*  NAME
*     host_is_referenced() -- Is a given host referenced in other objects? 
*
*  SYNOPSIS
*     bool host_is_referenced(const lListElem *host, 
*                             lList **answer_list, 
*                             const lList *queue_list
*                             const lList *hgrp_list) 
*
*  FUNCTION
*     This function returns true if the given "host" is referenced
*     in a cqueue contained in "queue_list" or in a host group. 
*     If this is the case than a corresponding message will be added 
*     to the "answer_list". 
*
*  INPUTS
*     const lListElem *host   - EH_Type, AH_Type or SH_Type object 
*     lList **answer_list     - AN_Type list 
*     const lList *queue_list - CQ_Type list 
*     const lList *hgrp_list  - HGRP_Type list (Master list)
*
*  RESULT
*     int - true (1) or false (0) 
******************************************************************************/
bool host_is_referenced(const lListElem *host, 
                        lList **answer_list,
                        const lList *queue_list,
                        const lList *hgrp_list)
{
   bool ret = false;

   if (host != NULL) {
      lListElem *cqueue = NULL;
      lListElem *queue = NULL;
      const char *hostname = NULL;
      int nm = NoName;

      if (object_has_type(host, EH_Type)) {
         nm = object_get_primary_key(EH_Type);
      } else if (object_has_type(host, AH_Type)) {
         nm = object_get_primary_key(AH_Type);
      } else if (object_has_type(host, SH_Type)) {
         nm = object_get_primary_key(SH_Type);
      }
      hostname = lGetHost(host, nm);

      /* look at all the queue instances and figure out, if one still references
         the host we are looking for */
      for_each(cqueue, queue_list) { 
         queue = lGetSubHost(cqueue, QU_qhostname, hostname, CQ_qinstances); 

         if (queue != NULL) {
            const char *queuename = lGetString(cqueue, CQ_name);

            sprintf(SGE_EVENT, MSG_HOSTREFINQUEUE_SS, hostname, queuename);
            answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN,
                            ANSWER_QUALITY_ERROR);
            ret = true;
            break;
         }
      }
Beispiel #10
0
/****** sgeobj/href/href_list_compare() ***************************************
*  NAME
*     href_list_compare() -- Finds additional entries in list 
*
*  SYNOPSIS
*     bool 
*     href_list_compare(const lList *this_list, lList **answer_list, 
*                       const lList *list, lList **add_hosts, 
*                       lList **add_groups, lList **equity_hosts,
*                       lList **equity_groups) 
*
*  FUNCTION
*     This function will find differences between two hostref lists
*     given by 'this_list' and 'list'. Hosts and hostgroups which are
*     only in 'this_list' can be found in 'add_hosts' and 'add_groups'.
*     References which are contained in both lists can be found in 
*     'equity_hosts' and 'equity_groups' after a call to this function.
*
*     If the calling function is not interested in one ore more of the
*     result lists than NULL should be used as parameter. The calling
*     function is responsible to free all result lists. 
*
*     If the callee is also interested in the references which are
*     only part of 'list' than this function can not be used.
*     href_list_find_diff() should be used in this case. 
*
*  INPUTS
*     const lList *this_list - HR_Type list to comapre
*     lList **answer_list    - AN_Type list 
*     const lList *list      - 2nd HR_Type list to be compared
*     lList **add_hosts      - HR_Type list 
*     lList **add_groups     - HR_Type list 
*     lList **equity_hosts   - HR_Type list
*     lList **equity_groups  - HR_Type list
*
*  RESULT
*     bool - error state
*        true  - Success
*        false - Error
*
*  SEE ALSO
*     sgeobj/href/href_list_find_diff()
*******************************************************************************/
bool 
href_list_compare(const lList *this_list, lList **answer_list,
                  const lList *list, lList **add_hosts,
                  lList **add_groups, lList **equity_hosts, 
                  lList **equity_groups) 
{
   bool ret = true;
   lListElem *this_elem;   /* HR_Type */
  
   DENTER(HOSTREF_LAYER, "href_list_compare"); 

   for_each(this_elem, this_list) {
      const char *host_or_group = lGetHost(this_elem, HR_name);

      if (!href_list_has_member(list, host_or_group)) {
         if (is_hgroup_name(host_or_group)) {
            if (add_groups != NULL) {
               ret = href_list_add(add_groups, answer_list, host_or_group);
            }
         } else if (add_hosts != NULL) {
            ret = href_list_add(add_hosts, answer_list, host_or_group);
         }
      } else {
         if (is_hgroup_name(host_or_group)) {
            if (equity_groups != NULL) {
               ret = href_list_add(equity_groups, answer_list, host_or_group);
            }
         } else if (equity_hosts != NULL) {
            ret = href_list_add(equity_hosts, answer_list, host_or_group);
         }
      }
      if (!ret) {
         break;
      }
   }
   DRETURN(ret);
}
/*-------------------------------------------------------------------------*/
static void set_StringList(
Widget w,
XtPointer address,
XrmQuark type,
Cardinal size 
) {
   lList *lp = NULL;
   Widget parent;

   /*
    * Here special Qmon Quarks are used. Does it work ?
    */

   if (type != QmonQUS_Type && type != QmonQMR_Type && 
       type != QmonQPR_Type && type != QmonQSTR_Type && 
       type != QmonQSTU_Type && type != QmonQHR_Type) {
      XmtWarningMsg("XmtDialogSetDialogValues", "XbaeMatrix",
         "Type Mismatch: Widget '%s':\n\tCan't set widget values"
         " from a resource of type '%s'",
          XtName(w), XrmQuarkToString(type));

      return;
   }

   if (size == sizeof(lList*))
      lp = *(lList**) address;
   else
      return;


   /* if our parent is a layout widget disable/reenable it */
   parent = XtParent(w);
   while (parent && !XtIsSubclass(parent, xmtLayoutWidgetClass))
      parent = XtParent(parent);

   XmtLayoutDisableLayout(parent);
   if (type == QmonQUS_Type) {
      UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, US_name);
   }
   
   if (type == QmonQPR_Type) {
      UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, PR_name);
   }
   
   if (type == QmonQHR_Type) {
      UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, HR_name);
   }
   
   if (type == QmonQMR_Type) {
      String *str_table = NULL;
      Cardinal itemCount;
      StringConst str1, str2;
      int size, i;
      char buf[BUFSIZ];
      lListElem *ep = NULL;
      
      XtVaGetValues(w, XmNitemCount, &itemCount, NULL);

      if (!lp) {
         if (itemCount)
            XmListDeleteAllItems(w);
         return;
      }

      if ((size = lGetNumberOfElem(lp)) <=0) {
         return;
      }
      
      if (!(str_table = (String *)XtMalloc(sizeof(String)*size))) {
         return;
      }

      for (ep=lFirst(lp), i=0; ep; ep=lNext(ep), i++) {
         str1 = (StringConst)lGetString(ep, MR_user);
         str2 = (StringConst)lGetHost(ep, MR_host);
         if (str1) {
            if (!str2)
               sge_strlcpy(buf, str1, BUFSIZ);
            else
               snprintf(buf, BUFSIZ, "%s@%s", str1, str2);
            str_table[i] = XtNewString(buf);
         }
         else
            str_table[i] = NULL;
      }
      UpdateXmList(w, str_table, size, XmFONTLIST_DEFAULT_TAG);
      StringTableFree(str_table, size);
   }   
   
   if (type == QmonQSTR_Type) {
      UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, ST_name);
   }

   if (type == QmonQSTU_Type) {
      UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, STU_name);
   }
      
   XmtLayoutEnableLayout(parent);

}
/****** spool/utilities/spool_default_validate_func() ****************
*  NAME
*     spool_default_validate_func() -- validate objects
*
*  SYNOPSIS
*     bool
*     spool_default_validate_func(lList **answer_list, 
*                               const lListElem *type, 
*                               const lListElem *rule, 
*                               const lListElem *object, 
*                               const char *key, 
*                               const sge_object_type object_type) 
*
*  FUNCTION
*     Verifies an object.
*
*  INPUTS
*     lList **answer_list - to return error messages
*     const lListElem *type           - object type description
*     const lListElem *rule           - rule to use
*     const lListElem *object         - object to validate
*     const sge_object_type object_type - object type
*
*  RESULT
*     bool - true on success, else false
*
*  NOTES
*     This function should not be called directly, it is called by the
*     spooling framework.
*
*  SEE ALSO
*******************************************************************************/
bool spool_default_validate_func(lList **answer_list, 
                          const lListElem *type, 
                          const lListElem *rule,
                          lListElem *object,
                          const sge_object_type object_type)
{
   bool ret = true;

   DENTER(TOP_LAYER, "spool_default_validate_func");

   switch(object_type) {
      case SGE_TYPE_ADMINHOST:
      case SGE_TYPE_EXECHOST:
      case SGE_TYPE_SUBMITHOST:
         {
            int cl_ret;
            int key_nm = object_type_get_key_nm(object_type);
            char *old_name = strdup(lGetHost(object, key_nm));

            /* try hostname resolving */
            if (strcmp(old_name, SGE_GLOBAL_NAME) != 0) {
               cl_ret = sge_resolve_host(object, key_nm);

               /* if hostname resolving failed: create error */
               if (cl_ret != CL_RETVAL_OK) {
                  if (cl_ret != CL_RETVAL_GETHOSTNAME_ERROR) {
                     answer_list_add_sprintf(answer_list, STATUS_EUNKNOWN, 
                                             ANSWER_QUALITY_ERROR, 
                                             MSG_SPOOL_CANTRESOLVEHOSTNAME_SS, 
                                             old_name, cl_get_error_text(ret)); 
                     ret = false;
                  } else {
                     answer_list_add_sprintf(answer_list, STATUS_EUNKNOWN, 
                                             ANSWER_QUALITY_WARNING, 
                                             MSG_SPOOL_CANTRESOLVEHOSTNAME_SS, 
                                             old_name, cl_get_error_text(ret));
                  }
               } else {
                  /* if hostname resolving changed hostname: spool */
                  const char *new_name;
                  new_name = lGetHost(object, key_nm);
                  if (strcmp(old_name, new_name) != 0) {
                     spooling_write_func write_func = 
                             (spooling_write_func)lGetRef(rule, SPR_write_func);
                     spooling_delete_func delete_func = 
                             (spooling_delete_func)lGetRef(rule, SPR_delete_func);
                     write_func(answer_list, type, rule, object, new_name, 
                                object_type);
                     delete_func(answer_list, type, rule, old_name, object_type);
                  }
               }
            }

            sge_free(&old_name);

            if (object_type == SGE_TYPE_EXECHOST && ret) {
               lListElem *load_value;
               lList *master_centry_list = *object_type_get_master_list(SGE_TYPE_CENTRY);

               /* all spooled load values are static, therefore we tag them here */
               for_each(load_value, lGetList(object, EH_load_list)) {
                  lSetBool(load_value, HL_static, true);
               }

               /* necessary to init double values of consumable configuration */
               centry_list_fill_request(lGetList(object, EH_consumable_config_list), 
                     NULL, master_centry_list, true, false, true);
               /* necessary to setup actual list of exechost */
               debit_host_consumable(NULL, object, master_centry_list, 0, true, NULL);

               if (ensure_attrib_available(NULL, object, 
                                           EH_consumable_config_list)) {
                  ret = false;
               }
            }
         }
/****** sge_c_report() *******************************************************
*  NAME
*     sge_c_report() -- process execd load report
*
*  SYNOPSIS
*     void sge_c_report(char *rhost, char *commproc, int id, lList *report_list)
*
*  FUNCTION
*
*  INPUTS
*     char *rhost
*     char *commproc
*     int id
*     lList *report_list
*
*  RESULT
*     void - nothing
*
*  NOTES
*     MT-NOTE: sge_c_report() is MT safe
*
******************************************************************************/
void sge_c_report(sge_gdi_ctx_class_t *ctx, char *rhost, char *commproc, int id, lList *report_list, monitoring_t *monitor)
{
   lListElem *hep = NULL;
   u_long32 rep_type;
   lListElem *report;
   int ret = 0;
   u_long32 this_seqno, last_seqno;
   u_long32 rversion;
   sge_pack_buffer pb;   
   bool is_pb_used = false;
   bool send_tag_new_conf = false;

   DENTER(TOP_LAYER, "sge_c_report");

   if (lGetNumberOfElem(report_list) == 0) {
      DPRINTF(("received empty report\n"));
      if (rhost != NULL) {
         WARNING((SGE_EVENT, MSG_QMASTER_RECEIVED_EMPTY_LOAD_REPORT_S, rhost));
      } else {
         WARNING((SGE_EVENT, MSG_QMASTER_RECEIVED_EMPTY_LOAD_REPORT_S, "unknown"));
      }
      DRETURN_VOID;
   }

   /* accept reports only from execd's */
   if (strcmp(prognames[EXECD], commproc)) {
      ERROR((SGE_EVENT, MSG_GOTSTATUSREPORTOFUNKNOWNCOMMPROC_S, commproc));
      DRETURN_VOID;
   }

   /* do not process load reports from old execution daemons */
   rversion = lGetUlong(lFirst(report_list), REP_version);
   if (verify_request_version(NULL, rversion, rhost, commproc, id)) {
      DRETURN_VOID;
   }
   
   this_seqno = lGetUlong(lFirst(report_list), REP_seqno);

   /* need exec host for all types of reports */
   if (!(hep = host_list_locate(*object_type_get_master_list(SGE_TYPE_EXECHOST), rhost))) {
      ERROR((SGE_EVENT, MSG_GOTSTATUSREPORTOFUNKNOWNEXECHOST_S, rhost));
      DRETURN_VOID;
   }

   /* prevent old reports being proceeded 
      frequent loggings of outdated reports can be an indication 
      of too high message traffic arriving at qmaster */ 
   last_seqno = lGetUlong(hep, EH_report_seqno);

   if ((this_seqno < last_seqno && (last_seqno - this_seqno) <= 9000) &&
      !(last_seqno > 9990 && this_seqno < 10)) {
      /* this must be an old report, log and then ignore it */
      INFO((SGE_EVENT, MSG_QMASTER_RECEIVED_OLD_LOAD_REPORT_UUS, 
               sge_u32c(this_seqno), sge_u32c(last_seqno), rhost));
      DRETURN_VOID;
   }
   
   lSetUlong(hep, EH_report_seqno, this_seqno);

   /* RU: */
   /* tag all reschedule_unknown list entries we hope to 
      hear about in that job report */
   update_reschedule_unknown_list(ctx, hep);

   /*
   ** process the reports one after the other
   ** usually there will be a load report
   ** and a configuration version report
   */
   for_each(report, report_list) {
      rep_type = lGetUlong(report, REP_type);

      switch (rep_type) {
      case NUM_REP_REPORT_LOAD:
      case NUM_REP_FULL_REPORT_LOAD:
         MONITOR_ELOAD(monitor); 
         /* Now handle execds load reports */
         if (lGetUlong(hep, EH_lt_heard_from) == 0 && rep_type != NUM_REP_FULL_REPORT_LOAD) {
            host_notify_about_full_load_report(ctx, hep);
         } else {
            if (!is_pb_used) {
               is_pb_used = true;
               init_packbuffer(&pb, 1024, 0);
            }
            sge_update_load_values(ctx, rhost, lGetList(report, REP_list));

            if (mconf_get_simulate_execds()) {
               lList *master_exechost_list = *object_type_get_master_list(SGE_TYPE_EXECHOST);
               lListElem *shep;
               lListElem *simhostElem=NULL; 

               for_each(shep, master_exechost_list) {
                  simhostElem = lGetSubStr(shep, CE_name, "load_report_host", EH_consumable_config_list);
                  if (simhostElem != NULL) {
                     const char *real_host = lGetString(simhostElem, CE_stringval);
                     if (real_host != NULL && sge_hostcmp(real_host, rhost) == 0) {
                        const char* sim_host = lGetHost(shep, EH_name);
                        lListElem *clp = NULL;

                        DPRINTF(("Copy load values of %s to simulated host %s\n",
                                rhost, sim_host));

                        for_each(clp, lGetList(report, REP_list)) {
                           if (strcmp(lGetHost(clp, LR_host), SGE_GLOBAL_NAME) != 0) {
                              lSetHost(clp, LR_host, sim_host);
                           }
                        }
                        sge_update_load_values(ctx, sim_host, lGetList(report, REP_list));
                     }
                  }
               }
            }

            pack_ack(&pb, ACK_LOAD_REPORT, this_seqno, 0, NULL);
         }
         break;
      case NUM_REP_REPORT_CONF: 
         MONITOR_ECONF(monitor); 
         if (sge_compare_configuration(hep, lGetList(report, REP_list)) != 0) {
            DPRINTF(("%s: configuration on host %s is not up to date\n", SGE_FUNC, rhost));
            send_tag_new_conf = true;
         }
         break;
         
      case NUM_REP_REPORT_PROCESSORS:
         /*
         ** save number of processors
         */
         MONITOR_EPROC(monitor);
         ret = update_license_data(ctx, hep, lGetList(report, REP_list)); 
         if (ret) {
            ERROR((SGE_EVENT, MSG_LICENCE_ERRORXUPDATINGLICENSEDATA_I, ret));
         }
         break;

      case NUM_REP_REPORT_JOB:
         MONITOR_EJOB(monitor);
         if (!is_pb_used) {
            is_pb_used = true;
            init_packbuffer(&pb, 1024, 0);
         }
         process_job_report(ctx, report, hep, rhost, commproc, &pb, monitor);
         break;

      default:   
         DPRINTF(("received invalid report type %ld\n", (long) rep_type));
      }
/****** qmaster/sge_mod_configuration() ****************************************
*  NAME
*     sge_mod_configuration() -- modify cluster configuration
*
*  SYNOPSIS
*     int sge_mod_configuration(lListElem *aConf, lList **anAnswer, char *aUser,
*                               char *aHost)
*
*  FUNCTION
*     Modify cluster configuration. 'confp' is a pointer to a 'CONF_Type' list
*     element and does contain the modified configuration entry. Adding a new
*     configuration entry is also viewed as a modification.
*
*  INPUTS
*     lListElem *aConf  - CONF_Type element containing the modified conf
*     lList **anAnswer  - answer list
*     char *aUser       - target user
*     char *aHost       - target host
*
*  RESULT
*     int - 0 success
*          -1 error
*
*  NOTES
*     MT-NOTE: sge_mod_configuration() is MT safe 
*
*******************************************************************************/
int sge_mod_configuration(sge_gdi_ctx_class_t *ctx, lListElem *aConf, lList **anAnswer, char *aUser, char *aHost)
{
   lListElem *old_conf;
   const char *tmp_name = NULL;
   char unique_name[CL_MAXHOSTLEN];
   int ret = -1;
   const char *cell_root = ctx->get_cell_root(ctx);
   const char *qualified_hostname = ctx->get_qualified_hostname(ctx);
   u_long32 progid = ctx->get_who(ctx);

   DENTER(TOP_LAYER, "sge_mod_configuration");

   if (!aConf || !aUser || !aHost) {
      CRITICAL((SGE_EVENT, MSG_SGETEXT_NULLPTRPASSED_S, SGE_FUNC));
      answer_list_add(anAnswer, SGE_EVENT, STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR);
      DRETURN(STATUS_EUNKNOWN);
   }

   if ((tmp_name = lGetHost(aConf, CONF_name)) == NULL) {
      CRITICAL((SGE_EVENT, MSG_SGETEXT_MISSINGCULLFIELD_SS, lNm2Str(CONF_name), SGE_FUNC));
      answer_list_add(anAnswer, SGE_EVENT, STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR);
      DRETURN(STATUS_EUNKNOWN);
   }

   if ((ret = sge_resolve_hostname(tmp_name, unique_name, EH_name, sizeof(unique_name)))
       != CL_RETVAL_OK) {
      DPRINTF(("%s: error %s resolving host %s\n", SGE_FUNC, cl_get_error_text(ret), tmp_name));
      ERROR((SGE_EVENT, MSG_SGETEXT_CANTRESOLVEHOST_S, tmp_name));
      answer_list_add(anAnswer, SGE_EVENT, STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR);
      DRETURN(STATUS_EUNKNOWN);
   }
   
   if ((ret = check_config(anAnswer, aConf))) {
      DRETURN(ret); 
   }

   if ((old_conf = sge_get_configuration_for_host(unique_name)) != NULL) {
      int ret = -1;
      
      ret = do_mod_config(ctx, unique_name, old_conf, aConf, anAnswer);
      
      lFreeElem(&old_conf);
      
      if (ret == 0) {    
         INFO((SGE_EVENT, MSG_SGETEXT_MODIFIEDINLIST_SSSS, aUser, aHost, unique_name, MSG_OBJ_CONF));
         answer_list_add(anAnswer, SGE_EVENT, STATUS_OK, ANSWER_QUALITY_INFO);
      } else {
         DRETURN(STATUS_EUNKNOWN);
      }
   } else {
      do_add_config(ctx, unique_name, aConf, anAnswer);
            
      INFO((SGE_EVENT, MSG_SGETEXT_ADDEDTOLIST_SSSS, aUser, aHost, unique_name, MSG_OBJ_CONF));            
      answer_list_add(anAnswer, SGE_EVENT, STATUS_OK, ANSWER_QUALITY_INFO);
   }
   
   if (strcmp(SGE_GLOBAL_NAME, unique_name) == 0) {
      sge_add_event(0, sgeE_GLOBAL_CONFIG, 0, 0, NULL, NULL, NULL, NULL);
   }

   /*
   ** is the configuration change relevant for the qmaster itsself?
   ** if so, initialise conf struct anew
   */
   if (strcmp(unique_name, SGE_GLOBAL_NAME) == 0 || sge_hostcmp(unique_name, qualified_hostname) == 0) {
      lListElem *local = NULL;
      lListElem *global = NULL;
      lList *answer_list = NULL;
      char* qmaster_params = NULL;
      int accounting_flush_time = mconf_get_accounting_flush_time();

      if ((local = sge_get_configuration_for_host(qualified_hostname)) == NULL) {
         WARNING((SGE_EVENT, MSG_CONF_NOLOCAL_S, qualified_hostname));
      }
      
      if ((global = sge_get_configuration_for_host(SGE_GLOBAL_NAME)) == NULL) {
         ERROR((SGE_EVENT, SFNMAX, MSG_CONF_NOGLOBAL));
      }
            
      if (merge_configuration(&answer_list, progid, cell_root, global, local, NULL) != 0) {
         ERROR((SGE_EVENT, MSG_CONF_CANTMERGECONFIGURATIONFORHOST_S, qualified_hostname));
      }
      answer_list_output(&answer_list);

      /* Restart the accounting flush event if needed. */
      if ((accounting_flush_time == 0) &&
          (mconf_get_accounting_flush_time() != 0)) {
         te_event_t ev = te_new_event(time(NULL), TYPE_ACCOUNTING_TRIGGER, ONE_TIME_EVENT, 1, 0, NULL);
         te_add_event(ev);
         te_free_event(&ev);
      }
      
      lFreeElem(&local);
      lFreeElem(&global);
      
      sge_show_conf();

      /* 'max_unheard' may have changed */
      cl_commlib_set_connection_param(cl_com_get_handle("qmaster", 1), HEARD_FROM_TIMEOUT, mconf_get_max_unheard());

      /* fetching qmaster_params and begin to parse */
      qmaster_params = mconf_get_qmaster_params();

      /* updating the commlib paramterlist and gdi_timeout with new or changed parameters */
      cl_com_update_parameter_list(qmaster_params);

      sge_free(&qmaster_params);
   }
    
   /* invalidate configuration cache */
   mconf_set_new_config(true);
   
   DRETURN(STATUS_OK);
}
static int check_config(lList **alpp, lListElem *conf)
{
   lListElem *ep;
   const char *name, *value;
   const char *conf_name;
 
   DENTER(TOP_LAYER, "check_config");
 
   conf_name = lGetHost(conf, CONF_name);
 
   for_each(ep, lGetList(conf, CONF_entries)) {
      name = lGetString(ep, CF_name);
      value = lGetString(ep, CF_value);
 
      if (name == NULL) {
         ERROR((SGE_EVENT, MSG_CONF_NAMEISNULLINCONFIGURATIONLISTOFX_S,
               conf_name));
         answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
         DRETURN(STATUS_EEXIST);
      }
      if (value == NULL) {
         ERROR((SGE_EVENT, MSG_CONF_VALUEISNULLFORATTRXINCONFIGURATIONLISTOFY_SS,
                name, conf_name));
         answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
         DRETURN(STATUS_EEXIST);
      }

      if (!strcmp(name, "loglevel")) {
         u_long32 tmp_uval;
         if (sge_parse_loglevel_val(&tmp_uval, value) != 1) {
            ERROR((SGE_EVENT, MSG_CONF_GOTINVALIDVALUEXFORLOGLEVEL_S, value));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            DRETURN(STATUS_EEXIST);
         }
      } else if (strcmp(name, "jsv_url") == 0) {
         if (strcasecmp("none", value) != 0) {
            dstring input = DSTRING_INIT;
            dstring type = DSTRING_INIT;
            dstring user = DSTRING_INIT;
            dstring path = DSTRING_INIT;
            bool lret = true;

            sge_dstring_append(&input, value);
            lret = jsv_url_parse(&input, alpp, &type, &user, &path, false); 
            sge_dstring_free(&input);
            sge_dstring_free(&type);
            sge_dstring_free(&user);
            sge_dstring_free(&path);
            if (!lret) {
               /* answer is written by jsv_url_parse */
               DRETURN(STATUS_EEXIST);
            }
         } 
      } else if (!strcmp(name, "shell_start_mode")) {
         if ((strcasecmp("unix_behavior", value) != 0) && 
             (strcasecmp("posix_compliant", value) != 0) &&
             (strcasecmp("script_from_stdin", value) != 0) ) {
            ERROR((SGE_EVENT, MSG_CONF_GOTINVALIDVALUEXFORSHELLSTARTMODE_S, value));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            DRETURN(STATUS_EEXIST);
         }
      } else if (!strcmp(name, "shell")) {
         if (!path_verify(name, alpp, "shell", true)) {
            ERROR((SGE_EVENT, MSG_CONF_GOTINVALIDVALUEXFORSHELL_S, value));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            DRETURN(STATUS_EEXIST);
         }
      } else if (!strcmp(name, "load_report_time")) {
         /* do not allow infinity entry for load_report_time */
         if (strcasecmp(value, "infinity") == 0) {
            ERROR((SGE_EVENT, MSG_CONF_INFNOTALLOWEDFORATTRXINCONFLISTOFY_SS, name, conf_name));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            DRETURN(STATUS_EEXIST);
         }
      } else if (!strcmp(name, "max_unheard")) {
         /* do not allow infinity entry */
         if (strcasecmp(value,"infinity") == 0) {
            ERROR((SGE_EVENT, MSG_CONF_INFNOTALLOWEDFORATTRXINCONFLISTOFY_SS, name, conf_name));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            DRETURN(STATUS_EEXIST);
         }
      } else if (!strcmp(name, "admin_user")) {
         struct passwd pw_struct;
         char *buffer;
         int size;

         size = get_pw_buffer_size();
         buffer = sge_malloc(size);
         if (strcasecmp(value, "none") && !sge_getpwnam_r(value, &pw_struct, buffer, size)) {
            ERROR((SGE_EVENT, MSG_CONF_GOTINVALIDVALUEXASADMINUSER_S, value));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            sge_free(&buffer);
            DRETURN(STATUS_EEXIST);
         }
         sge_free(&buffer);
      } else if (!strcmp(name, "user_lists")||!strcmp(name, "xuser_lists")) {
         lList *tmp = NULL;
         int ok;

         /* parse just for .. */ 
         if (lString2ListNone(value, &tmp, US_Type, US_name, " \t,")) {
            ERROR((SGE_EVENT, MSG_CONF_FORMATERRORFORXINYCONFIG_SS, name, conf_name));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            DRETURN(STATUS_EEXIST);
         }

         /* .. checking userset names */
         ok = (userset_list_validate_acl_list(tmp, alpp) == STATUS_OK);
         lFreeList(&tmp);
         if (!ok) {
            DRETURN(STATUS_EEXIST);
         }
      } else if (!strcmp(name, "projects") || !strcmp(name, "xprojects")) {
         lList *tmp = NULL;
         int ok=1;

         /* parse just for .. */ 
         if (lString2ListNone(value, &tmp, PR_Type, PR_name, " \t,")) {
            ERROR((SGE_EVENT, MSG_CONF_FORMATERRORFORXINYCONFIG_SS, name, conf_name));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            DRETURN(STATUS_EEXIST);
         }

         /* .. checking project names */
         ok = (verify_project_list(alpp, tmp, *object_type_get_master_list(SGE_TYPE_PROJECT),
                    name, "configuration", conf_name)==STATUS_OK);
         lFreeList(&tmp);
         if (!ok) {
            DRETURN(STATUS_EEXIST);
         }
      } else if (!strcmp(name, "prolog") || !strcmp(name, "epilog")
                 || !strcmp(name, "mailer")) {
         if (strcasecmp(value, "none")) {
            const char *t, *script = value;

            /* skip user name */
            if ((t = strpbrk(script, "@ ")) && *t == '@')
               script = &t[1];

            /* force use of absolute paths if string <> none */
            if (script[0] != '/' ) {
               ERROR((SGE_EVENT, MSG_CONF_THEPATHGIVENFORXMUSTSTARTWITHANY_S, name));
               answer_list_add(alpp, SGE_EVENT, STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR);
               DRETURN(STATUS_EEXIST);
            }
   
            /* ensure that variables are valid */
            if (replace_params(script, NULL, 0, prolog_epilog_variables)) {
               ERROR((SGE_EVENT, MSG_CONF_PARAMETERXINCONFIGURATION_SS, name, err_msg));
               answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
               DRETURN(STATUS_EEXIST);
            }
         }
      } else if (!strcmp(name, "auto_user_oticket") || !strcmp(name, "auto_user_fshare")) {
         u_long32 uval = 0;
         if (!extended_parse_ulong_val(NULL, &uval, TYPE_INT, value, NULL, 0, 0, true)) {
            ERROR((SGE_EVENT, MSG_CONF_FORMATERRORFORXINYCONFIG_SS, name, value ? value : "(NULL)"));
            answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
            DRETURN(STATUS_EEXIST);
         }
      }

      /* 
       * check paths, see also CR 6506580.
       * The following must be none or a valid absolute path:
       * - load_sensor
       * - set_token_cmd
       * - pag_cmd
       * - shepherd_cmd
       *
       * The following must be a valid absolute path:
       * - mailer
       * - xterm
       * - *_daemon, may also be "builtin"
       */
      else if (strcmp(name, "set_token_cmd") == 0 ||
          strcmp(name, "pag_cmd") == 0 ||
          strcmp(name, "shepherd_cmd") == 0) {
         if (strcasecmp(value, "none") != 0) {
            if (!path_verify(value, alpp, name, true)) {
               answer_list_log(alpp, false, false);
               DRETURN(STATUS_EEXIST);
            }
         }
      } else if (strcmp(name, "mailer") == 0 ||
          strcmp(name, "xterm") == 0) {
         if (!path_verify(value, alpp, name, true)) {
            answer_list_log(alpp, false, false);
            DRETURN(STATUS_EEXIST);
         }
      } else if (strcmp(name, "qlogin_daemon") == 0 ||
          strcmp(name, "rlogin_daemon") == 0 ||
          strcmp(name, "rsh_daemon") == 0) {
         if (strcasecmp(value, "builtin") != 0) {
            if (!path_verify(value, alpp, name, true)) {
               answer_list_log(alpp, false, false);
               DRETURN(STATUS_EEXIST);
            }
         }
      }

      /* load_sensor is a comma separated list of scripts */
      else if (strcmp(name, "load_sensor") == 0 && strcasecmp(value, "none") != 0) {
         struct saved_vars_s *context = NULL;
         const char *path = sge_strtok_r(value, ",", &context);
         do {
            if (!path_verify(path, alpp, name, true)) {
               answer_list_log(alpp, false, false);
               sge_free_saved_vars(context);
               DRETURN(STATUS_EEXIST);
            }
         } while ((path = sge_strtok_r(NULL, ",", &context)) != NULL);
         sge_free_saved_vars(context);
      }
   }
static bool
hgroup_mod_hostlist(lListElem *hgroup, lList **answer_list,
                    lListElem *reduced_elem, int sub_command,
                    lList **add_hosts, lList **rem_hosts,
                    lList **occupant_groups)
{
    bool ret = true;

    DENTER(TOP_LAYER, "hgroup_mod_hostlist");
    if (hgroup != NULL && reduced_elem != NULL) {
        int pos = lGetPosViaElem(reduced_elem, HGRP_host_list, SGE_NO_ABORT);

        if (pos >= 0) {
            lList *list = lGetPosList(reduced_elem, pos);
            lList *old_href_list = lCopyList("", lGetList(hgroup, HGRP_host_list));
            lList *master_list = *(hgroup_list_get_master_list());
            lList *href_list = NULL;
            lList *add_groups = NULL;
            lList *rem_groups = NULL;

            if (ret) {
                ret &= href_list_resolve_hostnames(list, answer_list, true);
            }
            if (ret) {
                attr_mod_sub_list(answer_list, hgroup, HGRP_host_list, HR_name,
                                  reduced_elem, sub_command, SGE_ATTR_HOSTLIST,
                                  SGE_OBJ_HGROUP, 0);
                href_list = lGetList(hgroup, HGRP_host_list);
            }
            if (ret) {
                ret &= href_list_find_diff(href_list, answer_list, old_href_list,
                                           add_hosts, rem_hosts, &add_groups,
                                           &rem_groups);
            }
            if (ret && add_groups != NULL) {
                ret &= hgroup_list_exists(master_list, answer_list, add_groups);
            }
            if (ret) {
                ret &= href_list_find_effective_diff(answer_list, add_groups,
                                                     rem_groups, master_list,
                                                     add_hosts, rem_hosts);
            }
            if (ret) {
                ret &= href_list_resolve_hostnames(*add_hosts, answer_list, false);
            }

            /*
             * Try to find cycles in the definition
             */
            if (ret) {
                ret &= hgroup_find_all_referencees(hgroup, answer_list,
                                                   master_list, occupant_groups);
                ret &= href_list_add(occupant_groups, answer_list,
                                     lGetHost(hgroup, HGRP_name));
                if (ret) {
                    if (*occupant_groups != NULL && add_groups != NULL) {
                        lListElem *add_group = NULL;

                        for_each(add_group, add_groups) {
                            const char *name = lGetHost(add_group, HR_name);

                            if (href_list_has_member(*occupant_groups, name)) {
                                break;
                            }
                        }
                        if (add_group == NULL) {
                            /*
                             * No cycle found => success
                             */
                            ;
                        } else {
                            SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_HGROUP_CYCLEINDEF_SS,
                                                   lGetHost(add_group, HR_name),
                                                   lGetHost(hgroup, HGRP_name)));
                            answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX,
                                            ANSWER_QUALITY_ERROR);
                            ret = false;
                        }
                    }
                }
            }
lList *cull_unparse_job_parameter(
sge_gdi_ctx_class_t *ctx,
lList **pcmdline,
lListElem *job,
int flags 
) {
   const char *cp;
   u_long32 ul;
   lList *answer = NULL;
   char str[1024 + 1];
   lList *lp;
   int ret;
   lListElem *ep_opt;
   const char *username = ctx->get_username(ctx);
   const char *qualified_hostname = ctx->get_qualified_hostname(ctx);

   DENTER(TOP_LAYER, "cull_unparse_job_parameter");

   /*
   ** -a
   ** problem with submission time, but that is not a good
   ** default option anyway, is not unparsed
   */

   /*
   ** -A
   */
   if (sge_unparse_account_string(job, pcmdline, &answer) != 0) {
      DEXIT;
      return answer;
   }

   /*
   ** -c
   */
   if (sge_unparse_checkpoint_option(job, pcmdline, &answer) != 0) {
      DEXIT;
      return answer;
   }
  
   /*
    * -ckpt 
    */
   if (sge_unparse_string_option(job, JB_checkpoint_name, "-ckpt", 
            pcmdline, &answer) != 0) {
      DEXIT;
      return answer;
   }


   /*
   ** -cwd
   */
   if (lGetString(job, JB_cwd)) {
      ep_opt = sge_add_noarg(pcmdline, cwd_OPT, "-cwd", NULL);
   }

   /*
    * -P
    */
   if (sge_unparse_string_option(job, JB_project, "-P",
            pcmdline, &answer) != 0) {
      DEXIT;
      return answer;
   }

#if 0
   /*
   ** -C
   */
   if (sge_unparse_string_option(job, JB_directive_prefix, "-C", 
            pcmdline, &answer) != 0) {
      DEXIT;
      return answer;
   }
#endif   

   /*
   ** -e
   */
   if (sge_unparse_path_list(job, JB_stderr_path_list, "-e", pcmdline, 
                     &answer) != 0) {
      DEXIT;
      return answer;
   }

   /*
   ** -h, here only user hold supported at the moment
   */
   if  ((ul = lGetUlong(lFirst(lGetList(job, JB_ja_tasks)), JAT_hold))) {
      ep_opt = sge_add_noarg(pcmdline, h_OPT, "-h", NULL);
   }

   /*
   ** -hold_jid
   */
   if ((lp = lGetList(job, JB_jid_request_list))) {
      int fields[] = { JRE_job_name, 0 };
      const char *delis[] = {NULL, ",", NULL};

      ret = uni_print_list(NULL, str, sizeof(str) - 1, lp, fields, delis, 0);
      if (ret) {
         DPRINTF(("Error %d formatting jid_request_list as -hold_jid\n", ret));
         sprintf(str, MSG_LIST_ERRORFORMATINGJIDPREDECESSORLISTASHOLDJID);
         answer_list_add(&answer, str, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR);
         return answer;
      }
      ep_opt = sge_add_arg(pcmdline, hold_jid_OPT, lListT, "-hold_jid", str);
      lSetList(ep_opt, SPA_argval_lListT, lCopyList("hold_jid list", lp));      
   }

   /*
   ** -hold_jid_ad
   */
   if ((lp = lGetList(job, JB_ja_ad_request_list))) {
      int fields[] = { JRE_job_name, 0 };
      const char *delis[] = {NULL, ",", NULL};

      ret = uni_print_list(NULL, str, sizeof(str) - 1, lp, fields, delis, 0);
      if (ret) {
         DPRINTF(("Error %d formatting ja_ad_request_list as -hold_jid_ad\n", ret));
         sprintf(str, MSG_LIST_ERRORFORMATINGJIDPREDECESSORLISTASHOLDJIDAD);
         answer_list_add(&answer, str, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR);
         return answer;
      }
      ep_opt = sge_add_arg(pcmdline, hold_jid_ad_OPT, lListT, "-hold_jid_ad", str);
      lSetList(ep_opt, SPA_argval_lListT, lCopyList("hold_jid_ad list", lp));      
   }

   /*
   ** -i
   */
   if (sge_unparse_path_list(job, JB_stdin_path_list, "-i", pcmdline, 
                     &answer) != 0) {
      DEXIT;
      return answer;
   }

   /*
   ** -j
   */
   if ((ul = lGetBool(job, JB_merge_stderr))) {
      ep_opt = sge_add_arg(pcmdline, j_OPT, lIntT, "-j", "y");
      lSetInt(ep_opt, SPA_argval_lIntT, true);
   }
   
   /*
   ** -jid
   */
   if ((lp = lGetList(job, JB_job_identifier_list))) {
      int fields[] = { JRE_job_number, 0};
      const char *delis[] = {"", ",", NULL};

      ret = uni_print_list(NULL, str, sizeof(str) - 1, lp, fields, delis, 
         0);
      if (ret) {
         DPRINTF(("Error %d formatting job_identifier_list as -jid\n", ret));
         sprintf(str, MSG_LIST_ERRORFORMATINGJOBIDENTIFIERLISTASJID);
         answer_list_add(&answer, str, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR);
         return answer;
      }
      ep_opt = sge_add_arg(pcmdline, jid_OPT, lListT, "-jid", str);
      lSetList(ep_opt, SPA_argval_lListT, lCopyList("jid list", lp));      
   }

   /*
   ** -js
   */
   if ((ul = lGetUlong(job, JB_jobshare)) != 0)  {
      sprintf(str, sge_u32, ul);
      ep_opt = sge_add_arg(pcmdline, js_OPT, lUlongT, "-js", str);
      lSetUlong(ep_opt, SPA_argval_lUlongT, ul);
   }

   /*
   ** -lj is in parsing but can't be unparsed here
   */

   /*
   ** -l
   */
   if (sge_unparse_resource_list(job, JB_hard_resource_list,
            pcmdline, &answer) != 0) {
      DEXIT;
      return answer;
   }
   if (sge_unparse_resource_list(job, JB_soft_resource_list,
            pcmdline, &answer) != 0) {
      DEXIT;
      return answer;
   }






   /*
   ** -m
   */
   if ((ul = lGetUlong(job, JB_mail_options))) {
      cp = sge_unparse_mail_options(ul);
      if (!cp) {
         DPRINTF(("Error unparsing mail options\n"));
         sprintf(str, MSG_PARSE_ERRORUNPARSINGMAILOPTIONS);
         answer_list_add(&answer, str, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR);
         return answer;
      }
      ep_opt = sge_add_arg(pcmdline, m_OPT, lIntT, "-m", cp);
      lSetInt(ep_opt, SPA_argval_lIntT, ul);
   }

   /*
   ** -M obviously a problem!!!
   ** not unparsed at the moment
   ** does it make sense as a default, after all?
   */
   if ((lp = lGetList(job, JB_mail_list))) {
      lList *lp_new = NULL;
      lListElem *ep_new = NULL;
      lListElem *ep = NULL;
      const char *host;
      const char *user;

      /*
      ** or rather take all if there are more than one elements?
      */
      for_each(ep, lp) {
         user = lGetString(ep, MR_user);
         host = lGetHost(ep, MR_host);
         if (sge_strnullcmp(user, username) || 
             sge_hostcmp(host, qualified_hostname)) {
            lp_new = lCreateList("mail list", MR_Type);
            ep_new = lAddElemStr(&lp_new, MR_user, user, MR_Type);
            lSetHost(ep_new, MR_host, host);
         }
      }
Beispiel #18
0
/*-------------------------------------------------------------------------*/
void qmonSet2xN(
Widget w,
lList *lp,
int field1,
int field2 
) {
   lListElem *ep;
   int row;
   int max_rows;
   const char *col1 = NULL, *col2 = NULL;
   int val;
   double dval;
   char buf[128];
   
   DENTER(GUI_LAYER, "qmonSet2xN");
   
   /* clear the area */
   XtVaSetValues(w, XmNcells, NULL, NULL);
   
   if (!lp) {
      DEXIT;
      return;
   }
      
   XtVaGetValues(w, XmNrows, &max_rows, NULL);

   for (ep = lFirst(lp), row = 0; ep; ep = lNext(ep), row++) {
      if (row == max_rows) {
         XbaeMatrixAddRows(w, 
                           max_rows, 
                           NULL,       /* empty rows  */
                           NULL,       /* no lables   */
                           NULL,       /* no different colors */
                           1);         /* we add 1 rows      */
         max_rows++;
      }
      /*
      ** the first column of the matrix can be string or host type
      **
      */
      switch (lGetType(lGetListDescr(lp), field1)) {
         case lStringT:
            col1 = (StringConst)lGetString(ep, field1);
            break;
         case lHostT:
            col1 = (StringConst)lGetHost(ep,field1);
            break;
      }
      /*
      ** the second column can be of different type
      */
      switch (lGetType(lGetListDescr(lp), field2)) {
         case lStringT:
            col2 = (StringConst)lGetString(ep, field2);
            break;
         case lHostT:
            col2 = (StringConst)lGetHost(ep,field2);
            break;
         case lUlongT:
            val = (int)lGetUlong(ep, field2);
            if (val) {
               sprintf(buf, "%d", val);
               col2 = buf;
            }
            else
               col2 = NULL;
            break;
         case lDoubleT:
            dval = lGetDouble(ep, field2);
            sprintf(buf, "%.2f", dval);
            col2 = buf;
            break;
      }

      if (col1) {
         /* FIX_CONST_GUI */
         XbaeMatrixSetCell(w, row, 0 , col1 ? (String)col1 : "");
         /* FIX_CONST_GUI */
         XbaeMatrixSetCell(w, row, 1 , col2 ? (String)col2 : "");
      }
   }
       
   DEXIT;
}
Beispiel #19
0
/*-------------------------------------------------------------------------*/
void qmonSetNxN(Widget w, lList *lp, int num_fields, ...)
{
   lListElem *ep;
   int i, row;
   int max_rows;
   int val;
   double dval;
   char buf[128];
   int *field;
   const char **col;
   va_list ap;
   
   DENTER(GUI_LAYER, "qmonSetNxN");
   
   /* clear the area */
   XtVaSetValues(w, XmNcells, NULL, NULL);
   
   if (!lp)
   {
      DEXIT;
      return;
   }

   field = malloc(num_fields*sizeof(int));
   col   = malloc(num_fields*sizeof(char *));
   if (field == NULL || col == NULL)
      abort();

   va_start(ap, num_fields);
   for(i=0; i<num_fields; i++)
      field[i] = va_arg(ap, int);

   XtVaGetValues(w, XmNrows, &max_rows, NULL);

   for (ep = lFirst(lp), row = 0; ep; ep = lNext(ep), row++)
   {
      if (row == max_rows)
      {
         XbaeMatrixAddRows(w, 
                           max_rows, 
                           NULL,       /* empty rows  */
                           NULL,       /* no lables   */
                           NULL,       /* no different colors */
                           1);         /* we add 1 rows      */
         max_rows++;
      }

      memset(col, 0, num_fields*sizeof(char *));

      /*
       * get column values
       */

      for(i=0; i<num_fields; i++)
      {
         switch (lGetType(lGetListDescr(lp), field[i]))
         {
            case lStringT:
               col[i] = (StringConst)lGetString(ep, field[i]);
               break;
            case lHostT:
               col[i] = (StringConst)lGetHost(ep,field[i]);
               break;
            case lUlongT:
               val = (int)lGetUlong(ep, field[i]);
#if 0
               if (val) {
                  sprintf(buf, "%d", val);
                  col[i] = buf;
               }
               else
                  col[i] = NULL;
#else
               sprintf(buf, "%d", val);
               col[i] = buf;
#endif
               break;
            case lDoubleT:
               dval = lGetDouble(ep, field[i]);
               sprintf(buf, "%.2f", dval);
               col[i] = buf;
               break;
         }
      }

      if (col[0])
      {
         /* FIX_CONST_GUI */
         for(i=0; i<num_fields; i++)
            XbaeMatrixSetCell(w, row, i, col[i] ? (String)col[i] : "");
      }
   }

   va_end(ap);
   free(field);
   free(col);
       
   DEXIT;
}
Beispiel #20
0
/****** sge_select_queue/get_queue_resource() ***************************************
*  NAME
*     get_queue_resource() -- extracts attribut information from the queue 
*
*  SYNOPSIS
*    static lListElem* get_queue_resource(lListElem *queue, lList *centry_list, const char *attrname)
* 
*  FUNCTION
*     All fixed queue attributes are directly coded into the queue structure. These have to extraced
*     and formed into a CE structure. That is, what this function does. It takes a name for an attribut
*     and returns a full CE structure, if the attribut is set in the queue. Otherwise it returns NULL.
*
*  INPUTS
*     lListElem *queue_elem - 
*     lListElm  *queue      -
*     const char *attrname  - name of the attribute.
*  RESULT
*     bool -  
*
*
*******************************************************************************/
bool get_queue_resource(lListElem *queue_elem, const lListElem *queue, const char *attrname){
   double dval=0.0;
   const char *value=NULL;
   char as_str[100];
   int type, field;

   DENTER(BASIS_LAYER, "get_queue_resource");

   if(!queue_elem){
      /* error */
      DRETURN(false);
   }

   if (get_rsrc(attrname, true, &field, NULL, NULL, &type)!=0) {
      DPRINTF(("is not a system queue attribute: %s\n", attrname));
      DRETURN(false);
   }

   /* read stuff from queue and set to new elements */
   switch(type) {
   case TYPE_INT:
      dval = (double)lGetUlong(queue, field);
      snprintf(as_str, 100, sge_u32, lGetUlong(queue, field));
      break;

   case TYPE_TIM:
   case TYPE_MEM:
   case TYPE_DOUBLE:
      if ((value = lGetString(queue, field))) {
         parse_ulong_val(&dval, NULL, type, value, NULL, 0); 
      } 
      break;

   case TYPE_BOO:
      dval = (double)lGetBool(queue, field);
      snprintf(as_str, 100, "%d", (int)lGetBool(queue, field));
      break;

   case TYPE_STR: 
   case TYPE_CSTR:
   case TYPE_RESTR:
      value = lGetString(queue, field);
      break;
   case TYPE_HOST:
      value = lGetHost(queue, field);
      break;
   }
  

   if (!is_attr_prior2(queue_elem, dval, CE_doubleval, CE_dominant)){
      lSetUlong(queue_elem,CE_dominant , DOMINANT_LAYER_QUEUE|DOMINANT_TYPE_FIXED);
      lSetDouble(queue_elem,CE_doubleval , dval);

      if(value){
         lSetString(queue_elem, CE_stringval, value);
      } 
      else{
         lSetString(queue_elem,CE_stringval , as_str);
      }
   }

   DRETURN(true);
}
/*
 * Delete configuration 'confp' from cluster configuration.
 *
 * TODO: A fix for IZ issue #79 is needed. For this to be done it may be 
 * necessary to introduce something like 'protected' configuration entries.
 */
int 
sge_del_configuration(sge_gdi_ctx_class_t *ctx,
                      lListElem *aConf, lList **anAnswer, 
                      char *aUser, char *aHost)
{
   const char *tmp_name = NULL;
   char unique_name[CL_MAXHOSTLEN];
   int ret = -1;

   DENTER(TOP_LAYER, "sge_del_configuration");

   if (!aConf || !aUser || !aHost) {
      CRITICAL((SGE_EVENT, MSG_SGETEXT_NULLPTRPASSED_S, SGE_FUNC));
      answer_list_add(anAnswer, SGE_EVENT, 
                      STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR);
      DRETURN(STATUS_EUNKNOWN);
   }
   
   if ((tmp_name = lGetHost(aConf, CONF_name)) == NULL) {
      CRITICAL((SGE_EVENT, MSG_SGETEXT_MISSINGCULLFIELD_SS, 
                lNm2Str(CONF_name), SGE_FUNC));
      answer_list_add(anAnswer, SGE_EVENT, 
                      STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR);
      DRETURN(STATUS_EUNKNOWN);
   }

   /*
    * Due to CR 6319231 IZ 1760:
    *    try to resolve the hostname
    *    if it is not resolveable then
    *       ignore this and use the hostname stored in the configuration obj
    *       or use the given name if no object can be found
    */
   ret = sge_resolve_hostname(tmp_name, unique_name, EH_name, sizeof(unique_name));
   if (ret != CL_RETVAL_OK) {
      lListElem *conf_obj = NULL;
 
      DPRINTF(("%s: error %s resolving host %s\n", SGE_FUNC,
               cl_get_error_text(ret), tmp_name));
 
      conf_obj = sge_get_configuration_for_host(tmp_name);
      if (conf_obj != NULL) {
         DPRINTF(("using hostname stored in configuration object\n"));
         strcpy(unique_name, lGetHost(conf_obj, CONF_name));
         lFreeElem(&conf_obj);
      } else {
         ERROR((SGE_EVENT, MSG_SGETEXT_CANT_DEL_CONFIG2_S, tmp_name));
         answer_list_add(anAnswer, SGE_EVENT,
                         STATUS_EEXIST, ANSWER_QUALITY_ERROR);
         DRETURN(STATUS_EEXIST);
      }
   }

   /* Do not allow to delete global configuration */
   if (!strcasecmp(SGE_GLOBAL_NAME, unique_name)) {
      ERROR((SGE_EVENT, MSG_SGETEXT_CANT_DEL_CONFIG_S, unique_name));
      answer_list_add(anAnswer, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR);
      DRETURN(STATUS_EEXIST);
   }

   sge_event_spool(ctx, anAnswer, 0, sgeE_CONFIG_DEL, 0, 0, unique_name, NULL, NULL, NULL, NULL, NULL, true, true);
    
   remove_conf_by_name(unique_name);
   
   INFO((SGE_EVENT, MSG_SGETEXT_REMOVEDFROMLIST_SSSS, aUser, aHost, unique_name, MSG_OBJ_CONF ));
   answer_list_add(anAnswer, SGE_EVENT, STATUS_OK, ANSWER_QUALITY_INFO);
   
   update_reschedule_unknown_timout_values(unique_name);

   /* invalidate cached configuration values */
   mconf_set_new_config(true);
    
   DRETURN(STATUS_OK);
}
Beispiel #22
0
/****** Eventmirror/job/job_update_master_list() *****************************
*  NAME
*     job_update_master_list() -- update the master list of jobs
*
*  SYNOPSIS
*     bool job_update_master_list(sge_object_type type,
*                                     sge_event_action action,
*                                     lListElem *event, void *clientdata)
*
*  FUNCTION
*     Update the global master list of jobs
*     based on an event.
*     The function is called from the event mirroring interface.
*
*     A jobs array tasks are not updated by this function,
*     as they are maintained by separate events.
*     In addition, some scheduler specific attributes, that
*     are only used in scheduler, are not updated.
*
*  INPUTS
*     sge_object_type type     - event type
*     sge_event_action action - action to perform
*     lListElem *event        - the raw event
*     void *clientdata        - client data
*
*  RESULT
*     bool - true, if update is successfull, else false
*
*  NOTES
*     The function should only be called from the event mirror interface.
*
*  SEE ALSO
*     Eventmirror/--Eventmirror
*     Eventmirror/sge_mirror_update_master_list()
*     Eventmirror/job/job_update_master_list_usage()
*******************************************************************************/
sge_callback_result
job_update_master_list(sge_evc_class_t *evc, object_description *object_base, sge_object_type type, 
                       sge_event_action action, lListElem *event, void *clientdata)
{
   lList **list;
   const lDescr *list_descr;
   u_long32 job_id;
   lListElem *job = NULL;
   lList *ja_tasks = NULL;

   char id_buffer[MAX_STRING_SIZE];
   dstring id_dstring;

   DENTER(TOP_LAYER, "job_update_master_list");

   sge_dstring_init(&id_dstring, id_buffer, MAX_STRING_SIZE);

   list = sge_master_list(object_base, SGE_TYPE_JOB);
   list_descr = lGetListDescr(lGetList(event, ET_new_version)); 
   job_id = lGetUlong(event, ET_intkey);
   job = job_list_locate(*list, job_id);

   if (action == SGE_EMA_MOD) {
      u_long32 event_type = lGetUlong(event, ET_type);

      if (job == NULL) {
         ERROR((SGE_EVENT, MSG_JOB_CANTFINDJOBFORUPDATEIN_SS,
                job_get_id_string(job_id, 0, NULL, &id_dstring), "job_update_master_list"));
         DRETURN(SGE_EMA_FAILURE);
      }

      if (event_type == sgeE_JOB_USAGE || event_type == sgeE_JOB_FINAL_USAGE ) {
         /* special handling needed for JOB_USAGE and JOB_FINAL_USAGE events.
         * they are sent for jobs, ja_tasks and pe_tasks and only contain
         * the usage list.
         * Preferable would probably be to send MOD events for the different
         * object types.
         */
         bool ret = job_update_master_list_usage(*list, event);
         DRETURN(ret?SGE_EMA_OK:SGE_EMA_FAILURE);
      } else {
         /* this is the true modify event.
          * we may not update several fields:
          * - JB_ja_tasks is the task list - it is maintained by JATASK events
          * - JB_host and JB_category are scheduler internal attributes
          *   they may not be overwritten.
          *   Better would be to move them from JB_Type to some scheduler specific
          *   object.
          */

          lListElem *modified_job;

          modified_job = lFirst(lGetList(event, ET_new_version));
          if(job != NULL && modified_job != NULL) {
            /* we want to preserve the old ja_tasks, since job update events to not contain them */
            lXchgList(job, JB_ja_tasks, &ja_tasks);
            lSetHost(modified_job, JB_host, lGetHost(job, JB_host));
            lSetRef(modified_job, JB_category, lGetRef(job, JB_category));
          }
      }
   }

   if (sge_mirror_update_master_list(list, list_descr, job, job_get_id_string(job_id, 0, NULL, &id_dstring), action, event) != SGE_EM_OK) {
      lFreeList(&ja_tasks);
      DRETURN(SGE_EMA_FAILURE);
   }

   /* restore ja_task list after modify event */
   if (action == SGE_EMA_MOD && ja_tasks != NULL) {
      /* we have to search the replaced job */
      job = job_list_locate(*list, job_id);
      if(job == NULL) {
         ERROR((SGE_EVENT, MSG_JOB_CANTFINDJOBFORUPDATEIN_SS,
                job_get_id_string(job_id, 0, NULL, &id_dstring), "job_update_master_list"));
         lFreeList(&ja_tasks);
         DRETURN(SGE_EMA_FAILURE);
      }

      lXchgList(job, JB_ja_tasks, &ja_tasks);
      lFreeList(&ja_tasks);
   }

   DRETURN(SGE_EMA_OK);
}
Beispiel #23
0
/************************************************************************
 Master routine for job exit

 We need a rusage struct filled.
 In normal cases this is done by the execd, sending this structure
 to notify master about job finish.

 In case of an error noticed by the master which needs the job to be 
 removed we can fill this structure by hand. We need:

 rusage->job_number
 rusage->qname to clean up the queue (if we didn't find it we nevertheless
               clean up the job

 for functions regarding rusage see sge_rusage.c
 ************************************************************************/
void sge_job_exit(sge_gdi_ctx_class_t *ctx, lListElem *jr, lListElem *jep, lListElem *jatep, monitoring_t *monitor) 
{
   lListElem *queueep = NULL;
   const char *err_str = NULL;
   const char *qname = NULL;  
   const char *hostname = MSG_OBJ_UNKNOWNHOST;
   u_long32 jobid, jataskid;
   lListElem *hep = NULL;
   u_long32 timestamp;
   object_description *object_base = object_type_get_object_description();

   u_long32 failed, general_failure;
   lList *saved_gdil;

   DENTER(TOP_LAYER, "sge_job_exit");

   /* JG: TODO: we'd prefer some more precise timestamp, e.g. from jr */
   timestamp = sge_get_gmt();
                     
   qname = lGetString(jr, JR_queue_name);
   if (qname == NULL) {
      qname = (char *)MSG_OBJ_UNKNOWNQ;
   }

   err_str = lGetString(jr, JR_err_str);
   if (err_str == NULL) {
      err_str = MSG_UNKNOWNREASON;
   }

   jobid = lGetUlong(jr, JR_job_number);
   jataskid = lGetUlong(jr, JR_ja_task_number);
   failed = lGetUlong(jr, JR_failed);
   general_failure = lGetUlong(jr, JR_general_failure);

   cancel_job_resend(jobid, jataskid);

   /* This only has a meaning for Hibernator jobs. The job pid must
    * be saved accross restarts, since jobs get their old pid
    */
   lSetUlong(jatep, JAT_pvm_ckpt_pid, lGetUlong(jr, JR_job_pid));

   DPRINTF(("reaping job "sge_u32"."sge_u32" in queue >%s< job_pid %d\n", 
      jobid, jataskid, qname, (int) lGetUlong(jatep, JAT_pvm_ckpt_pid)));

   queueep = cqueue_list_locate_qinstance(*object_base[SGE_TYPE_CQUEUE].list, qname);
   if (queueep == NULL) {
      ERROR((SGE_EVENT, MSG_JOB_WRITEJFINISH_S, qname));
   }

   sge_job_remove_enforce_limit_trigger(jobid, jataskid);

   /* retrieve hostname for later use */
   if (queueep != NULL) {
      hostname = lGetHost(queueep, QU_qhostname);
   }

   if (failed) {        /* a problem occured */
      WARNING((SGE_EVENT, MSG_JOB_FAILEDONHOST_UUSSSS, sge_u32c(jobid), 
               sge_u32c(jataskid), 
               hostname,
               general_failure ? MSG_GENERAL : "",
               get_sstate_description(failed), err_str));
   } else {
      INFO((SGE_EVENT, MSG_JOB_JFINISH_UUS,  sge_u32c(jobid), sge_u32c(jataskid), hostname));
   }

   /*-------------------------------------------------*/

   /* test if this job is in state JRUNNING or JTRANSFERING */
   if (lGetUlong(jatep, JAT_status) != JRUNNING && 
       lGetUlong(jatep, JAT_status) != JTRANSFERING) {
      ERROR((SGE_EVENT, MSG_JOB_JEXITNOTRUN_UU, sge_u32c(lGetUlong(jep, JB_job_number)), sge_u32c(jataskid)));
      DRETURN_VOID;
   }

   saved_gdil = lCopyList("cpy", lGetList(jatep, JAT_granted_destin_identifier_list));

   /*
    * case 1: job being trashed because 
    *    --> failed starting interactive job
    *    --> job was deleted
    *    --> a failed batch job that explicitely shall not enter error state
    */
   if (((lGetUlong(jatep, JAT_state) & JDELETED) == JDELETED) ||
         (failed && !lGetString(jep, JB_exec_file)) ||
         (failed && general_failure==GFSTATE_JOB && JOB_TYPE_IS_NO_ERROR(lGetUlong(jep, JB_type)))) {
      reporting_create_acct_record(ctx, NULL, jr, jep, jatep, false);
      /* JG: TODO: we need more information in the log message */
      reporting_create_job_log(NULL, timestamp, JL_DELETED, MSG_EXECD, hostname, jr, jep, jatep, NULL, MSG_LOG_JREMOVED);

      sge_commit_job(ctx, jep, jatep, jr, COMMIT_ST_FINISHED_FAILED_EE, COMMIT_DEFAULT | COMMIT_NEVER_RAN, monitor);

      if (lGetUlong(jep, JB_ar) != 0 && (lGetUlong(jatep, JAT_state) & JDELETED) == JDELETED) {
         /* get AR and remove it if no other jobs are debited */
         lList *master_ar_list = *object_base[SGE_TYPE_AR].list;
         lListElem *ar = ar_list_locate(master_ar_list, lGetUlong(jep, JB_ar));

         if (ar != NULL && lGetUlong(ar, AR_state) == AR_DELETED) {
            lListElem *ar_queue;
            u_long32 ar_id = lGetUlong(ar, AR_id);

            for_each(ar_queue, lGetList(ar, AR_reserved_queues)) {
               if (qinstance_slots_used(ar_queue) != 0) {
                  break;
               }
            }
            if (ar_queue == NULL) {
               /* no jobs registered in advance reservation */
               dstring buffer = DSTRING_INIT;

               sge_dstring_sprintf(&buffer, sge_U32CFormat,
                                   sge_u32c(ar_id));

               ar_do_reservation(ar, false);

               reporting_create_ar_log_record(NULL, ar, ARL_DELETED, 
                                              "AR deleted",
                                              timestamp);
               reporting_create_ar_acct_records(NULL, ar, timestamp); 

               lRemoveElem(master_ar_list, &ar);

               sge_event_spool(ctx, NULL, 0, sgeE_AR_DEL, 
                      ar_id, 0, sge_dstring_get_string(&buffer), NULL, NULL,
                      NULL, NULL, NULL, true, true);
               sge_dstring_free(&buffer);
            }
         }