/****** execd/loadsensor/sge_ls_start_ls() ************************************
*  NAME
*     sge_ls_start_ls -- starts a loadsensor  
*
*  SYNOPSIS
*     static void sge_ls_start_ls(const char *qualified_hostname, lListElem *this_ls)
*
*  FUNCTION
*     An additional loadsensor process will be started. The name
*     of the script has to be stored in the LS_command entry of
*     'this_ls' before this function will be called. 
*
*     The process environment of the loadsensor will contain
*     the HOST variable. This variable contains the hostname
*     of the execution daemon which calls this function.
*
*     If 'this_ls' correlates to the 'qidle'-loadsensor then 
*     also the XAUTHORITY environment variable will be set.
*
*  INPUTS
*     qualified_hostname - qualified host name
*     this_ls - pointer to a CULL element of type LS_Type
*
*  RESULT
*     An additional loadsensor process will be started. 
*     [this_ls] - the CULL element will be modified
*        LS_pid contains the pid of the ls process
*        LS_in, LS_out, LS_err are the FILE-streams for the
*        communication with the ls-process     
*        returns LS_OK
*     If sge_peopen fails, returns LS_CANT_PEOPEN     
******************************************************************************/
static int sge_ls_start_ls(const char *qualified_hostname, lListElem *this_ls)
{
   pid_t pid = -1;
   FILE *fp_in = NULL;
   FILE *fp_out = NULL;
   FILE *fp_err = NULL;
   char buffer[1024];
   char **envp = NULL;

   DENTER(TOP_LAYER, "sge_ls_start_ls");

   snprintf(buffer, sizeof(buffer), "%s=%s", "HOST", qualified_hostname);
   if (has_to_use_qidle
       && !strcmp(lGetString(this_ls, LS_name), IDLE_LOADSENSOR_NAME)) {
      envp = sge_malloc(sizeof(char *) * 3);
      envp[0] = buffer;
      envp[1] = "XAUTHORITY=/tmp/.xauthority";
      envp[2] = NULL;
   } else {
      envp = sge_malloc(sizeof(char *) * 2);
      envp[0] = buffer;
      envp[1] = NULL;
   }

   /* we need fds for select() .. */
   pid = sge_peopen("/bin/sh", 0, lGetString(this_ls, LS_command), NULL, envp,
                &fp_in, &fp_out, &fp_err, true);

   if (envp) {
      sge_free(&envp);
   }
   if (pid == -1) {
      return LS_CANT_PEOPEN;
   }
   /* we need load reports non blocking */
   fcntl(fileno(fp_out), F_SETFL, O_NONBLOCK);

   sge_ls_set_pid(this_ls, pid);
   lSetRef(this_ls, LS_in, fp_in);
   lSetRef(this_ls, LS_out, fp_out);
   lSetRef(this_ls, LS_err, fp_err);

   DPRINTF(("%s: successfully started load sensor \"%s\"\n",
            SGE_FUNC, lGetString(this_ls, LS_command)));

   /* request first load report after starting */
   ls_send_command(this_ls, "\n");

   return LS_OK;
}
/******* execd/loadsensor/sge_ls_create_ls() **********************************
*  NAME
*     sge_ls_create_ls -- creates a new CULL loadsensor element 
*
*  SYNOPSIS
*     static lListElem* sge_ls_create_ls(const char *qualified_hostname,
*                                        char *name, const char *scriptfile)
*
*  FUNCTION
*     The function creates a new CULL element of type LS_Type and
*     returns a pointer to this object. The loadsensor will be
*     started immediately.
*     If it cannot be started then, LS_has_to_restart is set to 
*     true so that it will be attempted to be restarted in the next load interval
*
*  INPUTS
*     qualified_hostname - qualified host name
*     name - pseudo name of the ls
*              "extern" for user defined loadsensors
*              "intern" for qidle and qloadsensor
*     scriptfile - absolute path to the ls scriptfile
*
*  RESULT
*     new CULL element of type LS_Type will be returned
*     and a new loadsensor process will be created by this function
******************************************************************************/
static lListElem *sge_ls_create_ls(const char *qualified_hostname, char *name, const char *scriptfile)
{
   lListElem *new_ls = NULL;    /* LS_Type */
   SGE_STRUCT_STAT st;

   DENTER(TOP_LAYER, "sge_ls_create_ls");

   if (scriptfile != NULL) {
      if (SGE_STAT(scriptfile, &st) != 0) {
         if (strcmp(name, "extern") == 0) {
            WARNING((SGE_EVENT, MSG_LS_NOMODTIME_SS, scriptfile,
                   strerror(errno)));
         }
         DRETURN(NULL);
      }

      new_ls = lCreateElem(LS_Type);
      if (new_ls) {
         /* initialize all attributes */
         lSetString(new_ls, LS_name, name);
         lSetString(new_ls, LS_command, scriptfile);
         sge_ls_set_pid(new_ls, -1);
         lSetRef(new_ls, LS_in, NULL);
         lSetRef(new_ls, LS_out, NULL);
         lSetRef(new_ls, LS_err, NULL);
         lSetBool(new_ls, LS_has_to_restart, false);
         lSetUlong(new_ls, LS_tag, 0);
         lSetList(new_ls, LS_incomplete, lCreateList("", LR_Type));
         lSetList(new_ls, LS_complete, lCreateList("", LR_Type));
         lSetUlong(new_ls, LS_last_mod, st.st_mtime);

         /* start loadsensor, if couldn't set the restart flag so that we
          * restart it in the next load interval
          */
         if (sge_ls_start_ls(qualified_hostname, new_ls) != LS_OK) {
            lSetBool(new_ls, LS_has_to_restart, true);
         }
      }
   }
   DRETURN(new_ls);
}
示例#3
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);
}