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