int MMBCopyAll( mmb_t **DstHead, /* O (modified/alloc) */ mmb_t *SrcHead) /* I */ { mmb_t *mptr; mmb_t *MB; const char *FName = "MMBCopyAll"; MDB(7,fSTRUCT) MLog("%s(DstHead,SrcHead)\n", FName); if (DstHead == NULL) { return(FAILURE); } if (SrcHead == NULL) { return(SUCCESS); } for (mptr = SrcHead;mptr != NULL;mptr = mptr->Next) { if (MMBAdd( DstHead, mptr->Data, mptr->Owner, mptr->Type, mptr->ExpireTime, mptr->Priority, &MB) == FAILURE) { continue; } MB->Count = mptr->Count; MB->IsPrivate = mptr->IsPrivate; MB->CTime = mptr->CTime; if (mptr->Label != NULL) MUStrDup(&MB->Label,mptr->Label); if (mptr->Source != NULL) MUStrDup(&MB->Source,mptr->Source); } /* END for (mptr) */ return(SUCCESS); } /* END MMBCopyAll() */
int MDAGSetAnd( marray_t *DP, /* I */ enum MDependEnum DType, /* I */ char *Value, /* I (optional) */ char *SValue, /* I (optional) */ mbitmap_t *FlagBM) /* I */ { mdepend_t *tmpD; mdepend_t *NewD; const char *FName = "MDAGSetAnd"; MDB(5,fALL) MLog("%s(DP,%s,%s,%s)\n", FName, MDependType[DType], (Value != NULL) ? Value : "NULL", (SValue != NULL) ? SValue : "NULL"); if ((DP == NULL) || (DP->Array == NULL)) return(FAILURE); tmpD = ((mdepend_t **)DP->Array)[0]; if (MDAGCreate(DP,&NewD) == FAILURE) { return(FAILURE); } if (tmpD != NULL) { while (tmpD->NextAnd != NULL) { tmpD = tmpD->NextAnd; } tmpD->NextAnd = NewD; } NewD->Type = DType; MUStrDup(&NewD->SValue,SValue); MUStrDup(&NewD->Value,Value); bmcopy(&NewD->BM,FlagBM); return(SUCCESS); } /* END MDAGSetAnd() */
int MDAGSetOr( marray_t *DList, enum MDependEnum DType, char *Value, char *SValue) { mdepend_t *tmpD; mdepend_t *NewD; const char *FName = "MDAGSetOr"; MDB(5,fALL) MLog("%s(DList,%s,%s,%s)\n", FName, MDependType[DType], (Value != NULL) ? Value : "NULL", (SValue != NULL) ? SValue : "NULL"); if ((DList == NULL) || (DList->Array == NULL)) return(FAILURE); tmpD = (mdepend_t *)MUArrayListGetPtr(DList,0); if (MDAGCreate(DList,&NewD) == FAILURE) { return(FAILURE); } if (tmpD != NULL) { while (tmpD->NextOr != NULL) { tmpD = tmpD->NextOr; } tmpD->NextOr = NewD; } NewD->Type = DType; MUStrDup(&NewD->SValue,SValue); MUStrDup(&NewD->Value,Value); return(SUCCESS); } /* END MDAGSetOr() */
int MASNet1TransCreate( masnet1_t *N, char *FileName, int FileSize, /* in MB */ long *StageTimePtr) { int tindex; masnet1trans_t **T; if (N == NULL) return(FAILURE); for (tindex = 0;tindex < MAX_MNODE;tindex++) { T = &N->ActiveList[tindex]; if (*T == (masnet1trans_t *)NULL) break; if (*T == (masnet1trans_t *)1) break; } /* END for (tindex) */ if (tindex == MAX_MNODE) { /* transaction buffer is full */ return(FAILURE); } (*T) = (masnet1trans_t *)calloc(1,sizeof(masnet1trans_t)); MUStrDup(&(*T)->FileName,FileName); (*T)->FileSize = FileSize << 10; (*T)->CompletionTime = (long *)StageTimePtr; /* enable transfer */ (*T)->State = TRUE; if (StageTimePtr != NULL) *(long *)StageTimePtr = 0; return(SUCCESS); } /* END MASNet1TransCreate() */
int MMBSetAttr( mmb_t *MB, /* I (modified) */ enum MMBAttrEnum AIndex, /* I */ void *Val, /* I */ enum MDataFormatEnum DIndex) /* I */ { if (MB == NULL) { return(FAILURE); } switch (AIndex) { case mmbaCount: MB->Count = *(int *)Val; break; case mmbaLabel: /* NYI */ break; case mmbaSource: MUStrDup(&MB->Source,(char *)Val); break; default: /* not supported */ return(FAILURE); /*NOTREACHED*/ break; } /* END switch (AIndex) */ return(SUCCESS); } /* END MMBSetAttr() */
int MTrigApplyTemplate( marray_t **DstTP, /* O (modified/alloc) */ marray_t *SrcT, /* I */ void *O, /* I parent object */ enum MXMLOTypeEnum OType, /* parent object type */ char *OName) /* parent object name */ { mtrig_t *T; int tindex; marray_t *DstT; if ((DstTP == NULL) || (SrcT == NULL)) { return(FAILURE); } MTListCopy(SrcT,DstTP,TRUE); DstT = *DstTP; for (tindex = 0; tindex < DstT->NumItems;tindex++) { T = (mtrig_t *)MUArrayListGetPtr(DstT,tindex); /* update trigger OID with new RID */ T->O = O; T->OType = OType; /* FIXME: why set etime immediately? DstT[tindex]->ETime = MSched.Time; */ MUStrDup(&T->OID,OName); MTrigInitialize(T); } /* END for (tindex) */ return(SUCCESS); } /* END MTrigApplyTemplate() */
int __MSysTestJobGetSNRange() { #if 0 mjob_t tmpJ; mnode_t tmpN; mre_t RE[MMAX_RSV_DEPTH << 1]; mrsv_t *R[MMAX_RSV_DEPTH]; int RC[MMAX_RSV_DEPTH]; mreq_t tmpRQ; char tmpLine[MMAX_LINE]; mrange_t GRange[MMAX_RANGE]; mrange_t ARange[MMAX_RANGE]; char Affinity; enum MResourceAvailabilityPolicyEnum NAvailPolicy[mrLAST]; memset(&tmpJ,0,sizeof(tmpJ)); memset(&tmpN,0,sizeof(tmpN)); memset(&tmpRQ,0,sizeof(tmpRQ)); memset(NAvailPolicy,0,sizeof(NAvailPolicy)); /* configure general */ MSched.Time = 1213931845; MSched.MaxRsvPerNode = 8; /* MSched.RsvSearchAlgo = mrsaWide; */ mlog.logfp = stderr; mlog.Threshold = 8; /* configure reservation */ /* now = 1213931845 */ /* wclimit = 1440000 */ MRsvInitialize(&MRsv[0],NULL,"430806",FALSE); MRsv[0]->Type = mrtJob; MRsv[0]->StartTime = 1213931844; MRsv[0]->EndTime = 1215371844; MRsv[0]->DRes.Procs = 1; bmclear(&MRsv[0]->Flags); MRsv[0]->J = &tmpJ; MRsvInitialize(&MRsv[1],NULL,"elston.437",FALSE); MRsv[1]->Type = mrtUser; MRsv[1]->StartTime = 0; MRsv[1]->EndTime = MMAX_TIME - 1; MRsv[1]->DRes.Procs = 8; bmclear(&MRsv[1]->Flags); MUStrDup(&MRsv[1]->RsvGroup,"elston"); MUStrCpy(tmpLine,"USER==wightman",sizeof(tmpLine)); MACLLoadConfigLine(&MRsv[1]->ACL,tmpLine,mSet,NULL,FALSE); /* configure node */ strcpy(tmpN.Name,"tango065"); tmpN.CRes.Procs = 8; tmpN.ARes.Procs = 8; memcpy(tmpN.NAvailPolicy,NAvailPolicy,sizeof(tmpN.NAvailPolicy)); tmpN.NAvailPolicy[mrProc] = mrapDedicated; /* link node */ tmpN.R = R; tmpN.RE = RE; tmpN.RC = RC; tmpN.R[0] = MRsv[1]; tmpN.RC[0] = 1; tmpN.R[1] = MRsv[0]; tmpN.RC[1] = 8; tmpN.RE[0].Type = mreStart; tmpN.RE[0].BRes.Procs = 1; tmpN.RE[0].Time = 1213931845 - 1; tmpN.RE[0].Index = 1; tmpN.RE[1].Type = mreStart; tmpN.RE[1].BRes.Procs = 0; tmpN.RE[1].Time = 1213931845; tmpN.RE[1].Index = 0; tmpN.RE[2].Type = mreEnd; tmpN.RE[2].BRes.Procs = 8; tmpN.RE[2].Time = 1213931845 - 1 + 1440000; tmpN.RE[2].Index = 1; tmpN.RE[3].Type = mreEnd; tmpN.RE[3].BRes.Procs = 0; tmpN.RE[3].Time = 1213931845 - 1 + 1440000; tmpN.RE[3].Index = 0; tmpN.RE[4].Type = mreStart; tmpN.RE[4].BRes.Procs = 8; tmpN.RE[4].Time = 1213931845 - 1 + 1440000; tmpN.RE[4].Index = 0; tmpN.RE[5].Type = mreEnd; tmpN.RE[5].BRes.Procs = 8; tmpN.RE[5].Time = MMAX_TIME - 1; tmpN.RE[5].Index = 0; tmpN.RE[6].Type = mreNONE; MNode[0] = &tmpN; /* configure job */ strcpy(tmpJ.Name,"430806"); tmpJ.Req[0] = &tmpRQ; tmpJ.WCLimit = 1440000; tmpJ.SpecWCLimit[0] = 1440000; tmpJ.Request.TC = 8; MACLSet(&tmpJ.Cred.CL,maUser,(void *)"wightman",mcmpSEQ,mnmPositiveAffinity,0,FALSE); bmset(&tmpJ.Flags,mjfAdvRsv); MUStrDup(&tmpJ.ReqRID,"elston"); tmpRQ.DRes.Procs = 1; /* configure range requirements */ GRange[0].TC = 8; GRange[0].NC = 0; GRange[0].STime = 1213931845; GRange[0].ETime = 1213931845 + 1440000; GRange[1].ETime = 0; MJobGetSNRange( &tmpJ, &tmpRQ, &tmpN, GRange, MMAX_RANGE, &Affinity, NULL, ARange, NULL, FALSE, NULL); exit(0); /*NOTREACHED*/ #endif /* 0 */ return(SUCCESS); } /* __MSysTestJobGetSNRange() */
int MMBFromString( char *Buf, /* I */ mmb_t **MBP) /* O (alloc) */ { int CTok; mxml_t *E = NULL; mxml_t *ME; char tmpLine[MMAX_LINE << 1]; char Owner[MMAX_NAME]; char Label[MMAX_NAME]; int count; int priority; mmb_t *tmpMB; enum MMBTypeEnum type; mulong etime; char *ptr; /* NOTE: sync w/MMBFromXML() */ if ((Buf == NULL) || (MBP == NULL)) { return(FAILURE); } if (MXMLFromString(&E,Buf,NULL,NULL) == FAILURE) { return(FAILURE); } CTok = -1; while (MXMLGetChild(E,"message",&CTok,&ME) == SUCCESS) { if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaCount],NULL,tmpLine,sizeof(tmpLine)) == SUCCESS) { count = (int)strtol(tmpLine,NULL,10); } else { count = 1; } if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaPriority],NULL,tmpLine,sizeof(tmpLine)) == SUCCESS) { priority = (int)strtol(tmpLine,NULL,10); } else { priority = 1; } MXMLGetAttr(ME,(char *)MMBAttr[mmbaType],NULL,tmpLine,sizeof(tmpLine)); type = (enum MMBTypeEnum)MUGetIndexCI(tmpLine,MMBType,FALSE,mmbtNONE); if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaExpireTime],NULL,tmpLine,sizeof(tmpLine)) == SUCCESS) { etime = strtol(tmpLine,NULL,10); } else { etime = MSched.Time + MCONST_DAYLEN; } if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaOwner],NULL,Owner,sizeof(Owner)) == FAILURE) strcpy(Owner,"N/A"); MXMLGetAttr(ME,(char *)MMBAttr[mmbaLabel],NULL,Label,sizeof(Label)); if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaData],NULL,tmpLine,sizeof(tmpLine)) == FAILURE) { MXMLDestroyE(&E); return(FAILURE); } ptr = tmpLine; /* NOTE: restore checkpoint newlines - sync w/MJobToXML() */ while ((ptr = strchr(ptr,'\7')) != NULL) { *ptr = '\n'; } MXMLDestroyE(&E); if (MMBAdd( MBP, tmpLine, /* I */ Owner, type, etime, priority, &tmpMB) == FAILURE) { return(FAILURE); } if (count > 1) MMBSetAttr(tmpMB,mmbaCount,(void *)&count,mdfInt); if (Label[0] != '\0') MUStrDup(&tmpMB->Label,Label); } /* END while (MXMLGetChild() == SUCCESS) */ return(SUCCESS); } /* END MMBFromString() */
int MCacheWriteJob( mtransjob_t *J) { int rc = SUCCESS; const char *FName = "MCacheWriteJob"; MDB(7,fTRANS) MLog("%s(%s)\n", FName, (MUStrIsEmpty(J->Name)) ? "NULL" : J->Name); if (MCache == NULL) { return(FAILURE); } pthread_rwlock_wrlock(&MCache->JobLock); /* NOTE: we may also want to check J->GridJobID (corresponds to SystemJID * in mjob_t) */ if (!bmisset(&J->TFlags,mtransfLimitedTransition)) { if ((bmisset(&J->TFlags,mtransfDeleteExisting)) && (!MUStrIsEmpty(J->SourceRMJobID))) { rc = MUHTRemove(&MCache->Jobs,J->SourceRMJobID,&MJobTransitionFree); } rc = MUHTAdd(&MCache->Jobs,J->Name,(void*)J,NULL,&MJobTransitionFree); } else { mtransjob_t *tmpJ; if (MUHTGet(&MCache->Jobs,J->Name,(void **)&tmpJ,NULL) == SUCCESS) { int rqindex; /* swap out minimal attributes * All of these attributes are LIMITED TRANSTION, ensure MJobToTransitionStruct() * is in sync with these */ tmpJ->State = J->State; tmpJ->ExpectedState = J->ExpectedState; tmpJ->SubState = J->SubState; tmpJ->StartTime = J->StartTime; tmpJ->CompletionTime = J->CompletionTime; tmpJ->UsedWalltime = J->UsedWalltime; tmpJ->MSUtilized = J->MSUtilized; tmpJ->PSUtilized = J->PSUtilized; tmpJ->PSDedicated = J->PSDedicated; bmcopy(&tmpJ->TFlags,&J->TFlags); tmpJ->Priority = J->Priority; tmpJ->RunPriority = J->RunPriority; tmpJ->EffQueueDuration = J->EffQueueDuration; tmpJ->EligibleTime = J->EligibleTime; bmcopy(&tmpJ->TFlags,&J->TFlags); tmpJ->HoldTime = J->HoldTime; tmpJ->SuspendTime = J->SuspendTime; tmpJ->MaxProcessorCount = J->MaxProcessorCount; tmpJ->CompletionCode = J->CompletionCode; tmpJ->MaxProcessorCount = J->MaxProcessorCount; tmpJ->RsvStartTime = J->RsvStartTime; MUStrDup(&tmpJ->ReservationAccess,J->ReservationAccess); if (!MUStrIsEmpty(J->PerPartitionPriority)) MUStrDup(&tmpJ->PerPartitionPriority,J->PerPartitionPriority); MUStrDup(&tmpJ->BlockReason,J->BlockReason); MUStrDup(&tmpJ->Messages,J->Messages); MUStrDup(&tmpJ->Flags,J->Flags); MUStrDup(&tmpJ->ParentVCs,J->ParentVCs); bmcopy(&tmpJ->GenericAttributes,&J->GenericAttributes); for (rqindex = 0;rqindex < MMAX_REQ_PER_JOB;rqindex++) { if ((J->Requirements[rqindex] == NULL) || (tmpJ->Requirements[rqindex] == NULL)) { /* this could be a serious problem where the job in the cache only has 1 req but the real job has 2, and we are trying to update the second req in the cache but it doesn't exist, this job needs a full transition. For now just ignore (MOAB-2018) */ break; } /* Is the AllocNodeList mstring_t present AND * Does the AllocNodeList have a buffer? NOTE: not is there a non-null string in it */ if ((J->Requirements[rqindex]->AllocNodeList != NULL) && (J->Requirements[rqindex]->AllocNodeList->capacity() > 0)) { /* Copy the AllocNodeList string to the tmpJ AllocNodeList */ *(tmpJ->Requirements[rqindex]->AllocNodeList) = *(J->Requirements[rqindex]->AllocNodeList); } if (J->Requirements[rqindex]->UtilSwap > 0) { tmpJ->Requirements[rqindex]->UtilSwap = J->Requirements[rqindex]->UtilSwap; } if (J->Requirements[rqindex]->MinNodeCount > 0) { tmpJ->Requirements[rqindex]->MinNodeCount = J->Requirements[rqindex]->MinNodeCount; } if (J->Requirements[rqindex]->MinTaskCount > 0) { tmpJ->Requirements[rqindex]->MinTaskCount = J->Requirements[rqindex]->MinTaskCount; } } } } if (DBWRITE) { MMongoInterface::MTransOToMongo(J,mxoJob); } pthread_rwlock_unlock(&MCache->JobLock); if (bmisset(&J->TFlags,mtransfLimitedTransition)) { MJobTransitionFree((void **)&J); } return (rc); } /* END MCacheWriteJob() */
int MMBAdd( mmb_t **Head, /* I (modified) */ char const *MString, /* I */ char const *Owner, /* I (optional) */ enum MMBTypeEnum Type, /* I */ long ExpireTime, /* I (optional, set to <= 0 for default) */ int Priority, /* I */ mmb_t **MMBP) /* O (optional) */ { mmb_t **Tail; mmb_t *MBPtr; char tmpLine[MMAX_LINE << 1]; char *Msg; char *ptr; char *tail; char *Label = NULL; int Index; const char *FName = "MMBAdd"; MDB(7,fSTRUCT) MLog("%s(Head,%.32s...,%s,%s,%ld,%d,MMBP)\n", FName, (MString != NULL) ? MString : "", (Owner != NULL) ? Owner : "NULL", MMBType[Type], ExpireTime, Priority); if (Head == NULL) { return(FAILURE); } if ((MString == NULL) || (MString[0] == '\0')) { return(FAILURE); } /* FORMAT: [<LABEL>:]<MESSAGE> */ /* if label is specified and message is empty, destroy existing label messages */ strncpy(tmpLine,MString,sizeof(tmpLine)); Msg = tmpLine; if ((ptr = strchr(Msg,'\"')) != NULL) { MUStrReplaceChar(ptr,'\"','\'',FALSE); } if ((tail = strchr(Msg,':')) != NULL) { /* label must not contain whitespace and cannot be reserved strings error, alert, or info */ for (ptr = Msg;ptr < tail;ptr++) { if (isspace(*ptr)) break; } if (ptr == tail) { /* label located */ Label = Msg; *tail = '\0'; Msg = tail + 1; } } /* END if ((cp = strchr(AVal[sindex],':')) != NULL) */ if ((Label != NULL) && (MMBGetIndex(*Head,Label,NULL,mmbtNONE,&Index,&MBPtr) == SUCCESS)) { /* messages may be different */ if (Msg[0] == '\0') { /* clear message */ MMBRemove(Index,Head); if (MMBP != NULL) *MMBP = NULL; return(SUCCESS); } else if ((MBPtr->Data == NULL) || strcmp(MBPtr->Data,Msg)) { /* update message - messages are different */ MUStrDup(&MBPtr->Data,Msg); } } else { /* locate existing message or find next available message slot */ if (__MMBFindMessage(*Head,Msg,&MBPtr) != SUCCESS) { MMBGetTail(Head,&Tail); *Tail = (mmb_t *)MUCalloc(1,sizeof(mmb_t)); MBPtr = *Tail; if (Label != NULL) MUStrDup(&MBPtr->Label,Label); MUStrDup(&MBPtr->Data,Msg); } } MBPtr->Count++; if (ExpireTime <= 0) MBPtr->ExpireTime = MSched.Time + MCONST_DAYLEN; else MBPtr->ExpireTime = ExpireTime; MBPtr->Priority = Priority; if (Owner != NULL) MUStrDup(&MBPtr->Owner,Owner); MBPtr->Type = Type; MUGetTime((mulong *)&MBPtr->CTime,mtmNONE,&MSched); if (MMBP != NULL) *MMBP = MBPtr; return(SUCCESS); } /* END MMBAdd() */
int MJobProcessTerminated( mjob_t *J, /* I (modified) */ enum MJobStateEnum JState) /* I */ { if (J == NULL) { return(FAILURE); } MSched.EnvChanged = TRUE; if (J->Cost == 0.0) MJobGetCost(J,FALSE,NULL); if (MSched.PushEventsToWebService == TRUE) { MEventLog *Log = new MEventLog(meltJobEnd); Log->SetCategory(melcEnd); Log->SetFacility(melfJob); Log->SetPrimaryObject(J->Name,mxoJob,(void *)J); if (JState == mjsRemoved) { /* Job was unsuccessful */ Log->SetStatus("failure"); } MEventLogExportToWebServices(Log); delete Log; } /* END if (MSched.PushEventsToWebService == TRUE) */ MJobUpdateFailRate(J); /* update array job information */ if (bmisset(&J->Flags,mjfArrayJob)) { MJobArrayUpdateJobInfo(J,JState); } /* Update any before dependencies */ if (J->Depend != NULL) { mdepend_t *JobDep; mbool_t UpdateDep; JobDep = J->Depend; while (JobDep != NULL) { UpdateDep = FALSE; switch (JobDep->Type) { case mdJobBefore: /* Taken care of in MJobStart */ break; case mdJobBeforeAny: UpdateDep = TRUE; break; case mdJobBeforeSuccessful: if (J->CompletionCode == 0) UpdateDep = TRUE; break; case mdJobBeforeFailed: if (J->CompletionCode != 0) UpdateDep = TRUE; break; default: break; } if (UpdateDep == TRUE) { mjob_t *OtherJ; if (MJobFind(JobDep->Value,&OtherJ,mjsmExtended) == FAILURE) { /* Couldn't find the dependent job */ MDB(4,fSTAT) MLog("WARNING: could not find job '%s' to update %s dependency for job '%s'\n", JobDep->Value, MDependType[JobDep->Type], J->Name); } else { /* Job Found, update any onCount dependencies */ mdepend_t *OtherDep; OtherDep = OtherJ->Depend; while (OtherDep != NULL) { char *UsedJobs = NULL; if (OtherDep->Type != mdJobOnCount) { OtherDep = OtherDep->NextAnd; continue; } if (OtherDep->DepList == NULL) { /* ctor the mstring_t */ OtherDep->DepList = new mstring_t(MMAX_LINE); OtherDep->ICount = strtol(OtherDep->Value,NULL,10); /* 0 is error in strtol */ if (OtherDep->ICount == 0) { OtherDep = OtherDep->NextAnd; continue; } } MUStrDup(&UsedJobs,OtherDep->DepList->c_str()); if ((UsedJobs != NULL) && (MUStrRemoveFromList(UsedJobs,J->Name,',',FALSE) != FAILURE)) { /* Job dependency was already reported */ OtherDep = OtherDep->NextAnd; continue; } *OtherDep->DepList += ','; *OtherDep->DepList += J->Name; OtherDep->ICount--; if (UsedJobs != NULL) MUFree(&UsedJobs); OtherDep = OtherDep->NextAnd; } /* END while (OtherDep != NULL) */ } /* END else (MJobFind returned SUCCESS) */ } /* END if (UpdateDep == TRUE) */ JobDep = JobDep->NextAnd; } } /* If job is a VM destroy job, removed blocking flags on VM */ __MJobProcessVMDestroy(J); /* Copy any VC variables to the VC. This is so that pending actions will still have access to variables at the service level. This may be removed later once pending actions are fully designed with the workflow model */ MVCGrabVarsInHierarchy(J->ParentVCs,&J->Variables,TRUE); if (MSched.EnableHighThroughput == FALSE) MJobTransition(J,TRUE,FALSE); return(SUCCESS); } /* END MJobProcessTerminated() */
int MUMAGetIndex( enum MExpAttrEnum AIndex, /* I Attribute Type */ char const *Value, /* I Attribute Index */ enum MObjectSetModeEnum Mode) /* I Search Mode */ { /* determine index of up to MMAX_ATTR attribute values */ int index; int len; const char *FName = "MUMAGetIndex"; MDB(9,fSTRUCT) MLog("%s(%s,%s,%s)\n", FName, MAttrType[AIndex], (Value != NULL) ? Value : "NULL", MObjOpType[Mode]); if ((AIndex == meGRes) || (AIndex == meGMetrics)) { return(MUGenericGetIndex(AIndex,Value,Mode)); } if ((Value == NULL) || (Value[0] == '\0')) { /* FAILURE */ return(0); } len = sizeof(MAList[0][0]) - 1; for (index = 1;index < MMAX_ATTR;index++) { if (!strncasecmp(MAList[AIndex][index],Value,len)) { return(index); } if (MAList[AIndex][index][0] == '\0') break; } /* END for (index) */ if (Mode == mVerify) { /* didn't find value -- FAILURE */ return(0); } /* NOTE: GRes may be more constrained than MAList, return failure */ if ((AIndex == meGRes) && (Mode == mAdd)) { if (index >= MSched.M[mxoxGRes] + 1) { if (MSched.OFOID[mxoxGRes] == NULL) MUStrDup(&MSched.OFOID[mxoxGRes],Value); MDB(1,fCONFIG) MLog("ALERT: no empty slots for %s in MAList[%s] (increase MAXGRES)\n", Value, MAttrType[AIndex]); /* FAILURE */ return(0); } MSched.GResCount = MAX(MSched.GResCount,index); } /* END if ((AIndex == meGRes) && ...) */ /* add new value to table */ MUStrCpy(MAList[AIndex][index],Value,sizeof(MAList[0][0])); MDB(5,fCONFIG) MLog("INFO: adding MAList[%s][%d]: '%s'\n", MAttrType[AIndex], index, Value); /* SUCCESS */ return(index); } /* END MUMAGetIndex() */
int MNodeProcessConfig( mnode_t *N, /* I (modified) */ mrm_t *R, /* I (optional) */ char *Value) /* I (modified) */ { char *ptr; char *TokPtr; char *ptr2; char ValBuf[MMAX_BUFFER]; char AttrArray[MMAX_NAME]; int aindex; enum MNodeAttrEnum AIndex; int tmpInt; int tmpI; double tmpD; int SlotsUsed = -1; int rc; enum MObjectSetModeEnum CIndex; mbool_t FailureDetected; const char *FName = "MNodeProcessConfig"; MDB(5,fSTRUCT) MLog("%s(%s,%s,%s)\n", FName, (N != NULL) ? N->Name : "NULL", (R != NULL) ? R->Name : "NULL", (Value != NULL) ? Value : "NULL"); if ((N == NULL) || (Value == NULL) || (Value[0] == '\0')) { return(FAILURE); } ptr = MUStrTokE(Value," \t\n",&TokPtr); FailureDetected = FALSE; while (ptr != NULL) { /* parse name-value pairs */ /* FORMAT: <ATTR>=<VALUE>[,<VALUE>] */ if (MUGetPair( ptr, (const char **)MNodeAttr, &aindex, /* O */ AttrArray, TRUE, &tmpI, /* O */ ValBuf, /* O */ MMAX_BUFFER) == FAILURE) { char tmpLine[MMAX_LINE]; /* cannot parse value pair */ snprintf(tmpLine,sizeof(tmpLine),"unknown attribute '%.128s' specified", ptr); MDB(3,fSTRUCT) MLog("WARNING: unknown attribute '%s' specified for node %s\n", ptr, (N != NULL) ? N->Name : "NULL"); MMBAdd(&N->MB,tmpLine,NULL,mmbtNONE,0,0,NULL); ptr = MUStrTokE(NULL," \t\n",&TokPtr); continue; } rc = SUCCESS; AIndex = (enum MNodeAttrEnum)aindex; switch (tmpI) { case 1: CIndex = mIncr; break; case -1: CIndex = mDecr; break; case 0: default: CIndex = mSet; break; } /* END switch (CIndex) */ switch (AIndex) { case mnaAccess: case mnaAccountList: case mnaArch: case mnaCfgClass: case mnaClassList: case mnaFlags: case mnaGroupList: case mnaJTemplateList: case mnaNodeIndex: case mnaPowerPolicy: case mnaMaxProcPerClass: case mnaProvRM: case mnaQOSList: case mnaUserList: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,CIndex); break; case mnaComment: /* add as node message */ { mmb_t *MB; MMBAdd( &N->MB, (char *)ValBuf, MSCHED_SNAME, mmbtAnnotation, MMAX_TIME, 0, &MB); if (MB != NULL) MUStrDup(&MB->Label,"comment"); } /* END BLOCK (case mnaComment) */ break; case mnaAvlClass: if (!bmisset(&N->IFlags,mnifRMClassUpdate)) { MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); } break; case mnaAvlMemW: if ((N->P != NULL) || (MNPrioAlloc(&N->P) == SUCCESS)) { N->P->CW[mnpcAMem] = strtod(ValBuf,NULL); N->P->CWIsSet = TRUE; } break; case mnaAvlProcW: if ((N->P != NULL) || (MNPrioAlloc(&N->P) == SUCCESS)) { N->P->CW[mnpcAProcs] = strtod(ValBuf,NULL); N->P->CWIsSet = TRUE; } break; case mnaRCMem: { bmunset(&N->IFlags,mnifMemOverride); /* unset so that new values can be set dynamically */ MNodeSetAttr(N,mnaRCMem,(void **)ValBuf,mdfString,mSet); if (ValBuf[strlen(ValBuf) - 1] == '^') bmset(&N->IFlags,mnifMemOverride); } break; case mnaCfgMemW: if ((N->P != NULL) || (MNPrioAlloc(&N->P) == SUCCESS)) { N->P->CW[mnpcCMem] = strtod(ValBuf,NULL); N->P->CWIsSet = TRUE; } break; case mnaRCProc: N->CRes.Procs = (int)strtol(ValBuf,NULL,10); break; case mnaCfgProcW: if ((N->P != NULL) || (MNPrioAlloc(&N->P) == SUCCESS)) { N->P->CW[mnpcCProcs] = strtod(ValBuf,NULL); N->P->CWIsSet = TRUE; } break; case mnaRCSwap: { bmunset(&N->IFlags,mnifSwapOverride); /* unset so that value can be set dynamically */ MNodeSetAttr(N,mnaRCSwap,(void **)ValBuf,mdfString,mSet); if (ValBuf[strlen(ValBuf) - 1] == '^') bmset(&N->IFlags,mnifSwapOverride); } break; case mnaFailure: { char *ptr; char *TokPtr; int findex; enum MNodeFailEnum { mnfNONE, mnfState, mnfMem, mnfSwap, mnfLoad }; const char *NFType[] = { NONE, "STATE", "MEM", "SWAP", "LOAD", NULL }; ptr = MUStrTok(ValBuf,",",&TokPtr); while (ptr != NULL) { findex = MUGetIndex(ptr,NFType,FALSE,0); switch (findex) { case mnfState: MNodeSetState(N,mnsDown,FALSE); if (N->Message == NULL) { MUStrDup(&N->Message,"node is down"); } break; case mnfMem: tmpInt = 0; MNodeSetAttr(N,mnaRAMem,(void **)&tmpInt,mdfInt,mSet); MUStrDup(&N->Message,"memory is low"); break; case mnfSwap: tmpInt = 3; MNodeSetAttr(N,mnaRASwap,(void **)&tmpInt,mdfInt,mSet); MUStrDup(&N->Message,"swap is low"); break; case mnfLoad: N->ARes.Procs = 0; N->Load = 4.3; MUStrDup(&N->Message,"excessive processor usage"); break; case mnfNONE: default: /* NO-OP */ break; } /* END switch (findex) */ ptr = MUStrTok(NULL,",",&TokPtr); } /* END while (ptr != NULL) */ } /* END BLOCK */ break; case mnaFeatures: { char tmpBuffer[MMAX_BUFFER]; char *TokPtr2; /* FORMAT: <FEATURE>[{ ,:}<FEATURE>]... */ /* NOTE: Mode == mDecr NOT supported */ /* if '!' specified, update named feature */ /* NOTE: if features specified via config file, should be appended to features discovered via RM */ MSched.NodeFeaturesSpecifiedInConfig = TRUE; if (CIndex == mSet) { bmclear(&N->FBM); } strcpy(tmpBuffer,ValBuf); ptr2 = MUStrTok(tmpBuffer,":, \t\n",&TokPtr2); while (ptr2 != NULL) { MNodeProcessFeature(N,ptr2); ptr2 = MUStrTok(NULL,":, \t\n",&TokPtr2); } /* END while (ptr != NULL) */ } /* END BLOCK (case mnaFeatures) */ /* Moab owns feature indicated by clearing RM ownership bit */ bmunset(&N->RMAOBM,mnaFeatures); break; case mnaCfgGRes: case mnaChargeRate: case mnaEnableProfiling: if (MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet) == FAILURE) { /* complete or partial failure setting attribute */ /* NO-OP */ } break; case mnaKbdDetectPolicy: case mnaKbdIdleTime: case mnaMinPreemptLoad: case mnaMinResumeKbdIdleTime: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); break; case mnaLoadW: if ((N->P != NULL) || (MNPrioAlloc(&N->P) == SUCCESS)) { N->P->CW[mnpcLoad] = strtod(ValBuf,NULL); N->P->CWIsSet = TRUE; } break; case mnaLogLevel: N->LogLevel = (int)strtol(ValBuf,NULL,10); break; case mnaMaxJob: { tmpI = (int)strtol(ValBuf,NULL,10); if (AttrArray[0] == '\0') { N->AP.HLimit[mptMaxJob] = tmpI; } else { /* NYI */ } } /* END BLOCK */ break; case mnaMaxProc: { tmpI = (int)strtol(ValBuf,NULL,10); if (AttrArray[0] == '\0') { N->AP.HLimit[mptMaxProc] = tmpI; } } /* END BLOCK */ break; case mnaMaxJobPerGroup: tmpI = (int)strtol(ValBuf,NULL,10); if (N->NP == NULL) { if ((N->NP = (mnpolicy_t *)MUCalloc(1,sizeof(mnpolicy_t))) == NULL) break; } N->NP->MaxJobPerGroup = tmpI; break; case mnaMaxJobPerUser: tmpI = (int)strtol(ValBuf,NULL,10); if (N->NP == NULL) { if ((N->NP = (mnpolicy_t *)MUCalloc(1,sizeof(mnpolicy_t))) == NULL) break; } N->NP->MaxJobPerUser = tmpI; break; case mnaMaxLoad: case mnaMaxWCLimitPerJob: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); break; case mnaMaxProcPerGroup: tmpI = (int)strtol(ValBuf,NULL,10); if (N->NP == NULL) { if ((N->NP = (mnpolicy_t *)MUCalloc(1,sizeof(mnpolicy_t))) == NULL) break; } N->NP->MaxProcPerGroup = tmpI; break; case mnaMaxProcPerUser: tmpI = (int)strtol(ValBuf,NULL,10); if (N->NP == NULL) { if ((N->NP = (mnpolicy_t *)MUCalloc(1,sizeof(mnpolicy_t))) == NULL) break; } N->NP->MaxProcPerUser = tmpI; break; case mnaMaxWatts: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); break; case mnaOS: case mnaOSList: case mnaVMOSList: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); break; case mnaNodeType: MUStrDup(&N->NodeType,ValBuf); break; case mnaResOvercommitFactor: case mnaAllocationLimits: if (N->ResOvercommitFactor == NULL) { if ((N->ResOvercommitFactor = (double *)MUCalloc(1,sizeof(double) * mrlLAST)) == NULL) { return(FAILURE); } } MUResFactorArrayFromString((char *)ValBuf,N->ResOvercommitFactor,NULL,TRUE,FALSE); break; case mnaResOvercommitThreshold: case mnaUtilizationThresholds: if (N->ResOvercommitThreshold == NULL) { if ((N->ResOvercommitThreshold = (double *)MUCalloc(1,sizeof(double) * mrlLAST)) == NULL) { return(FAILURE); } } if (N->GMetricOvercommitThreshold == NULL) { int gmindex; if ((N->GMetricOvercommitThreshold = (double *)MUCalloc(1,sizeof(double) * MSched.M[mxoxGMetric])) == NULL) { return(FAILURE); } /* initialize all thresholds to 'unset' value */ for (gmindex = 0;gmindex < MSched.M[mxoxGMetric]; gmindex++) { N->GMetricOvercommitThreshold[gmindex] = MDEF_GMETRIC_VALUE; } } MUResFactorArrayFromString((char *)ValBuf,N->ResOvercommitThreshold,N->GMetricOvercommitThreshold,TRUE,FALSE); break; case mnaOwner: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); break; case mnaPartition: case mnaPreemptMaxCPULoad: case mnaPreemptMinMemAvail: case mnaPreemptPolicy: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); break; case mnaPrioF: { mnprio_t *tmpPriorityFunc = NULL; if (MProcessNAPrioF(&tmpPriorityFunc,ValBuf) == FAILURE) { MNPrioFree(&tmpPriorityFunc); return(FAILURE); } /* clear out existing priority function */ MNPrioFree(&N->P); N->P = tmpPriorityFunc; } /* END BLOCK */ break; case mnaPriority: N->Priority = (int)strtol(ValBuf,NULL,10); N->PrioritySet = TRUE; break; case mnaPrioW: if ((N->P != NULL) || (MNPrioAlloc(&N->P) == SUCCESS)) { N->P->CW[mnpcPriority] = strtod(ValBuf,NULL); N->P->CWIsSet = TRUE; } break; case mnaProcSpeed: tmpI = (int)strtol(ValBuf,NULL,10); N->ProcSpeed = tmpI; break; case mnaRack: { /* FORMAT: <RACKINDEX>|<RACKNAME> */ if (isdigit(ValBuf[0])) { tmpI = (int)strtol(ValBuf,NULL,10); } else { if (MRackAdd(ValBuf,&tmpI,NULL) == FAILURE) { /* cannot add rack */ break; } } rc = MNodeSetAttr(N,mnaRack,(void **)&tmpI,mdfInt,mSet); } /* END BLOCK */ break; case mnaRADisk: case mnaRCDisk: case mnaMaxPE: case mnaMaxPEPerJob: case mnaRMList: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); break; case mnaSize: tmpI = (int)strtol(ValBuf,NULL,10); SlotsUsed = tmpI; break; case mnaSlot: rc = MNodeSetAttr(N,mnaSlot,(void **)ValBuf,mdfString,mSet); break; case mnaSpeed: tmpD = strtod(ValBuf,NULL); if (tmpD == 0.0) { tmpD = 0.01; } N->Speed = MIN(100.0,tmpD); break; case mnaSpeedW: if ((N->P != NULL) || (MNPrioAlloc(&N->P) == SUCCESS)) { N->P->CW[mnpcSpeed] = strtod(ValBuf,NULL); N->P->CWIsSet = TRUE; } break; case mnaTrigger: { marray_t TList; int tindex; mtrig_t *T; MUArrayListCreate(&TList,sizeof(mtrig_t *),4); MTrigLoadString(&N->T,ValBuf,TRUE,FALSE,mxoNode,N->Name,&TList,NULL); if (N->T != NULL) { for (tindex = 0;tindex < TList.NumItems;tindex++) { T = (mtrig_t *)MUArrayListGetPtr(&TList,tindex); if (MTrigIsValid(T) == FALSE) continue; MTrigInitialize(T); } /* END for (tindex) */ } MUArrayListFree(&TList); } /* END BLOCK mnaTrigger */ break; case mnaUsageW: if ((N->P != NULL) || (MNPrioAlloc(&N->P) == SUCCESS)) { N->P->CW[mnpcUsage] = strtod(ValBuf,NULL); N->P->CWIsSet = TRUE; } break; #if 0 /* this is not used anywhere */ case mnaResource: /* FORMAT: <RESNAME>:<RESCOUNT>[,<RESNAME>:<RESCOUNT>]... */ { char *ptr; char *TokPtr; ptr = MUStrTok(ValBuf,", \t",&TokPtr); while (ptr != NULL) { /* FORMAT: <RESDESC>[{ \t,}<RESDESC]... */ MNodeSetAttr(N,mnaCfgGRes,(void **)ptr,mdfString,mSet); ptr = MUStrTok(NULL,", \t",&TokPtr); } } /* END BLOCK */ break; #endif case mnaVariables: MNodeSetAttr(N,AIndex,(void **)ValBuf,mdfString,mSet); break; default: /* NO-OP */ break; } /* END switch (AIndex) */ if (rc == FAILURE) FailureDetected = TRUE; ptr = MUStrTokE(NULL," \t\n",&TokPtr); } /* END while (ptr != NULL) */ if (FailureDetected == TRUE) { return(FAILURE); } /* sync 'side-effects' */ if (SlotsUsed > 0) { N->SlotsUsed = SlotsUsed; if ((N->RackIndex > 0) && (N->SlotIndex > 0)) MSys[N->RackIndex][N->SlotIndex].SlotsUsed = SlotsUsed; } return(SUCCESS); } /* END MNodeProcessConfig() */
int MTrigLaunchInternalAction( mtrig_t *T, /* I (optional) */ char *ActionString, /* I */ mbool_t *Complete, /* O */ char *Msg) /* O (optional,minsize=MMAX_LINE) */ { /* FORMAT: <OTYPE>:<OID>:<ACTION>:<context information> */ char *ptr = NULL; char *TokPtr = NULL; char *tmpAString = NULL; char ArgLine[MMAX_LINE*10]; char OID[MMAX_BUFFER]; char Action[MMAX_LINE*10]; enum MXMLOTypeEnum OType; const char *FName = "MTrigLaunchInternalAction"; MDB(4,fSCHED) MLog("%s(%s,%s,Msg)\n", FName, ((T != NULL) && (T->TName != NULL)) ? T->TName : "NULL", (ActionString != NULL) ? ActionString : "NULL"); if (Msg != NULL) Msg[0] = '\0'; if (Complete != NULL) *Complete = TRUE; if (ActionString == NULL) { if (Msg != NULL) strcpy(Msg,"internal error"); return(FAILURE); } MUStrDup(&tmpAString,ActionString); /* NOTE: this format and parsing is duplicated in MTrigCheckInternalAction() any update here must be copied to that routine */ ptr = MUStrTok(tmpAString,":",&TokPtr); if (ptr == NULL) { MDB(4,fSCHED) MLog("ERROR: invalid action"); if (Msg != NULL) strcpy(Msg,"invalid action"); MUFree(&tmpAString); return(FAILURE); } OType = (enum MXMLOTypeEnum)MUGetIndexCI(ptr,MXO,FALSE,mxoNONE); if (OType == mxoNONE) { MDB(4,fSCHED) MLog("ERROR: invalid object type '%s' in %s\n", ptr, FName); if (Msg != NULL) strcpy(Msg,"invalid object type"); MUFree(&tmpAString); return(FAILURE); } ptr = MUStrTok(NULL,":",&TokPtr); if (ptr == NULL) { MDB(4,fSCHED) MLog("ERROR: cannot extract object ID in %s\n", FName); if (Msg != NULL) strcpy(Msg,"invalid object id"); MUFree(&tmpAString); return(FAILURE); } MUStrCpy(OID,ptr,sizeof(OID)); ptr = MUStrTok(NULL,":",&TokPtr); if (ptr == NULL) { MDB(4,fSCHED) MLog("ERROR: cannot parse action in %s\n", FName); if (Msg != NULL) strcpy(Msg,"cannot locate action"); MUFree(&tmpAString); return(FAILURE); } MUStrCpy(Action,ptr,sizeof(Action)); if ((TokPtr != NULL) && (TokPtr[0] != '\0')) MUStrCpy(ArgLine,TokPtr,sizeof(ArgLine)); else ArgLine[0] = '\0'; MUFree(&tmpAString); switch (OType) { case mxoJob: { mjob_t *J; char *JID; char *TokPtr; /* OID FORMAT: <JID>[+<JID>]... */ mbool_t FailureDetected; enum MJobCtlCmdEnum atype; atype = (enum MJobCtlCmdEnum)MUGetIndexCI(Action,MJobCtlCmds,FALSE,mjcmNONE); if (atype == mjcmNONE) { MDB(4,fSCHED) MLog("ERROR: cannot parse job action '%s' in %s\n", Action, FName); return(FAILURE); } FailureDetected = FALSE; JID = MUStrTok(OID,"+",&TokPtr); while (JID != NULL) { if (!strcmp(JID,"-")) { if (T == NULL) return(FAILURE); J = (mjob_t *)T->O; } else if (MJobFind(JID,&J,mjsmExtended) == FAILURE) { MDB(4,fSCHED) MLog("ERROR: cannot locate job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } switch (atype) { case mjcmCancel: { char *CCodeCheck; char UpperArgLine[MMAX_LINE]; MDB(7,fSCHED) MLog(" INFO: Job flaged for cancel by trigger action. '%s' in %s\n", JID, FName); bmset(&J->IFlags, mjifCancel); MUStrToUpper(ArgLine,UpperArgLine,MMAX_LINE); /* If specified, allow trigger to set the completion code of the job */ if ((CCodeCheck = strstr(UpperArgLine,"CCODE=")) != NULL) { CCodeCheck += strlen("CCODE="); /* Skip the "CCODE:" part */ if (CCodeCheck[0] != '\0') { J->CompletionCode = strtol(CCodeCheck,NULL,10); } } else { J->CompletionCode = 273; /* Completion code for a canceled job in TORQUE */ } } /* END case mjcmCancel */ break; case mjcmComplete: { char *CCodeCheck; char UpperArgLine[MMAX_LINE]; if ((!bmisset(&J->Flags,mjfSystemJob) && !bmisset(&J->Flags,mjfNoRMStart))) { MDB(4,fSCHED) MLog("ERROR: job %s in bad state for complete in %s\n", J->Name, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } /* the next three lines set the WCLimit to the exact runtime * this also causes MS3WorkloadQuery to remove the job */ J->SpecWCLimit[0] = MSched.Time - J->StartTime; J->SpecWCLimit[1] = MSched.Time - J->StartTime; J->WCLimit = MSched.Time - J->StartTime; if (MJOBISACTIVE(J) == TRUE) { MRsvJCreate(J,NULL,J->StartTime,mjrActiveJob,NULL,FALSE); /* just removes active rsv? */ } MUStrToUpper(ArgLine,UpperArgLine,MMAX_LINE); if ((CCodeCheck = strstr(UpperArgLine,"CCODE=")) != NULL) { CCodeCheck += strlen("CCODE="); /* Skip the "CCODE:" part */ if (CCodeCheck[0] != '0') { J->CompletionCode = strtol(CCodeCheck,NULL,10); } } /* MSched.TrigCompletedJob = TRUE; -- not sure why we wanted to skip the UI phase here... */ } /* END BLOCK (case mjcmComplete) */ break; case mjcmModify: { char *TokPtr; char *Attr = NULL; char *Value = NULL; char *Msg = NULL; enum MJobAttrEnum aindex; enum MObjectSetModeEnum Op; if (strstr(ArgLine,"+=")) Op = mAdd; else if (strstr(ArgLine,"-=")) Op = mDecr; else Op = mSet; Attr = MUStrTok(ArgLine,"+-=",&TokPtr); Value = MUStrTok(NULL,"=: \t\n",&TokPtr); Msg = MUStrTok(NULL,":\t\n",&TokPtr); /* extract message */ aindex = (enum MJobAttrEnum)MUGetIndexCI(Attr,MJobAttr,FALSE,mnaNONE); switch (aindex) { case mjaHold: if (MJobSetAttr(J,mjaHold,(Value != NULL) ? (void **)Value : (void **)"batch",mdfString,mSet) == FAILURE) { MDB(4,fSCHED) MLog("ERROR: cannot hold job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } if (Msg != NULL) { /* attach provided message */ MMBAdd( &J->MessageBuffer, Msg, NULL, mmbtHold, 0, 0, NULL); } if (MJOBISACTIVE(J)) { /* Set to idle but don't clear DRM and DRMJID */ MJobToIdle(J,FALSE,FALSE); J->SubState = mjsstNONE; } /* checkpoint change (make this configurable at this point?) */ MOCheckpoint(mxoJob,(void *)J,FALSE,NULL); break; case mjaVariables: { char tmpLine[MMAX_LINE*2]; snprintf(tmpLine,sizeof(tmpLine),"%s=%s", Value, Msg); if (MJobSetAttr(J,mjaVariables,(void **)tmpLine,mdfString,Op) == FAILURE) { MDB(4,fSCHED) MLog("ERROR: cannot set trigvar job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } } /* END BLOCK */ break; default: if (!strcasecmp(Attr,"gres")) { if ((Op == mAdd) && (MJobAddRequiredGRes( J, Value, 1, mxaGRes, FALSE, FALSE) == SUCCESS)) { /* SUCCESS - NO-OP */ } else if ((Op == mDecr) && (MJobRemoveGRes(J,Value,TRUE) == SUCCESS)) { /* SUCCESS -- Do Nothing */ } else { MDB(4,fSCHED) MLog("ERROR: cannot adjust gres for job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } } else { MDB(4,fSCHED) MLog("ERROR: cannot modify attribute '%s' for job '%s' in %s\n", Attr, JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } break; } } /* END BLOCK (case mjcmModify) */ break; case mjcmSignal: { char EMsg[MMAX_LINE]; int SC; if (MRMJobSignal(J,-1,ArgLine,EMsg,&SC) == FAILURE) { MDB(4,fSCHED) MLog("ERROR: cannot send signal '%s' to job '%s' in %s\n", ArgLine, JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } } /* END BLOCK (case mjcmSignal) */ break; case mjcmStart: /* FIXME: check reservation, check allocation */ { J->SubState = mjsstNONE; /* set "copy-tasklist" flag */ bmset(&J->IFlags,mjifCopyTaskList); if (MRMJobStart(J,NULL,NULL) == FAILURE) { MDB(4,fSCHED) MLog("ERROR: cannot start job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } J->State = mjsRunning; } /* END BLOCK (case mjcmStart) */ break; case mjcmRequeue: /* FIXME: check reservation, check allocation */ { char EMsg[MMAX_LINE]; J->SubState = mjsstNONE; /* set "copy-tasklist" flag */ if (MJobRequeue(J,NULL,"workflow failure",EMsg,NULL) == FAILURE) { MDB(4,fSCHED) MLog("ERROR: cannot requeue job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } J->State = mjsIdle; } /* END BLOCK (case mjcmStart) */ default: MDB(4,fSCHED) MLog("ERROR: action '%s' not handled in %s\n", Action, FName); return(FAILURE); /*NOTREACHED*/ break; } /* END switch (atype) */ JID = MUStrTok(NULL,"+",&TokPtr); } /* END while (JID != NULL) */ if (FailureDetected == TRUE) { return(FAILURE); } } /* END BLOCK (case mxoJob) */ break; case mxoNode: { enum MNodeCtlCmdEnum atype; char *rsvProfile = NULL; atype = (enum MNodeCtlCmdEnum)MUGetIndexCI(Action,MNodeCtlCmds,FALSE,mncmNONE); if (!strcasecmp(Action,"reserve")) { char tmpLine[MMAX_LINE]; snprintf(tmpLine,sizeof(tmpLine),"auto-trigger-rsv.%s", T->TName); if (ArgLine[0] != '\0') { char *Attr = MUStrTok(ArgLine,"=",&TokPtr); char *Value = MUStrTok(NULL,"= \t\n",&TokPtr); if ((Attr != NULL) && (strncasecmp(Attr,"rsvprofile",strlen("rsvprofile")) == 0)) rsvProfile = Value; } if (T->OType != mxoRsv) { MNodeReserve( (mnode_t *)T->O, MCONST_EFFINF, tmpLine, rsvProfile, "Reservation created by trigger"); return(SUCCESS); } else { return(FAILURE); } } else if ((!strcasecmp(Action,"evacvms")) && (MSched.AllowVMMigration == TRUE)) { /* Evacuate all vms on nodes held by this reservation */ char tmpMsg[MMAX_LINE]; int rc = SUCCESS; mnl_t NL; MNLInit(&NL); MNLFromString(OID,&NL,1,FALSE); rc = MNodeEvacVMsMultiple(&NL); MNLFree(&NL); /* Write out events */ snprintf(tmpMsg,sizeof(tmpMsg),"attempting to migrate vms from node '%s' for evacvms reservation '%s' (TID: %s)", OID, ((mrsv_t *)T->O)->Name, (T->TName != NULL) ? T->TName : "NULL"); MDB(5,fSTRUCT) MLog("INFO: %s\n", tmpMsg); return(rc); } /* END if (!strcasecmp(Action,"evacvms")) */ if (atype == mncmNONE) { return(FAILURE); } switch (atype) { case mncmModify: if (MSched.AggregateNodeActions == FALSE) { char *ptr; char *TokPtr; mnode_t *N; char *Attr; char *Value; enum MNodeAttrEnum aindex; /* always look on the bright side of life */ mbool_t NodeModifySuccessDetected; /* FORMAT: <ARG>=<VALUE> */ Attr = MUStrTok(ArgLine,"=",&TokPtr); Value = MUStrTok(NULL,"= \t\n",&TokPtr); aindex = (enum MNodeAttrEnum)MUGetIndexCI(Attr,MNodeAttr,FALSE,mnaNONE); NodeModifySuccessDetected = FALSE; /* FORMAT: OID = node[,node]... */ ptr = MUStrTok(OID,",",&TokPtr); if ((ptr == NULL) || (aindex == mnaNONE)) { MDB(4,fSCHED) MLog("ERROR: unknown attribute to modify on node '%s'\n", Attr); return(FAILURE); } while (ptr != NULL) { if (MNodeFind(ptr,&N) == FAILURE) { ptr = MUStrTok(NULL,",",&TokPtr); continue; } switch (aindex) { case mnaOS: { char EMsg[MMAX_LINE]; if (!strcmp(Value,MAList[meOpsys][0])) { if ((N->PowerSelectState == mpowOff) && (MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify) == FAILURE)) { if (Msg != NULL) MUStrCpy(Msg,EMsg,MMAX_LINE); /* do not return failure just because one provisioning job fails */ } } else if (MNodeProvision(N,NULL,NULL,Value,TRUE,EMsg,NULL) == FAILURE) { if (Msg != NULL) MUStrCpy(Msg,EMsg,MMAX_LINE); /* do not return failure just because one provisioning job fails */ } else { NodeModifySuccessDetected = TRUE; } } break; case mnaPowerIsEnabled: /* NOTE: do not return failure just because node modify fails * the routine will fail if all node modifies fail */ if (!strcmp(Value,"on")) { /* power node on */ if (MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify) == SUCCESS) { NodeModifySuccessDetected = TRUE; } } else if (!strcasecmp(Value,"off")) { /* power node off */ if (MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"false",mdfString,mVerify) == SUCCESS) { NodeModifySuccessDetected = TRUE; } } else if (!strcasecmp(Value,"reset")) { char EMsg[MMAX_LINE]; /* reset node */ if (MNodeReboot(N,NULL,EMsg,NULL) == FAILURE) { if (Msg != NULL) MUStrCpy(Msg,EMsg,MMAX_LINE); } else { NodeModifySuccessDetected = TRUE; } } else if (!strcasecmp(Value,"on+")) { /* power node on, but trigger isn't finished until action is complete */ if (Complete != NULL) *Complete = FALSE; if (T != NULL) MUStrDup(&T->CompleteAction,ActionString); MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify); T->PID = 1; } else if (!strcasecmp(Value,"off+")) { /* power node off, but trigger isn't finished until action is complete */ if (T != NULL) MUStrDup(&T->CompleteAction,ActionString); if (Complete != NULL) *Complete = FALSE; MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"false",mdfString,mVerify); T->PID = 1; } break; default: return(FAILURE); /*NOTREACHED*/ break; } /* END switch (aindex) */ ptr = MUStrTok(NULL,",",&TokPtr); } /* END while (ptr != NULL) */ /* if none of the node modify requests (non-aggregating) succeeded, then return failure. (success just means it was submitted at this stage) */ if ((aindex == mnaOS) && (NodeModifySuccessDetected == FALSE)) { return (FAILURE); } } /* END if (MSched.AggregateNodeActions == FALSE) */ else { mnl_t NL; char *Attr; char *Value; enum MNodeAttrEnum aindex; int nindex; /* FORMAT: <ARG>=<VALUE> */ Attr = MUStrTok(ArgLine,"=",&TokPtr); Value = MUStrTok(NULL,"= \t\n",&TokPtr); aindex = (enum MNodeAttrEnum)MUGetIndexCI(Attr,MNodeAttr,FALSE,mnaNONE); /* FORMAT: OID = node[,node]... */ if (aindex == mnaNONE) { return(FAILURE); } MNLInit(&NL); MNLFromString(OID,&NL,-1,FALSE); /* NOTE: in the node aggregating case, return failure when there is an error * performing node modify operations (e.g. communicating with the RM) */ switch (aindex) { case mnaNodeState: { enum MStatusCodeEnum SC; char EMsg[MMAX_LINE]; if (MNodeModify(NULL,OID,mnaNodeState,Value,EMsg,&SC) == FAILURE) { MDB(2,fRM) MLog("WARNING: cannot modify state of '%s' = %s\n", OID, EMsg); return(FAILURE); } } /* END case mnaNodeState */ break; case mnaOS: { char EMsg[MMAX_LINE]; if (MNLGetemReady(&NL,Value,EMsg) == FAILURE) { /* NYI: append EMsg to Msg */ if (Msg != NULL) MUStrCpy(Msg,EMsg,MMAX_LINE); MNLFree(&NL); return (FAILURE); } } /* END BLOCK case mnaOS */ break; case mnaPowerIsEnabled: { mnode_t *N; for (nindex = 0;MNLGetNodeAtIndex(&NL,nindex,&N) == SUCCESS;nindex++) { if (N == MSched.GN) continue; if ((!strcasecmp(Value,"on")) || (!strcasecmp(Value,"on+"))) { /* power node on */ if ((N->PowerSelectState == mpowOn) || (MNodeGetSysJob(N,msjtPowerOn,MBNOTSET,NULL) == SUCCESS)) { /* skip this node */ MDB(5,fSCHED) MLog("INFO: not powering node '%s' on--power select state is already 'ON'\n", N->Name); MNLRemove(&NL,N); continue; } } else if ((!strcasecmp(Value,"off")) || (!strcasecmp(Value,"off+"))) { /* power node off */ if ((N->PowerSelectState == mpowOff) || (MNodeGetSysJob(N,msjtPowerOff,TRUE,NULL) == SUCCESS)) { /* skip this node */ MDB(5,fSCHED) MLog("INFO: not powering node '%s' off--power select state is already 'OFF'\n", N->Name); MNLRemove(&NL,N); continue; } } } /* END for (nindex) */ } /* END BLOCK */ if (!strcmp(Value,"on")) { /* power node on */ if (MNLSetAttr(&NL,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify) == FAILURE) { MNLFree(&NL); return (FAILURE); } } else if (!strcasecmp(Value,"off")) { /* power node off */ if (MNLSetAttr(&NL,mnaPowerIsEnabled,(void **)"false",mdfString,mVerify) == FAILURE) { MNLFree(&NL); return (FAILURE); } } else if (!strcasecmp(Value,"reset")) { char EMsg[MMAX_LINE]; /* reset node */ if (MNodeReboot(NULL,&NL,EMsg,NULL) == FAILURE) { MNLFree(&NL); /* NYI: append EMsg to Msg */ if (Msg != NULL) MUStrCpy(Msg,EMsg,MMAX_LINE); return (FAILURE); } } else if (!strcasecmp(Value,"on+")) { /* power node on, but trigger isn't finished until action is complete */ if (MNLSetAttr(&NL,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify) == FAILURE) { MNLFree(&NL); if (Complete != NULL) *Complete = TRUE; return(FAILURE); } if (Complete != NULL) *Complete = FALSE; if (T != NULL) MUStrDup(&T->CompleteAction,ActionString); T->PID = 1; } else if (!strcasecmp(Value,"off+")) { /* power node off, but trigger isn't finished until action is complete */ if (MNLSetAttr(&NL,mnaPowerIsEnabled,(void **)"false",mdfString,mVerify) == FAILURE) { MNLFree(&NL); if (Complete != NULL) *Complete = TRUE; return(FAILURE); } if (Complete != NULL) *Complete = FALSE; if (T != NULL) MUStrDup(&T->CompleteAction,ActionString); T->PID = 1; } break; default: MNLFree(&NL); return (FAILURE); /*NOTREACHED*/ break; } /* END switch (aindex) */ } /* END else */ break; case mncmCreate: { int rc; mnode_t *N; char EMsg[MMAX_LINE]; char tmpLine[MMAX_LINE*10]; /* FORMAT: COUNT:OS */ if (MNodeFind(OID,&N) == FAILURE) { if (Msg != NULL) snprintf(Msg,MMAX_LINE,"cannot locate hostlist '%s'",OID); return(FAILURE); } /* FORMAT: COUNT:OS */ snprintf(tmpLine,sizeof(tmpLine),"%s:%s%s%s", N->Name, ArgLine, ((T->OType == mxoJob) && ((mjob_t *)T->O != NULL)) ? ":operationid=" : "", ((T->OType == mxoJob) && ((mjob_t *)T->O != NULL)) ? ((mjob_t *)T->O)->Name : ""); mstring_t Output(MMAX_LINE); rc = MRMVMCreate(tmpLine,&Output,EMsg,NULL); if (rc == FAILURE) { if (Msg != NULL) MUStrCpy(Msg,EMsg,MMAX_LINE); MUStrCpy(Msg,Output.c_str(),MMAX_LINE); } return(rc); } /* END BLOCK (case mncmCreate) */ break; case mncmMigrate: { int rc; char *TokPtr = ArgLine; char *VMName; char *SrcNodeName; char *DestNodeName; mnode_t *SrcNode; mnode_t *DestNode; mln_t *VMLink; char *VMList[2]; mnl_t DestNL; /* FORMAT: <VM>:<DestNode>,... */ TokPtr = ArgLine; VMName = MUStrTok(NULL,":=",&TokPtr); DestNodeName = MUStrTok(NULL,":=",&TokPtr); SrcNodeName = OID; if ((DestNodeName == NULL) || (VMName == NULL) ||(SrcNodeName) == NULL) { return(FAILURE); } if (MNodeFind(SrcNodeName,&SrcNode) == FAILURE) { return(FAILURE); } if (MNodeFind(DestNodeName,&DestNode) == FAILURE) { return(FAILURE); } if (MULLCheck(SrcNode->VMList,VMName,&VMLink) == FAILURE) { /* Should we be checking this here? */ /* return(FAILURE); */ } MNLInit(&DestNL); VMList[0] = VMName; MNLSetNodeAtIndex(&DestNL,0,DestNode); MNLSetTCAtIndex(&DestNL,0,1); MNLTerminateAtIndex(&DestNL,1); VMList[1] = NULL; rc = MRMJobMigrate((mjob_t *)T->O,VMList,&DestNL,Msg,NULL); MNLFree(&DestNL); return(rc); } /* END BLOCK (case mncmMigrateVM) */ break; default: return(FAILURE); /*NOTREACHED*/ break; } } /* END BLOCK (case mxoNode) */ break; case mxoxJobGroup: { job_iter JTI; marray_t JArray; int jindex; mjob_t *J; char *JID; char *ptr; char *TokPtr; /* OID FORMAT: <JID>[+<JID>]... */ mbool_t FailureDetected; enum MJobCtlCmdEnum atype; char *Attr = NULL; char *Value = NULL; char *Msg = NULL; enum MJobAttrEnum aindex = mjaNONE; atype = (enum MJobCtlCmdEnum)MUGetIndexCI(Action,MJobCtlCmds,FALSE,mjcmNONE); if (atype == mjcmNONE) { MDB(4,fSCHED) MLog("ERROR: cannot parse job action '%s' in %s\n", Action, FName); return(FAILURE); } if (atype == mjcmModify) { char *TokPtr; Attr = MUStrTok(ArgLine,"+-=",&TokPtr); Value = MUStrTok(NULL,"=: \t\n",&TokPtr); Msg = MUStrTok(NULL,":\t\n",&TokPtr); /* extract message */ aindex = (enum MJobAttrEnum)MUGetIndexCI(Attr,MJobAttr,FALSE,mnaNONE); } FailureDetected = FALSE; JID = MUStrTok(OID,"+",&TokPtr); while (JID != NULL) { MUArrayListCreate(&JArray,sizeof(mjob_t *),1); if (!strcmp(JID,"-")) { if (T == NULL) return(FAILURE); ptr = T->OID; } else { ptr = JID; } MJobIterInit(&JTI); while (MJobTableIterate(&JTI,&J) == SUCCESS) { if ((J->JGroup != NULL) && (J->JGroup->Name != NULL) && (!strcmp(ptr,J->JGroup->Name))) { MUArrayListAppend(&JArray,&J); } } if (MUArrayListGet(&JArray,0) == NULL) { MDB(4,fSCHED) MLog("ERROR: cannot locate job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } for (jindex = 0;jindex < JArray.NumItems;jindex++) { J = *(mjob_t **)MUArrayListGet(&JArray,jindex); if (J == NULL) continue; switch (atype) { case mjcmCancel: { char *CCodeCheck; char UpperArgLine[MMAX_LINE]; if (MJobCancel(J,NULL,FALSE,Msg,NULL) == FAILURE) { MDB(4,fSCHED) MLog("ERROR: cannot cancel job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } MUStrToUpper(ArgLine,UpperArgLine,MMAX_LINE); /* If specified, allow trigger to set the completion code of the job */ if ((CCodeCheck = strstr(UpperArgLine,"CCODE=")) != NULL) { CCodeCheck += strlen("CCODE="); /* Skip the "CCODE:" part */ if (CCodeCheck[0] != '\0') { J->CompletionCode = strtol(CCodeCheck,NULL,10); } } else { J->CompletionCode = 273; /* Completion code for a canceled job in TORQUE */ } } /* END case mjcmCancel */ break; case mjcmModify: switch (aindex) { case mjaHold: if (MJobSetAttr( J, mjaHold, (Value != NULL) ? (void **)Value : (void **)"batch", mdfString, mSet) == FAILURE) { MDB(4,fSCHED) MLog("ERROR: cannot hold job '%s' in %s\n", JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } if (Msg != NULL) { /* attach provided message */ MMBAdd( &J->MessageBuffer, Msg, NULL, mmbtHold, 0, 0, NULL); } if (J->SubState == mjsstProlog) { J->SubState = mjsstNONE; } /* checkpoint change (make this configurable at this point?) */ MOCheckpoint(mxoJob,(void *)J,FALSE,NULL); break; default: MDB(4,fSCHED) MLog("ERROR: cannot modify attribute '%s' for job '%s' in %s\n", Attr, JID, FName); JID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; break; } /* END switch (aindex) */ break; default: MDB(4,fSCHED) MLog("ERROR: action '%s' not handled in %s\n", Action, FName); return(FAILURE); /*NOTREACHED*/ break; } /* END switch (atype) */ } /* END for (jindex) */ JID = MUStrTok(NULL,"+",&TokPtr); MUArrayListFree(&JArray); } /* END while (JID != NULL) */ if (FailureDetected == TRUE) { return(FAILURE); } } /* END BLOCK (case mxoxJobGroup) */ break; case mxoSched: { enum MSchedCtlCmdEnum atype; atype = (enum MSchedCtlCmdEnum)MUGetIndexCI(Action,MSchedCtlCmds,FALSE,msctlNONE); switch (atype) { case msctlVMMigrate: { enum MVMMigrationPolicyEnum aindex; aindex = (enum MVMMigrationPolicyEnum)MUGetIndexCI(ArgLine,MVMMigrationPolicy,FALSE,mvmmmNONE); return(MUIVMCtlPlanMigrations(aindex,FALSE,FALSE,NULL)); } default: return(FAILURE); } /* END switch (atype) */ } /* END case mxoSched */ break; case mxoTrig: { enum MSchedCtlCmdEnum atype; atype = (enum MSchedCtlCmdEnum)MUGetIndexCI(Action,MSchedCtlCmds,FALSE,msctlNONE); if (atype == msctlNONE) { return(FAILURE); } switch (atype) { case msctlModify: { char *TokPtr; mtrig_t *T; char *Attr; char *Value; enum MTrigAttrEnum aindex; Attr = MUStrTok(ArgLine,"=",&TokPtr); Value = MUStrTok(NULL,"\"",&TokPtr); /* FORMAT: OID = trigid */ aindex = (enum MTrigAttrEnum)MUGetIndexCI(Attr,MTrigAttr,FALSE,mtaNONE); if ((OID == NULL) || (OID[0] == '\0') || (aindex == mtaNONE)) { return(FAILURE); } if (MTrigFind(OID,&T) == FAILURE) { return(FAILURE); } switch (aindex) { case mtaActionData: if (MTrigSetAttr(T,aindex,Value,mdfString,mSet) == FAILURE) { return(FAILURE); } break; default: return(FAILURE); /*NOTREACHED*/ break; } /* END switch (aindex) */ break; } /* END case msctlModify */ default: return(FAILURE); /*NOTREACHED*/ break; } /* END switch (atype) */ } /* END BLOCK (case mxoTrig) */ break; case mxoRM: { mrm_t *R = NULL; char *RMID; char *TokPtr; mbool_t FailureDetected; enum MRMCtlCmdEnum atype; atype = (enum MRMCtlCmdEnum)MUGetIndexCI(Action,MRMCtlCmds,FALSE,mrmctlNONE); if (atype == mrmctlNONE) { MDB(4,fSCHED) MLog("ERROR: cannot parse rm action '%s' in %s\n", Action, FName); return(FAILURE); } FailureDetected = FALSE; RMID = MUStrTok(OID,"+",&TokPtr); while (RMID != NULL) { if (!strcmp(RMID, "-")) { if (T == NULL) return(FAILURE); R = (mrm_t *)T->O; } else if (MRMFind(RMID,&R) == FAILURE) { if (Msg != NULL) strcpy(Msg,"cannot locate specified RM"); RMID = MUStrTok(NULL,"+",&TokPtr); FailureDetected = TRUE; continue; } switch (atype) { case mrmctlModify: { char *TokPtr; enum MRMAttrEnum aindex; char *Attr; char *Value; /* FORMAT: <attr>=<value> */ Attr = MUStrTok(ArgLine,"=",&TokPtr); Value = MUStrTok(NULL,"\"",&TokPtr); aindex = (enum MRMAttrEnum)MUGetIndexCI(Attr,MRMAttr,FALSE,mrmaNONE); switch (aindex) { case mrmaState: return(MRMSetAttr(R,aindex,(void **)Value,mdfString,mSet)); break; default: if (Msg != NULL) strcpy(Msg,"cannot modify specified attribute"); return(FAILURE); /* NOTREACHED */ break; } /* END switch (aindex) */ } /* END BLOCK (case mrmctlModify) */ break; case mrmctlDestroy: MDB(3,fUI) MLog("WARNING: cannot destroy static RM\n"); if (Msg != NULL) strcpy(Msg,"WARNING: cannot destroy static RM\n"); return(FAILURE); /* NOTREACHED */ break; case mrmctlPurge: return(MRMPurge(R)); break; default: if (Msg != NULL) strcpy(Msg,"action not supported for RM object"); return(FAILURE); /*NOTREACHED*/ break; } /* END switch (atype) */ RMID = MUStrTok(NULL,"+",&TokPtr); } /* END while (RMID != NULL */ if (FailureDetected == TRUE) { return(FAILURE); } } /* END BLOCK (case mxoRM) */ break; case mxoRsv: { enum MRsvCtlCmdEnum atype; atype = (enum MRsvCtlCmdEnum)MUGetIndexCI(Action,MRsvCtlCmds,FALSE,mrcmNONE); if (atype == mrcmNONE) { return(FAILURE); } switch (atype) { case mrcmModify: { char *ptr; char *TokPtr; enum MRsvAttrEnum attr; mrsv_t *R; if (!strcmp(OID,"-")) { if (T == NULL) return(FAILURE); R = (mrsv_t *)T->O; } else if (MRsvFind(OID,&R,mraNONE) == FAILURE) { return(FAILURE); } ptr = MUStrTok(ArgLine,":",&TokPtr); attr = (enum MRsvAttrEnum)MUGetIndexCI(ptr,MRsvAttr,FALSE,mraNONE); switch (attr) { case mraACL: { enum MObjectSetModeEnum Mode; if (MUStrIsEmpty(TokPtr)) Mode = mSet; else if (strstr(TokPtr,"-=") != NULL) Mode = mDecr; else if (strstr(TokPtr,"+=") != NULL) Mode = mAdd; else Mode = mSet; MRsvSetAttr(R,mraACL,(void *)TokPtr,mdfString,Mode); } break; default: return(FAILURE); /*NOTREACHED*/ break; } } /* END case mrcmModify */ break; case mrcmDestroy: { mrsv_t *R; if (!strcmp(OID,"-")) { if (T == NULL) return(FAILURE); R = (mrsv_t *)T->O; } else if (MRsvFind(OID,&R,mraNONE) == FAILURE) { return(FAILURE); } R->CancelIsPending = TRUE; R->EndTime = MSched.Time - 1; R->ExpireTime = 0; /* remove reservation */ MRsvCheckStatus(NULL); if ((long)R->StartTime <= MUIDeadLine) { /* adjust UI phase wake up time */ if (MSched.AdminEventAggregationTime >= 0) MUIDeadLine = MIN(MUIDeadLine,(long)MSched.Time + MSched.AdminEventAggregationTime); } } /* END case mrcmDestroy */ break; case mrcmOther: { mrsv_t *R; if (!strcmp(OID,"-")) { if (T == NULL) { return(FAILURE); } R = (mrsv_t *)T->O; } else if (MRsvFind(OID,&R,mraNONE) == FAILURE) { return(FAILURE); } /* parse argline */ if (strstr(ArgLine,"submit") != NULL) { MJobSubmitFromJSpec(R->SpecJ,NULL,Msg); } /* END if (strstr(ArgLine,"submit") != NULL) */ } /* END BLOCK (case mrcmOther) */ break; default: return(FAILURE); /*NOTREACHED*/ break; } /* END switch (atype) */ } /* END BLOCK (case mxoRsv) */ break; case mxoxVPC: { mpar_t *VPC; MVPCFind(OID,&VPC,TRUE); if (!strcasecmp(Action,"destroy")) { MVPCDestroy(&VPC,ArgLine); } else { return(FAILURE); } } /* END case mxoxVPC */ break; default: if (Msg != NULL) strcpy(Msg,"unsupported trigger object type"); return(FAILURE); /* NOTREACHED */ break; } /* END switch (OType) */ /*NOTE: return may (and does) return in above switch statement */ return(SUCCESS); } /* END MTrigLaunchInternalAction() */
int MSysProcessRequest( msocket_t *S, /* I */ mbool_t RequestIsPreLoaded) /* I */ { char Message[MMAX_LINE]; int HeadSize; int sindex; /* enum MSvcEnum */ mbitmap_t AuthBM; char SName[MMAX_LINE]; char Auth[MMAX_NAME]; char Passwd[MMAX_NAME]; char tmpLine[MMAX_LINE]; int SC; int Align; char *ptr; char *ptr2; char *args; char *TokPtr; int rc; const char *FName = "MSysProcessRequest"; MDB(3,fUI) MLog("%s(S,%s)\n", FName, MBool[RequestIsPreLoaded]); if (S == NULL) { return(FAILURE); } if ((MGlobalReqBuf == NULL) && (MSUAllocSBuf( &MGlobalReqBuf, MSched.M[mxoJob], MPar[0].ConfigNodes, &MGlobalReqBufSize, FALSE) == FAILURE)) { MDB(1,fUI) MLog("ERROR: cannot allocate request buffer\n"); return(FAILURE); } else if (MIncrGlobalReqBuf == TRUE) { if (MSUAllocSBuf( &MGlobalReqBuf, 0, 0, &MGlobalReqBufSize, TRUE) == FAILURE) { MDB(1,fUI) MLog("ERROR: cannot allocate increase request buffer\n"); return(FAILURE); } MIncrGlobalReqBuf = FALSE; } if (RequestIsPreLoaded == FALSE) { char EMsg[MMAX_LINE]; enum MStatusCodeEnum SC; if (MSURecvData(S,MSched.SocketWaitTime,TRUE,&SC,EMsg) == FAILURE) { MDB(3,fSOCK) MLog("ALERT: cannot read client packet\n"); MUStrDup(&MSched.UIBadRequestMsg,EMsg); if (S->RemoteHost != NULL) MUStrDup(&MSched.UIBadRequestor,S->RemoteHost); else MUStrDup(&MSched.UIBadRequestor,"???"); if (MSched.DefaultDropBadRequest == FALSE) { MUStrDup(&S->SMsg,EMsg); if (SC == mscNoAuth) S->StatusCode = (long)msfESecServerAuth; else S->StatusCode = (long)msfEGServer; MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); } MSUDisconnect(S); return(FAILURE); } /* END if (MSURecvData(S,MMAX_SOCKETWAIT,TRUE,&SC,EMsg) == FAILURE) */ } /* END if (RequestIsPreLoaded == FALSE) */ S->SBuffer = MGlobalReqBuf; S->SBufSize = MGlobalReqBufSize; if (S->ProcessTime == 0) MUGetMS(NULL,(long *)&S->ProcessTime); switch (S->WireProtocol) { case mwpXML: case mwpS32: { int SC; /* new style request - process and return */ rc = MUISProcessRequest(S,Message,&SC); if (rc == FAILURE) { if (SC != mscNoEnt) MUISAddData(S,"ERROR: command not supported"); MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); } return(rc); } /* END BLOCK */ /*NOTREACHED*/ break; default: /* NO-OP */ break; } /* END switch (S->WireProtocol) */ /* old style request - process below */ MGlobalReqBuf[0] = '\0'; S->SBuffer = MGlobalReqBuf; S->SBufSize = MGlobalReqBufSize; MUStrCpy(CurrentHostName,S->Host,MMAX_NAME); /* NOTE: not threadsafe */ /* locate/process args */ if ((args = strstr(S->RBuffer,MCKeyword[mckArgs])) == NULL) { MDB(3,fSOCK) MLog("ALERT: cannot locate command arg\n"); sprintf(S->SBuffer,"%s%d %s%s\n", MCKeyword[mckStatusCode], scFAILURE, MCKeyword[mckArgs], "ERROR: cannot locate command args"); S->SBufSize = strlen(S->SBuffer); MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); return(FAILURE); } *args = '\0'; args += strlen(MCKeyword[mckArgs]); /* get service */ SName[0] = '\0'; if ((ptr = strstr(S->RBuffer,MCKeyword[mckCommand])) == NULL) { MDB(3,fSOCK) MLog("ALERT: cannot locate command\n"); sprintf(S->SBuffer,"%s%d %s%s\n", MCKeyword[mckStatusCode], scFAILURE, MCKeyword[mckArgs], "ERROR: cannot locate command"); S->SBufSize = strlen(S->SBuffer); MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); return(FAILURE); } ptr += strlen(MCKeyword[mckCommand]); MUStrCpy(SName,ptr,sizeof(SName)); for (ptr2 = &SName[0];*ptr2 != '\0';ptr2++) { if (isspace(*ptr2)) { *ptr2 = '\0'; break; } } /* END for (ptr2) */ /* get authentication */ if ((ptr = strstr(S->RBuffer,MCKeyword[mckAuth])) == NULL) { MDB(3,fSOCK) MLog("ALERT: cannot locate authentication\n"); sprintf(S->SBuffer,"%s%d %s%s\n", MCKeyword[mckStatusCode], scFAILURE, MCKeyword[mckArgs], "ERROR: cannot locate authentication"); S->SBufSize = (long)strlen(S->SBuffer); MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); return(FAILURE); } ptr += strlen(MCKeyword[mckAuth]); MUStrCpy(Auth,ptr,sizeof(Auth)); /* FORMAT: <USERNAME>[:<PASSWORD>] */ for (ptr2 = &Auth[0];*ptr2 != '\0';ptr2++) { if (isspace(*ptr2)) { *ptr2 = '\0'; break; } } /* END for (ptr2) */ if ((ptr2 = MUStrTok(Auth,":",&TokPtr)) != NULL) { MUStrCpy(Passwd,ptr2,sizeof(Passwd)); } else { Passwd[0] = '\0'; } /* determine service */ for (sindex = 1;MUI[sindex].SName != NULL;sindex++) { if (!strcmp(SName,MUI[sindex].SName)) break; } /* END for (sindex) */ if ((MUI[sindex].SName == NULL) || (MUI[sindex].Func == NULL)) { MDB(3,fUI) MLog("ALERT: cannot support service '%s'\n", SName); sprintf(Message,"ERROR: cannot support service '%s' (%s)", SName, (MUI[sindex].SName == NULL) ? "service" : "func"); sprintf(S->SBuffer,"%s%d %s%s\n", MCKeyword[mckStatusCode], scFAILURE, MCKeyword[mckArgs], Message); S->SBufSize = (long)strlen(S->SBuffer); MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); return(FAILURE); } /* END if (MUI[sindex].SName == NULL) */ if (S->SIndex == mcsNONE) S->SIndex = (enum MSvcEnum)sindex; MDB(3,fUI) MLog("INFO: client '%s' read (%ld bytes) initiating service call for '%s' (Auth: %s)\n", S->Name, S->SBufSize, MUI[sindex].SName, Auth); /* fail if name is not recognized */ if (Auth[0] == '\0') { MDB(2,fUI) MLog("WARNING: client id '%s' is unknown\n", Auth); sprintf(S->SBuffer,"%s%d %s%s\n", MCKeyword[mckStatusCode], scFAILURE, MCKeyword[mckArgs], "ERROR: cannot authenticate client"); S->SBufSize = (long)strlen(S->SBuffer); MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); return(FAILURE); } MSysGetAuth(Auth,(enum MSvcEnum)sindex,0,&AuthBM); if (!bmisset(&AuthBM,mcalOwner) && !bmisset(&AuthBM,mcalGranted)) { sprintf(Message,"ERROR: user '%s' is not authorized to run command '%s'\n", Auth, MUI[sindex].SName); sprintf(S->SBuffer,"%s%d %s%s\n", MCKeyword[mckStatusCode], scFAILURE, MCKeyword[mckArgs], Message); S->SBufSize = (long)strlen(S->SBuffer); MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); return(FAILURE); } S->SBufSize = (long)MGlobalReqBufSize; sprintf(tmpLine,"%s%d ", MCKeyword[mckStatusCode], scFAILURE); Align = (int)strlen(tmpLine) + (int)strlen(MCKeyword[mckArgs]); sprintf(S->SBuffer,"%s%*s%s", tmpLine, 16 - (Align % 16), " ", MCKeyword[mckArgs]); HeadSize = (int)strlen(S->SBuffer); S->SBufSize -= HeadSize; SC = (*MUI[sindex].Func)( args, S->SBuffer + HeadSize, &AuthBM, Auth, &S->SBufSize); ptr = S->SBuffer + strlen(MCKeyword[mckStatusCode]); *ptr = SC + '0'; if (S->SBufSize != MGlobalReqBufSize) S->SBufSize += (long)HeadSize; else S->SBufSize = (long)strlen(S->SBuffer); MSUSendData(S,MSched.SocketWaitTime,TRUE,TRUE,NULL,NULL); fflush(mlog.logfp); /* mrelAllSchedCommand --- Record all commands. * mrelSchedCommand --- Record only commands that perform an action. */ if (bmisset(&MSched.RecordEventList,mrelAllSchedCommand)) { MSysRecordCommandEvent(S,(enum MSvcEnum)sindex,SC,Auth); } else if (bmisset(&MSched.RecordEventList,mrelSchedCommand)) { switch (sindex) { /* info only commands, do not record event under only mrelSchedCommand */ case mcsShowQueue: case mcsShowState: case mcsStatShow: case mcsCheckJob: case mcsRsvShow: case mcsCheckNode: case mcsShowResAvail: case mcsShowEstimatedStartTime: case mcsShowConfig: case mcsMShow: case mcsMDiagnose: break; /* info/action commands, do not ALWAYS record event here. * Instrument these functions intenally to determine whether to record * command events */ case mcsMJobCtl: case mcsMRsvCtl: case mcsMSchedCtl: case mcsMVCCtl: case mcsMVMCtl: if (bmisset(&S->Flags,msftReadOnlyCommand)) { break; } /* else fall though... */ default: MSysRecordCommandEvent(S,(enum MSvcEnum)sindex,SC,Auth); break; } /* END switch (sindex) */ } /* END if (bmisset(&MSched.RecordEventList,mrelSchedCommand)) */ return(SUCCESS); } /* END MSysProcessRequest() */
int MCfgGetVal( char **Buf, const char *Parm, char *IName, int *Index, char *Value, int ValSize, char **SymTable) { char *ptr; char *tmp; char *head; char *tail; char IndexName[MAX_MNAME]; int iindex; const char *FName = "MCfgGetVal"; DBG(7,fCONFIG) DPrint("%s(Buf,%s,%s,Index,Value,%d,SymTable)\n", FName, Parm, (IName != NULL) ? IName : "NULL", ValSize); if (Parm == NULL) return(FAILURE); IndexName[0] = '\0'; /* FORMAT: { '\0' || '\n' }[<WS>]<VAR>[<[><WS><INDEX><WS><]>]<WS><VALUE> */ ptr = *Buf; while (ptr != NULL) { if ((head = strstr(ptr,Parm)) == NULL) break; ptr = head + strlen(Parm); /* look backwards for newline or start of buffer */ if (head > *Buf) tmp = head - 1; else tmp = *Buf; while ((tmp > *Buf) && ((*tmp == ' ') || (*tmp == '\t'))) tmp--; if ((tmp != *Buf) && (*tmp != '\n')) continue; if ((IName != NULL) && (IName[0] != '\0')) { /* requested index name specified */ if (*ptr != '[') continue; ptr++; while (isspace(*ptr)) ptr++; if (strncmp(IName,ptr,strlen(IName)) != 0) continue; ptr += strlen(IName); while (isspace(*ptr)) ptr++; if (*ptr != ']') continue; ptr++; /* requested index found */ } else if (isspace(*ptr)) { /* no index specified */ if (Index != NULL) *Index = 0; } else { /* index specified, no specific index requested */ if (*ptr != '[') continue; ptr++; while (isspace(*ptr)) ptr++; head = ptr; while ((!isspace(*ptr)) && (*ptr != ']')) ptr++; MUStrCpy(IndexName,head,MIN(ptr - head + 1,MAX_MNAME)); while (isspace(*ptr)) ptr++; if (*ptr != ']') continue; ptr++; if (Index != NULL) { *Index = (int)strtol(IndexName,&tail,10); if (*tail != '\0') { /* index is symbolic */ if (SymTable == NULL) return(FAILURE); for (iindex = 0;SymTable[iindex] != NULL;iindex++) { if (!strcmp(SymTable[iindex],IndexName)) { *Index = iindex; break; } } if (SymTable[iindex] == NULL) { MUStrDup(&SymTable[iindex],IndexName); *Index = iindex; } } } } /* END else ... */ while ((*ptr == ' ') || (*ptr == '\t')) ptr++; if ((tail = strchr(ptr,'\n')) == NULL) tail = *Buf + strlen(*Buf); MUStrCpy(Value,ptr,MIN(tail - ptr + 1,ValSize)); if ((IName != NULL) && (IName[0] == '\0')) MUStrCpy(IName,IndexName,MAX_MNAME); Value[tail - ptr] = '\0'; *Buf = tail; return(SUCCESS); } /* END while(ptr != NULL) */ Value[0] = '\0'; return(FAILURE); } /* END MCfgGetVal() */
int MTrigParseInternalAction( char *ActionString, enum MXMLOTypeEnum *OType, char *OID, /* MMAX_BUFFER */ char *Action, /* MMAX_LINE */ char *ArgLine, /* MMAX_LINE */ char *Msg) /* MMAX_LINE */ { /* FORMAT: <OTYPE>:<OID>:<ACTION>:<context information> */ char *ptr; char *TokPtr = NULL; char *tmpAString = NULL; const char *FName = "MTrigPraseInternalAction"; MDB(4,fSCHED) MLog("%s(%s,OType,OID,Action,ArgLine,,Msg)\n", FName, (ActionString != NULL) ? ActionString : "NULL"); if (Msg != NULL) Msg[0] = '\0'; if ((ActionString == NULL) || (OType == NULL) || (OID == NULL) || (Action == NULL) || (ArgLine == NULL)) { if (Msg != NULL) strcpy(Msg,"internal error"); return(FAILURE); } OID[0] = '\0'; Action[0] = '\0'; ArgLine[0] = '\0'; MUStrDup(&tmpAString,ActionString); /* NOTE: this format and parsing is duplicated in MTrigCheckInternalAction() any update here must be copied to that routine */ ptr = MUStrTok(tmpAString,":",&TokPtr); if (ptr == NULL) { if (Msg != NULL) strcpy(Msg,"invalid action"); MUFree(&tmpAString); return(FAILURE); } *OType = (enum MXMLOTypeEnum)MUGetIndexCI(ptr,MXO,FALSE,mxoNONE); if (*OType == mxoNONE) { MDB(4,fSCHED) MLog("ERROR: invalid object type '%s' in %s\n", ptr, FName); if (Msg != NULL) strcpy(Msg,"invalid object type"); MUFree(&tmpAString); return(FAILURE); } ptr = MUStrTok(NULL,":",&TokPtr); if (ptr == NULL) { MDB(4,fSCHED) MLog("ERROR: cannot extract object ID in %s\n", FName); if (Msg != NULL) strcpy(Msg,"invalid object id"); MUFree(&tmpAString); return(FAILURE); } MUStrCpy(OID,ptr,MMAX_BUFFER); ptr = MUStrTok(NULL,":",&TokPtr); if (ptr == NULL) { MDB(4,fSCHED) MLog("ERROR: cannot parse action in %s\n", FName); if (Msg != NULL) strcpy(Msg,"cannot locate action"); MUFree(&tmpAString); return(FAILURE); } MUStrCpy(Action,ptr,MMAX_LINE); if ((TokPtr != NULL) && (TokPtr[0] != '\0')) MUStrCpy(ArgLine,TokPtr,MMAX_LINE); else ArgLine[0] = '\0'; MUFree(&tmpAString); return(SUCCESS); } /* END MTrigParseInternalAction() */
int MTrigSetFlags( mtrig_t *T, char *Buf) { char *vptr; int vindex; char UBuf[MMAX_LINE]; if ((T == NULL) || (Buf == NULL)) { return(FAILURE); } MUStrCpy(UBuf,Buf,sizeof(UBuf)); MUStrToLower(UBuf); for (vindex = 0;MTrigFlag[vindex] != NULL;vindex++) { if ((vptr = strstr(UBuf,MTrigFlag[vindex])) && (vptr != NULL)) { switch (vindex) { case mtfUser: { char *ptr; char *TokPtr; char tmpLine[MMAX_LINE]; bmset(&T->SFlags,vindex); if (strchr(vptr,'+') == NULL) break; MUStrCpy(tmpLine,vptr,sizeof(tmpLine)); ptr = MUStrTok(tmpLine,"[] \t\n:,|.",&TokPtr); if (ptr != NULL) { vptr = strchr(ptr,'+'); if ((vptr == NULL) || (vptr[1] == '\0')) break; MUStrDup(&T->UserName,&vptr[1]); } } break; case mtfGlobalVars: { char *ptr; char *TokPtr; char tmpLine[MMAX_LINE]; bmset(&T->SFlags,vindex); if (strchr(vptr,'+') == NULL) break; MUStrCpy(tmpLine,vptr,sizeof(tmpLine)); ptr = MUStrTok(tmpLine,"[] \t\n:,|.",&TokPtr); if (ptr != NULL) { vptr = strchr(ptr,'+'); if ((vptr == NULL) || (vptr[1] == '\0')) break; MUStrDup(&T->GetVars,&vptr[1]); } } break; case mtfMultiFire: bmset(&T->SFlags,vindex); bmset(&T->InternalFlags,mtifMultiFire); break; case mtfGenericSysJob: case mtfSoftKill: case mtfCleanup: case mtfInterval: case mtfProbe: case mtfProbeAll: case mtfAttachError: case mtfRemoveStdFiles: case mtfResetOnModify: case mtfCheckpoint: case mtfObjectXMLStdin: case mtfAsynchronous: bmset(&T->SFlags,vindex); break; default: /* NO-OP */ break; } } } /* END for (vindex) */ return(SUCCESS); } /* END MTrigSetFlags() */
int MRsvJCreate( mjob_t *J, /* I job reserving nodes */ mnl_t **MNodeList, /* I nodes to be reserved (optional) */ long StartTime, /* I time reservation starts */ enum MJRsvSubTypeEnum RsvSType, /* I reservation subtype */ mrsv_t **RP, /* O reservation pointer (optional) */ mbool_t NoRsvTransition) /* I don't transition */ { int rqindex; int rqindex2; int nindex; mrsv_t *R; mnode_t *N; mreq_t *RQ; int RC; double NPFactor; int TaskCount; const char *FName = "MRsvJCreate"; char TString[MMAX_LINE]; MULToTString(StartTime - MSched.Time,TString); MDB(3,fSTRUCT) MLog("%s(%s,MNodeList,%s,%s,RP)\n", FName, (J != NULL) ? J->Name : "NULL", TString, MJRType[RsvSType]); if ((J == NULL) || (J->Req[0] == NULL)) { MDB(1,fSTRUCT) MLog("ERROR: invalid job passed to %s()\n", FName); return(FAILURE); } if (bmisset(&J->Flags,mjfRsvMap)) { return(SUCCESS); } if (J->Rsv != NULL) { MDB(0,fSTRUCT) MLog("ERROR: reservation created for reserved job '%s' (existing reservation '%s' deleted)\n", J->Name, J->Rsv->Name); MJobReleaseRsv(J,TRUE,FALSE); } rqindex2 = 0; /* So valgrind won't complain */ /* NOTE: must create per req rsv if task resource definitions differ */ for (rqindex = 0;rqindex < MMAX_REQ_PER_JOB;rqindex++) { R = NULL; RQ = J->Req[rqindex]; if (RQ == NULL) break; /* verify nodelist */ if ((MNodeList == NULL) && ((RQ == NULL) || (MNLIsEmpty(&RQ->NodeList)))) { MDB(1,fSTRUCT) MLog("ERROR: invalid nodelist passed to %s()\n", FName); return(FAILURE); } MRsvInitialize(&R); R->HostExpIsSpecified = TRUE; R->CTime = MSched.Time; R->CIteration = MSched.Iteration; if (rqindex == 0) { /* NOTE: returned rsv pointer and J->R only point to req 0 rsv */ if (RP != NULL) *RP = R; /* link job to reservation */ J->Rsv = R; } /* END if (rqindex == 0) */ RQ->R = R; R->J = J; /* all req reservations point to J */ R->Mode = 0; /* build reservation */ if (rqindex > 0) { snprintf(R->Name,MMAX_NAME,"%s.%d", J->Name, rqindex); } else { MUStrCpy(R->Name,J->Name,MMAX_NAME); } MRsvTableInsert(R->Name,R); if (bmisset(&J->Flags,mjfMeta) && bmisset(&J->Flags,mjfSystemJob) && bmisset(&J->Flags,mjfNoRMStart)) { R->Type = mrtMeta; R->SubType = mrsvstMeta; } else { R->Type = mrtJob; R->SubType = mrsvstJob; } /* get partition number from first node */ R->StartTime = StartTime; NPFactor = MNODESPEEDNOTSET; /* NOTE: all rsv's of multi-req job must be scaled by same factor resulting in same duration */ if (MNodeList != NULL) { double tmpD; /* get partition number from first node */ if (MNLGetNodeAtIndex(MNodeList[rqindex],0,&N) == SUCCESS) { R->PtIndex = N->PtIndex; MDB(7,fSTRUCT) MLog("INFO: job '%s' reservation partition set to %s from first node in node list\n", J->Name, MPar[R->PtIndex].Name); } else { R->PtIndex = 0; MDB(7,fSTRUCT) MLog("INFO: job '%s' reservation partition set to %s since node in nodelist is NULL\n", J->Name, MPar[R->PtIndex].Name); } for (rqindex2 = 0;MNLGetNodeAtIndex(MNodeList[rqindex2],0,&N) == SUCCESS;rqindex2++) { if (MUNLGetMinAVal( &MNodeList[rqindex2][0], mnaSpeed, NULL, (void **)&tmpD) == SUCCESS) { NPFactor = MIN(NPFactor,tmpD); } } /* END for (rqindex2) */ if (NPFactor == MNODESPEEDNOTSET) { /* speed not set */ NPFactor = 1.0; } } /* END if (MNodeList != NULL) */ else { double tmpD; mreq_t *tRQ; /* get partition number from first node */ if (MNLGetNodeAtIndex(&RQ->NodeList,0,&N) == SUCCESS) { R->PtIndex = N->PtIndex; MDB(7,fSTRUCT) MLog("INFO: job '%s' reservation partition set to %s from first node in requested node list\n", J->Name, MPar[R->PtIndex].Name); } else { R->PtIndex = MCONST_DEFAULTPARINDEX; MDB(7,fSTRUCT) MLog("INFO: job '%s' reservation partition set to %s since first node in requested node list is NULL\n", J->Name, MPar[R->PtIndex].Name); } for (rqindex2 = 0;J->Req[rqindex2] != NULL;rqindex2++) { tRQ = J->Req[rqindex2]; if (!MNLIsEmpty(&tRQ->NodeList)) { if (MUNLGetMinAVal( &tRQ->NodeList, mnaSpeed, NULL, (void **)&tmpD) == FAILURE) { continue; } NPFactor = MIN(NPFactor,tmpD); } } /* END for (rqindex2) */ } /* END else (MNodeList != NULL) */ /* record rsv nodelist */ if (!MNLIsEmpty(&RQ->NodeList)) { MNLCopy(&R->NL,&RQ->NodeList); } else if (MNodeList != NULL) { /* NOTE: idle jobs with rsv will not have RQ->NodeList populated */ /* NOTE: R->NL may be to small if J allocation is dynamic */ MNLCopy(&R->NL,MNodeList[RQ->Index]); } if ((NPFactor <= 0.0001) || (NPFactor >= MNODESPEEDNOTSET - 1)) { NPFactor = 1.0; } R->EndTime = MAX( StartTime + (long)((double)J->SpecWCLimit[0] / NPFactor), (long)MSched.Time + 1); R->EndTime = MIN(R->EndTime,MMAX_TIME - 1); if (J->SubState == mjsstPreempted) { /* NOTE: Job was just preempted -- preempted resources will not be available to preemptor this iteration. Maintain reservation for MSched.JobRsvRetryInterval to prevent preemptor from using resources immediately. This will enable him to create a reservation in the future. */ R->EndTime = MIN(R->EndTime,MSched.Time + MSched.JobRsvRetryInterval); } if (StartTime == 0) { MDB(0,fSTRUCT) MLog("ERROR: invalid StartTime specified for reservation on job rsv '%s'\n", R->Name); StartTime = 1; } /* link nodes to reservation */ MDB(6,fSTRUCT) MLog("INFO: linking nodes to reservation '%s'\n", R->Name); R->AllocNC = 0; R->AllocTC = 0; R->AllocPC = MReqGetPC(J,RQ); /* copy ACL/CL info */ if (!MACLIsEmpty(J->Credential.ACL)) { MACLCopy(&R->ACL,J->Credential.ACL); } else { MACLFreeList(&R->ACL); } if (!MACLIsEmpty(J->Credential.CL)) { MACLCopy(&R->CL,J->Credential.CL); } else { MACLFreeList(&R->CL); } MACLSet(&R->ACL,maJob,J->Name,mcmpSEQ,mnmNeutralAffinity,0,0); /* copy DRes info */ MCResCopy(&R->DRes,&RQ->DRes); /* make each job a member of an rsv group with the job name */ MUStrDup(&R->RsvGroup,J->Name); /* if this is a remote req must export reservation */ if ((RQ->RemoteR == NULL) && (MNLGetNodeAtIndex(&R->NL,0,&N) == SUCCESS) && (N->RM != NULL) && (N->RM->Type == mrmtMoab) && bmisset(&N->RM->Flags,mrmfRsvExport)) { char tmpRsvName[MMAX_NAME]; enum MStatusCodeEnum SC; if (MRMRsvCtl( R, N->RM, mrcmCreate, (void **)tmpRsvName, NULL, &SC) == SUCCESS) { MOAddRemoteRsv((void *)R,mxoRsv,N->RM,tmpRsvName); MOAddRemoteRsv((void *)RQ,mxoReq,N->RM,tmpRsvName); } } else if ((RQ->RemoteR != NULL) && (MNLGetNodeAtIndex(&R->NL,0,&N) == SUCCESS) && (N->RM != NULL) && (N->RM->Type == mrmtMoab) && bmisset(&N->RM->Flags,mrmfRsvExport)) { MOAddRemoteRsv((void *)R,mxoRsv,N->RM,RQ->RemoteR->Name); } } /* END for (rqindex) */ nindex = 0; rqindex = 0; while (1) { RQ = J->Req[rqindex]; /* NYI : must handle class ACL management for multi-req jobs */ if (MNodeList == NULL) { if ((RQ == NULL) || (MNLIsEmpty(&RQ->NodeList)) || (rqindex >= MMAX_REQ_PER_JOB)) { break; } if ((MNLGetNodeAtIndex(&RQ->NodeList,nindex,NULL) == FAILURE) || (MNLGetTCAtIndex(&RQ->NodeList,nindex) == 0)) { rqindex++; nindex = 0; continue; } MNLGetNodeAtIndex(&RQ->NodeList,nindex,&N); TaskCount = MNLGetTCAtIndex(&RQ->NodeList,nindex); nindex++; } else { if ((RQ == NULL) || (rqindex >= MMAX_REQ_PER_JOB)) { break; } if ((MNLGetNodeAtIndex(MNodeList[rqindex],0,NULL) == FAILURE) || (MNLGetTCAtIndex(MNodeList[rqindex],0) == 0)) { break; } if ((MNLGetNodeAtIndex(MNodeList[rqindex],nindex,NULL) == FAILURE) || (MNLGetTCAtIndex(MNodeList[rqindex],nindex) == 0)) { rqindex++; nindex = 0; continue; } MNLGetNodeAtIndex(MNodeList[rqindex],nindex,&N); TaskCount = MNLGetTCAtIndex(MNodeList[rqindex],nindex); nindex++; } /* END else (MNodeList == NULL) */ if ((N->Name[0] == '\0') || (N->Name[0] == '\1')) { MDB(0,fSTRUCT) MLog("ERROR: job '%s' rsv nodelist contains invalid node at index %d\n", J->Name, nindex - 1); MJobReleaseRsv(J,FALSE,FALSE); return(FAILURE); } /* END if ((N->Name[0] == '\0') || (N->Name[0] == '\1')) */ if ((N->PtIndex != RQ->R->PtIndex) && (N->PtIndex != 0) && !bmisset(&J->Flags,mjfCoAlloc)) { MDB(0,fSTRUCT) MLog("ERROR: job '%s' reservation spans partitions (node %s: %d)\n", J->Name, N->Name, N->PtIndex); MJobReleaseRsv(J,FALSE,FALSE); return(FAILURE); } if ((RQ->NAccessPolicy == mnacSingleJob) || (RQ->NAccessPolicy == mnacSingleTask)) { /* node is dedicated - allocate all node procs */ MCResClear(&RQ->R->DRes); RQ->R->DRes.Procs = -1; RC = 1; } else if (MJOBREQUIRESVMS(J)) { mvm_t *V; /* locate associated VM */ if (MJobFindNodeVM(J,N,&V) == SUCCESS) { MCResCopy(&RQ->R->DRes,&V->CRes); } else { /* cannot locate associated VM - use job's DRes */ MCResCopy(&RQ->R->DRes,&RQ->DRes); } RC = 1; } else { /* normal job - use job's DRes */ MCResCopy(&RQ->R->DRes,&RQ->DRes); RC = TaskCount; } RQ->R->AllocNC ++; RQ->R->AllocTC += RC; /* RC is always a positive number */ if (MRsvAdjustNode(RQ->R,N,RC,0,FALSE) == FAILURE) { MJobReleaseRsv(J,FALSE,FALSE); return(FAILURE); } if (RQ->R->StartTime > MSched.Time) { MUStrDup(&RQ->R->RsvGroup,"idle"); } } /* END while (1) */ J->RType = RsvSType; if (!NoRsvTransition) MRsvTransition(R,FALSE); #if 0 MSysJobUpdateRsvFlags(J); #endif MRsvTableDumpToLog(__FUNCTION__,__LINE__); return(SUCCESS); } /* END MRsvJCreate() */
int MVMSetAttr( mvm_t *VM, /* I * (modified) */ enum MVMAttrEnum AIndex, /* I */ void const *Value, /* I */ enum MDataFormatEnum Format, /* I */ enum MObjectSetModeEnum Mode) /* I */ { const char *FName = "MVMSetAttr"; char const *ValAsString = (char const *)Value; MDB(6,fSTRUCT) MLog("%s(%s,%s,Value,%s,%s)\n", FName, (VM != NULL) ? VM->VMID : "NULL", MVMAttr[AIndex], MFormatMode[Format], MObjOpType[Mode]); if (VM == NULL) { return(FAILURE); } switch (AIndex) { case mvmaActiveOS: { int OS = MUMAGetIndex(meOpsys,ValAsString,mSet); if (OS != 0) VM->ActiveOS = OS; /*TODO: what if OS is not in VM's OSList? */ } break; case mvmaADisk: VM->ARes.Disk = strtol(ValAsString,NULL,0); break; case mvmaAlias: { if (Mode != mClear) { mvoid_t *Element; if (MUHTGet(&MNetworkAliasesHT,ValAsString,NULL,NULL) == SUCCESS) { /* Specified alias is already in use. Do not allow */ return(FAILURE); } /* Add to table now */ /* Done as mvoid_t so that node aliases work as well */ Element = (mvoid_t *)MUCalloc(1,sizeof(mvoid_t)); Element->Ptr = (void *)VM; Element->PtrType = mxoxVM; MUStrCpy(Element->Name,VM->VMID,sizeof(Element->Name)); MUHTAdd(&MNetworkAliasesHT,ValAsString,(void *)Element,NULL,MUFREE); } if ((Mode == mSet) || (Mode == mClear)) { /* Clear list, remove from global table */ mln_t *freePtr = NULL; while (MULLIterate(VM->Aliases,&freePtr) == SUCCESS) { MUHTRemove(&MNetworkAliasesHT,freePtr->Name,MUFREE); } /* TODO: send out signal to outside system to free alias */ MULLFree(&VM->Aliases,MUFREE); } if ((Mode == mSet) || (Mode == mAdd)) { /* Set has already been cleared, treat as add */ /* These must be added one at a time */ if (VM->Aliases == NULL) { MULLCreate(&VM->Aliases); } if (MULLAdd(&VM->Aliases,ValAsString,NULL,NULL,MUFREE) == FAILURE) return(FAILURE); /* TODO: send out signal to outside system to set alias */ } } /* END BLOCK mvmaAlias */ break; case mvmaAMem: VM->ARes.Mem = strtol(ValAsString,NULL,0); break; case mvmaAProcs: /* NOTE: set ARes.Procs to 0 if VM is not available */ if (MNSISUP(VM->State) && (VM->State != mnsUnknown)) { VM->ARes.Procs = strtol(ValAsString,NULL,0); } else { VM->ARes.Procs = 0; } break; case mvmaCDisk: VM->CRes.Disk = strtol(ValAsString,NULL,0); break; case mvmaCMem: VM->CRes.Mem = strtol(ValAsString,NULL,0); break; case mvmaCProcs: VM->CRes.Procs = strtol(ValAsString,NULL,0); break; case mvmaCPULoad: VM->CPULoad = strtod(ValAsString,NULL); break; case mvmaDescription: MUStrDup(&VM->Description,ValAsString); break; case mvmaEffectiveTTL: VM->EffectiveTTL = strtol(ValAsString,NULL,10); break; case mvmaFlags: bmfromstring((char *)Value,MVMFlags,&VM->Flags); break; case mvmaGMetric: { char *GMTok; char *GMName; char *GMVal; char *TokPtr = NULL; char *TokPtr2 = NULL; int gmindex; /* generic metrics */ /* FORMAT: <GMETRIC>{:=}<VAL>[,<GMETRIC>{:=}<VAL>]... */ GMTok = MUStrTok((char *)Value,", \t\n",&TokPtr); while (GMTok != NULL) { GMName = MUStrTok(GMTok,"=:",&TokPtr2); GMVal = MUStrTok(NULL,"=:",&TokPtr2); GMTok = MUStrTok(NULL,", \t\n",&TokPtr); if ((GMName == NULL) || (GMVal == NULL)) { /* mal-formed value, ignore */ continue; } gmindex = MUMAGetIndex(meGMetrics,GMName,mAdd); if ((gmindex <= 0) || (gmindex >= MSched.M[mxoxGMetric])) continue; /* valid gmetric located */ MVMSetGMetric(VM,gmindex,GMVal); } /* END while (GMTok != NULL) */ } /* END BLOCK (case mvmaGMetric) */ break; case mvmaID: MUStrCpy(VM->VMID,ValAsString,sizeof(VM->VMID)); break; case mvmaLastMigrateTime: VM->LastMigrationTime = (mulong)strtol(ValAsString,NULL,10); break; case mvmaLastSubState: MUStrDup(&VM->LastSubState,ValAsString); break; case mvmaLastSubStateMTime: VM->LastSubStateMTime = (mulong)strtol(ValAsString,NULL,10); break; case mvmaMigrateCount: VM->MigrationCount = (int)strtol(ValAsString,NULL,10); break; case mvmaNextOS: { int OS = MUMAGetIndex(meOpsys,ValAsString,mSet); if (OS != 0) VM->NextOS = OS; /*TODO: what if OS is not in VM's OSList? */ } case mvmaNodeTemplate: case mvmaOSList: case mvmaSlotIndex: case mvmaState: break; case mvmaSovereign: { mbool_t WasSovereign = bmisset(&VM->Flags,mvmfSovereign); mbool_t NewVal = MUBoolFromString(ValAsString,FALSE); if (NewVal == TRUE) bmset(&VM->Flags,mvmfSovereign); else bmunset(&VM->Flags,mvmfSovereign); if ((!bmisset(&VM->Flags,mvmfSovereign)) && (WasSovereign == TRUE)) { if (VM->J != NULL) { /* is this how to handle previously sovereign VMs correctly? */ bmset(&VM->J->IFlags,mjifCancel); } } } break; case mvmaSpecifiedTTL: VM->SpecifiedTTL = strtol(ValAsString,NULL,10); break; case mvmaStartTime: VM->StartTime = (mulong)strtol(ValAsString,NULL,10); break; case mvmaSubState: if (ValAsString == NULL) { MUFree(&VM->SubState); } else { MUStrDup(&VM->SubState,(char *)ValAsString); } break; case mvmaStorageRsvNames: MUStrDup(&VM->StorageRsvNames,(char *)ValAsString); break; case mvmaVariables: if (Mode == mSet) { /* Clear the current attrs */ MUHTClear(&VM->Variables,TRUE,(mfree_t)MUFree); } /* FORMAT: attr:value[+attr:value]... */ /* value is a string (alphanumeric and '_') */ if ((Mode == mAdd) || (Mode == mSet)) { char *ptr; char *TokPtr = NULL; char *TokPtr2 = NULL; ptr = MUStrTok((char *)ValAsString,"+",&TokPtr); while (ptr != NULL) { char *AName; char *AVal; char *MallocVal = NULL; char ANameNoQuotes[MMAX_LINE]; AName = MUStrTok(ptr,":",&TokPtr2); AVal = MUStrTok(NULL,":",&TokPtr2); MUStrReplaceStr(AName,"\"","",ANameNoQuotes,sizeof(ANameNoQuotes)); if (AVal != NULL) { int AValLen = (strlen(AVal) * sizeof(char)) + 1; MallocVal = (char *)MUMalloc(AValLen); MUStrReplaceStr(AVal,"\"","",MallocVal,strlen(AVal) + 1); } MUHTAdd(&VM->Variables,ANameNoQuotes,(void *)MallocVal,NULL,MUFREE); ptr = MUStrTok(NULL,"+",&TokPtr); } /* END while (ptr != NULL) */ } /* END if ((Mode == mAdd) || (Mode == mSet)) */ break; case mvmaTrigger: if (Format == mdfString) { mtrig_t *T; marray_t TList; int tindex; MUArrayListCreate(&TList,sizeof(mtrig_t *),10); if (MTrigLoadString( &VM->T, (char *)Value, TRUE, FALSE, mxoxVM, VM->VMID, &TList, NULL) == FAILURE) { return(FAILURE); } for (tindex = 0; tindex < TList.NumItems;tindex++) { T = (mtrig_t *)MUArrayListGetPtr(&TList,tindex); if (MTrigIsValid(T) == FALSE) continue; MTrigInitialize(T); MOAddTrigPtr(&VM->T,T); } /* END for (tindex) */ return(SUCCESS); } /* END if (Format == mdfString) */ /* END BLOCK mvmaTrigger */ break; case mvmaNONE: case mvmaLAST: default: break; } /* END switch (AIndex) */ return(SUCCESS); } /* END MVMSetAttr() */
int MSysDoTest() { char *tptr; char *aptr; char *ptr; int aindex; int rc; char tmpLine[MMAX_LINE]; const char *TName[] = { NONE, "COMPRESS", "SCHED", "XML", "RANGEAND", "RANGECOLLAPSE", "RANGEMERGE", "GETSNRANGE", "NODEPRIO", "SPAWN", "WIKINODE", "WIKIJOB", "WIKICLUSTER", "RMX", "JOBNAME", "JOBDIST", "CHECKSUM", "LLSUBMIT", "LLQUERY", "MAIL", "PBSPARSE", "PBSPARSE2", "NODERANGE", "BGRANGE", "ODBCTEST", "SQLITE3TEST", "STRINGTEST", "RMXTEST", "STATCONVTEST", "GEOTEST", "DISATEST", "MACADDRESS", NULL }; enum { mirtNONE = 0, mirtCompress, mirtSched, mirtXML, mirtRLAND, mirtJobSelectFRL, mirtRLMerge, mirtJobGetSNRange, mirtNodePrio, mirtSpawn, mirtWikiNode, mirtWikiJob, mirtWikiCluster, mirtRMExtension, mirtJobName, mirtJobDist, mirtChecksum, mirtLLSubmit, mirtLLQuery, mirtMail, mirtPBSParse, mirtPBSParse2, mirtNodeRange, mirtBGRange, mirtODBCTest, mirtSQLite3Test, mirtStringTest, mirtRMX, mirtStatConvTest, mirtGeoTest, mirtDisaTest, mirtMacAddress, mirtLAST }; if ((tptr = getenv(MSCHED_ENVTESTVAR)) == NULL) { return(SUCCESS); } MUStrCpy(tmpLine,tptr,sizeof(tmpLine)); aindex = MUGetIndexCI(tmpLine,TName,TRUE,0); aptr = NULL; if ((ptr = strchr(tmpLine,':')) != NULL) { aptr = ptr + 1; } fprintf(stderr,"INFO: running test %s, data='%s'\n", TName[aindex], (aptr != NULL) ? aptr : ""); switch (aindex) { case mirtCompress: MUCompressTest(); break; case mirtXML: __MSysTestXML(aptr); break; case mirtRLAND: __MSysTestRLAND(); break; case mirtGeoTest: __MSysTestGeo(aptr); break; case mirtJobSelectFRL: __MSysTestJobSelectFRL(); break; case mirtRLMerge: __MSysTestRLMerge(); break; case mirtJobGetSNRange: __MSysTestJobGetSNRange(); break; case mirtMacAddress: __MSysTestMacAddress(); break; case mirtNodePrio: __MSysTestNPrioF(); break; case mirtSpawn: __MSysTestSpawn(); break; case mirtWikiNode: MWikiTestNode(aptr); break; case mirtWikiJob: MWikiTestJob(aptr); break; case mirtWikiCluster: MWikiTestCluster(aptr); break; case mirtRMExtension: MJobTestRMExtension(aptr); break; case mirtJobName: MJobTestName(aptr); break; case mirtChecksum: MSecTestChecksum(aptr); break; case mirtLLSubmit: { int JC; char *ptr; char *TokPtr = NULL; mjob_t tmpJ; mreq_t tmpRQ; mnode_t *N; int tmpTM[4]; MRM[0].Type = mrmtLL; MRM[0].U.LL.ProcVersionNumber = 9; strcpy(tmpJ.Name,"test"); /* FORMAT: <FROMHOST>.<CLUSTER>,<NODEID> */ ptr = MUStrTok(aptr,".,",&TokPtr); tmpJ.SubmitHost = NULL; MUStrDup(&tmpJ.SubmitHost,ptr); ptr = MUStrTok(NULL,".,",&TokPtr); ptr = MUStrTok(NULL,",",&TokPtr); if (MNodeAdd(ptr,&N) == FAILURE) { exit(1); } N->RM = &MRM[0]; tmpJ.TaskMap = tmpTM; tmpJ.TaskMapSize = 4; tmpJ.TaskMap[0] = N->Index; tmpJ.TaskMap[1] = -1; tmpJ.Req[0] = &tmpRQ; tmpJ.Req[1] = NULL; tmpRQ.RMIndex = 0; MRMWorkloadQuery(&JC,NULL,NULL,NULL); MRMJobStart(&tmpJ,NULL,NULL); exit(1); } /* END BLOCK (case mirtLLSubmit) */ break; case mirtLLQuery: /* NYI */ exit(1); break; case mirtMail: rc = MSysSendMail( MSysGetAdminMailList(1), NULL, "moab test", NULL, "test mail"); if (rc == FAILURE) exit(1); exit(0); break; case mirtPBSParse: case mirtPBSParse2: { /* NOTE: select must be translated different than "neednodes", if select is specified, memory is assigned as a per task resource and arch as a per req constraint */ /* > qsub -l select=4 (it requests 4 default chunks) > > or > > qsub -l select=2:ncpus=1:mem=10GB+3:ncpus=2:mem=8GB:arch=linux > (requests 2 chunks of 1 cpu,10gb of mem and 3 chunks of > 2 cpus, 8gb of mem, arch=linux). */ int rc; mjob_t *J = NULL; int *TaskList = NULL; MRM[0].Type = mrmtPBS; MJobMakeTemp(&J); MRMJobPreLoad(J,"PBSParse",&MRM[0]); TaskList = (int *)MUMalloc(sizeof(int) * MSched.JobMaxTaskCount); if (aindex == mirtPBSParse) rc = MJobGetPBSTaskList(J,aptr,TaskList,FALSE,TRUE,FALSE,FALSE,NULL,NULL); else rc = MJobGetSelectPBSTaskList(J,aptr,TaskList,FALSE,FALSE,NULL); MUFree((char **)TaskList); if (rc == FAILURE) { exit(1); } exit(0); } /* END BLOCK (case mirtPBSParse) */ break; case mirtNodeRange: { int nindex; mnode_t *N; mnl_t tmpNL; MNLInit(&tmpNL); nindex = 0; MNodeAdd("node12",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 4); MNodeAdd("node11",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 4); MNodeAdd("node03",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 4); MNodeAdd("node04",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 2); MNodeAdd("node05",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 2); MNodeAdd("node06",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 1); MNodeAdd("node09",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 4); MNodeAdd("node08",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 4); MNodeAdd("node07",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 4); MNodeAdd("node10",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 3); MNodeAdd("node01",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 4); MNodeAdd("node02",&N); MNLSetNodeAtIndex(&tmpNL,nindex,N); MNLSetTCAtIndex(&tmpNL,nindex++, 3); MNLTerminateAtIndex(&tmpNL,nindex); mstring_t TaskBuf(MMAX_BUFFER); MUNLToRangeString( &tmpNL, NULL, -1, TRUE, TRUE, &TaskBuf); fprintf(stderr,"Range: '%s'\n", TaskBuf.c_str()); exit(0); } /* END BLOCK */ break; case mirtBGRange: { char tmpLine[MMAX_LINE]; int NCount; int NListIndex = 0; char **NCharList = NULL; /* make dynamic */ NCharList = (char **)MUCalloc(1,sizeof(char *) * MSched.M[mxoNode]); snprintf(tmpLine,sizeof(tmpLine),"002x233,702x733"); MUParseBGRangeString(tmpLine,NCharList,MSched.M[mxoNode] - NListIndex,&NCount); exit(0); } break; case mirtDisaTest: rc = MDISATest(); exit((rc == SUCCESS) ? 0 : 1); break; default: { int tindex; /* cannot determine test */ fprintf(stderr,"ERROR: invalid test specified (%s) - use ", tptr); for (tindex = 1;tindex < mirtLAST;tindex++) { fprintf(stderr,"%s%s", (tindex > 1) ? "," : "", TName[tindex]); } fprintf(stderr,"\n"); } /* END BLOCK */ exit(1); /*NOTREACHED*/ break; } /* END switch (aindex) */ return(SUCCESS); } /* END MSysDoTest() */
int MASNet1Create( masnet1_t **N, char *ConfigString) { char *ptr; char *TokPtr; char ValLine[MAX_MLINE]; int aindex; mreq_t *RQ; if (N == NULL) return(FAILURE); /* create AS data structure */ if (*N == NULL) { *N = (masnet1_t *)calloc(1,sizeof(masnet1_t)); } if (ConfigString != NULL) { /* process config data */ /* FORMAT: BANDWIDTH=<BANDWIDTH>;NAME=<NAME>;STATE=<ACTIVE>... */ ptr = MUStrTok(ConfigString,"; \t\n",&TokPtr); while (ptr != NULL) { if (MUGetPair( ptr, (const char **)MASNet1AttributeType, &aindex, NULL, TRUE, NULL, ValLine, MAX_MNAME) == FAILURE) { /* cannot parse value pair */ ptr = MUStrTok(NULL,"; \t\n",&TokPtr); continue; } switch(aindex) { case masnet1aBandwidth: /* FORMAT: <BANDWIDTH> */ (*N)->Bandwidth = (int)strtol(ValLine,NULL,0); break; case masnet1aName: MUStrDup(&(*N)->Name,ValLine); break; case masnet1aState: /* enable network by default */ (*N)->State = 1; break; default: break; } /* END switch(aindex) */ ptr = MUStrTok(NULL,"; \t\n",&TokPtr); } /* END while (ptr != NULL) */ } /* END if (ConfigString != NULL) */ /* clear network state */ /* NYI */ return(SUCCESS); } /* END MASNet1Create() */
int MWikiSDUpdateAttr( char *AttrString, /* I */ msdata_t *SD, /* I (modified) */ mrm_t *R, /* I (optional) */ char *EMsg) /* O (optional,minsize=MMAX_LINE) */ { char *ptr; char *Value; char tmpLine[MMAX_LINE]; char *TokPtr; int aindex; const char *FName = "MWikiSDUpdateAttr"; MDB(6,fWIKI) MLog("%s(%.32s,SD,R,EMsg)\n", FName, (AttrString != NULL) ? AttrString : "NULL"); if (EMsg != NULL) EMsg[0] = '\0'; if ((SD == NULL) || (AttrString == NULL)) { return(FAILURE); } if ((ptr = MUStrChr(AttrString,'=')) == NULL) { if (EMsg != NULL) { snprintf(EMsg,MMAX_LINE,"attribute '%s' malformed - no '='", AttrString); } return(FAILURE); } /* FORMAT: <ATTR>={"<ALNUM_STRING>"|<ALNUM_STRING>} */ /* make copy of attribute string */ MUStrCpy(tmpLine,AttrString,sizeof(tmpLine)); ptr = MUStrTokE(tmpLine,"=",&TokPtr); aindex = MUGetIndex(ptr,MWikiSDAttr,FALSE,0); if (aindex == 0) { if (EMsg != NULL) { snprintf(EMsg,MMAX_LINE,"invalid attribute '%s' specified", AttrString); } return(FAILURE); } Value = MUStrTokE(NULL,"=",&TokPtr); if (Value == NULL) { snprintf(EMsg,MMAX_LINE,"missing value for attribute '%s'", AttrString); return(FAILURE); } switch (aindex) { case mwsdaBytesTransferred: { mulong NewSize; NewSize = strtol(Value,NULL,10); if (NewSize != SD->DstFileSize) { /* mark that the staging operating is not stalled */ SD->UTime = MSched.Time; } MSDSetAttr(SD,msdaDstFileSize,(void **)&NewSize,mdfLong,mSet); } /* END BLOCK */ break; case mwsdaEndTime: /* data staging operation has finished? */ /* NYI */ break; case mwsdaError: MUStrDup(&SD->EMsg,Value); break; case mwsdaFileSize: { mulong tmpL = strtol(Value,NULL,10); MSDSetAttr(SD,msdaSrcFileSize,(void **)&tmpL,mdfLong,mSet); } /* END BLOCK */ break; case mwsdaRemoveTime: /* NYI */ break; case mwsdaSourceURL: /* verify that this URL matches what we expect */ if (strcmp(SD->SrcLocation,Value)) { /* URL's do not match - mismatched record! */ MDB(2,fWIKI) MLog("WARNING: stage-data src location is being incorrectly reported via WIKI '%s' != '%s'\n", Value, SD->SrcLocation); return(FAILURE); } break; case mwsdaStartTime: { mulong tmpL = strtol(Value,NULL,10); MSDSetAttr(SD,msdaTStartDate,(void **)&tmpL,mdfLong,mSet); } /* END BLOCK */ break; case mwsdaState: MSDSetAttr(SD,msdaState,(void **)Value,mdfString,mSet); break; case mwsdaUser: /* NYI */ break; default: MDB(2,fWIKI) MLog("INFO: WIKI keyword '%s'(%d) not handled\n", MWikiSDAttr[aindex], aindex); return(FAILURE); /*NOTREACHED*/ break; } /* END switch (aindex) */ return(SUCCESS); } /* END MWikiSDUpdateAttr() */
int MASLSJobCreate( mjob_t *J, char *ConfigString) { char *ptr; char *TokPtr; char *ptr2; char *TokPtr2; char *ptr3; char ValLine[MAX_MLINE]; int aindex; mreq_t *RQ; maslsdata_t *D; if (J == NULL) return(FAILURE); /* NOTE: by default, each job uses 100% of all dedicated resources */ /* set 'RQ->URes.Procs' */ /* set 'RQ->URes.Mem' */ /* create AS data structure */ if (J->ASData == NULL) { J->ASData = calloc(1,sizeof(maslsdata_t)); } D = (maslsdata_t *)J->ASData; if (ConfigString != NULL) { /* process config data */ /* FORMAT: INPUT=<INPUTDATANAME>:<INPUTDATASIZE>;OUTPUT=<OUTPUTDATANAME>:<OUTPUTDATASIZE> */ ptr = MUStrTok(ConfigString,"; \t\n",&TokPtr); while (ptr != NULL) { if (MUGetPair( ptr, (const char **)MASLSAttributeType, &aindex, NULL, TRUE, NULL, ValLine, MAX_MNAME) == FAILURE) { /* cannot parse value pair */ ptr = MUStrTok(NULL,"; \t\n",&TokPtr); continue; } switch(aindex) { case maslsaInput: /* FORMAT: <FILENAME>[<@<SOURCE>]:<FILESIZE> */ if (strchr(ValLine,'@') != NULL) { if ((ptr2 = MUStrTok(ValLine,":@",&TokPtr2)) != NULL) { MUStrDup(&D->IFileName,ptr2); if ((ptr2 = MUStrTok(NULL,":@",&TokPtr2)) != NULL) { MGResFind(ptr2,-1,&D->INetRes); } } } else { if ((ptr2 = MUStrTok(ValLine,":",&TokPtr2)) != NULL) { MUStrDup(&D->IFileName,ptr2); } } if (D->INetRes == NULL) { MGResFind(NULL,-1,&D->INetRes); } if ((ptr2 = MUStrTok(NULL,":@",&TokPtr2)) != NULL) { D->IFileSize = (int)strtol(ptr2,NULL,0); } D->IFileStaged = 0; break; case maslsaOutput: /* FORMAT: <FILENAME>[<@<SOURCE>]:<FILESIZE> */ if (strchr(ValLine,'@') != NULL) { if ((ptr2 = MUStrTok(ValLine,":@",&TokPtr2)) != NULL) { MUStrDup(&D->OFileName,ptr2); if ((ptr2 = MUStrTok(NULL,":@",&TokPtr2)) != NULL) { MGResFind(ptr2,-1,&D->ONetRes); } } } else { if ((ptr2 = MUStrTok(ValLine,":",&TokPtr2)) != NULL) { MUStrDup(&D->OFileName,ptr2); } } if (D->ONetRes == NULL) { MGResFind(NULL,-1,&D->ONetRes); } if ((ptr2 = MUStrTok(NULL,":@",&TokPtr2)) != NULL) { D->OFileSize = (int)strtol(ptr2,NULL,0); } D->OFileStaged = 0; break; default: break; } /* END switch(aindex) */ ptr = MUStrTok(NULL,"; \t\n",&TokPtr); } /* END while (ptr != NULL) */ } /* END if (ConfigString != NULL) */ /* clear resource usage */ RQ = J->Req[0]; memset(&RQ->URes,0,sizeof(RQ->URes)); return(SUCCESS); } /* END MASLSJobCreate() */
int MClassSetAttr( mclass_t *C, /* I (modified) */ int AIndex, /* I */ void **Value, /* I */ int Format, /* I */ int Mode) /* I */ { if (C == NULL) { return(FAILURE); } switch(AIndex) { case mclaOCNode: MUStrDup(&C->OCNodeName,(char *)Value); break; case mclaDefReqFeature: { /* FORMAT: <FEATURE>[{ \t:,}<FEATURE>]... */ char *ptr; char *TokPtr; /* detect default feature requirements */ ptr = MUStrTok((char *)Value,":",&TokPtr); while (ptr != NULL) { MUGetMAttr(eFeature,ptr,mAdd,C->DefFBM,sizeof(C->DefFBM)); ptr = MUStrTok(NULL,":",&TokPtr); } /* END while (ptr != NULL) */ } /* END BLOCK */ break; case mclaMaxProcPerNode: { int tmpI; if (Format == mdfString) tmpI = (int)strtol((char *)Value,NULL,0); else tmpI = *(int *)Value; C->MaxProcPerNode = tmpI; } /* END BLOCK */ break; case mclaOCDProcFactor: { double tmpD; if (Format == mdfString) tmpD = (double)strtod((char *)Value,NULL); else tmpD = *(double *)Value; C->OCDProcFactor = tmpD; } /* END BLOCK */ break; case mclaState: { int tmpI; if (Format == mdfString) tmpI = (int)strtol((char *)Value,NULL,0); else tmpI = *(int *)Value; C->IsDisabled = (tmpI == mjsRunning) ? TRUE : FALSE; } /* END BLOCK */ break; case mclaWCOverrun: { int tmpL; if (Format == mdfString) tmpL = MUTimeFromString((char *)Value); else tmpL = *(long *)Value; C->F.Overrun = tmpL; } /* END BLOCK */ default: /* NO-OP */ return(FAILURE); /*NOTREACHED*/ break; } /* END switch(AIndex) */ return(SUCCESS); } /* END MClassSetAttr() */
int MRMJobValidate( mjob_t *J, /* I */ mrm_t *R, /* I */ char *EMsg, /* O (optional,minsize=MMAX_LINE) */ enum MJobCtlCmdEnum *FailureAction, /* I (optional) */ int *SC) /* O (optional) */ { enum MWJobAttrEnum aindex; enum MRMSubTypeEnum SType; int index; char SPath[MMAX_BUFFER]; char *BPtr; int BSpace; char *ptr; char *TokPtr; char *ptr2; char *TokPtr2; char tEMsg[MMAX_LINE]; enum MStatusCodeEnum tmpSC; mbool_t GRes = FALSE; const char *FName = "MRMJobValidate"; MDB(2,fRM) MLog("%s(%s,%s,EMsg,FailureAction,SC)\n", FName, (J != NULL) ? J->Name : "NULL", (R != NULL) ? R->Name : "NULL"); if (EMsg != NULL) EMsg[0] = '\0'; if (SC != NULL) *SC = 0; if (J == NULL) { return(FAILURE); } if (R->ND.URL[mrmXJobValidate] == NULL) { /* no job validate script specified */ return(SUCCESS); } MUSNInit(&BPtr,&BSpace,SPath,sizeof(SPath)); MUSNPrintF(&BPtr,&BSpace,"%s=%s ", MWikiJobAttr[mwjaUName], J->Credential.U->Name); if (J->EUser != NULL) { /* report execution user */ MUSNPrintF(&BPtr,&BSpace,"%s=%s ", "EUSER", J->EUser); } if (J->Credential.G != NULL) { MUSNPrintF(&BPtr,&BSpace,"%s=%s ", MWikiJobAttr[mwjaGName], J->Credential.G->Name); } if (J->SpecWCLimit[0] > 0) { MUSNPrintF(&BPtr,&BSpace,"%s=%ld ", MWikiJobAttr[mwjaWCLimit], J->SpecWCLimit[0]); } /* if (J->Request.TC > 0) { MUSNPrintF(&BPtr,&BSpace,"%s=%d ", MWikiJobAttr[mwjaTasks], J->Request.TC); } */ if (J->Credential.C != NULL) { MUSNPrintF(&BPtr,&BSpace,"%s=%s ", MWikiJobAttr[mwjaRClass], J->Credential.C->Name); } if (J->QOSRequested != NULL) { MUSNPrintF(&BPtr,&BSpace,"%s=%s ", MWikiJobAttr[mwjaQOS], J->QOSRequested->Name); } if (J->Env.Cmd != NULL) { char *ptr; char *TokPtr; char tmpLine[MMAX_LINE]; MUStrCpy(tmpLine,J->Env.Cmd,sizeof(tmpLine)); ptr = MUStrTok(tmpLine," ",&TokPtr); MUStringChop(ptr); MUSNPrintF(&BPtr,&BSpace,"%s=%s ", MWikiJobAttr[mwjaExec], ptr); } /* END if (J->E.Cmd != NULL) */ if (!bmisclear(&J->Req[0]->ReqFBM)) { char tmpLine[MMAX_LINE]; MUSNPrintF(&BPtr,&BSpace,"%s=%s ", MWikiJobAttr[mwjaRFeatures], MUNodeFeaturesToString(',',&J->Req[0]->ReqFBM,tmpLine)); } if (J->Variables.Table != NULL) { mstring_t tmp(MMAX_LINE); MJobAToMString(J,mjaVariables,&tmp); MUSNPrintF(&BPtr,&BSpace,"%s=%s ", MWikiJobAttr[mwjaVariables], tmp.c_str()); } /* display generic resources */ for (index = 1;index < MSched.M[mxoxGRes];index++) { if (MGRes.Name[index][0] == '\0') break; if (MSNLGetIndexCount(&J->Req[0]->DRes.GenericRes,index) == 0) continue; if (GRes == FALSE) { MUSNPrintF(&BPtr,&BSpace,"GRES=%s:%d", MGRes.Name[index], MSNLGetIndexCount(&J->Req[0]->DRes.GenericRes,index)); GRes = TRUE; } else { MUSNPrintF(&BPtr,&BSpace,",%s:%d", MGRes.Name[index], MSNLGetIndexCount(&J->Req[0]->DRes.GenericRes,index)); } } /* END for (index) */ /* send this off to JOBVALIDATEURL */ SType = R->ND.NatType; R->ND.NatType = mrmstX1E; mstring_t Response(MMAX_LINE); /* NOTE: should we pass-in Job Validate specific timeout, ie 2 seconds? (NYI) */ if (MNatDoCommand( &R->ND, SPath, mrmXJobValidate, R->ND.Protocol[mrmXJobValidate], FALSE, NULL, NULL, &Response, tEMsg, /* O */ &tmpSC) == FAILURE) { R->ND.NatType = SType; /* make failure action configurable */ if ((ptr = strstr(tEMsg,"ACTION=")) != NULL) { ptr += strlen("ACTION="); ptr2 = MUStrTok(ptr," \n\t",&TokPtr); if (FailureAction != NULL) *FailureAction = (enum MJobCtlCmdEnum)MUGetIndexCI(ptr2,MJobCtlCmds,FALSE,mjcmNONE); } if (EMsg != NULL) MUStrCpy(EMsg,tEMsg,MMAX_LINE); if (SC != NULL) *SC = (int)tmpSC; return(FAILURE); } if (SC != NULL) *SC = (int)tmpSC; R->ND.NatType = SType; for (index = 0;Response[index] != '\0';index++) { if (Response[index] == '\n') Response[index] = ' '; } mstring_t tmpString(MMAX_LINE); MWikiFromAVP(NULL,Response.c_str(),&tmpString); /* Need a char array that can be modified, not the immutable tmpString */ char *mutableResponse = NULL; MUStrDup(&mutableResponse,tmpString.c_str()); ptr = MUStrTok(mutableResponse,";",&TokPtr); int rc = SUCCESS; /* NYI: change other job attributes such as NodeCount RMXString User/Group */ while (ptr != NULL) { ptr2 = MUStrTok(ptr,"=",&TokPtr2); aindex = (enum MWJobAttrEnum)MUGetIndexCI(ptr2,MWikiJobAttr,FALSE,mwjaNONE); switch (aindex) { case mwjaAccount: if ((J->Credential.A == NULL) || (strcmp(TokPtr2,J->Credential.A->Name))) { if (MRMJobModify( J, "Account_Name", NULL, TokPtr2, mSet, "account modified by jobvalidate interface", tEMsg, /* O */ NULL) != SUCCESS) { MDB(2,fSCHED) MLog("INFO: cannot set account on job %s to '%s' - invalid account - %s\n", J->Name, TokPtr2, tEMsg); if (EMsg != NULL) strcpy(EMsg,"cannot set account"); rc = FAILURE; goto cleanupExit; } MAcctAdd(TokPtr2,&J->Credential.A); bmset(&J->IFlags,mjifAccountLocked); } break; case mwjaRClass: if ((J->Credential.C == NULL) || (strcmp(TokPtr2,J->Credential.C->Name))) { mclass_t *C; if (MClassFind(TokPtr2,&C) == FAILURE) { MDB(2,fSCHED) MLog("INFO: cannot set class on job %s to '%s' - invalid class\n", J->Name, TokPtr2); if (EMsg != NULL) strcpy(EMsg,"cannot locate class"); rc = FAILURE; goto cleanupExit; } if (MJobSetClass(J,C,TRUE,tEMsg) == FAILURE) { MDB(2,fSCHED) MLog("INFO: cannot set class on job %s to '%s' - %s\n", J->Name, C->Name, tEMsg); if (EMsg != NULL) strcpy(EMsg,"cannot set class"); rc = FAILURE; goto cleanupExit; } bmset(&J->IFlags,mjifClassLocked); } /* END if ((J->Cred.C == NULL) || ...) */ break; case mwjaQOS: /* bypass qos checks and put qos directly onto job */ J->QOSRequested = NULL; if (MQOSFind(TokPtr2,&J->Credential.Q) != SUCCESS) { MDB(2,fSCHED) MLog("INFO: cannot set qos on job %s to '%s' - invalid QoS\n", J->Name, TokPtr2); if (EMsg != NULL) strcpy(EMsg,"cannot locate qos"); rc = FAILURE; goto cleanupExit; } bmset(&J->IFlags,mjifQOSLocked); break; case mwjaRFeatures: MReqSetAttr(J,J->Req[0],mrqaReqNodeFeature,(void **)TokPtr2,mdfString,mSet); break; case mwjaWCLimit: if (MRMJobModify( J, "Resource_List", "walltime", TokPtr2, mSet, "walltime modified by jobvalidate interface", tEMsg, NULL) == FAILURE) { MDB(2,fSCHED) MLog("INFO: cannot modify walltime for rm job %s - '%s'\n", J->Name, tEMsg); if (EMsg != NULL) strcpy(EMsg,"cannot modify walltime"); rc = FAILURE; goto cleanupExit; } break; case mwjaVariables: MJobSetAttr(J,mjaVariables,(void **)TokPtr2,mdfString,mAdd); break; default: /* NO-OP */ break; } /* END switch (aindex) */ ptr = MUStrTok(NULL,";",&TokPtr); } /* END while (ptr != NULL) */ cleanupExit: MUFree(&mutableResponse); return(rc); } /* END MRMJobValidate() */
int MMBFromXML( mmb_t **MBP, /* I (modified) */ mxml_t *E) /* I */ { int CTok; mxml_t *ME; char tmpLine[MMAX_LINE << 1]; char Owner[MMAX_NAME]; char Source[MMAX_NAME]; char Label[MMAX_NAME]; int count; int priority; enum MMBTypeEnum type; char *ptr; mulong etime; mmb_t *tmpMB; CTok = -1; while (MXMLGetChild(E,"message",&CTok,&ME) == SUCCESS) { if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaCount],NULL,tmpLine,sizeof(tmpLine)) == SUCCESS) { count = (int)strtol(tmpLine,NULL,10); } else { count = 1; } if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaPriority],NULL,tmpLine,sizeof(tmpLine)) == SUCCESS) { priority = (int)strtol(tmpLine,NULL,10); } else { priority = 1; } MXMLGetAttr(ME,(char *)MMBAttr[mmbaType],NULL,tmpLine,sizeof(tmpLine)); type = (enum MMBTypeEnum)MUGetIndexCI(tmpLine,MMBType,FALSE,mmbtNONE); if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaExpireTime],NULL,tmpLine,sizeof(tmpLine)) == SUCCESS) { etime = strtol(tmpLine,NULL,10); } else { etime = MSched.Time + MCONST_DAYLEN; } if (MXMLGetAttr(ME,(char *)MMBAttr[mmbaOwner],NULL,Owner,sizeof(Owner)) == FAILURE) strcpy(Owner,"N/A"); MXMLGetAttr(ME,(char *)MMBAttr[mmbaLabel],NULL,Label,sizeof(Label)); MXMLGetAttr(ME,(char *)MMBAttr[mmbaSource],NULL,Source,sizeof(Source)); if (MXMLGetAttr( ME, (char *)MMBAttr[mmbaData], NULL, tmpLine, sizeof(tmpLine)) == FAILURE) { return(FAILURE); } /* NOTE: should 'pack/unpack' messages to handle '<' and '\n' characters (NYI) */ if ((ptr = strchr(tmpLine,'\7')) != NULL) { /* unpack ckpt string - replace '\7' w/newlines */ for (;ptr != NULL;ptr = strchr(ptr,'\7')) { *ptr = '\n'; } } if (MMBAdd( MBP, tmpLine, Owner, type, etime, priority, &tmpMB) == FAILURE) { return(FAILURE); } if (count > 1) MMBSetAttr(tmpMB,mmbaCount,(void *)&count,mdfInt); if (Source[0] != '\0') MMBSetAttr(tmpMB,mmbaSource,(void *)Source,mdfString); if (Label[0] != '\0') MUStrDup(&tmpMB->Label,Label); } /* END while (MXMLGetChild() == SUCCESS) */ return(SUCCESS); } /* END MMBFromXML() */
int MTraceLoadWorkload( char *Buffer, /* I */ int *TraceLen, /* I (optional,modified) */ mjob_t *J, /* O */ int Mode, /* I */ int *Version) /* O */ { char *tail; char *head; char *ptr; char *ptr2; char *tok; char *TokPtr; char Line[MAX_MLINE << 4]; char tmpLine[MAX_MLINE]; char MHostName[MAX_MNAME]; char MReqHList[MAX_MLINE << 2]; char Reservation[MAX_MNAME]; char tmpTaskRequest[MAX_MLINE]; char tmpSpecWCLimit[MAX_MLINE]; char tmpState[MAX_WORD]; char tmpOpsys[MAX_WORD]; char tmpArch[MAX_WORD]; char tmpNetwork[MAX_WORD]; char tmpMemCmp[MAX_WORD]; char tmpDiskCmp[MAX_WORD]; char tmpReqNFList[MAX_MLINE]; char tmpClass[MAX_MLINE]; char tmpRMName[MAX_MLINE]; char tmpCmd[MAX_MLINE]; char tmpRMXString[MAX_MLINE >> 2]; char tmpParName[MAX_MNAME]; char tmpJFlags[MAX_MLINE]; char tmpQReq[MAX_WORD]; char tmpASString[MAX_MLINE]; char tmpRMemBuf[MAX_MNAME]; char tmpRDiskBuf[MAX_MNAME]; char tmpDSwapBuf[MAX_MNAME]; char tmpDMemBuf[MAX_MNAME]; char tmpDDiskBuf[MAX_MNAME]; char UName[MAX_MNAME]; char GName[MAX_MNAME]; char AName[MAX_MNAME]; char SetString[MAX_MLINE]; unsigned long tmpQTime; unsigned long tmpDTime; unsigned long tmpSTime; unsigned long tmpCTime; unsigned long tmpSQTime; unsigned long tmpSDate; unsigned long tmpEDate; int TPN; int TasksAllocated; int index; int rc; int tindex; int nindex; mqos_t *QDef; mreq_t *RQ[MAX_MREQ_PER_JOB]; mnode_t *N; long ReqProcSpeed; const char *FName = "MTraceLoadWorkload"; DBG(5,fSIM) DPrint("%s(Buffer,TraceLen,J,%d,%d)\n", FName, Mode, (Version != NULL) ? *Version : -1); if (J == NULL) { DBG(5,fSIM) DPrint("ALERT: NULL job pointer passed in %s()\n", FName); return(FAILURE); } if (Buffer == NULL) { return(FAILURE); } if ((tail = strchr(Buffer,'\n')) == NULL) { /* assume line is '\0' terminated */ if (TraceLen != NULL) tail = Buffer + *TraceLen; else tail = Buffer + strlen(Buffer); } head = Buffer; MUStrCpy(Line,head,MIN(tail - head + 1,sizeof(Line))); DBG(6,fSIM) DPrint("INFO: parsing trace line '%s'\n", Line); if (TraceLen != NULL) *TraceLen = (tail - head) + 1; /* eliminate comments */ if ((ptr = strchr(Line,'#')) != NULL) { DBG(5,fSIM) DPrint("INFO: detected trace comment line, '%s'\n", Line); *ptr = '\0'; } if (Line[0] == '\0') { return(FAILURE); } /* look for VERSION settings */ if (!strncmp(Line,TRACE_WORKLOAD_VERSION_MARKER,strlen(TRACE_WORKLOAD_VERSION_MARKER))) { if (MTraceGetWorkloadVersion(Line,Version) == FAILURE) { DBG(0,fSIM) DPrint("ALERT: cannot determine workload trace version\n"); /* assume default version */ if (Version != NULL) *Version = DEFAULT_WORKLOAD_TRACE_VERSION; } else { DBG(3,fSIM) DPrint("INFO: workload trace version %d detected\n", (Version != NULL) ? *Version : -1); } return(FAILURE); } /* END if (!strncmp(Line,TRACE_WORKLOAD_VERSION_MARKER)) */ /* set default workload attributes */ memset(J,0,sizeof(mjob_t)); if (MReqCreate(J,NULL,&J->Req[0],FALSE) == FAILURE) { DBG(0,fSIM) DPrint("ALERT: cannot create job req\n"); return(FAILURE); } MRMJobPreLoad(J,NULL,0); RQ[0] = J->Req[0]; RQ[0]->Index = 0; J->StartCount = 0; J->R = NULL; switch(*Version) { case 230: /* Name NR TReq User Grop WClk Stat Clss QUT DST STT CMT netw Arch Opsy MemC RMem DskC RDsk Feat SQT TA TPN QO MO AC CM CC BP PU Part DPrc DMem DDisk DSwap STARTDATE ENDDATE MNODE RM HL RES RES1 RES2 RES3 OVERFLOW */ rc = sscanf(Line,"%64s %d %64s %64s %64s %64s %64s %64s %lu %lu %lu %lu %64s %64s %64s %64s %64s %64s %64s %64s %lu %d %d %64s %1024s %64s %1024s %1024s %d %lf %64s %d %64s %64s %64s %lu %lu %1024s %64s %1024s %64s %64s %1024s %s %s", J->Name, &J->Request.NC, tmpTaskRequest, UName, GName, tmpSpecWCLimit, tmpState, tmpClass, &tmpQTime, &tmpDTime, &tmpSTime, &tmpCTime, tmpNetwork, tmpArch, tmpOpsys, tmpMemCmp, tmpRMemBuf, tmpDiskCmp, tmpRDiskBuf, tmpReqNFList, &tmpSQTime, /* SystemQueueTime */ &TasksAllocated, /* allocated task count */ &TPN, tmpQReq, tmpJFlags, AName, tmpCmd, tmpRMXString, /* RM extension string */ &J->Bypass, /* Bypass */ &J->PSUtilized, /* PSUtilized */ tmpParName, /* partition used */ &RQ[0]->DRes.Procs, tmpDMemBuf, tmpDDiskBuf, tmpDSwapBuf, &tmpSDate, &tmpEDate, MHostName, tmpRMName, MReqHList, Reservation, SetString, /* resource sets required by job */ tmpASString, /* application simulator name */ tmpLine, /* RES1 */ tmpLine /* check for too many fields */ ); /* fail if all fields not read in */ switch (rc) { case 43: strcpy(MHostName,NONE); J->RM = &MRM[0]; break; case 44: /* canonical 230 trace */ if (isdigit(tmpRMName[0])) J->RM = &MRM[(int)strtol(tmpRMName,NULL,0)]; else J->RM = &MRM[0]; break; default: DBG(1,fSIM) DPrint("ALERT: version %d workload trace is corrupt '%s' (%d of %d fields read) ignoring line\n", *Version, Line, rc, 44); MJobDestroy(&J); return(FAILURE); /*NOTREACHED*/ break; } /* END switch(rc) */ RQ[0]->RequiredMemory = MURSpecToL(tmpRMemBuf,mvmMega,mvmMega); RQ[0]->RequiredDisk = MURSpecToL(tmpRDiskBuf,mvmMega,mvmMega); RQ[0]->DRes.Mem = MURSpecToL(tmpDMemBuf,mvmMega,mvmMega); RQ[0]->DRes.Swap = MURSpecToL(tmpDSwapBuf,mvmMega,mvmMega); RQ[0]->DRes.Disk = MURSpecToL(tmpDDiskBuf,mvmMega,mvmMega); if (Mode != msmProfile) { ptr = NULL; ptr2 = NULL; if (strcmp(tmpASString,NONE)) { if ((ptr = MUStrTok(tmpASString,":",&TokPtr)) != NULL) { ptr2 = MUStrTok(NULL,"|",&TokPtr); } } if (MASGetDriver((void **)&J->ASFunc,ptr,msdApplication) == SUCCESS) { (*J->ASFunc)(J,mascCreate,ptr2,NULL); } } /* END if (Mode != msmProfile) */ /* obtain job step number from LL based job name */ /* FORMAT: <FROM_HOST>.<CLUSTER>.<PROC> */ MUStrCpy(tmpLine,J->Name,sizeof(tmpLine)); if ((ptr = MUStrTok(tmpLine,".",&TokPtr)) != NULL) { MUStrCpy(J->SubmitHost,ptr,sizeof(J->SubmitHost)); if ((ptr = MUStrTok(NULL,".",&TokPtr)) != NULL) { J->Cluster = (int)strtol(ptr,NULL,0); if ((ptr = MUStrTok(NULL,".",&TokPtr)) != NULL) { J->Proc = (int)strtol(ptr,NULL,0); } } } /* adjust job flags */ if (Mode == msmProfile) { MUStrDup(&J->MasterHostName,MHostName); /* NOTE: flags may be specified as string or number */ if ((J->SpecFlags = strtol(tmpJFlags,NULL,0)) == 0) { MUBMFromString(tmpJFlags,MJobFlags,&J->SpecFlags); } } else { /* simulation mode */ if ((MSim.Flags & (1 << msimfIgnMode)) || (MSim.Flags & (1 << msimfIgnAll))) { J->SpecFlags = 0; } else { /* NOTE: flags may be specified as string or number */ if ((J->SpecFlags = strtol(tmpJFlags,NULL,0)) == 0) { MUBMFromString(tmpJFlags,MJobFlags,&J->SpecFlags); } if (J->SysFlags & (1 << mjfBackfill)) J->SysFlags ^= (1 << mjfBackfill); if ((J->SpecFlags & (1 << mjfHostList)) && (MSim.Flags & (1 << msimfIgnHostList))) { J->SpecFlags ^= (1 << mjfHostList); } } } /* END else (Mode == msmProfile) */ /* extract arbitrary job attributes */ /* FORMAT: JATTR:<ATTR>[=<VALUE>] */ { char *ptr; char *TokPtr; ptr = MUStrTok(tmpJFlags,"[]",&TokPtr); while (ptr != NULL) { if (!strncmp(ptr,"JATTR:",strlen("JATTR:"))) { MJobSetAttr(J,mjaGAttr,(void **)(ptr + strlen("JATTR:")),0,mSet); } ptr = MUStrTok(NULL,"[]",&TokPtr); } /* END while (ptr != NULL) */ } /* END BLOCK */ /* set default flags, remove set 'ignore' flags */ J->SpecFlags |= MSim.TraceDefaultJobFlags; for (index = 0;index < M64.INTBITS;index++) { if (!(MSim.TraceIgnoreJobFlags & (1 << index))) continue; if (!(J->SpecFlags & (1 << index))) continue; J->SpecFlags ^= (1 << index); } /* END for (index) */ /* load task info */ if (!strncmp(tmpTaskRequest,"PBS=",strlen("PBS="))) { char tmpLine[MAX_MLINE]; tpbsa_t tmpA; short TaskList[MAX_MTASK]; memset(&tmpA,0,sizeof(tmpA)); sprintf(tmpLine,"Resource_List,nodes,%s", &tmpTaskRequest[strlen("PBS=")]); MPBSJobSetAttr(J,NULL,tmpLine,&tmpA,TaskList,0); MPBSJobAdjustResources(J,&tmpA,J->RM); } else { ptr = MUStrTok(tmpTaskRequest,",",&TokPtr); tindex = 1; while (ptr != NULL) { if (strchr(ptr,'-') != NULL) { /* NOTE: not handled */ } else { RQ[0]->TaskRequestList[tindex] = atoi(ptr); tindex++; } ptr = MUStrTok(NULL,",",&TokPtr); } RQ[0]->TaskRequestList[tindex] = 0; RQ[0]->TaskRequestList[0] = RQ[0]->TaskRequestList[1]; RQ[0]->TaskCount = RQ[0]->TaskRequestList[0]; J->Request.TC = RQ[0]->TaskRequestList[0]; RQ[0]->TasksPerNode = MAX(0,TPN); if (MPar[0].JobNodeMatch & (1 << nmExactNodeMatch)) { RQ[0]->NodeCount = RQ[0]->TaskCount; J->Request.NC = RQ[0]->TaskCount; } if (MPar[0].JobNodeMatch & (1 << nmExactProcMatch)) { if (RQ[0]->TasksPerNode >= 1) { RQ[0]->RequiredProcs = RQ[0]->TasksPerNode; RQ[0]->ProcCmp = mcmpEQ; } if (RQ[0]->TasksPerNode > J->Request.TC) { RQ[0]->TasksPerNode = 0; } } } /* END BLOCK */ /* process WCLimit constraints */ ptr = MUStrTok(tmpSpecWCLimit,",:",&TokPtr); tindex = 1; while (ptr != NULL) { if (strchr(ptr,'-') != NULL) { /* NOTE: not handled */ } else { J->SpecWCLimit[tindex] = strtol(ptr,NULL,0); tindex++; } ptr = MUStrTok(NULL,",:",&TokPtr); } /* END while (ptr != NULL) */ J->SpecWCLimit[tindex] = 0; J->SpecWCLimit[0] = J->SpecWCLimit[1]; J->SubmitTime = tmpQTime; J->DispatchTime = MAX(tmpDTime,tmpSTime); J->StartTime = MAX(tmpDTime,tmpSTime); J->CompletionTime = tmpCTime; J->SystemQueueTime = tmpSQTime; J->SpecSMinTime = tmpSDate; J->CMaxTime = tmpEDate; /* determine required reservation */ if (strcmp(Reservation,NONE) && strcmp(Reservation,J->Name)) { J->SpecFlags |= (1 << mjfAdvReservation); if (strcmp(Reservation,ALL) != 0) { strcpy(J->ResName,Reservation); } } /* determine job class */ if ((MSim.Flags & (1 << msimfIgnClass)) || (MSim.Flags & (1 << msimfIgnAll))) { mclass_t *C; MClassAdd("DEFAULT",&C); /* ignore specified classes */ RQ[0]->DRes.PSlot[0].count = 1; RQ[0]->DRes.PSlot[C->Index].count = 1; } else { int cindex; MUNumListFromString(RQ[0]->DRes.PSlot,tmpClass,eClass); for (cindex = 1;cindex < MAX_MCLASS;cindex++) { if (RQ[0]->DRes.PSlot[cindex].count > 0) { MClassAdd(MAList[eClass][cindex],NULL); } } /* END for (cindex) */ } if (Mode != msmProfile) { if ((strcmp(MReqHList,NONE) != 0) && !(MSim.Flags & (1 << msimfIgnHostList)) && !(MSim.Flags & (1 << msimfIgnAll))) { J->SpecFlags |= (1 << mjfHostList); ptr = MUStrTok(MReqHList,":",&TokPtr); nindex = 0; if (J->ReqHList == NULL) J->ReqHList = (mnalloc_t *)calloc(1,sizeof(mnalloc_t) * (MAX_MNODE_PER_JOB + 1)); J->ReqHList[0].N = NULL; while (ptr != NULL) { if (MNodeFind(ptr,&N) == FAILURE) { if (MSched.DefaultDomain[0] != '\0') { if ((tail = strchr(ptr,'.')) != NULL) { /* try short name */ MUStrCpy(MReqHList,ptr,MIN(sizeof(MReqHList),(tail - ptr + 1))); } else { /* append default domain */ if (MSched.DefaultDomain[0] == '.') { sprintf(MReqHList,"%s%s", ptr, MSched.DefaultDomain); } else { sprintf(MReqHList,"%s.%s", ptr, MSched.DefaultDomain); } } if (MNodeFind(MReqHList,&N) != SUCCESS) { DBG(1,fUI) DPrint("ALERT: cannot locate node '%s' for job '%s' hostlist\n", ptr, J->Name); N = NULL; } } else { DBG(1,fUI) DPrint("ALERT: cannot locate node '%s' for job '%s' hostlist\n", ptr, J->Name); N = NULL; } } /* END if (MNodeFind() == FAILURE) */ if (N != NULL) { if (J->ReqHList[nindex].N == N) { J->ReqHList[nindex].TC++; } else { if (J->ReqHList[nindex].N != NULL) nindex++; J->ReqHList[nindex].N = N; J->ReqHList[nindex].TC = 1; } } ptr = MUStrTok(NULL,":",&TokPtr); } /* END while (ptr != NULL) */ J->ReqHList[nindex + 1].N = NULL; } /* END if (strcmp(MReqHList,NONE)) */ else if ((J->SpecFlags & (1 << mjfHostList)) && (J->ReqHList == NULL)) { DBG(1,fSIM) DPrint("ALERT: job %s requests hostlist but has no hostlist specified\n", J->Name); J->SpecFlags ^= (1 << mjfHostList); } } /* END if (MODE != msmProfile) */ break; default: DBG(4,fSIM) DPrint("ALERT: cannot load version %d workload trace record\n", *Version); MJobDestroy(&J); return(FAILURE); /*NOTREACHED*/ break; } /* END switch(*Version) */ if (!strcmp(AName,NONE) || !strcmp(AName,"0")) { AName[0] = '\0'; } if ((strcmp(tmpRMXString,NONE) != 0) && (strcmp(tmpRMXString,"0") != 0)) { MJobSetAttr(J,mjaRMXString,(void **)tmpRMXString,mdfString,0); } if (RQ[0]->DRes.Procs == 0) RQ[0]->DRes.Procs = 1; if (J->SpecWCLimit[0] == (unsigned long)-1) J->SpecWCLimit[0] = MAX_MTIME; MUStrDup(&J->E.Cmd,tmpCmd); if (Mode == msmSim) { J->State = mjsIdle; J->EState = mjsIdle; J->Bypass = 0; J->PSUtilized = 0.0; J->SystemQueueTime = J->SubmitTime; J->SimWCTime = MAX(1,J->CompletionTime - J->StartTime); J->StartTime = 0; J->DispatchTime = 0; J->CompletionTime = 0; J->WCLimit = J->SpecWCLimit[0]; } else { /* profile mode */ int tmpI; tmpI = (int)strtol(tmpParName,NULL,0); if (tmpI > 0) { RQ[0]->PtIndex = tmpI; } else { mpar_t *P; MParFind(tmpParName,&P); RQ[0]->PtIndex = P->Index; } J->TaskCount = TasksAllocated; J->PSDedicated = MJobGetProcCount(J) * (J->CompletionTime - J->StartTime); J->WCLimit = J->SpecWCLimit[0]; for (index = 0;MJobState[index] != NULL;index++) { if (!strcmp(tmpState,MJobState[index])) { J->State = index; J->EState = index; break; } } /* END for (index) */ } if (J->State == mjsNotRun) { DBG(3,fSIM) DPrint("ALERT: ignoring job '%s' (job never ran, state '%s')\n", J->Name, MJobState[J->State]); MJobDestroy(&J); return(FAILURE); } /* check for timestamp corruption */ if (Mode == msmProfile) { /* profiler mode */ if (MSched.TraceFlags & (1 << tfFixCorruption)) { if (J->StartTime < J->DispatchTime) { DBG(2,fSIM) DPrint("WARNING: fixing job '%s' with corrupt dispatch/start times (%ld < %ld)\n", J->Name, J->DispatchTime, J->StartTime); J->DispatchTime = J->StartTime; } if (J->SubmitTime > J->StartTime) { DBG(2,fSIM) DPrint("WARNING: fixing job '%s' with corrupt queue/start times (%ld > %ld)\n", J->Name, J->SubmitTime, J->StartTime); if (J->SystemQueueTime > 0) J->SubmitTime = MIN(J->StartTime,J->SystemQueueTime); else J->SubmitTime = J->StartTime; } if (J->SystemQueueTime > J->DispatchTime) { DBG(2,fSIM) DPrint("WARNING: fixing job '%s' with corrupt system queue/dispatch times (%ld > %ld)\n", J->Name, J->SystemQueueTime, J->DispatchTime); J->SystemQueueTime = J->DispatchTime; } if (J->SystemQueueTime < J->SubmitTime) { DBG(2,fSIM) DPrint("WARNING: fixing job '%s' with corrupt system queue/queue time (%ld < %ld)\n", J->Name, J->SystemQueueTime, J->SubmitTime); J->SystemQueueTime = J->SubmitTime; } } /* END if (MSched.TraceFlags & (1 << tfFixCorruption)) */ if ((J->SubmitTime > J->DispatchTime) || (J->DispatchTime > J->CompletionTime)) { DBG(1,fSIM) DPrint("ALERT: ignoring job '%s' with corrupt queue/start/completion times (%ld > %ld > %ld)\n", J->Name, J->SubmitTime, J->DispatchTime, J->CompletionTime); MJobDestroy(&J); return(FAILURE); } } /* END if (Mode != msmSim) */ if (MJobSetCreds(J,UName,GName,AName) == FAILURE) { DBG(1,fSTRUCT) DPrint("ALERT: ignoring job '%s' with invalid authentication info (%s:%s:%s)\n", J->Name, UName, GName, AName); MJobDestroy(&J); return(FAILURE); } /* determine network */ if (strstr(tmpNetwork,MAList[eNetwork][0]) == NULL) { RQ[0]->Network = MUMAGetIndex(eNetwork,tmpNetwork,mAdd); } if (strstr(tmpOpsys,MAList[eOpsys][0]) == NULL) { if ((RQ[0]->Opsys = MUMAGetIndex(eOpsys,tmpOpsys,mAdd)) == FAILURE) { DBG(0,fSIM) DPrint("WARNING: cannot add opsys '%s' for job '%s'\n", tmpOpsys, J->Name); } } if (strstr(tmpArch,MAList[eArch][0]) == NULL) { if ((RQ[0]->Arch = MUMAGetIndex(eArch,tmpArch,mAdd)) == FAILURE) { DBG(0,fSIM) DPrint("WARNING: cannot add arch '%s' for job '%s'\n", tmpArch, J->Name); } } /* load feature values */ if ((MSched.ProcSpeedFeatureHeader[0] != '\0') && (MSched.ReferenceProcSpeed > 0)) { sprintf(tmpLine,"[%s", MSched.ProcSpeedFeatureHeader); if ((ptr = strstr(tmpReqNFList,tmpLine)) != NULL) { ReqProcSpeed = strtol(ptr + strlen(tmpLine),NULL,0); J->SimWCTime *= (long)((double)ReqProcSpeed / MSched.ReferenceProcSpeed); } } if ((MSched.Mode != msmSim) || !(MSim.Flags & (1 << msimfIgnFeatures))) { if (!strstr(tmpReqNFList,MAList[eFeature][0])) { tok = MUStrTok(tmpReqNFList,"[]",&TokPtr); do { MUGetMAttr(eFeature,tok,mAdd,RQ[0]->ReqFBM,sizeof(RQ[0]->ReqFBM)); } while ((tok = MUStrTok(NULL,"[]",&TokPtr)) != NULL); } } RQ[0]->MemCmp = MUCmpFromString(tmpMemCmp,NULL); RQ[0]->DiskCmp = MUCmpFromString(tmpDiskCmp,NULL); RQ[0]->NAccessPolicy = MSched.DefaultNAccessPolicy; RQ[0]->TaskCount = J->Request.TC; RQ[0]->NodeCount = J->Request.NC; MJobProcessExtensionString(J,J->RMXString); if ((MSim.Flags & (1 << msimfIgnQOS))) { tmpQReq[0] = '\0'; } { char *ptr; char *TokPtr; ptr = MUStrTok(tmpQReq,":",&TokPtr); if ((ptr != NULL) && (ptr[0] != '\0') && strcmp(ptr,"-1") && strcmp(ptr,"0") && strcmp(ptr,NONE) && strcmp(ptr,DEFAULT)) { if (MQOSAdd(ptr,&J->QReq) == FAILURE) { /* cannot locate requested QOS */ MQOSFind(DEFAULT,&J->QReq); } if (Mode == msmProfile) { if ((ptr = MUStrTok(NULL,":",&TokPtr)) != NULL) { MQOSAdd(ptr,&J->Cred.Q); } } } /* END if ((ptr != NULL) && ...) */ } /* END BLOCK */ if (Mode == msmSim) { if ((MQOSGetAccess(J,J->QReq,NULL,&QDef) == FAILURE) || (J->QReq == NULL) || (J->QReq == &MQOS[0])) { MJobSetQOS(J,QDef,0); } else { MJobSetQOS(J,J->QReq,0); } } /* END if (Mode == msmSim) */ if ((SetString[0] != '0') && (strcmp(SetString,NONE))) { /* FORMAT: ONEOF,FEATURE[,X:Y:Z] */ if ((ptr = MUStrTok(SetString,",: \t",&TokPtr)) != NULL) { /* determine selection type */ RQ[0]->SetSelection = MUGetIndex(ptr,(const char **)MResSetSelectionType,0,mrssNONE); if ((ptr = MUStrTok(NULL,",: \t",&TokPtr)) != NULL) { /* determine set attribute */ RQ[0]->SetType = MUGetIndex(ptr,(const char **)MResSetAttrType,0,mrstNONE); index = 0; if ((ptr = MUStrTok(NULL,", \t",&TokPtr)) != NULL) { /* determine set list */ while (ptr != NULL) { MUStrDup(&RQ[0]->SetList[index],ptr); index++; ptr = MUStrTok(NULL,", \t",&TokPtr); } } RQ[0]->SetList[index] = NULL; } /* END if ((ptr = MUStrTok(NULL)) != NULL) */ } /* END if ((ptr = MUStrTok(SetString)) != NULL) */ } /* END if ((SetString[0] != '0') && (strcmp(SetString,NONE))) */ if (MJobEval(J) == FAILURE) { /* job not properly formed */ DBG(1,fSTRUCT) DPrint("ALERT: ignoring job '%s' with corrupt configuration\n", J->Name); MJobDestroy(&J); return(FAILURE); } DBG(6,fSIM) DPrint("INFO: job '%s' loaded. class: %s opsys: %s arch: %s\n", J->Name, MUCAListToString(RQ[0]->DRes.PSlot,NULL,NULL), MAList[eOpsys][RQ[0]->Opsys], MAList[eArch][RQ[0]->Arch]); return(SUCCESS); } /* END MTraceLoadWorkload() */
int MJobProcessRestrictedAttrs( mjob_t *J, /* I */ char *EMsg) /* O */ { const char *FName = "MJobProcessRestrictedAttrs"; MDB(5,fSCHED) MLog("%s(%s)\n", FName, (J != NULL) ? J->Name : NULL); if ((J->Triggers != NULL) && (J->TemplateExtensions == NULL)) { /* triggers can come from other places (ie. CLASSCFG[] JOBTRIGGERS) */ MOReportEvent((void *)J,J->Name,mxoJob,mttCreate,J->CTime,TRUE); return(SUCCESS); } else if ((J->Triggers != NULL) && (J->TemplateExtensions != NULL)) { MOReportEvent((void *)J,J->Name,mxoJob,mttCreate,J->CTime,TRUE); } if (J->TemplateExtensions == NULL) { return(SUCCESS); } if (J->TemplateExtensions->SpecTrig[0] != NULL) { char tmpBuf[MMAX_BUFFER]; int VarValBufSize; int index; mln_t *VarList = NULL; for (index = 0;index < MDEF_VARVALBUFCOUNT;index++) { tmpVarValBuf2[index][0] = '\0'; } if ((J->Credential.Q == NULL) || (!bmisset(&J->Credential.Q->Flags,mqfTrigger))) { MMBAdd( &J->MessageBuffer, "trigger specified but not allowed by QOS", NULL, mmbtOther, MSched.Time + MCONST_DAYLEN, 0, NULL); } else { int tindex; marray_t HashList; /* NOTE: loop through all elements in linked list (NYI) */ VarValBufSize = MDEF_VARVALBUFCOUNT - 1; MJobGetVarList( J, &VarList, tmpVarValBuf2, &VarValBufSize); MUArrayListCreate(&HashList,sizeof(mhash_t *),4); if (J->Variables.Table != NULL) { MUArrayListAppendPtr(&HashList,&J->Variables); } if (J->JGroup != NULL) { mjob_t *tmpJ = NULL; if (MJobFind(J->JGroup->Name,&tmpJ,mjsmExtended) == SUCCESS) { if (tmpJ->Variables.Table != NULL) { MUArrayListAppendPtr(&HashList,&tmpJ->Variables); } } } for (tindex = 0;tindex < MMAX_SPECTRIG;tindex++) { if (J->TemplateExtensions->SpecTrig[tindex] == NULL) break; MUInsertVarList( J->TemplateExtensions->SpecTrig[tindex], VarList, /* var name array */ (mhash_t **)HashList.Array, /* variables in hashtables */ NULL, tmpBuf, /* O */ sizeof(tmpBuf), TRUE); MUArrayListFree(&HashList); if (MTrigLoadString(&J->Triggers,tmpBuf,TRUE,FALSE,mxoJob,J->Name,NULL,EMsg) == FAILURE) { return(FAILURE); } MUFree(&J->TemplateExtensions->SpecTrig[tindex]); } /* END for (tindex) */ #ifdef MYAHOO /* make sure that holds continue to disable triggers, even after new ones are loaded */ if (J->Hold != 0) { MTrigDisable(J->Triggers); } #endif /* MYAHOO */ if (J->Triggers != NULL) { mtrig_t *T; int tindex; for (tindex = 0; tindex < J->Triggers->NumItems;tindex++) { T = (mtrig_t *)MUArrayListGetPtr(J->Triggers,tindex); if (MTrigIsValid(T) == FALSE) continue; MTrigInitialize(T); if (MSched.ForceTrigJobsIdle == TRUE) bmset(&J->IFlags,mjifWaitForTrigLaunch); } /* END for (tindex) */ /* report events for admin reservations */ MOReportEvent((void *)J,J->Name,mxoJob,mttCreate,J->CTime,TRUE); } } /* END else ((J->Cred.Q == NULL) || (!bmisset(&J->Cred.Q->Flags,mqfTrigger))) */ MULLFree(&VarList,MUFREE); } /* END if (J->TX->SpecTrig != NULL) */ if (J->TemplateExtensions->SpecMinPreemptTime != NULL) { if ((J->Credential.Q == NULL) || (!bmisset(&J->Credential.Q->Flags,mqfPreemptCfg))) { MMBAdd( &J->MessageBuffer, "minpreempttime specified but not allowed by QOS", NULL, mmbtOther, MSched.Time + MCONST_DAYLEN, 0, NULL); } else { MJobSetAttr(J,mjaMinPreemptTime,(void **)J->TemplateExtensions->SpecMinPreemptTime,mdfString,mSet); } MUFree((char **)&J->TemplateExtensions->SpecMinPreemptTime); } /* if (J->TX->SpecMinPreemptTime != NULL) */ if ((J->TemplateExtensions->SpecTemplates != NULL) && (J->TemplateExtensions->SpecTemplates[0] != '\0')) { /* Apply templates */ mjob_t *SJ; char Templates[MMAX_LINE << 2]; char *Value; char *ptr; char tmpLine[MMAX_LINE << 2]; char *TokPtr2; MUStrCpy(Templates,J->TemplateExtensions->SpecTemplates,sizeof(Templates)); Value = Templates; if (!bmisset(&J->Flags,mjfTemplatesApplied)) { if (Value[0] == '^') { bmset(&J->IFlags,mjifNoTemplates); Value++; } TokPtr2 = Value; strncpy(tmpLine,Value,sizeof(tmpLine)); while ((ptr = MUStrTok(TokPtr2,":,",&TokPtr2)) != NULL) { if ((MTJobFind(ptr,&SJ) == SUCCESS) && (SJ->TemplateExtensions != NULL) && (bmisset(&SJ->TemplateExtensions->TemplateFlags,mtjfTemplateIsSelectable))) { if (MJobApplySetTemplate(J,SJ,EMsg) == FAILURE) { return(FAILURE); } } else { char errMsg[MMAX_LINE]; snprintf(errMsg,sizeof(errMsg),"WARNING: cannot apply template '%s'", ptr); MMBAdd(&J->MessageBuffer,errMsg,NULL,mmbtNONE,0,0,NULL); } if (!J->TemplateExtensions->ReqSetTemplates.empty()) MStringAppend(&J->TemplateExtensions->ReqSetTemplates,","); MStringAppend(&J->TemplateExtensions->ReqSetTemplates,ptr); } } bmset(&J->Flags,mjfTemplatesApplied); bmset(&J->SysFlags,mjfTemplatesApplied); /* Free the memory, we don't need it anymore */ MUFree(&J->TemplateExtensions->SpecTemplates); } /* END if ((J->TX->SpecTemplates != NULL) && ...) */ if ((J->WCLimit == MMAX_TIME) && (!bmisset(&MSched.Flags,mschedfAllowInfWallTimeJobs))) { if (EMsg != NULL) { sprintf(EMsg,"infinite walltime jobs not allowed\n"); return(FAILURE); } } if ((J->TemplateExtensions->SpecArray != NULL) && (J->TemplateExtensions->SpecArray[0] != '\0') && (J->Array == NULL) && (!bmisset(&J->IFlags,mjifWasLoadedFromCP))) { char *ptr; char *TokPtr = NULL; char *arrayStr = NULL; mulong BM; MUStrDup(&arrayStr,J->TemplateExtensions->SpecArray); /* Alloc the Array control container */ if (MJobArrayAlloc(J) == FAILURE) { /* NO MEMORY ERROR */ return(FAILURE); } ptr = MUStrTok(arrayStr,"[]",&TokPtr); MUStrCpy(J->Array->Name,ptr,MMAX_NAME); ptr = MUStrTok(NULL,"[]",&TokPtr); MUParseRangeString( ptr, &BM, J->Array->Members, MMAX_JOBARRAYSIZE, &J->Array->Count, NULL); ptr = MUStrTok(NULL,"%\n\t",&TokPtr); if ((ptr != NULL) && (ptr[0] != '\0')) { J->Array->Limit = strtol(ptr,NULL,10); } /* NO ERROR CHECKING ON 'NO MEMORY' CONDITION ??? */ J->Array->JPtrs = (mjob_t **)MUCalloc(1,sizeof(mjob_t *) * J->Array->Count + 1); J->Array->JName = (char **)MUCalloc(1,sizeof(char *) * J->Array->Count + 1); J->Array->JState = (enum MJobStateEnum *)MUCalloc(1,sizeof(enum MJobStateEnum) * J->Array->Count + 1); MUFree(&arrayStr); } return(SUCCESS); } /* END MJobProcessRestrictedAttrs() */