/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1990-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Bell Laboratories
*
* remote coshell server scheduling support
*/
#include "service.h"
#define RNK(p,a) (((p)->mode&SHELL_DISABLE)?INT_MAX:((p)->flags&IGN)?(INT_MAX/2):((((p)->stat.load/(p)->scale)+((p)->running*BIAS+CPU((p)->cpu,(a)->bias)))*(p)->bias*(((p)==state.home&&(p)->cpu==1)?400:100)/(p)->rating))
/*
* allocate and copy string v into s
*/
static char*
dupstring(char* s, const char* v)
{
if (v)
{
strcpy(s, v);
}
else if (s)
{
free(s);
s = 0;
}
return(s);
}
/*
* search for name in the shell table
* op is a combination of {DEF,GET,JOB,NEW,SET}
* a points to optional attribute return value
* d points to optional default attributes
*/
{
int bypass;
int matched;
int xm;
int n;
int nopen;
int noverride;
unsigned long sv;
unsigned long v;
unsigned long addr;
static unsigned long dt;
static unsigned long scan;
/*
* extract the attributes
*/
if (!a) a = &attr;
attributes(name, a, d);
{
{
{
}
{
{
}
}
{
}
}
}
/*
* check previous entries
*/
{
}
{
}
{
{
}
xm = 0;
sv = ~0;
scan++;
{
}
/*
* shell scheduling
*
* cp head of close list
* dp worst open from last time [close after dt]
* mp best closed match
* sp best open match [value is sv]
* xp worst open
*
* non-busy shells failing idle criteria are marked for close
*/
do
{
{
matched = 0;
}
message((-6, "search: %s name=%s misc=%s matched=%d", ap->name, (a->set & SETNAME) ? a->name : "*", ((a->set | op) & (SETMISC|DEF|NEW|SET)) == SETMISC ? a->misc : "*", matched));
{
{
if (!ap->home && (!xp || ap->temp < PCT(xp->temp, H_TEMP) || (ap->mode & SHELL_DENIED) || matched && xm && PCT(ap->temp, H_TEMP) < xp->temp && ap->rank > xp->rank))
{
}
}
{
continue;
}
if (ap != state.shell && (ap->override || !IDLE(ap->stat.idle, ap->idle) && (!ap->bypass || !(bypass = miscmatch(ap, ap->bypass)))))
{
{
{
}
{
}
}
if (sp) continue;
}
}
if (matched)
{
{
if (v < sv && ap->running < (state.perhost ? state.perhost : ap->cpu * state.percpu) && (!state.maxload || (ap->stat.load / ap->scale) < state.maxload) && (!sp || bypass || IDLE(ap->stat.idle, ap->idle) || !IDLE(sp->stat.idle, sp->idle)))
{
sv = v;
}
}
else if (!ap->fd && (!mp || ap->rank < mp->rank) && (IDLE(ap->stat.idle, ap->idle) || ap->home || ap->bypass && miscmatch(ap, ap->bypass) || ((a->set | op) & (SETMISC|DEF|NEW|SET)) == SETMISC)) mp = ap;
}
message((-4, "open=%d override=%d sp=%s mp=%s xp=%s dp=%s dt=%s", nopen, noverride, sp ? sp->name : "*", mp ? mp->name : "*", xp ? xp->name : "*", dp ? dp->name : "*", dp && dt > cs.time ? fmtelapsed(dt - cs.time, 1) : "*"));
{
if (!xp->running && (nopen - xp->cpu >= state.pool + noverride || state.open - xp->cpu >= state.fdtotal / 2 || xp == dp && cs.time > dt && (!xm || !mp || mp->rank < PCT(xp->rank, H_RANK))))
{
dp = 0;
}
{
}
}
{
if (sp)
{
goto found;
}
}
else if (sp) do
{
/*
* a->name may be an alias
*/
{
if (state.check.host && !strmatch(a->name, state.check.host) && !strmatch(csntoa(addr), state.check.host)) return(0);
/*
* add a new entry
*/
{
}
{
n = 0;
for (;;)
{
n++;
}
}
else
{
}
{
case DEF:
break;
case JOB:
{
}
/*FALLTHROUGH*/
default:
return(sp);
case NEW:
{
a->idle = 0;
}
/*FALLTHROUGH*/
case SET:
{
}
break;
break;
}
{
}
{
}
{
}
{
{
{
}
}
}
if (!sp->update && !(op & GET) || (a->set & (SETBIAS|SETCPU|SETIDLE|SETIGNORE|SETRATING|SETSCALE)) && sp->update <= cs.time + UPDATE) update(sp);
return(sp);
}
/*
* update shell status
*/
void
{
register long n;
{
}
else
{
{
n = X_RANK;
{
n -= W_USER;
}
}
else
{
n = 0;
n += W_LOAD * (((sp->stat.load / sp->scale) + CPU(sp->cpu, W_JOB * LOAD)) / T_LOAD) * sp->bias / sp->rating;
{
{
else if (sp->stat.idle < R_IDLE * sp->idle) n += W_IDLE * (R_IDLE * sp->idle - sp->stat.idle) / ((R_IDLE - 1) * sp->idle);
}
}
{
else n = PCT(X_RANK, C_RANK) + (n - PCT(X_RANK, C_RANK)) / (2 * X_RANK - PCT(X_RANK, C_RANK) - 1) * (X_RANK - PCT(X_RANK, C_RANK) - 1);
}
}
else
{
}
message((-4, "%s: %s=%s idle=%s load=%s users=%d rank=%s", sp->name, sp->stat.up < 0 ? "down" : "up", fmtelapsed(sp->stat.up < 0 ? -sp->stat.up : sp->stat.up, 1), fmtelapsed(sp->stat.idle, 1), fmtfloat(sp->stat.load), sp->stat.users, fmtfloat(sp->rank)));
}
}
/*
* gather host info from file
*/
{
register char* s;
static char* apath;
{
{
if (!(file = sfstrrsrv(state.string, PATH_MAX)) || !pathaccess(csvar(CS_VAR_TRUST, 1), csvar(CS_VAR_SHARE, 0), CS_SVC_ACCESS, PATH_REGULAR, file, PATH_MAX) || !(file = strdup(file)))
{
return(0);
}
}
{
apath = 0;
return(0);
}
{
return(0);
}
}
{
return(0);
}
}
/*
* compare shells by name
*/
int
byname(const char* a, const char* b)
{
}
/*
* compare shells by rank from best to worst
*/
int
byrank(const char* a, const char* b)
{
return(0);
}
/*
* compare shells by temperature from hottest to coolest
*/
int
bytemp(const char* a, const char* b)
{
return(0);
}