Files
maui/src/moab/MSR.c
T
dev 9a0042c61e Initial revision
git-svn-id: svn://opensvn.adaptivecomputing.com/maui/trunk@2 3f5042e3-fb1d-0410-be18-d6ca2573e517
2005-07-12 21:12:53 +00:00

3315 lines
62 KiB
C

/* HEADER */
#include "moab.h"
#include "msched-proto.h"
extern msched_t MSched;
extern msim_t MSim;
extern mnode_t *MNode[];
extern mstat_t MStat;
extern mpar_t MPar[];
extern mattrlist_t MAList;
extern mres_t *MRes[];
extern sres_t SRes[];
extern sres_t OSRes[];
extern mqos_t MQOS[];
extern mam_t MAM[];
extern mlog_t mlog;
#define MSRCfgParm "SRCFG"
extern const char *MWeekDay[];
extern const char *MPolicyMode[];
extern const char *MDefReason[];
extern const char *MWEEKDAY[];
extern const char *MSRPeriodType[];
extern const char *MResFlags[];
extern const char *MComp[];
extern const char *MSResAttr[];
extern const char *MXOC[];
int MSRLoadConfig(
char *SRName)
{
char IndexName[MAX_MNAME];
char Value[MAX_MLINE];
char *ptr;
sres_t *SR;
/* FORMAT: <KEY>=<VAL>[<WS><KEY>=<VAL>]... */
/* <VAL> -> <ATTR>=<VAL>[:<ATTR>=<VAL>]... */
/* load all/specified SR config info */
if (MSched.ConfigBuffer == NULL)
{
return(FAILURE);
}
if ((SRName == NULL) || (SRName[0] == '\0'))
{
/* load ALL SR config info */
ptr = MSched.ConfigBuffer;
IndexName[0] = '\0';
while (MCfgGetSVal(
MSched.ConfigBuffer,
&ptr,
MSRCfgParm,
IndexName,
NULL,
Value,
sizeof(Value),
0,
NULL) != FAILURE)
{
if ((MSRFind(IndexName,&SR) == FAILURE) &&
(MSRAdd(IndexName,&SR) == FAILURE))
{
/* unable to locate/create SR */
IndexName[0] = '\0';
continue;
}
/* load SR specific attributes */
MSRProcessConfig(SR,Value);
IndexName[0] = '\0';
} /* END while (MCfgGetSVal() != FAILURE) */
} /* END if ((SRName == NULL) || (SRName[0] == '\0')) */
else
{
/* load specified SR config info */
ptr = MSched.ConfigBuffer;
SR = NULL;
while (MCfgGetSVal(
MSched.ConfigBuffer,
&ptr,
MSRCfgParm,
SRName,
NULL,
Value,
sizeof(Value),
0,
NULL) == SUCCESS)
{
if ((SR == NULL) &&
(MSRFind(SRName,&SR) == FAILURE) &&
(MSRAdd(SRName,&SR) == FAILURE))
{
/* unable to add standing reservation */
return(FAILURE);
}
/* load SR attributes */
MSRProcessConfig(SR,Value);
} /* END while (MCfgGetSVal() == SUCCESS) */
if (SR == NULL)
{
return(FAILURE);
}
if (MSRCheckConfig(SR) == FAILURE)
{
MSRDestroy(&SR);
/* invalid standing reservation destroyed */
return(FAILURE);
}
} /* END else ((SRName == NULL) || (SRName[0] == '\0')) */
return(SUCCESS);
} /* END MSRLoadConfig() */
int MSRCheckConfig(
sres_t *SR) /* I */
{
/* no check required */
return(SUCCESS);
} /* END MSRCheckConfig() */
int MSRDestroy(
sres_t **SR)
{
if (SR == NULL)
return(SUCCESS);
if (*SR == NULL)
return(SUCCESS);
memset(*SR,0,sizeof(sres_t));
return(SUCCESS);
} /* END MSRDestroy() */
int MSRFind(
char *SRName,
sres_t **SRPtr)
{
/* if found, return success with SRPtr pointing to standing reservation. */
int srindex;
sres_t *SR;
if (SRPtr != NULL)
*SRPtr = NULL;
if ((SRName == NULL) ||
(SRName[0] == '\0'))
{
return(FAILURE);
}
for (srindex = 0;srindex < MAX_MSRES;srindex++)
{
SR = &SRes[srindex];
if ((SR == NULL) || (SR->Name[0] == '\0') || (SR->Name[0] == '\1'))
{
break;
}
if (strcmp(SR->Name,SRName) != 0)
continue;
/* reservation found */
if (SRPtr != NULL)
*SRPtr = SR;
return(SUCCESS);
} /* END for (srindex) */
/* entire table searched */
return(FAILURE);
} /* END MSRFind() */
int MSRAdd(
char *SRName, /* I */
sres_t **SRPtr) /* O (optional) */
{
int srindex;
sres_t *SR;
const char *FName = "MSRAdd";
DBG(6,fSTRUCT) DPrint("%s(%s,%s)\n",
FName,
(SRName != NULL) ? "SRName" : "NULL",
(SRPtr != NULL) ? "SRPtr" : "NULL");
if ((SRName == NULL) || (SRName[0] == '\0'))
{
return(FAILURE);
}
if (SRPtr != NULL)
*SRPtr = NULL;
for (srindex = 0;srindex < MAX_MSRES;srindex++)
{
SR = &SRes[srindex];
if ((SR != NULL) && !strcmp(SR->Name,SRName))
{
/* SR already exists */
if (SRPtr != NULL)
*SRPtr = SR;
return(SUCCESS);
}
if ((SR != NULL) &&
(SR->Name[0] != '\0') &&
(SR->Name[0] != '\1'))
{
continue;
}
/* empty slot found */
/* create/initialize new record */
if (SR == NULL)
{
if (MSRCreate(SRName,&SRes[srindex]) == FAILURE)
{
DBG(1,fALL) DPrint("ERROR: cannot alloc memory for SR '%s'\n",
SRName);
return(FAILURE);
}
SR = &SR[srindex];
}
/* initialize empty record */
MSRInitialize(SR,SRName);
if (SRPtr != NULL)
*SRPtr = SR;
SR->Index = srindex;
/* update SR record */
if (MSched.Mode != msmSim)
MCPRestore(mcpSRes,SRName,(void *)SR);
DBG(5,fSTRUCT) DPrint("INFO: SR %s added\n",
SRName);
return(SUCCESS);
} /* END for (srindex) */
/* end of table reached */
DBG(1,fSTRUCT) DPrint("ALERT: SR table overflow. cannot add %s\n",
SRName);
return(SUCCESS);
} /* END MSRAdd() */
int MSRCreate(
char *SRName, /* I */
sres_t *SR) /* I (modified) */
{
if (SR == NULL)
{
return(FAILURE);
}
/* use static memory for now */
memset(SR,0,sizeof(sres_t));
if ((SRName != NULL) && (SRName[0] != '\0'))
MUStrCpy(SR->Name,SRName,sizeof(SR->Name));
return(SUCCESS);
} /* END MSRCreate() */
int MSRSelectNodeList(
mjob_t *J, /* I */
sres_t *SR, /* I */
nodelist_t DstNL, /* O: selected nodes */
int *NodeCount, /* O: number of nodes found */
long StartTime, /* I */
nodelist_t ReqNL, /* I */
unsigned long ResMode) /* I */
{
int TC;
int BestTC;
mpar_t *BestP;
int MaxTasks;
int rqindex;
int nindex;
int nindex2;
int pindex;
nodelist_t *FNL;
mnodelist_t AvailMNL;
mnodelist_t tmpMNL;
mnodelist_t BestFMNL;
char NodeMap[MAX_MNODE];
mpar_t *P;
mreq_t *RQ;
int IsSizeFlex; /* (boolean) */
int IsSpaceFlex; /* (boolean) */
const char *FName = "MSRSelectNodeList";
DBG(3,fSCHED) DPrint("%s(%s,%s,DstNL,NodeCount,%s,ReqNL,%ld)\n",
FName,
(J != NULL) ? J->Name : "NULL",
SR->Name,
MULToTString(StartTime - MSched.Time),
ResMode);
if (J == NULL)
return(FAILURE);
/* NOTE: only support single req SR's */
TC = 0;
BestTC = 0;
BestP = NULL;
IsSizeFlex = TRUE;
MaxTasks = J->Request.TC;
if (IsSizeFlex == TRUE)
{
J->TaskCount = 1;
J->Req[0]->TaskCount = 1;
}
for (rqindex = 0;J->Req[rqindex] != NULL;rqindex++)
{
RQ = J->Req[rqindex];
for (pindex = 0;pindex < MAX_MPAR;pindex++)
{
P = &MPar[pindex];
if (P->CRes.Procs <= 0)
continue;
if (SR->PName[0] != '\0')
{
if (!strcmp(SR->PName,"ALL"))
{
/* reservation may span */
if (pindex != 0)
continue;
}
else
{
if (strcmp(P->Name,SR->PName))
continue;
}
}
else
{
/* reservation may not span */
if (pindex == 0)
continue;
} /* END else (SR->PName[0] != '\0') */
if ((strcmp(SR->PName,"ALL") != 0) &&
(P->Index == 0))
{
continue;
}
DBG(6,fSCHED) DPrint("INFO: checking partition %s for resources for reservation %s\n",
P->Name,
SR->Name);
memset(tmpMNL,0,sizeof(mnodelist_t));
FNL = (nodelist_t *)tmpMNL[rqindex];
if (MReqGetFNL(
J,
RQ,
P,
NULL,
*FNL,
NodeCount,
&TC,
MAX_MTIME,
ResMode) == FAILURE)
{
DBG(6,fSCHED) DPrint("INFO: cannot get feasible tasks for job %s:%d in partition %s\n",
J->Name,
rqindex,
P->Name);
TC = 0;
continue;
}
if (TC > BestTC)
{
BestTC = TC;
BestP = P;
/* save best feasible list */
memcpy(BestFMNL,tmpMNL,sizeof(mnodelist_t));
}
/* NOTE: should be modified to select partition with most tasks */
} /* END for (pindex) */
if (BestP == NULL)
{
/* no feasible nodes located */
DBG(6,fSCHED) DPrint("INFO: no feasible tasks found for job %s:%d in partition %s\n",
J->Name,
rqindex,
SR->PName);
DstNL[0].N = NULL;
return(FAILURE);
}
} /* END for (rqindex) */
/* NOTE: SR->TaskCount should only 'cap' SR */
if (!(SR->Flags & (1 << mrfSpaceFlex)) &&
((ResMode & (1 << stForce)) ||
(SR->TaskCount == 0) ||
(SR->Flags & (1 << mrfForce))))
{
/* NOTE: HostExpression specified or TaskCount not specified, */
/* select from all feasible nodes */
IsSpaceFlex = FALSE;
}
else
{
IsSpaceFlex = TRUE;
}
RQ = J->Req[0]; /* FIXME */
if (IsSpaceFlex == FALSE)
{
/* NOTE: make all feasible nodes available for allocation selection *
* regardless of current state */
/* if HostExpression specified or if TaskCount not specified, */
/* select from all feasible nodes */
memset(NodeMap,nmNone,sizeof(NodeMap));
memcpy(AvailMNL,BestFMNL,sizeof(AvailMNL));
TC = BestTC;
}
else
{
/* determine available nodes from feasible nodes */
if (MJobGetAMNodeList(
J,
BestFMNL,
AvailMNL,
NodeMap,
NodeCount,
&TC,
StartTime) == FAILURE)
{
DBG(4,fSCHED) DPrint("INFO: cannot locate available tasks in partition %s for job %s at time %ld\n",
SR->PName,
J->Name,
StartTime);
DstNL[0].N = NULL;
return(FAILURE);
}
else
{
TC = MIN(MaxTasks,TC);
J->TaskCount = TC;
RQ->TaskCount = TC;
}
} /* END else (IsSizeFlex == TRUE) */
for (nindex = 0;ReqNL[nindex].N != NULL;nindex++)
{
for (rqindex = 0;J->Req[rqindex] != NULL;rqindex++)
{
for (nindex2 = 0;AvailMNL[rqindex][nindex2].N != NULL;nindex2++)
{
if (AvailMNL[rqindex][nindex2].N ==
ReqNL[nindex].N)
{
NodeMap[ReqNL[nindex].N->Index] = nmRequired;
break;
}
} /* END for (nindex2) */
} /* END for (rqindex) */
} /* END for (nindex) */
if (IsSizeFlex == TRUE)
{
/* adjust required task count */
if (SR->TaskCount > 0)
J->Request.TC = MIN(TC,SR->TaskCount);
else
J->Request.TC = TC;
RQ->TaskCount = J->Request.TC;
} /* END if (SizeFlex == TRUE) */
if (MJobAllocMNL(
J,
AvailMNL,
NodeMap,
tmpMNL,
MPar[J->Req[0]->PtIndex].NAllocPolicy,
StartTime) == FAILURE)
{
DBG(0,fSCHED) DPrint("ERROR: cannot allocate best nodes for job '%s'\n",
J->Name);
return(FAILURE);
}
RQ->TaskCount = 0; /* FIXME??? */
for (nindex = 0;tmpMNL[0][nindex].N != NULL;nindex++)
{
if (tmpMNL[0][nindex].TC == 0)
break;
RQ->TaskCount += tmpMNL[0][nindex].TC;
memcpy(&DstNL[nindex],&tmpMNL[0][nindex],sizeof(mnalloc_t));
} /* END for (nindex) */
DstNL[nindex].N = NULL;
if (NodeCount != NULL)
*NodeCount = nindex;
if (nindex == 0)
{
DBG(2,fSCHED) DPrint("INFO: no tasks found for job %s\n",
J->Name);
return(FAILURE);
}
return(SUCCESS);
} /* END MSRSelectNodeList() */
int MSRCheckReservation(
sres_t *SR,
mres_t *R)
{
int nindex;
int nrindex;
int TC;
mnode_t *N;
char tmpLine[MAX_MLINE];
/* return SUCCESS if complete reservation located */
/* return if reservation lacks adequate resources or */
/* has invalid resources allocated */
TC = 0;
if ((SR == NULL) || (R == NULL))
return(FAILURE);
for (nindex = 0;nindex < MAX_MNODE;nindex++)
{
N = MNode[nindex];
if ((N == NULL) || (N->Name[0] == '\0'))
break;
if (N->Name[0] == '\1')
continue;
for (nrindex = 0;nrindex < MSched.ResDepth;nrindex++)
{
if (N->R[nrindex] == NULL)
break;
if (N->R[nrindex] != R)
continue;
/* reservation located on node */
if ((SR->TaskCount > 0) &&
(R->StartTime <= MSched.Time) &&
(N->State != mnsIdle) &&
(N->State != mnsActive) &&
(N->State != mnsBusy))
{
/* floating reservation contains node in invalid state */
return(FAILURE);
}
TC += N->RC[nrindex];
break;
} /* END for (nrindex) */
} /* END for (nindex) */
if (TC < R->TaskCount)
{
sprintf(tmpLine,"RESERVATIONCORRUPTION: reservation corruption detected in reservation '%s' Req/Detected TC %d/%d\n",
R->Name,
R->TaskCount,
TC);
MSysRegEvent(tmpLine,0,0,1);
return(FAILURE);
}
return(SUCCESS);
} /* END MSRCheckReservation() */
int MSRRefresh()
{
sres_t tmpSR;
sres_t *SR;
int SRIndex;
int DIndex;
char Incomplete[MAX_MSRES];
int SRRefreshRequired;
SR = &tmpSR;
for (SRIndex = 0;SRIndex < MAX_MSRES;SRIndex++)
{
if (SRes[0].Name[0] == '\0')
break;
MSRGetCurrentValues(&SRes[SRIndex],&OSRes[SRIndex],SR);
if (SR->TaskCount == 0)
{
if (SR->HostExpression[0] == '\0')
{
/* continue if SR not specified */
DBG(7,fCORE) DPrint("INFO: SR[%d] is empty (TC: %d HL: '%s')\n",
SRIndex,
SR->TaskCount,
SR->HostExpression);
}
else
{
/* continue if exact hosts specified */
/* all hosts located and incorporated in reservation at node load time */
DBG(5,fCORE) DPrint("INFO: SR[%d] exactly specifies nodes (TC: %d HL: '%s')\n",
SRIndex,
SR->TaskCount,
SR->HostExpression);
}
continue;
}
memset(Incomplete,FALSE,sizeof(Incomplete));
SRRefreshRequired = FALSE;
for (DIndex = 0;DIndex < SR->Depth;DIndex++)
{
if ((SR->R[DIndex] == NULL) ||
(SR->R[DIndex]->TaskCount < SR->TaskCount) ||
(MSRCheckReservation(SR,SR->R[DIndex]) == FAILURE))
{
Incomplete[DIndex] = TRUE;
SRRefreshRequired = TRUE;
}
} /* END for (DIndex) */
if ((SRRefreshRequired == TRUE) ||
(MACLGet(SR->ACL,maDuration,NULL,NULL) == FAILURE))
{
MSim.QueueChanged = TRUE;
MSched.EnvChanged = TRUE;
}
else
{
/* standing reservation does not need to be refreshed */
continue;
}
for (DIndex = 0;DIndex < MAX_SRES_DEPTH;DIndex++)
{
if (DIndex >= SR->Depth)
break;
if (Incomplete[DIndex] == FALSE)
{
continue;
}
if (MSRSetRes(SR,SRIndex,DIndex) == SUCCESS)
{
if (SR->R[DIndex] != NULL)
{
while (SR->R[DIndex]->TaskCount < SR->TaskCount)
{
if (MResPreempt(SR->R[DIndex]) == FAILURE)
break;
MSRSetRes(SR,SRIndex,DIndex);
} /* END while (SR->R[DIndex]->TaskCount) */
}
} /* END if (SRCreate() == SUCCESS) */
else
{
DBG(2,fSCHED) DPrint("ALERT: cannot create standing reservation '%s'\n",
SR->Name);
}
} /* END for (DIndex) */
} /* END for (SRIndex) */
return(SUCCESS);
} /* END MSRRefresh() */
int MSRProcessConfig(
sres_t *SR,
char *Value)
{
int aindex;
int ValCmp;
char *ptr;
char *TokPtr;
char *ptr2;
char *TokPtr2;
char ValLine[MAX_MLINE];
char *ValList[2];
char tmpLine[MAX_MLINE];
const char *FName = "MSRProcessConfig";
DBG(2,fSCHED) DPrint("%s(SR,%s)\n",
FName,
(Value != NULL) ? Value : "NULL");
if ((SR == NULL) ||
(Value == NULL) ||
(Value[0] == '\0'))
{
return(FAILURE);
}
ValList[0] = tmpLine;
ValList[1] = NULL;
/* process value line */
ptr = MUStrTok(Value," \t\n",&TokPtr);
while(ptr != NULL)
{
/* parse name-value pairs */
/* FORMAT: <ATTR><CMP><VALUE>[,<VALUE>] */
if (MUGetPair(
ptr,
(const char **)MSResAttr,
&aindex,
NULL,
FALSE,
&ValCmp,
ValLine,
MAX_MLINE) == FAILURE)
{
/* cannot parse value pair */
DBG(2,fSCHED) DPrint("ALERT: cannot parse SR[%s] config attribute '%s'\n",
SR->Name,
ptr);
ptr = MUStrTok(NULL," \t\n",&TokPtr);
continue;
}
sprintf(tmpLine,"%s%s",
MComp[ValCmp],
ValLine);
switch(aindex)
{
case msraAccess:
if (!strcmp(ValLine,"SHARED"))
{
if (SR->Flags & (1 << mrfDedicatedResource))
SR->Flags ^= (1 << mrfDedicatedResource);
}
else if (!strcmp(ValLine,"DEDICATED"))
{
SR->Flags |= (1 << mrfDedicatedResource);
}
break;
case msraAccountList:
MACLLoadConfig(SR->ACL,ValList,1,maAcct);
break;
case msraChargeAccount:
MAcctAdd(ValLine,&SR->A);
break;
case msraClassList:
MACLLoadConfig(SR->ACL,ValList,1,maClass);
break;
case msraDays:
/* FORMAT: ALL|MON|TUE|... */
SR->Days = 0;
if (strstr(ValLine,"ALL") != NULL)
{
SR->Days = 255;
}
else
{
int dindex;
for (dindex = 0;MWeekDay[dindex] != NULL;dindex++)
{
if ((strstr(ValLine,MWeekDay[dindex]) != NULL) ||
(strstr(ValLine,MWEEKDAY[dindex]) != NULL))
{
SR->Days |= (1 << dindex);
}
} /* END for (dindex) */
} /* END else (strstr(ValLine,"ALL") != NULL) */
break;
case msraDepth:
SR->Depth = (int)strtol(ValLine,NULL,0);
break;
case msraEndTime:
SR->EndTime = MUTimeFromString(ValLine);
break;
case msraFlags:
MUBMFromString(ValLine,MResFlags,(unsigned long *)&SR->Flags);
break;
case msraGroupList:
MACLLoadConfig(SR->ACL,ValList,1,maGroup);
break;
case msraHostList:
{
char *ptr;
MUStrCpy(SR->HostExpression,ValLine,sizeof(SR->HostExpression));
/* replace commas with spaces */
while ((ptr = strchr(SR->HostExpression,',')) != NULL)
{
*ptr = ' ';
} /* END while() */
} /* END BLOCK */
break;
case msraIdleTime:
SR->MaxIdleTime = MUTimeFromString(ValLine);
break;
case msraJobAttrList:
MACLLoadConfig(SR->ACL,ValList,1,maJFeature);
break;
case msraMaxTime:
{
long MaxTime = MUTimeFromString(ValLine);
mbool_t Required = FALSE;
if (strchr(ValLine,'*') != NULL)
Required = TRUE;
MACLSet(
SR->ACL,
maDuration,
&MaxTime,
mcmpLE,
nmPositiveAffinity,
(Required == TRUE) ? (1 << maclRequired) : 0,
0);
} /* END BLOCK */
break;
case msraNodeFeatures:
if (!strcmp(ValLine,NONE))
break;
ptr2 = MUStrTok(ValLine,"[] \t",&TokPtr2);
while (ptr2 != NULL)
{
MUGetMAttr(eFeature,ptr2,mAdd,SR->FeatureMap,sizeof(SR->FeatureMap));
ptr2 = MUStrTok(NULL,"[] \t",&TokPtr2);
}
break;
case msraOwner:
MSRSetAttr(SR,aindex,(void **)ValLine,mdfString,mSet);
break;
case msraPartition:
MUStrCpy(SR->PName,ValLine,sizeof(SR->PName));
break;
case msraPeriod:
SR->Period = MUGetIndex(ValLine,MSRPeriodType,FALSE,mpDay);
break;
case msraPriority:
SR->Priority = strtol(ValLine,NULL,0);
break;
case msraProcLimit:
ValList[0] = ValLine;
MACLLoadConfig(SR->ACL,ValList,1,maProc);
break;
case msraQOSList:
MACLLoadConfig(SR->ACL,ValList,1,maQOS);
break;
case msraResources:
/* FORMAT: <X>=<Y>[+<X>=<Y>]... */
memset(&SR->DRes,0,sizeof(SR->DRes));
MUCResFromString(&SR->DRes,ValLine);
break;
case msraStartTime:
SR->StartTime = MUTimeFromString(ValLine);
break;
case msraTaskCount:
SR->TaskCount = strtol(ValLine,NULL,0);
break;
case msraTaskLimit:
ValList[0] = ValLine;
MACLLoadConfig(SR->ACL,ValList,1,maTask);
break;
case msraTimeLimit:
ValList[0] = ValLine;
MACLLoadConfig(SR->ACL,ValList,1,maDuration);
break;
case msraTPN:
SR->TPN = (int)strtol(ValLine,NULL,0);
break;
case msraUserList:
MACLLoadConfig(SR->ACL,ValList,1,maUser);
break;
case msraWEndTime:
SR->WEndTime = MUTimeFromString(ValLine);
break;
case msraWStartTime:
SR->WStartTime = MUTimeFromString(ValLine);
break;
default:
DBG(4,fFS) DPrint("WARNING: SR attribute '%s' not handled\n",
MSResAttr[aindex]);
break;
} /* END switch(aindex) */
ptr = MUStrTok(NULL," \t\n",&TokPtr);
} /* END while (ptr != NULL) */
return(SUCCESS);
} /* END MSRProcessConfig() */
int MSRShow(
sres_t *SR, /* I */
char *Buffer, /* O */
int VFlag, /* I */
int PIndex) /* I */
{
char tmpLine[MAX_MLINE];
char SRLine[MAX_MLINE];
int index;
struct {
int PIndex;
int OIndex;
} AList[] = {
{ msraAccountList, maAcct },
{ msraClassList, maClass },
{ msraUserList, maUser },
{ msraGroupList, maGroup },
{ msraQOSList, maQOS },
{ -1, -1 } };
if ((SR == NULL) || (Buffer == NULL))
return(FAILURE);
/* display SR if enabled */
if ((SR->Name[0] == '\0') ||
(PIndex != -1))
{
return(SUCCESS);
}
SRLine[0] = '\0';
/* show ACLs */
for (index = 0;AList[index].PIndex != -1;index++)
{
if (MACLListShow(
SR->ACL,
AList[index].OIndex,
(1 << mfmHuman),
tmpLine) == NULL)
{
continue;
}
if ((tmpLine[0] == '\0') || !strcmp(tmpLine,NONE))
{
continue;
}
sprintf(SRLine,"%s%s=%s ",
SRLine,
MSResAttr[AList[index].PIndex],
tmpLine);
} /* END for (index) */
/* show general attributes */
if (SR->TaskCount != 0)
{
sprintf(SRLine,"%s%s=%d ",
SRLine,
MSResAttr[msraTaskCount],
SR->TaskCount);
} /* END if (SR->TaskCount != 0) */
/* show hostlist */
if (SR->HostExpression[0] != '\0')
{
sprintf(SRLine,"%s%s=%s ",
SRLine,
MSResAttr[msraHostList],
SR->HostExpression);
} /* END if (SR->HostExpression[0] != '\0') */
/* show all flags */
if (SR->Flags != 0)
{
char tmpLine[MAX_MLINE];
sprintf(SRLine,"%s%s=%s ",
SRLine,
MSResAttr[msraFlags],
MUBMToString(SR->Flags,MResFlags,' ',tmpLine,NONE));
}
strcpy(tmpLine,MUMAList(eFeature,SR->FeatureMap,sizeof(SR->FeatureMap)));
if (strcmp(tmpLine,NONE))
{
sprintf(SRLine,"%s%s=%s ",
SRLine,
MSResAttr[msraNodeFeatures],
tmpLine);
}
MUShowSSArray(MSRCfgParm,SR->Name,SRLine,Buffer);
return(SUCCESS);
} /* END MSRShow() */
int MSRDiag(
sres_t *SRS,
char *SBuffer,
int SBufSize,
int Flags)
{
int srindex;
int rindex;
char *BPtr;
int BSpace;
sres_t *SR;
mres_t *R;
int IsPartial;
if (SBuffer == NULL)
return(FAILURE);
SBuffer[0] = '\0';
BPtr = SBuffer;
BSpace = SBufSize;
MUSNPrintF(&BPtr,&BSpace,"evaluating standing reservations\n");
for (srindex = 0;srindex < MAX_MSRES;srindex++)
{
SR = &SRes[srindex];
if (SR->Name[0] == '\0')
continue;
if ((SRS != NULL) && (SRS != SR))
continue;
/* evaluate configuration */
if ((SR->TaskCount <= 0) &&
(SR->HostExpression[0] == '\0'))
{
/* NOTE: SR does not specify tasks */
MUSNPrintF(&BPtr,&BSpace,"SR %s does not specify requested resources (taskcount/hostexpression not set\n",
SR->Name);
continue;
}
/* evaluate active reservations */
for (rindex = 0;rindex < MAX_SRES_DEPTH;rindex++)
{
R = SR->R[rindex];
if (R == NULL)
{
/* if reservation should exist, determine why missing */
/* NYI */
continue;
}
MUSNPrintF(&BPtr,&BSpace,"SR %s has reservation %s created\n",
SR->Name,
R->Name);
IsPartial = FALSE;
if (SR->TaskCount > 0)
{
if (R->TaskCount < SR->TaskCount)
IsPartial = TRUE;
MUSNPrintF(&BPtr,&BSpace,"SR reservation %s is %s (TC: %d requested/%d reserved)\n",
R->Name,
(IsPartial == TRUE) ? "partial" : "complete",
SR->TaskCount,
R->TaskCount);
}
if (IsPartial == TRUE)
{
/* determine why resources are unavailable */
/* NYI */
}
} /* END for (rindex) */
} /* END for (srindex) */
return(FAILURE);
} /* END MSRDiag() */
int MSRInitialize(
sres_t *SR,
char *Name)
{
int srindex;
if ((SR == NULL) || (Name == NULL))
return(FAILURE);
for (srindex = 0;srindex < MAX_MSRES;srindex++)
{
if (&SRes[srindex] == SR)
{
SR->Index = srindex;
break;
}
} /* END for (srindex) */
MUStrCpy(SR->Name,Name,sizeof(SR->Name));
SR->Type = mrtUser;
SR->Depth = DEFAULT_SRDEPTH;
SR->Days = DEFAULT_SRDAYS;
SR->StartTime = DEFAULT_SRSTARTTIME;
SR->EndTime = DEFAULT_SRENDTIME;
SR->WStartTime = DEFAULT_SRSTARTTIME;
SR->WEndTime = DEFAULT_SRENDTIME;
SR->DRes.Procs = DEFAULT_SRPROCS;
if (SR->HostList != NULL)
MUFree((char **)&SR->HostList);
SR->Priority = DEFAULT_SRPRIORITY;
SR->Flags = DEFAULT_SRFLAGS;
SR->Period = DEFAULT_SRPERIOD;
return(SUCCESS);
} /* END MSRInitialize() */
int MSRConfigShow(
sres_t *SRP, /* I (optional) */
int VFlag, /* I */
int PIndex, /* I */
char *Buffer) /* O */
{
int srindex;
sres_t *SR;
char tmpLine[MAX_MLINE];
if (Buffer == NULL)
{
return(FAILURE);
}
for (srindex = 0;srindex < MAX_MSRES;srindex++)
{
SR = &SRes[srindex];
if ((SR->TaskCount == 0) &&
(SR->HostExpression[0] == '\0') &&
!VFlag)
{
continue;
}
if ((PIndex == -1) || (PIndex == pSRTaskCount))
strcat(Buffer,MUShowIArray(MParam[pSRTaskCount],srindex,SR->TaskCount));
if ((SR->TPN > 0) || (VFlag || (PIndex == -1) || (PIndex == pSRTPN)))
strcat(Buffer,MUShowIArray(MParam[pSRTPN],srindex,SR->TPN));
if ((SR->DRes.Procs != -1) || (VFlag || (PIndex == -1) || (PIndex == pSRResources)))
{
sprintf(tmpLine,"PROCS=%d;MEM=%d;DISK=%d;SWAP=%d",
SR->DRes.Procs,
SR->DRes.Mem,
SR->DRes.Disk,
SR->DRes.Swap);
strcat(Buffer,MUShowSArray(MParam[pSRResources],srindex,tmpLine));
}
if ((SR->Depth != DEFAULT_SRDEPTH) || (VFlag || (PIndex == -1) || (PIndex == pSRDepth)))
strcat(Buffer,MUShowIArray(MParam[pSRDepth],srindex,SR->Depth));
if ((SR->StartTime != -1) || (VFlag || (PIndex == -1) || (PIndex == pSRStartTime)))
strcat(Buffer,MUShowSArray(MParam[pSRStartTime],srindex,MULToTString(SR->StartTime)));
if ((SR->EndTime != -1) || (VFlag || (PIndex == -1) || (PIndex == pSREndTime)))
strcat(Buffer,MUShowSArray(MParam[pSREndTime],srindex,MULToTString(SR->EndTime)));
if ((SR->WStartTime != -1) || (VFlag || (PIndex == -1) || (PIndex == pSRWStartTime)))
strcat(Buffer,MUShowSArray(MParam[pSRWStartTime],srindex,MULToTString(SR->WStartTime)));
if ((SR->WEndTime != -1) || (VFlag || (PIndex == -1) || (PIndex == pSRWEndTime)))
strcat(Buffer,MUShowSArray(MParam[pSRWEndTime],srindex,MULToTString(SR->WEndTime)));
if ((SR->Days != 255) || (VFlag || (PIndex == -1) || (PIndex == pSRDays)))
{
if (SR->Days == 255)
{
strcpy(tmpLine,"ALL");
}
else
{
int index;
tmpLine[0] = '\0';
for (index = 0;MWeekDay[index] != NULL;index++)
{
if (SR->Days & (1 << index))
{
if (tmpLine[0] != '\0')
strcat(tmpLine,"|");
strcat(tmpLine,MWeekDay[index]);
}
} /* END for (index) */
}
strcat(Buffer,MUShowSArray(MParam[pSRDays],srindex,tmpLine));
} /* END if (SRDays != 255) ... */
if ((SR->HostExpression[0] != '\0') ||
(VFlag || (PIndex == -1) || (PIndex == pSRHostList)))
{
strcat(Buffer,MUShowSArray(MParam[pSRHostList],srindex,SR->HostExpression));
}
if ((SR->A != NULL) || (VFlag || (PIndex == -1) || (PIndex == pSRChargeAccount)))
strcat(Buffer,MUShowSArray(MParam[pSRChargeAccount],srindex,(SR->A != NULL) ? SR->A->Name : ""));
MSRShow(SR,Buffer,VFlag,PIndex);
strcat(Buffer,"\n");
} /* END for (srindex) */
return(SUCCESS);
} /* END MSRConfigShow() */
int MSRGetAttributes(
sres_t *SR, /* IN: standing reservation description */
int PeriodIndex, /* IN: period index */
long *SRStartTime, /* OUT: time reservation should start */
unsigned long *SRDuration) /* OUT: duration of reservation */
{
long SRStartOffset;
long SREndOffset;
long DayTime;
long WeekTime;
int WeekDay;
struct tm *Time;
long PeriodStart;
long tmpL;
time_t tmpTime;
const char *FName = "MSRGetAttributes";
DBG(3,fSTRUCT) DPrint("%s(%s,%d,Start,Duration)\n",
FName,
SR->Name,
PeriodIndex);
MUGetPeriodStart(MSched.Time,0,PeriodIndex,SR->Period,&PeriodStart);
if (PeriodIndex == 0)
tmpTime = (time_t)MAX(PeriodStart,MSched.Time);
else
tmpTime = (time_t)PeriodStart;
Time = localtime(&tmpTime);
DayTime = (3600 * Time->tm_hour) + (60 * Time->tm_min) + Time->tm_sec;
WeekTime = DayTime + (Time->tm_wday * DAY_LEN);
WeekDay = Time->tm_wday;
/* set reservation time boundaries */
SRStartOffset = 0;
switch (SR->Period)
{
case mpDay:
SREndOffset = DAY_LEN;
if ((SR->WStartTime != -1) &&
(WeekDay == (SR->WStartTime / DAY_LEN)))
{
SRStartOffset = SR->WStartTime % DAY_LEN;
}
if (SR->StartTime != -1)
{
SRStartOffset = SR->StartTime;
}
if ((SR->WEndTime > 0) &&
(WeekDay == (SR->WEndTime / DAY_LEN)))
{
SREndOffset = SR->WEndTime % DAY_LEN;
}
if (SR->EndTime > 0)
{
SREndOffset = SR->EndTime;
}
if (PeriodIndex == 0)
{
SRStartOffset = MAX(SRStartOffset,DayTime);
}
break;
case mpWeek:
SREndOffset = WEEK_LEN;
if (SR->WStartTime > 0)
{
SRStartOffset = SR->WStartTime;
}
if (SR->WEndTime > 0)
{
SREndOffset = SR->WEndTime;
}
if (PeriodIndex == 0)
{
SRStartOffset = MAX(SRStartOffset,WeekTime);
}
break;
case mpInfinity:
default:
SREndOffset = MAX_MTIME;
break;
} /* END switch(SR->Period) */
/* determine if reservation is needed for current period */
switch (SR->Period)
{
case mpDay:
if ((SR->Period == mpWeek) && ((SR->WStartTime / DAY_LEN) > WeekDay))
{
/* ignore, week reservation has not yet started */
DBG(6,fSTRUCT) DPrint("INFO: week reservation %s starts after day %d\n",
SR->Name,
WeekDay);
return(FAILURE);
}
if ((SR->WEndTime > 0) && (SR->WEndTime < WeekTime))
{
/* ignore, week reservation has ended */
DBG(6,fSTRUCT) DPrint("INFO: week reservation %s ends before %s\n",
SR->Name,
MULToTString(WeekTime));
return(FAILURE);
}
if (DayTime > SREndOffset)
{
/* ignore, day reservation has already ended */
DBG(6,fSTRUCT) DPrint("INFO: day reservation %s ends before %s\n",
SR->Name,
MULToTString(DayTime));
return(FAILURE);
}
if (!(SR->Days & (1 << WeekDay)))
{
/* day period is not included in SRDays */
DBG(6,fSTRUCT) DPrint("INFO: day reservation %s does not include day %d\n",
SR->Name,
WeekDay);
return(FAILURE);
}
break;
case mpWeek:
if (WeekTime > SREndOffset)
{
/* ignore, week reservation has ended */
DBG(6,fSTRUCT) DPrint("INFO: week reservation %s ends before %s\n",
SR->Name,
MULToTString(WeekTime));
return(FAILURE);
}
break;
case mpInfinity:
default:
if (PeriodIndex != 0)
{
/* ignore, only one infinite period reservation */
DBG(6,fSTRUCT) DPrint("INFO: ignoring infinite reservation %s for period %d\n",
SR->Name,
PeriodIndex);
return(FAILURE);
}
/* reservation not ended */
break;
} /* END switch (SR->Period) */
tmpL = (PeriodStart + SRStartOffset);
DBG(5,fSTRUCT) DPrint("INFO: res start: %s",
MULToDString((mulong *)&tmpL));
DBG(5,fSTRUCT) DPrint("INFO: standing res attributes: Start: %ld Duration: %ld (W: %d D: %s)\n",
PeriodStart + SRStartOffset,
SREndOffset - SRStartOffset,
WeekDay,
MULToTString(DayTime));
if (SRDuration != NULL)
*SRDuration = SREndOffset - SRStartOffset;
if (SRStartTime != NULL)
*SRStartTime = PeriodStart + SRStartOffset;
return(SUCCESS);
} /* END MSRGetAttributes() */
int MSRGetCurrentValues(
sres_t *Config,
sres_t *Override,
sres_t *SR)
{
const char *FName = "MSRGetCurrentValues";
DBG(6,fSCHED) DPrint("%s(%s,Override,SR)\n",
FName,
Config->Name);
memcpy(SR,Config,sizeof(sres_t));
if (Override->TaskCount > 0)
SR->TaskCount = Override->TaskCount;
if (Override->A != NULL)
SR->A = Override->A;
if (Override->StartTime > 0)
SR->StartTime = Override->StartTime;
if (Override->EndTime > 0)
SR->EndTime = Override->EndTime;
return(SUCCESS);
} /* END MSRGetCurrentValues() */
int MSRSetRes(
sres_t *SR, /* I */
int SRIndex, /* I */
int DIndex) /* I */
{
mjob_t tmpJ;
mjob_t *J;
long BestTime;
int sindex;
int aindex;
int nindex;
mnode_t *N;
long SRStartTime;
unsigned long SRDuration;
unsigned long SREndTime;
char TempString[MAX_MNAME];
int TC;
int PC;
nodelist_t NodeList;
mnalloc_t tmpJNodeList[MAX_MNODE + 1];
mnalloc_t tmpJReqHList[MAX_MNODE + 1];
nodelist_t tmpANodeList;
mnalloc_t tmpRQNodeList[MAX_MNODE + 1];
macl_t tmpACL[MAX_MACL];
macl_t tmpCL[MAX_MACL];
mreq_t tmpRQ;
mreq_t *RQ;
mres_t tmpR;
mres_t *R;
int Flags;
int TaskCount;
int ProcCount;
int NodeCount;
enum MHoldReasonEnum Reason;
int IsSpaceFlex; /* (boolean) */
double CurrentIdlePS;
double CurrentActivePS;
double TotalIdlePS;
double TotalActivePS;
unsigned long Mode;
mnalloc_t *HL;
const char *FName = "MSRSetRes";
DBG(3,fSCHED) DPrint("%s(%s,%d,%d)\n",
FName,
(SR != NULL) ? SR->Name : "NULL",
SRIndex,
DIndex);
#ifndef __MQ
if (SR == NULL)
{
return(FAILURE);
}
#endif /* !__MQ */
/* build 'standing reservation' job */
J = &tmpJ;
RQ = &tmpRQ;
tmpACL[0].Type = maNONE;
memset(RQ,0,sizeof(tmpRQ));
MJobMkTemp(J,RQ,tmpACL,tmpCL,tmpJNodeList,tmpRQNodeList);
/* determine reservation name */
if (SR->Name[0] == '\0')
{
sprintf(J->Name,"SR.%d",
SR->Index);
}
else
{
strcpy(J->Name,SR->Name);
}
sprintf(J->Name,"%s.%d",
J->Name,
DIndex);
J->SpecFlags |= (1 << mjfResMap);
if (!(SR->Flags & (1 << mrfDedicatedResource)))
J->SpecFlags |= (1 << mjfSharedResource);
if (SR->Flags & (1 << mrfByName))
J->SpecFlags |= (1 << mjfByName);
if (!strcmp(SR->PName,"ALL"))
J->SpecFlags |= (1 << mjfSpan);
if (SR->HostExpression[0] != '\0')
{
/* verify hostlist */
if (SR->HostList == NULL)
{
/* restore hostlist */
SR->HostList = (void *)calloc(1,sizeof(mnalloc_t) * (MAX_MNODE + 1));
}
HL = (mnalloc_t *)SR->HostList;
if (HL[0].N == NULL)
{
DBG(3,fSCHED) DPrint("INFO: SR %s hostlist %s\n",
SR->Name,
(MSched.Iteration == 0) ? "initialized" : "lost");
if (MSRBuildHostList(SR) == SUCCESS)
{
if (SR != &SRes[SRIndex])
{
if (SRes[SRIndex].HostList == NULL)
{
/* restore hostlist */
SRes[SRIndex].HostList = (void *)calloc(
1,
sizeof(mnalloc_t) * (MAX_MNODE + 1));
}
memcpy(
SRes[SRIndex].HostList,
SR->HostList,
(sizeof(mnalloc_t) * (MAX_MNODE + 1)));
}
} /* END if (MSRBuildHostList(SR) == SUCCESS) */
else
{
DBG(3,fSCHED) DPrint("ALERT: cannot build hostlist for SR %s in %s\n",
SR->Name,
FName);
} /* END else (MSRBuildHostList(SR) == SUCCESS) */
} /* END if (HL[0].N == NULL) */
} /* END if (SR->HostExpression[0] != '\0') */
Mode = 0;
/* use best effort in all cases */
if (SR->TaskCount >= 0)
{
J->SpecFlags |= (1 << mjfBestEffort);
Mode |= (1 << stBestEffort);
}
/* initialize requirements */
memcpy(RQ->ReqFBM,SR->FeatureMap,sizeof(RQ->ReqFBM));
RQ->RMIndex = -1;
TaskCount = 0;
HL = (mnalloc_t *)SR->HostList;
if ((HL != NULL) && (HL[0].N != NULL))
{
J->SpecFlags |= (1 << mjfHostList);
if (SR->TaskCount == 0)
J->SpecFlags |= (1 << mjfBestEffort);
J->ReqHList = &tmpJReqHList[0];
memcpy(J->ReqHList,HL,sizeof(tmpJReqHList));
for (nindex = 0;HL[nindex].N != NULL;nindex++)
{
N = HL[nindex].N;
TC = MNodeGetTC(N,&N->CRes,&N->CRes,&N->DRes,&SR->DRes,MAX_MTIME);
TaskCount += TC;
DBG(5,fUI) DPrint("INFO: evaluating node %sx%d of hostlist for reservation %s (%d)\n",
N->Name,
TC,
SR->Name,
TaskCount);
} /* END for (nindex) */
} /* END if ((HL != NULL) && (HL[0].N != NULL)) */
if (SR->TaskCount > 0)
{
if (SR->TaskCount != TaskCount)
Mode |= (1 << stBestEffort);
TaskCount = SR->TaskCount;
}
else
{
if (TaskCount < 1)
{
DBG(0,fUI) DPrint("ALERT: empty hostlist in %s()\n",
FName);
return(FAILURE);
}
} /* END if (SR->TaskCount > 0) */
if (SR->HostExpression[0] != '\0')
{
/* if SR is dedicated, grant global job access */
if (!(SR->Flags & (1 << mrfDedicatedResource)) || (SR->TaskCount == 0))
Mode |= (1 << stForce);
else
strcpy(J->RAList[0],"[ALLJOB]");
}
else
{
/* if no host expression set */
if (!(SR->Flags & (1 << mrfDedicatedResource)) ||
(SR->TaskCount == 0))
{
Mode |= (1 << stForce);
}
}
/* set credentials */
/* NOTE: location sets previous updated job flags */
if (MJobSetCreds(J,ALL,ALL,ALL) == FAILURE)
{
DBG(3,fUI) DPrint("INFO: cannot setup standing reservation job creds\n");
return(FAILURE);
}
MJobSetQOS(J,MSched.DefaultQ,0);
if (MSRGetAttributes(
SR,
DIndex,
&SRStartTime,
&SRDuration) == FAILURE)
{
DBG(3,fUI) DPrint("INFO: reservation not required for specified period\n");
return(SUCCESS);
}
RQ->TasksPerNode = SR->TPN;
J->WCLimit = MIN(SRDuration,MAX_MEFFINF);
J->SpecWCLimit[0] = J->WCLimit;
J->Request.TC = TaskCount;
RQ->TaskCount = TaskCount;
BestTime = MAX(MSched.Time,SRStartTime);
if (SR->ACL[0].Name[0] != '\0')
{
memcpy(J->Cred.CL,SR->ACL,(sizeof(macl_t) * MAX_MACL));
J->Cred.CredType |= (1 << ctACL);
}
else
{
J->Cred.CL = NULL;
}
memcpy(&RQ->DRes,&SR->DRes,sizeof(mcres_t));
if (RQ->TaskCount * RQ->DRes.Procs == 0)
{
DBG(2,fSCHED) DPrint("ALERT: no procs requested by reservation (%d:%d)\n",
RQ->TaskCount,
RQ->DRes.Procs);
if (SR->R[DIndex] != NULL)
{
MResDestroy(&SR->R[DIndex]);
}
return(SUCCESS);
}
strcpy(TempString,MULToTString(SRDuration));
PC = MJobGetProcCount(J);
DBG(3,fSCHED) DPrint("INFO: attempting standing reservation of %d procs in %s for %s\n",
PC,
MULToTString(SRStartTime - MSched.Time),
TempString);
/* SR job creation complete */
aindex = 0;
R = SR->R[DIndex];
if (R != NULL)
{
CurrentIdlePS = R->CIPS;
CurrentActivePS = R->CAPS;
TotalIdlePS = R->TIPS;
TotalActivePS = R->TAPS;
/* get current active reservation list */
for (nindex = 0;nindex < MAX_MNODE;nindex++)
{
N = MNode[nindex];
if ((N == NULL) || (N->Name[0] == '\0'))
break;
if (N->Name[0] == '\1')
continue;
for (sindex = 0;sindex < MSched.ResDepth;sindex++)
{
if (N->R[sindex] == NULL)
break;
if (N->R[sindex] == R)
{
if ((N->State == mnsBusy) || (N->State == mnsActive))
{
/* add node to list */
tmpANodeList[aindex].N = N;
tmpANodeList[aindex].TC = 1;
aindex++;
}
}
} /* END for (sindex) */
} /* END for (nindex) */
} /* END if (R != NULL) */
else
{
CurrentIdlePS = 0.0;
CurrentActivePS = 0.0;
TotalIdlePS = 0.0;
TotalActivePS = 0.0;
} /* END else (R != NULL) */
tmpANodeList[aindex].N = NULL;
if (MSRSelectNodeList(
J,
SR,
NodeList,
&NodeCount,
BestTime,
tmpANodeList,
Mode) == FAILURE)
{
DBG(1,fSCHED) DPrint("ALERT: cannot select %d procs in partition '%s' for SR '%s'\n",
PC,
(SR->PName[0] != '\0') ? SR->PName : ALL,
SR->Name);
return(FAILURE);
}
BestTime = MAX(BestTime,MSched.Time);
Flags = ((1 << mrfStandingRes) | SR->Flags);
if (SR->Flags & (1 << mrfSpaceFlex))
IsSpaceFlex = TRUE;
else
IsSpaceFlex = FALSE;
R = SRes[SRIndex].R[DIndex];
if (R != NULL)
{
memcpy(&tmpR,R,sizeof(tmpR));
R->A = NULL;
MResDestroy(&SRes[SRIndex].R[DIndex]);
R = NULL;
}
ProcCount = 0;
if ((SR->A != NULL) &&
strcmp(SR->A->Name,NONE))
{
for (nindex = 0;NodeList[nindex].N != NULL;nindex++)
{
if (RQ->DRes.Procs > 0)
ProcCount += RQ->DRes.Procs * NodeList[nindex].TC;
else
ProcCount += NodeList[nindex].N->CRes.Procs;
}
}
SREndTime = MIN(MAX_MTIME,(unsigned long)BestTime + SRDuration);
if (MResCreate(
mrtUser,
SR->ACL,
(SR->A != NULL) ? SR->A->Name : NULL,
Flags,
(mnalloc_t *)NodeList,
BestTime,
(long)SREndTime,
NodeCount,
ProcCount,
J->Name,
&SRes[SRIndex].R[DIndex],
SR->HostExpression,
&RQ->DRes) == FAILURE)
{
DBG(1,fSCHED) DPrint("ALERT: cannot reserve %d procs in partition '%s' for standing reservation\n",
SR->TaskCount * SR->DRes.Procs,
(SR->PName[0] != '\0') ? SR->PName : "[ANY]");
/* charge for previous segment */
if (IsSpaceFlex == TRUE)
{
if (tmpR.CIPS > 0.0)
{
if (MAMAllocRDebit(&MAM[0],&tmpR,&Reason,NULL) == FAILURE)
{
DBG(1,fSTAT) DPrint("ALERT: cannot charge %6.2lf PS to account %s for reservation %s\n",
tmpR.CIPS,
(tmpR.A != NULL) ? tmpR.A->Name : NONE,
tmpR.Name);
}
}
else
{
/* cancel account reservation */
if (MAMAllocResCancel(
(tmpR.A != NULL) ? tmpR.A->Name : NULL,
tmpR.Name,
"standing reservation removed",
NULL,
&Reason) == FAILURE)
{
DBG(1,fSCHED) DPrint("ERROR: cannot cancel allocation reservation for reservation %s, reason: %s\n",
tmpR.Name,
MDefReason[Reason]);
}
}
} /* END if (IsSpaceFlex == TRUE) */
return(FAILURE);
} /* END if (MResCreate() == FAILURE) */
R = SRes[SRIndex].R[DIndex];
R->CIPS = CurrentIdlePS;
R->CAPS = CurrentActivePS;
R->TIPS = TotalIdlePS;
R->TAPS = TotalActivePS;
R->Priority = SR->Priority;
if ((SR->A != NULL) && strcmp(SR->A->Name,NONE))
{
R->A = SR->A;
}
R->O = SR->O;
R->OType = SR->OType;
PC = MJobGetProcCount(J);
if (PC == R->AllocPC)
{
DBG(2,fSCHED) DPrint("INFO: full SR reserved %d procs in partition '%s' to start in %s at (%ld) %s",
PC,
(SR->PName[0] != '\0') ? SR->PName : "[ALL]",
MULToTString(BestTime - MSched.Time),
BestTime,
MULToDString((mulong *)&BestTime));
}
else
{
DBG(2,fSCHED) DPrint("WARNING: partial standing reservation %s reserved %d of %d procs in partition '%s' to start in %s at (%ld) %s",
SR->Name,
R->AllocPC,
PC,
(SR->PName[0] != '\0') ? SR->PName : "[ALL]",
MULToTString(BestTime - MSched.Time),
BestTime,
MULToDString((mulong *)&BestTime));
}
return(SUCCESS);
} /* END MSRSetRes() */
int MSRUpdate(
sres_t *SSR) /* I (optional) */
{
int SRIndex;
sres_t *SR;
int DIndex;
char ResName[MAX_MNAME];
sres_t tmpSR;
const char *FName = "MSRUpdate";
DBG(4,fCORE) DPrint("%s()\n",
FName);
SR = &tmpSR;
for (SRIndex = 0;SRIndex < MAX_MSRES;SRIndex++)
{
if (SRes[SRIndex].Name[0] == '\0')
break;
if ((SSR != NULL) && (SSR != &SRes[SRIndex]))
continue;
MSRGetCurrentValues(&SRes[SRIndex],&OSRes[SRIndex],SR);
/* erase expired reservation */
if (SR->R[0] != NULL)
{
if (SR->R[0]->EndTime > MSched.Time)
continue;
MResDestroy(&SR->R[0]);
SRes[SRIndex].R[0] = NULL;
}
if (SR->HostExpression[0] != '\0')
{
if (MSRBuildHostList(SR) == SUCCESS)
{
if (SR != &SRes[SRIndex])
{
if (SRes[SRIndex].HostList == NULL)
{
SRes[SRIndex].HostList =
(void *)calloc(1,sizeof(mnalloc_t) * (MAX_MNODE + 1));
}
memcpy(
SRes[SRIndex].HostList,
SR->HostList,
sizeof(SRes[SRIndex].HostList));
}
}
else
{
DBG(4,fCORE) DPrint("ALERT: cannot create hostlist for SR %s in %s\n",
SR->Name,
FName);
}
} /* END if (SR->HostExpression[0] == '\0') */
else
{
if (SR->TaskCount == 0)
continue;
}
/* roll standing reservations forward */
for (DIndex = 0;DIndex < (MAX_SRES_DEPTH - 1);DIndex++)
{
if (DIndex >= (SR->Depth - 1))
break;
SR->R[DIndex] = SR->R[DIndex + 1];
SRes[SRIndex].R[DIndex] = SR->R[DIndex + 1];
SR->R[DIndex + 1] = NULL;
SRes[SRIndex].R[DIndex + 1] = NULL;
if (SR->R[DIndex] == NULL)
{
/* create missing reservations */
MSRSetRes(SR,SRIndex,DIndex);
}
else
{
/* update name of standing reservation */
if (SR->Name[0] == '\0')
{
sprintf(ResName,"SR.%d",
SR->Index);
}
else
{
strcpy(ResName,SR->Name);
}
sprintf(ResName,"%s.%d",
ResName,
DIndex);
/* determine unique reservation name */
DBG(5,fSTRUCT) DPrint("INFO: creating reservation '%s'\n",
ResName);
strcpy(SR->R[DIndex]->Name,ResName);
} /* END else (SR->R[DIndex] == NULL) */
} /* END for (DIndex) */
if (MSRSetRes(SR,SRIndex,DIndex) == FAILURE)
{
DBG(2,fCORE) DPrint("ALERT: cannot create SR[%d] %s at depth %d\n",
SRIndex,
SR->Name,
DIndex);
}
} /* END for (SRIndex) */
return(SUCCESS);
} /* END MSRUpdate() */
int MSRBuildHostList(
sres_t *SR) /* I */
{
int nindex;
int oindex;
int NodeCount;
char Expr[MAX_MBUFFER];
char Buffer[MAX_MBUFFER];
short ObjList[MAX_MNODE];
int TC;
char *ptr;
char *TokPtr;
mnalloc_t *HL;
mnode_t *N;
mpar_t *P;
nindex = 0;
if (SR->HostList == NULL)
{
SR->HostList = (void *)calloc(1,sizeof(mnalloc_t) * (MAX_MNODE + 1));
}
HL = (mnalloc_t *)SR->HostList;
HL[0].N = NULL;
strcpy(Expr,SR->HostExpression);
ptr = MUStrTok(Expr," ",&TokPtr);
if (SR->PName[0] == '\0')
{
P = &MPar[0];
}
else
{
if (MParFind(SR->PName,&P) == FAILURE)
{
/* requested partition does not exist */
return(FAILURE);
}
}
while (ptr != NULL)
{
Buffer[0] = '\0';
if (MUREToList(ptr,mxoNode,P->Index,ObjList,&NodeCount,Buffer) == FAILURE)
{
DBG(2,fCONFIG) DPrint("ALERT: cannot expand hostlist '%s'\n",
ptr);
ptr = MUStrTok(NULL," ",&TokPtr);
continue;
}
ptr = MUStrTok(NULL," ",&TokPtr);
/* populate hostlist */
for (oindex = 0;oindex < NodeCount;oindex++)
{
for (nindex = 0;nindex < MAX_MNODE;nindex++)
{
if (HL[nindex].N == NULL)
{
/* add node to list */
HL[nindex].N = MNode[ObjList[oindex]];
HL[nindex].TC = 1;
HL[nindex + 1].N = NULL;
break;
}
if (HL[nindex].N->Index == ObjList[oindex])
{
/* node previously added */
break;
}
} /* END for (nindex) */
} /* END for (oindex) */
} /* END while (ptr != NULL) */
if (HL[0].N == NULL)
{
return(FAILURE);
}
for (nindex = 0;nindex < MAX_MNODE;nindex++)
{
if (HL[nindex].N == NULL)
break;
N = HL[nindex].N;
TC = MNodeGetTC(N,&N->ARes,&N->CRes,&N->DRes,&SR->DRes,MAX_MTIME);
if (SR->TaskCount > 0)
{
HL[nindex].TC = (short)MIN(TC,SR->TaskCount);
}
else
{
HL[nindex].TC = (short)TC;
}
} /* END for (nindex) */
return(SUCCESS);
} /* END MSRBuildHostList() */
int MSRProcessOConfig(
sres_t *SR,
int PIndex,
int IVal,
double DVal,
char *SVal,
char **SArray)
{
if (SR == NULL)
return(FAILURE);
switch (PIndex)
{
case pSRAccess:
if (!strcmp(SVal,"SHARED"))
{
if (SR->Flags & (1 << mrfDedicatedResource))
SR->Flags ^= (1 << mrfDedicatedResource);
}
break;
case pSRAccountList:
{
int index;
for (index = 0;SArray[index] != NULL;index++);
MACLLoadConfig(SR->ACL,SArray,index,maAcct);
}
break;
case pSRChargeAccount:
MAcctAdd(SVal,&SR->A);
break;
case pSRClassList:
{
int index;
for (index = 0;SArray[index] != NULL;index++);
MACLLoadConfig(SR->ACL,SArray,index,maClass);
}
break;
case pSRDays:
{
int index;
int dindex;
SR->Days = 0;
for (index = 0;SArray[index] != NULL;index++)
{
if (strstr(SArray[index],"ALL") != NULL)
{
SR->Days |= 255;
break;
}
else
{
for (dindex = 0;MWeekDay[dindex] != NULL;dindex++)
{
if ((strstr(SArray[index],MWeekDay[dindex]) != NULL) ||
(strstr(SArray[index],MWEEKDAY[dindex]) != NULL))
{
SR->Days |= (1 << dindex);
}
} /* END for (dindex) */
} /* END else (strstr() != NULL) */
} /* END for (index) */
DBG(2,fALL) DPrint("INFO: SRes[%s].Days set to %x\n",
SR->Name,
SR->Days);
} /* END BLOCK */
break;
case pSRDepth:
SR->Depth = IVal;
break;
case pSREndTime:
SR->EndTime = MUTimeFromString(SVal);
break;
case pSRFeatures:
{
char *ptr;
char *TokPtr;
int index;
int FMap[MAX_MATTR >> 5];
MUBMClear(FMap,MAX_MATTR);
for (index = 0;SArray[index] != NULL;index++)
{
ptr = MUStrTok(SArray[index],"[] \t",&TokPtr);
while (ptr != NULL)
{
MUGetMAttr(eFeature,ptr,mAdd,FMap,sizeof(FMap));
MUBMOR(SR->FeatureMap,FMap,MAX_MATTR);
ptr = MUStrTok(NULL,"[] \t",&TokPtr);
}
} /* END for (index) */
} /* END BLOCK */
break;
case pSRFlags:
MUBMFromString(SVal,MResFlags,(unsigned long *)&SR->Flags);
break;
case pSRGroupList:
{
int index;
for (index = 0;SArray[index] != NULL;index++);
MACLLoadConfig(SR->ACL,SArray,index,maGroup);
} /* END BLOCK */
break;
case pSRHostList:
{
int index;
MUStrCpy(SR->HostExpression,SArray[0],sizeof(SR->HostExpression));
for (index = 1;SArray[index] != NULL;index++)
{
MUStrCat(SR->HostExpression," ",sizeof(SR->HostExpression));
MUStrCat(SR->HostExpression,SArray[index],sizeof(SR->HostExpression));
} /* END for (index) */
} /* END BLOCK */
break;
case pSRIdleTime:
SR->MaxIdleTime = MUTimeFromString(SVal);
break;
case pSRMaxTime:
{
long MaxTime = MUTimeFromString(SVal);
MACLSet(
SR->ACL,
maDuration,
&MaxTime,
mcmpLE,
nmPositiveAffinity,
(1 << maclRequired),
0);
} /* END BLOCK */
break;
case pSRName:
/* no longer supported */
break;
case pSRPartition:
MUStrCpy(SR->PName,SVal,sizeof(SR->PName));
break;
case pSRPeriod:
SR->Period = MUGetIndex(SVal,MSRPeriodType,FALSE,SR->Period);
break;
case pSRPriority:
SR->Priority = IVal;
break;
case pSRQOSList:
{
int index;
for (index = 0;SArray[index] != NULL;index++);
MACLLoadConfig(SR->ACL,SArray,index,maQOS);
} /* END BLOCK */
break;
case pSRResources:
{
int index;
memset(&SR->DRes,0,sizeof(SR->DRes));
for (index = 0;SArray[index] != NULL;index++)
{
MUCResFromString(&SR->DRes,SArray[index]);
} /* END for (index) */
DBG(2,fALL) DPrint("INFO: SRes[%s].DRes set to P: %d M: %d D: %d S: %d\n",
SR->Name,
SR->DRes.Procs,
SR->DRes.Mem,
SR->DRes.Disk,
SR->DRes.Swap);
}
break;
case pSRStartTime:
SR->StartTime = MUTimeFromString(SVal);
break;
case pSRTaskCount:
SR->TaskCount = IVal;
break;
case pSRTPN:
SR->TPN = IVal;
break;
case pSRUserList:
{
int index;
for (index = 0;SArray[index] != NULL;index++);
MACLLoadConfig(SR->ACL,SArray,index,maUser);
}
break;
case pSRWEndTime:
SR->WEndTime = MUTimeFromString(SVal);
break;
case pSRWStartTime:
SR->WStartTime = MUTimeFromString(SVal);
break;
default:
break;
} /* END switch(PIndex) */
return(SUCCESS);
} /* END MSRProcessOConfig() */
int MSRAToString(
sres_t *SR, /* I */
int AIndex, /* I */
char *Buf, /* O */
int Mode) /* I */
{
if ((SR == NULL) || (Buf == NULL))
{
return(FAILURE);
}
Buf[0] = '\0';
switch(AIndex)
{
case msraChargeAccount:
if ((Mode & (1 << mcmVerbose)) || (OSRes[SR->Index].A != NULL))
{
strcpy(Buf,OSRes[SR->Index].A->Name);
}
break;
case msraEndTime:
if ((Mode & (1 << mcmVerbose)) || (OSRes[SR->Index].EndTime > 0))
{
sprintf(Buf,"%ld",
OSRes[SR->Index].EndTime);
}
break;
case msraOwner:
if (SR->OType != mxoNONE)
{
char *ptr;
MOGetName(SR->O,SR->OType,&ptr);
sprintf(Buf,"%s:%s",
MXOC[SR->OType],
ptr);
}
break;
case msraStartTime:
if ((Mode & (1 << mcmVerbose)) || (OSRes[SR->Index].StartTime > 0))
{
sprintf(Buf,"%ld",
OSRes[SR->Index].StartTime);
}
break;
case msraStIdleTime:
if ((Mode & (1 << mcmVerbose)) || (SR->IdleTime > 0.0))
{
sprintf(Buf,"%.2lf",
SR->IdleTime);
}
break;
case msraStTotalTime:
if ((Mode & (1 << mcmVerbose)) || (SR->TotalTime > 0.0))
{
sprintf(Buf,"%.2lf",
SR->TotalTime);
}
break;
case msraTaskCount:
/* display override */
if ((Mode & (1 << mcmVerbose)) || (OSRes[SR->Index].TaskCount > 0))
{
sprintf(Buf,"%d",
OSRes[SR->Index].TaskCount);
}
break;
default:
/* not supported */
return(FAILURE);
/*NOTREACHED*/
break;
} /* END switch(AIndex) */
return(SUCCESS);
} /* END MSRAToString() */
int MSRToString(
sres_t *SR, /* I */
char *Buf) /* O */
{
const int CPAList[] = {
msraName,
msraStIdleTime,
msraStTotalTime,
msraTaskCount,
msraChargeAccount,
msraStartTime,
msraEndTime,
-1 };
mxml_t *E = NULL;
if ((SR == NULL) || (Buf == NULL))
return(FAILURE);
MXMLCreateE(&E,"sres");
MSRToXML(SR,E,(int *)CPAList);
MXMLToString(E,Buf,MAX_MBUFFER,NULL,TRUE);
MXMLDestroyE(&E);
return(SUCCESS);
} /* END MSRToString() */
int MSRToXML(
sres_t *SR, /* I */
mxml_t *E, /* O */
int *SAList)
{
int DAList[] = {
msraName,
msraStIdleTime,
msraStTotalTime,
msraTaskCount,
msraChargeAccount,
msraStartTime,
msraEndTime,
-1 };
int aindex;
int *AList;
char tmpString[MAX_MLINE];
if ((SR == NULL) || (E == NULL))
return(FAILURE);
if (SAList != NULL)
AList = SAList;
else
AList = DAList;
for (aindex = 0;AList[aindex] != -1;aindex++)
{
if ((MSRAToString(SR,AList[aindex],tmpString,0) == FAILURE) ||
(tmpString[0] == '\0'))
{
continue;
}
MXMLSetAttr(E,(char *)MSResAttr[AList[aindex]],tmpString,mdfString);
} /* END for (aindex) */
return(FAILURE);
} /* END MSRToXML() */
int MSRFromString(
sres_t *SR, /* O (modified) */
char *Buf) /* I */
{
mxml_t *E = NULL;
int rc;
if ((Buf == NULL) || (SR == NULL))
{
return(FAILURE);
}
rc = MXMLFromString(&E,Buf,NULL,NULL);
if (rc == SUCCESS)
{
rc = MSRFromXML(SR,E);
}
MXMLDestroyE(&E);
if (rc == FAILURE)
{
return(FAILURE);
}
return(SUCCESS);
} /* END MSRFromString() */
int MSRFromXML(
sres_t *SR, /* O (modified) */
mxml_t *E) /* I */
{
int aindex;
int saindex;
if ((SR == NULL) || (E == NULL))
{
return(FAILURE);
}
/* NOTE: do not initialize. may be overlaying data */
for (aindex = 0;aindex < E->ACount;aindex++)
{
saindex = MUGetIndex(E->AName[aindex],MSResAttr,FALSE,0);
if (saindex == 0)
continue;
MSRSetAttr(SR,saindex,(void **)E->AVal[aindex],mdfString,mSet);
} /* END for (aindex) */
return(SUCCESS);
} /* END MSRFromXML() */
int MSRSetAttr(
sres_t *SR, /* I (modified) */
int AIndex, /* I */
void **Value, /* I */
int Format, /* I */
int Mode) /* I */
{
long tmpL;
int tmpI;
if (SR == NULL)
{
return(FAILURE);
}
tmpL = 0;
tmpI = 0;
if (Value != NULL)
{
switch (Format)
{
case mdfLong:
tmpL = *(long *)Value;
break;
case mdfInt:
tmpI = *(int *)Value;
break;
default:
tmpL = strtol((char *)Value,NULL,0);
tmpL = (int)tmpL;
break;
} /* END switch(Format) */
} /* END if (Value != NULL) */
switch(AIndex)
{
case msraChargeAccount:
MAcctAdd((char *)Value,&OSRes[SR->Index].A);
break;
case msraEndTime:
OSRes[SR->Index].EndTime = tmpL;
break;
case msraName:
/* NYI */
break;
case msraOwner:
{
if (Format == mdfString)
{
char tmpLine[MAX_MLINE];
int oindex;
char *TokPtr;
char *ptr;
void *optr;
/* FORMAT: <CREDTYPE>:<CREDID> */
MUStrCpy(tmpLine,(char *)Value,sizeof(tmpLine));
ptr = MUStrTok(tmpLine,": \t\n",&TokPtr);
if ((ptr == NULL) ||
((oindex = MUGetIndex(ptr,MXOC,FALSE,mxoNONE)) == mxoNONE))
{
/* invalid format */
return(FAILURE);
}
ptr = MUStrTok(NULL,": \t\n",&TokPtr);
if (MOGetObject(oindex,ptr,&optr,mAdd) == FAILURE)
{
return(FAILURE);
}
SR->O = optr;
SR->OType = oindex;
}
else
{
/* NYI */
return(FAILURE);
}
} /* END BLOCK */
break;
case msraStartTime:
OSRes[SR->Index].EndTime = tmpL;
break;
case msraStIdleTime:
SR->IdleTime = tmpL;
break;
case msraStTotalTime:
SR->TotalTime = tmpL;
break;
case msraTaskCount:
OSRes[SR->Index].TaskCount = tmpI;
break;
default:
/* not supported */
return(FAILURE);
/*NOTREACHED*/
break;
} /* END switch(AIndex) */
return(SUCCESS);
} /* END MSRSetAttr() */
/* END MSR.c */