diff --git a/src/include/pbs_ifl.h b/src/include/pbs_ifl.h index c056941..ae80dd7 100644 --- a/src/include/pbs_ifl.h +++ b/src/include/pbs_ifl.h @@ -180,6 +180,7 @@ #define ATTR_reported "reported" #define ATTR_intcmd "inter_cmd" #define ATTR_P "proxy_user" +#define ATTR_schedspec "sched_nodespec" #ifdef USEJOBCREATE #define ATTR_pagg "pagg_id" diff --git a/src/include/pbs_job.h b/src/include/pbs_job.h index cdc3227..159f7e9 100644 --- a/src/include/pbs_job.h +++ b/src/include/pbs_job.h @@ -296,6 +296,7 @@ enum job_atr JOB_ATR_jobtype, /* opaque job type string */ JOB_ATR_inter_cmd, /* command for interactive job */ JOB_ATR_proxy_user, + JOB_ATR_sched_spec, /* schedulers nodespec sent during job run request */ #ifdef USEJOBCREATE JOB_ATR_pagg_id, #endif /* USEJOBCREATE */ diff --git a/src/server/job_attr_def.c b/src/server/job_attr_def.c index adff3f0..9abaab7 100644 --- a/src/server/job_attr_def.c +++ b/src/server/job_attr_def.c @@ -933,6 +933,20 @@ attribute_def job_attr_def[] = PARENT_TYPE_JOB }, + /* JOB_ATR_sched_spec */ + { ATTR_schedspec, /* sched_nodespec */ + decode_str, + encode_str, + set_str, + comp_str, + free_str, + NULL_FUNC, + READ_ONLY | ATR_DFLAG_MOM, + ATR_TYPE_STR, + PARENT_TYPE_JOB + }, + + #ifdef USEJOBCREATE /* JOB_ATR_pagg_id */ { ATTR_pagg, /* "pagg_id" */ diff --git a/src/server/job_func.c b/src/server/job_func.c index 8eb0c12..4045805 100644 --- a/src/server/job_func.c +++ b/src/server/job_func.c @@ -661,6 +661,8 @@ void job_free( bp = (badplace *)GET_NEXT(pj->ji_rejectdest); } + free(pj->ji_expanded_spec); + /* now free the main structure */ free((char *)pj); diff --git a/src/server/node_manager.c b/src/server/node_manager.c index 8bbbbe8..65fcd1e 100644 --- a/src/server/node_manager.c +++ b/src/server/node_manager.c @@ -4974,7 +4974,8 @@ static void set_one_old( char *name, job *pjob, - int shared) /* how used flag, either INUSE_JOB or INUSE_JOBSHARE */ + int shared, /* how used flag, either INUSE_JOB or INUSE_JOBSHARE */ + int order) { int i; @@ -5025,8 +5026,11 @@ static void set_one_old( snp->jobs = jp; jp->job = pjob; + jp->order = order; } + adjust_resources_use(pnode,jp,INCR); + if (--pnode->nd_nsnfree <= 0) pnode->nd_state |= shared; @@ -5054,10 +5058,13 @@ void set_old_nodes( job *pjob) /* I (modified) */ { - char *old; - char *po; + char *old = NULL, *fold = NULL; + char *po, *ps; + char *spec = NULL, *fspec = NULL; resource *presc; int shared = INUSE_JOB; + int order = 1, remaining = 0; + int excl = 0; if ((pbsndmast != NULL) && (pjob->ji_wattr[(int)JOB_ATR_exec_host].at_flags & ATR_VFLAG_SET)) @@ -5077,25 +5084,88 @@ void set_old_nodes( } } + /* reset the jobs expanded nodespec from job attribute */ + if ((pjob->ji_wattr[(int)JOB_ATR_sched_spec].at_flags & ATR_VFLAG_SET) != 0) + { + free(pjob->ji_expanded_spec); + pjob->ji_expanded_spec = nodespec_expand(pjob->ji_wattr[(int)JOB_ATR_sched_spec].at_val.at_str,&excl); + } + + /* duplicate the expanded nodespec, so we can work with it */ + if (pjob->ji_expanded_spec != NULL) + { + spec = strdup(pjob->ji_expanded_spec); + fspec = spec; + ps = spec; + } + old = strdup(pjob->ji_wattr[(int)JOB_ATR_exec_host].at_val.at_str); + fold = old; + po = old; - if (old == NULL) + if (old == NULL || spec == NULL) { /* FAILURE - cannot alloc memory */ return; } - while ((po = strrchr(old, (int)'+')) != NULL) + /* nodes in exec host are in the right order, but we don't know + * how many belong to each of the nodespec parts + * we have to cut out the ppn=value and also the number of nodes */ + + do /* for each part of the nodespec */ { - *po++ = '\0'; + char *ppn = NULL; + + spec = ps; /* swap for the next part */ + + remaining = atoi(spec); /* determine number of nodes requested */ + if (remaining == 0) + remaining = 1; + + ps = strchr(ps,'+'); /* find next part */ + if (ps != NULL) + { + *ps = '\0'; ps++; + } + + /* determine ppn */ + ppn = strstr(spec,"ppn="); + if (ppn != NULL) /* there is ppn */ + { + int ppn_count; + ppn+=4; /* move beyond ppn= */ + + ppn_count = atoi(ppn); + if (ppn_count == 0) /* should not happen */ + ppn_count = 1; + + remaining *= ppn_count; /* vps are requested for each node */ + } + + do /* for each remaining, eat part from exec host */ + { + old = po; + + po = strchr(po,'+'); + if (po != NULL) + { + *po = '\0'; po++; + } + + set_one_old(old, pjob, shared, order); + remaining--; + } + while (remaining > 0 && po != NULL); - set_one_old(po, pjob, shared); + order++; } + while (ps != NULL); - set_one_old(old, pjob, shared); - free(old); + free(fold); + free(fspec); } /* END if ((pbsndmast != NULL) && ...) */ return; diff --git a/src/server/req_quejob.c b/src/server/req_quejob.c index daada74..3b9fd77 100644 --- a/src/server/req_quejob.c +++ b/src/server/req_quejob.c @@ -908,6 +908,8 @@ void req_quejob( pj->ji_qs.ji_un.ji_newt.ji_scriptsz = 0; + pj->ji_expanded_spec = NULL; + /* acknowledge the request with the job id */ if (reply_jobid(preq, pj->ji_qs.ji_jobid, BATCH_REPLY_CHOICE_Queue) != 0) diff --git a/src/server/req_runjob.c b/src/server/req_runjob.c index 5b30b9a..628442e 100644 --- a/src/server/req_runjob.c +++ b/src/server/req_runjob.c @@ -1729,6 +1729,13 @@ static int assign_hosts( hosttoalloc = PBS_DEFAULT_NODE; } + /* now we have a nodespec */ + job_attr_def[(int)JOB_ATR_sched_spec].at_decode( + &pjob->ji_wattr[(int)JOB_ATR_sched_spec], + NULL, + NULL, + hosttoalloc); /* we don't really care if this fails */ + /* do we need to allocate the (cluster) node(s)? */ if (svr_totnodes != 0)