Changes needed to support ubik (non-voting) clones.
====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================
Needed kaserver support for ubik clones
====================
Needed support for ubik clones for the ptserver
====================
Support for ubik clones in vlserver
====================
auth layer support for ubik readonly clones
====================
ubik library support for readonly clones
tdir->name = (char *) malloc(strlen(adir)+1);
strcpy(tdir->name, adir);
- code = afsconf_OpenInternal(tdir);
+ code = afsconf_OpenInternal(tdir, 0, 0);
if (code) {
char *afsconf_path, *getenv(), afs_confdir[128];
}
tdir->name = (char *) malloc(strlen(afsconf_path)+1);
strcpy(tdir->name, afsconf_path);
- code = afsconf_OpenInternal(tdir);
+ code = afsconf_OpenInternal(tdir, 0, 0);
if (code) {
free(tdir->name);
free(tdir);
#endif /* AFS_NT40_ENV */
-static int afsconf_OpenInternal(adir)
-register struct afsconf_dir *adir; {
+static int afsconf_OpenInternal(adir, cell, clones)
+register struct afsconf_dir *adir;
+char *cell;
+char clones[];
+{
FILE *tf;
register char *tp, *bp;
register struct afsconf_entry *curEntry;
return -1;
}
i = curEntry->cellInfo.numServers;
- code = ParseHostLine(tbuffer, (char *) &curEntry->cellInfo.hostAddr[i], curEntry->cellInfo.hostName[i]);
+ if (cell && !strcmp(cell, curEntry->cellInfo.name))
+ code = ParseHostLine(tbuffer, (char *) &curEntry->cellInfo.hostAddr[i], curEntry->cellInfo.hostName[i], &clones[i]);
+ else
+ code = ParseHostLine(tbuffer, (char *) &curEntry->cellInfo.hostAddr[i], curEntry->cellInfo.hostName[i], 0);
if (code) {
if (code == AFSCONF_SYNTAX) {
for (bp=tbuffer; *bp != '\n'; bp++) { /* Take out the <cr> from the buffer */
}
/* parse a line of the form
- *"128.2.1.3 #hostname"
+ *"128.2.1.3 #hostname" or
+ *"[128.2.1.3] #hostname" for clones
* into the appropriate pieces.
*/
-static ParseHostLine(aline, addr, aname)
-register struct sockaddr_in *addr;
-char *aline, *aname; {
+static ParseHostLine(aline, addr, aname, aclone)
+ char *aclone;
+ register struct sockaddr_in *addr;
+ char *aline, *aname;
+{
int c1, c2, c3, c4;
register afs_int32 code;
register char *tp;
- code = sscanf(aline, "%d.%d.%d.%d #%s", &c1, &c2, &c3, &c4, aname);
+ if (*aline == '[') {
+ if (aclone) *aclone = 1;
+ code = sscanf(aline, "[%d.%d.%d.%d] #%s", &c1, &c2, &c3, &c4, aname);
+ } else {
+ if (aclone) *aclone = 0;
+ code = sscanf(aline, "%d.%d.%d.%d #%s", &c1, &c2, &c3, &c4, aname);
+ }
if (code != 5) return AFSCONF_SYNTAX;
addr->sin_family = AF_INET;
addr->sin_port = 0;
}
afs_int32 afsconf_SawCell = 0;
+
+afsconf_GetExtendedCellInfo(adir, acellName, aservice, acellInfo, clones)
+ struct afsconf_dir *adir;
+ char *aservice;
+ char *acellName;
+ struct afsconf_cell *acellInfo;
+ char clones[];
+{
+ afs_int32 code;
+ char *cell;
+
+ code = afsconf_GetCellInfo(adir, acellName, aservice, acellInfo);
+ if (code)
+ return code;
+
+ if (acellName)
+ cell = acellName;
+ else
+ cell = (char *) &acellInfo->name;
+
+ code = afsconf_OpenInternal(adir, cell, clones);
+ return code;
+}
+
afsconf_GetCellInfo(adir, acellName, aservice, acellInfo)
struct afsconf_dir *adir;
char *aservice;
tcell = acellName;
cnLen = strlen(tcell)+1;
lcstring (tcell, tcell, cnLen);
- afsconf_SawCell = 1; /* will ignore the AFSCELL switch on future */
- /* call to afsconf_GetLocalCell: like klog */
+ afsconf_SawCell = 1; /* will ignore the AFSCELL switch on future */
+ /* call to afsconf_GetLocalCell: like klog */
} else {
i = afsconf_GetLocalCell(adir, tbuffer, sizeof(tbuffer));
if (i) {
register afs_int32 code;
code = afsconf_CloseInternal(adir);
if (code) return code;
- code = afsconf_OpenInternal(adir);
+ code = afsconf_OpenInternal(adir, 0, 0);
return code;
}
afsconf_SetCellInfo(adir, apath, acellInfo)
struct afsconf_dir *adir;
char *apath;
-struct afsconf_cell *acellInfo; {
+struct afsconf_cell *acellInfo;
+{
+ afs_int32 code;
+
+ code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, (char *)0);
+ return code;
+}
+
+afsconf_SetExtendedCellInfo(adir, apath, acellInfo, clones)
+ struct afsconf_dir *adir;
+ char *apath;
+ struct afsconf_cell *acellInfo;
+ char clones[];
+{
register afs_int32 code;
register int fd;
char tbuffer[1024];
code = acellInfo->hostAddr[i].sin_addr.s_addr; /* net order */
if (code == 0) continue; /* delete request */
code = ntohl(code); /* convert to host order */
- fprintf(tf, "%d.%d.%d.%d #%s\n", (code>>24) & 0xff, (code>>16)&0xff, (code>>8)&0xff, code&0xff, acellInfo->hostName[i]);
+ if (clones && clones[i])
+ fprintf(tf, "[%d.%d.%d.%d] #%s\n", (code>>24) & 0xff, (code>>16)&0xff, (code>>8)&0xff, code&0xff, acellInfo->hostName[i]);
+ else
+ fprintf(tf, "%d.%d.%d.%d #%s\n", (code>>24) & 0xff, (code>>16)&0xff, (code>>8)&0xff, code&0xff, acellInfo->hostName[i]);
}
if (ferror(tf)) {
fclose(tf);
register struct rx_connection *tconn;
register afs_int32 code;
register struct cmd_item *ti;
+ char name[MAXHOSTCHARS];
tconn = GetConn(as, 0);
for(ti = as->parms[1].items; ti; ti=ti->next) {
- code = BOZO_AddCellHost(tconn, ti->data);
+ if (as->parms[2].items) {
+ if (strlen(ti->data) > MAXHOSTCHARS - 3) {
+ fprintf(stderr, "bos: host name too long\n");
+ return E2BIG;
+ }
+ name[0] = '[';
+ strcpy(&name[1],ti->data);
+ strcat((char *)&name, "]");
+ code = BOZO_AddCellHost(tconn, name);
+ } else
+ code = BOZO_AddCellHost(tconn, ti->data);
if (code)
printf("bos: failed to add host %s (%s)\n", ti->data, em(code));
}
ts = cmd_CreateSyntax("addhost", AddHost, 0, "add host to cell dbase");
cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
cmd_AddParm(ts, "-host", CMD_LIST, 0, "host name");
+ cmd_AddParm(ts, "-clone", CMD_FLAG, CMD_OPTIONAL, "vote doesn't count");
add_std_args (ts);
ts = cmd_CreateSyntax("removehost", RemoveHost, 0,
int servers;
int initFlags;
int level; /* security level for Ubik */
+ afs_int32 i;
+ char clones[MAXHOSTSPERCELL];
struct rx_service *tservice;
struct rx_securityClass *sca[1];
OpenLog(AFSDIR_SERVER_KALOG_FILEPATH);
SetupLogSignals();
#endif
+ code = afsconf_GetExtendedCellInfo (KA_conf, cell, AFSCONF_KAUTHSERVICE,
+ &cellinfo, &clones);
if (servers) {
if (code = ubik_ParseServerList(argc, argv, &myHost, serverList)) {
com_err(whoami, code, "Couldn't parse server list");
exit(1);
}
+ cellinfo.hostAddr[0].sin_addr.s_addr = myHost;
+ for (i=1; i<MAXSERVERS; i++) {
+ if (!serverList[i]) break;
+ cellinfo.hostAddr[i].sin_addr.s_addr = serverList[i];
+ }
+ cellinfo.numServers = i;
}
else {
- code = afsconf_GetCellInfo (KA_conf, cell, AFSCONF_KAUTHSERVICE,
- &cellinfo);
code = convert_cell_to_ubik (&cellinfo, &myHost, serverList);
if (code) goto abort;
ViceLog (0, ("Using server list from %s cell database.\n", cell));
ubik_CheckRXSecurityRock = (char *)KA_conf;
ubik_nBuffers = 80;
- code = ubik_ServerInit (myHost, htons(AFSCONF_KAUTHPORT), serverList,
- dbpath, &KA_dbase);
+ if (servers)
+ code = ubik_ServerInit (myHost, htons(AFSCONF_KAUTHPORT), serverList,
+ dbpath, &KA_dbase);
+ else
+ code = ubik_ServerInitByInfo (myHost, htons(AFSCONF_KAUTHPORT),
+ &cellinfo, &clones, dbpath, &KA_dbase);
+
if (code) {
com_err(whoami, code, "Ubik init failed");
exit(2);
char **argv;
{
register afs_int32 code;
- afs_int32 serverList[MAXSERVERS];
afs_int32 myHost;
register struct hostent *th;
char hostname[64];
int kerberosKeys; /* set if found some keys */
afs_int32 i,j;
int lwps = 3;
+ char clones[MAXHOSTSPERCELL];
const char *pr_dbaseName;
char *whoami = "ptserver";
bcopy(th->h_addr,&myHost,sizeof(afs_int32));
/* get list of servers */
- code = afsconf_GetCellInfo(prdir,(char *)0,"afsprot",&info);
+ code = afsconf_GetExtendedCellInfo(prdir,(char *)0,"afsprot",
+ &info, &clones);
if (code) {
com_err (whoami, code, "Couldn't get server list");
PT_EXIT(2);
pr_realmName = info.name;
pr_realmNameLen = strlen (pr_realmName);
- for (i=0,j=0;i<info.numServers;i++)
- if (info.hostAddr[i].sin_addr.s_addr != myHost) /* ubik already tacks myHost onto list */
- serverList[j++] = info.hostAddr[i].sin_addr.s_addr;
- serverList[j] = 0;
-
#if 0
/* get keys */
code = afsconf_GetKey(prdir,999,&tkey);
* and the header are in separate Ubik buffers then 120 buffers may be
* required. */
ubik_nBuffers = 120 + /*fudge*/40;
- code = ubik_ServerInit(myHost, htons(AFSCONF_PROTPORT), serverList,
- pr_dbaseName, &dbase);
+ code = ubik_ServerInitByInfo(myHost, htons(AFSCONF_PROTPORT), &info,
+ &clones, pr_dbaseName, &dbase);
if (code) {
com_err (whoami, code, "Ubik init failed");
PT_EXIT(2);
#include <rx/xdr.h>
#include <rx/rx.h>
#include <rx/rx_multi.h>
+#include <afs/cellconfig.h>
#ifndef AFS_NT40_ENV
#include <afs/afsutil.h>
#include <afs/netutils.h>
int ubik_amSyncSite = 0; /* flag telling if I'm sync site */
static nServers; /* total number of servers */
static char amIMagic=0; /* is this host the magic host */
+char amIClone=0; /* is this a clone which doesn't vote */
+static char ubik_singleServer = 0;
extern struct rx_securityClass *rxnull_NewClientSecurityObject();
int (*ubik_CRXSecurityProc)();
char *ubik_CRXSecurityRock;
register afs_int32 rcode;
/* special case for fast startup */
- if (nServers == 1) {
+ if (nServers == 1 && !amIClone) {
return 1; /* one guy is always the sync site */
}
- if (ubik_amSyncSite == 0) rcode = 0; /* if I don't think I'm the sync site, say so */
+ if (ubik_amSyncSite == 0 || amIClone) rcode = 0; /* if I don't think I'm the sync site, say so */
else {
now = FT_ApproxTime();
if (syncSiteUntil <= now) { /* if my votes have expired, say so */
* is sync site. Without the magic host hack, if anyone crashed in a 2
* site system, we'd be out of business.
*/
+ubeacon_InitServerListByInfo(ame, info, clones)
+ afs_int32 ame;
+ struct afsconf_cell *info;
+ char clones[];
+{
+ afs_int32 code;
+
+ code = ubeacon_InitServerListCommon(ame, info, clones, 0);
+ return code;
+}
+
ubeacon_InitServerList(ame, aservers)
afs_int32 ame;
- register afs_int32 aservers[]; {
+ register afs_int32 aservers[];
+{
+ afs_int32 code;
+
+ code = ubeacon_InitServerListCommon(ame, (struct afsconf_cell *)0, 0,
+ aservers);
+ return code;
+}
+
+ubeacon_InitServerListCommon(ame, info, clones, aservers)
+ afs_int32 ame;
+ struct afsconf_cell *info;
+ char clones[];
+ register afs_int32 aservers[];
+{
register struct ubik_server *ts;
+ afs_int32 me = -1;
register afs_int32 servAddr;
register afs_int32 i, code;
afs_int32 magicHost;
struct ubik_server *magicServer;
/* verify that the addresses passed in are correct */
- if ( code = verifyInterfaceAddress(&ame, aservers ))
+ if (code = verifyInterfaceAddress(&ame, info, aservers))
return code;
/* get the security index to use, if we can */
ubikSecIndex = 0;
ubikSecClass = rxnull_NewClientSecurityObject();
}
- i = 0;
magicHost = ntohl(ame); /* do comparisons in host order */
magicServer = (struct ubik_server *) 0;
- while (servAddr = *aservers++) {
- if (i >= MAXSERVERS) return UNHOSTS; /* too many hosts */
- ts = (struct ubik_server *) malloc(sizeof(struct ubik_server));
- bzero(ts, sizeof(struct ubik_server));
- ts->next = ubik_servers;
- ubik_servers = ts;
- ts->addr[0] = servAddr; /* primary address in net byte order */
- ts->vote_rxcid = rx_NewConnection(servAddr, ubik_callPortal, VOTE_SERVICE_ID, ubikSecClass, ubikSecIndex); /* for vote reqs */
- ts->disk_rxcid = rx_NewConnection(servAddr, ubik_callPortal, DISK_SERVICE_ID, ubikSecClass, ubikSecIndex); /* for disk reqs */
- ts->up = 1;
- if (ntohl((afs_uint32) servAddr) < (afs_uint32) magicHost) {
- magicHost = ntohl(servAddr);
- magicServer = ts;
+
+ if (info) {
+ for (i = 0; i < info->numServers; i++) {
+ if (ntohl((afs_uint32) info->hostAddr[i].sin_addr.s_addr) ==
+ ntohl((afs_uint32) ame)) {
+ me = i;
+ if (clones[i]) {
+ amIClone = 1;
+ magicHost = 0;
+ }
+ }
+ }
+ nServers = 0;
+ for (i = 0; i < info->numServers; i++) {
+ if (i == me) continue;
+ ts = (struct ubik_server *) malloc(sizeof(struct ubik_server));
+ bzero(ts, sizeof(struct ubik_server));
+ ts->next = ubik_servers;
+ ubik_servers = ts;
+ ts->addr[0] = info->hostAddr[i].sin_addr.s_addr;
+ if (clones[i]) {
+ ts->isClone = 1;
+ } else {
+ if (!magicHost ||
+ ntohl((afs_uint32) ts->addr[0]) < (afs_uint32) magicHost) {
+ magicHost = ntohl(ts->addr[0]);
+ magicServer = ts;
+ }
+ ++nServers;
+ }
+ ts->vote_rxcid = rx_NewConnection(servAddr, ubik_callPortal,
+ VOTE_SERVICE_ID,
+ ubikSecClass, ubikSecIndex); /* for vote reqs */
+ ts->disk_rxcid = rx_NewConnection(servAddr, ubik_callPortal,
+ DISK_SERVICE_ID, ubikSecClass,
+ ubikSecIndex); /* for disk reqs */
+ ts->up = 1;
+ }
+ } else {
+ i = 0;
+ while (servAddr = *aservers++) {
+ if (i >= MAXSERVERS) return UNHOSTS; /* too many hosts */
+ ts = (struct ubik_server *) malloc(sizeof(struct ubik_server));
+ bzero(ts, sizeof(struct ubik_server));
+ ts->next = ubik_servers;
+ ubik_servers = ts;
+ ts->addr[0] = servAddr; /* primary address in net byte order */
+ ts->vote_rxcid = rx_NewConnection(servAddr, ubik_callPortal,
+ VOTE_SERVICE_ID,
+ ubikSecClass, ubikSecIndex); /* for vote reqs */
+ ts->disk_rxcid = rx_NewConnection(servAddr, ubik_callPortal,
+ DISK_SERVICE_ID, ubikSecClass,
+ ubikSecIndex); /* for disk reqs */
+ ts->isClone = 0; /* don't know about clones */
+ ts->up = 1;
+ if (ntohl((afs_uint32) servAddr) < (afs_uint32) magicHost) {
+ magicHost = ntohl(servAddr);
+ magicServer = ts;
+ }
+ i++;
}
- i++;
}
if (magicServer) magicServer->magic = 1; /* remember for when counting votes */
- else amIMagic = 1;
- nServers = i+1; /* count this server as well as the remotes */
+
+ if (!amIClone && !magicServer) amIMagic = 1;
+ if (info) {
+ if (!amIClone)
+ ++nServers; /* count this server as well as the remotes */
+ } else
+ nServers = i+1; /* count this server as well as the remotes */
+
ubik_quorum = (nServers>>1)+1; /* compute the majority figure */
/* send addrs to all other servers */
code = updateUbikNetworkAddress(ubik_host);
r_retryInterval = 2;
r_nRetries = (RPCTIMEOUT/r_retryInterval);
*/
- if (nServers == 1) { /* special case 1 server */
+ if (info) {
+ if (!ubik_servers) /* special case 1 server */
+ ubik_singleServer = 1;
+ if (nServers == 1 && !amIClone) {
+ ubik_amSyncSite = 1; /* let's start as sync site */
+ syncSiteUntil = 0x7fffffff; /* and be it quite a while */
+ }
+ } else {
+ if (nServers == 1) /* special case 1 server */
+ ubik_singleServer = 1;
+ }
+
+ if (ubik_singleServer) {
if (!ubik_amSyncSite) ubik_dprint("Ubik: I am the sync site - 1 server\n");
ubik_amSyncSite = 1;
syncSiteUntil = 0x7fffffff; /* quite a while */
lastWakeupTime = FT_ApproxTime(); /* started a new collection phase */
- if (nServers == 1) continue; /* special-case 1 server for speedy startup */
+ if (ubik_singleServer) continue; /* special-case 1 server for speedy startup */
if (!uvote_ShouldIRun()) continue; /* if voter has heard from a better candidate than us, don't bother running */
prepare to send them an r multi-call containing the beacon message */
i = 0; /* collect connections */
for(ts = ubik_servers; ts; ts=ts->next) {
- if (ts->up && ts->addr[0] != ubik_host[0]) {
+ if (ts->up && ts->addr[0] != ubik_host[0]) {
servers[i] = ts;
connections[i++] = ts->vote_rxcid;
}
ts->lastVoteTime = code;
if (code < oldestYesVote) oldestYesVote = code;
ts->lastVote = 1;
- yesVotes += 2;
+ if (!ts->isClone)
+ yesVotes += 2;
if (ts->magic) yesVotes++; /* the extra epsilon */
ts->up = 1; /* server is up (not really necessary: recovery does this for real) */
ts->beaconSinceDown = 1;
*
* Return Values : 0 on success, non-zero on failure
*/
-verifyInterfaceAddress(ame, aservers)
-afs_uint32 *ame; /* one of my interface addr in net byte order */
-afs_uint32 aservers[]; /* list of all possible server addresses */
+static verifyInterfaceAddress(ame, info, aservers)
+ struct afsconf_cell *info;
+ afs_uint32 aservers[]; /* list of all possible server addresses */
+ afs_uint32 *ame; /* one of my interface addr in net byte order */
{
- afs_uint32 myAddr[UBIK_MAX_INTERFACE_ADDR], *servList;
+ afs_uint32 myAddr[UBIK_MAX_INTERFACE_ADDR], *servList, tmpAddr;
int count, index, found, i, j, totalServers, start, end;
- /* count the number of servers */
- for ( totalServers=0, servList = aservers; *servList; servList++)
- totalServers++;
+ if (info)
+ totalServers = info->numServers;
+ else { /* count the number of servers */
+ for ( totalServers=0, servList = aservers; *servList; servList++)
+ totalServers++;
+ }
#ifdef AFS_NT40_ENV
/* for now use getaddr(). use getAllAddr when implemented */
*/
for ( j=0, found = 0; j < count; j++)
{
- for ( i=0; i < totalServers; i++)
- if ( myAddr[j] == aservers[i] )
- {
- *ame = aservers[i];
- aservers[i] = 0 ;
+ for ( i=0; i < totalServers; i++) {
+ if (info)
+ tmpAddr = ntohl((afs_uint32) info->hostAddr[i].sin_addr.s_addr);
+ else
+ tmpAddr = aservers[i];
+ if ( myAddr[j] == tmpAddr) {
+ *ame = tmpAddr;
+ if (!info)
+ aservers[i] = 0 ;
found = 1;
}
+ }
}
if ( found )
ubik_print("Using %s as my primary address\n", afs_inet_ntoa(*ame) );
- /* get rid of servers which were purged because all
- ** those interface addresses are myself
- */
- for ( start=0, end=totalServers-1; (start<end) ; start++, end--)
- {
- /* find the first zero entry from the beginning */
- for ( ; (start < end) && ( aservers[start] ); start++);
-
- /* find the last non-zero entry from the end */
- for ( ; (end >= 0) && ( !aservers[end] ); end-- );
-
- /* if there is nothing more to purge, exit from loop */
- if ( start >= end ) break;
+ if (!info) {
+ /* get rid of servers which were purged because all
+ ** those interface addresses are myself
+ */
+ for ( start=0, end=totalServers-1; (start<end) ; start++, end--)
+ {
+ /* find the first zero entry from the beginning */
+ for ( ; (start < end) && ( aservers[start] ); start++);
+
+ /* find the last non-zero entry from the end */
+ for ( ; (end >= 0) && ( !aservers[end] ); end-- );
+
+ /* if there is nothing more to purge, exit from loop */
+ if ( start >= end ) break;
- /* move the entry */
- aservers[start] = aservers[end];
- aservers[end] = 0; /* this entry was moved */
+ /* move the entry */
+ aservers[start] = aservers[end];
+ aservers[end] = 0; /* this entry was moved */
+ }
}
/* update all my addresses in ubik_host in such a way
bestDBVersion.counter = 0;
for(ts=ubik_servers; ts; ts=ts->next) {
if (!ts->up) continue; /* don't bother with these guys */
+ if (ts->isClone) continue;
code = DISK_GetVersion(ts->disk_rxcid, &ts->version);
if (code == 0) {
/* perhaps this is the best version */
#include <lock.h>
#include <rx/xdr.h>
#include <rx/rx.h>
+#include <afs/cellconfig.h>
#define UBIK_INTERNALS
#include "ubik.h"
ts->beaconSinceDown = 0;
urecovery_LostServer(); /* tell recovery to try to resend dbase later */
} else { /* success */
- okcalls++; /* count up how many worked */
+ if (!ts->isClone)
+ okcalls++; /* count up how many worked */
if (aflags & CStampVersion) {
ts->version = atrans->dbase->version;
}
Note that the host named by myHost should not also be listed in serverList.
*/
+int ubik_ServerInitByInfo(myHost, myPort, info, clones, pathName, dbase)
+ struct afsconf_cell *info; /* in */
+ char clones[];
+ afs_int32 myHost;
+ short myPort;
+ char *pathName; /* in */
+ struct ubik_dbase **dbase; /* out */
+{
+ afs_int32 code;
+
+ code = ubik_ServerInitCommon(myHost, myPort, info, clones, 0, pathName, dbase);
+ return code;
+}
+
int ubik_ServerInit(myHost, myPort, serverList, pathName, dbase)
+ afs_int32 serverList[]; /* in */
afs_int32 myHost;
short myPort;
+ char *pathName; /* in */
+ struct ubik_dbase **dbase; /* out */
+{
+ afs_int32 code;
+
+ code = ubik_ServerInitCommon(myHost, myPort, (struct afsconf_cell *)0, 0,
+ serverList, pathName, dbase);
+ return code;
+}
+
+int ubik_ServerInitCommon(myHost, myPort, info, clones, serverList, pathName, dbase)
+ afs_int32 myHost;
+ short myPort;
+ struct afsconf_cell *info; /* in */
+ char clones[];
afs_int32 serverList[]; /* in */
char *pathName; /* in */
- struct ubik_dbase **dbase; /* out */ {
+ struct ubik_dbase **dbase; /* out */
+{
register struct ubik_dbase *tdb;
register afs_int32 code;
PROCESS junk;
if (code) return code;
code = urecovery_Initialize(tdb);
if (code) return code;
- code = ubeacon_InitServerList(myHost, serverList);
+ if (info)
+ code = ubeacon_InitServerListByInfo(myHost, info, clones);
+ else
+ code = ubeacon_InitServerList(myHost, serverList);
if (code) return code;
/* now start up async processes */
char beaconSinceDown; /* did beacon get through since last crash? */
char currentDB; /* is dbase up-to-date */
char magic; /* the one whose vote counts twice */
+ char isClone; /* is only a clone, doesn't vote */
};
/* hold and release functions on a database */
/* list of all servers in the system */
extern struct ubik_server *ubik_servers;
+extern char amIClone;
/* network port info */
extern short ubik_callPortal;
#define VOTE_GETSYNCSITE 10003
#define VOTE_DEBUG 10004
#define VOTE_SDEBUG 10005
+#define VOTE_XDEBUG 10006
+#define VOTE_XSDEBUG 10007
/* Vote package interface calls */
Beacon (IN afs_int32 state,
SDebug (IN afs_int32 which,
OUT ubik_sdebug *db) = VOTE_SDEBUG;
+XDebug (OUT ubik_debug *db,
+ OUT afs_int32 *isClone) = VOTE_XDEBUG;
+
+XSDebug (IN afs_int32 which,
+ OUT ubik_sdebug *db,
+ OUT afs_int32 *isClone) = VOTE_XSDEBUG;
+
/* This package handles calls used to pass writes, begins and ends to other servers */
package DISK_
statindex 12
struct ubik_debug udebug;
struct ubik_sdebug usdebug;
int oldServer =0; /* are we talking to a pre 3.5 server? */
+ afs_int32 isClone = 0;
int32p = (as->parms[2].items ? 1 : 0);
tconn = rx_NewConnection(hostAddr, port, VOTE_SERVICE_ID, sc, 0);
/* now do the main call */
- code = VOTE_Debug(tconn, &udebug);
+ code = VOTE_XDebug(tconn, &udebug, &isClone);
+ if (code) code = VOTE_Debug(tconn, &udebug);
if ( code == RXGEN_OPCODE )
{
oldServer = 1; /* talking to a pre 3.5 server */
udebug.epochTime, udebug.tidCounter);
}
} else {
- printf("I am not sync site\n");
+ if (isClone)
+ printf("I am a clone and never can become sync site\n");
+ else
+ printf("I am not sync site\n");
inhostAddr.s_addr = htonl(udebug.lowestHost);
diff = udebug.now - udebug.lowestTime;
printf("Lowest host %s was set %d secs ago\n", inet_ntoa(inhostAddr), diff);
if (int32p || udebug.amSyncSite) {
/* now do the subcalls */
for(i=0;;i++) {
- if ( oldServer )
- { /* pre 3.5 server */
- memset(&usdebug, 0, sizeof(usdebug));
- code = VOTE_SDebugOld(tconn, i, &usdebug);
+ isClone = 0;
+ code = VOTE_XSDebug(tconn, i, &usdebug, &isClone);
+ if (code < 0) {
+ if ( oldServer ) { /* pre 3.5 server */
+ memset(&usdebug, 0, sizeof(usdebug));
+ code = VOTE_SDebugOld(tconn, i, &usdebug);
+ }
+ else
+ code = VOTE_SDebug(tconn, i, &usdebug);
}
- else
- code = VOTE_SDebug(tconn, i, &usdebug);
if (code > 0) break; /* done */
if (code < 0) {
printf("error code %d from VOTE_SDebug\n", code);
}
inhostAddr.s_addr = htonl(usdebug.addr);
/* otherwise print the structure */
- printf("\nServer( %s", afs_inet_ntoa(htonl(usdebug.addr)));
+ printf("\nServer (%s", afs_inet_ntoa(htonl(usdebug.addr)));
for ( j=0;((usdebug.altAddr[j]) &&
(j<UBIK_MAX_INTERFACE_ADDR-1)); j++)
printf(" %s", afs_inet_ntoa(htonl(usdebug.altAddr[j])));
- printf(" ): (db %d.%d)\n",
+ printf("): (db %d.%d)",
usdebug.remoteVersion.epoch, usdebug.remoteVersion.counter);
+ if (isClone)
+ printf(" is only a clone!");
+ printf("\n");
if (usdebug.lastVoteTime == 0) {
printf(" last vote never rcvd \n");
afs_int32 vote;
struct rx_connection *aconn;
struct rx_peer *rxp;
+ struct ubik_server *ts;
+ int isClone = 0;
now = FT_ApproxTime(); /* close to current time */
if (rxcall) { /* caller's host */
afs_inet_ntoa(rx_HostOf(rxp)));
return 0; /* I don't know about you: vote no */
}
- } else
+ for (ts = ubik_servers; ts; ts = ts->next) {
+ if (ts->addr[0] == otherHost) break;
+ }
+ if (!ts) ubik_dprint("Unknown host %x has sent a beacon\n", otherHost);
+ if (ts && ts->isClone) isClone = 1;
+ } else {
otherHost = ubik_host[0]; /* this host */
+ isClone = amIClone;
+ }
ubik_dprint("Received beacon type %d from host %s\n", astate,
afs_inet_ntoa(otherHost));
seconds, we ignore its presence in lowestHost: it may have crashed.
Note that we don't ever let anyone appear in our lowestHost if we're
lower than them, 'cause we know we're up. */
- if (ntohl((afs_uint32) otherHost) <= ntohl((afs_uint32) lowestHost)
- || lowestTime + BIGTIME < now) {
+ /* But do not consider clones for lowesHost since they never may become
+ sync site */
+ if (!isClone &&
+ (ntohl((afs_uint32) otherHost) <= ntohl((afs_uint32) lowestHost)
+ || lowestTime + BIGTIME < now)) {
lowestTime = now;
lowestHost = otherHost;
}
lowest. Need to prove: if one guy in the system is lowest and knows
he's lowest, these loops don't occur. because if someone knows he's
lowest, he will send out beacons telling others to vote for him. */
- if (ntohl((afs_uint32) ubik_host[0]) <= ntohl((afs_uint32) lowestHost)
- || lowestTime + BIGTIME < now) {
+ if (!amIClone &&
+ (ntohl((afs_uint32) ubik_host) <= ntohl((afs_uint32) lowestHost)
+ || lowestTime + BIGTIME < now)) {
lowestTime = now;
lowestHost = ubik_host[0];
}
/* someone else *is* a sync site, just say no */
if (syncHost && syncHost != otherHost)
return 0;
+ } else /* fast startup if this is the only non-clone */
+ if (lastYesHost == 0xffffffff && otherHost == ubik_host[0]) {
+ int i = 0;
+ for (ts = ubik_servers; ts; ts = ts->next) {
+ if (ts->addr[0] == otherHost) continue;
+ if (!ts->isClone) i++;
+ }
+ if (!i) lastYesHost = otherHost;
}
+
+
+ if (isClone) return 0; /* clone never can become sync site */
/* Don't promise sync site support to more than one host every BIGTIME
seconds. This is the heart of our invariants in this system. */
SVOTE_SDebug(rxcall, awhich, aparm)
struct rx_call *rxcall;
afs_int32 awhich;
- register struct ubik_sdebug *aparm; {
+ register struct ubik_sdebug *aparm;
+{
+ afs_int32 code, isClone;
+ code = SVOTE_XSDebug(rxcall, awhich, aparm, &isClone);
+ return code;
+}
+
+SVOTE_XSDebug(rxcall, awhich, aparm, isclone)
+ afs_int32 *isclone;
+ struct rx_call *rxcall;
+ afs_int32 awhich;
+ register struct ubik_sdebug *aparm;
+{
register struct ubik_server *ts;
register int i;
for(ts=ubik_servers; ts; ts=ts->next) {
aparm->up = ts->up;
aparm->beaconSinceDown = ts->beaconSinceDown;
aparm->currentDB = ts->currentDB;
+ *isclone = ts->isClone;
return 0;
}
}
return 2;
}
+SVOTE_XDebug(rxcall, aparm, isclone)
+ struct rx_call *rxcall;
+ register struct ubik_debug *aparm;
+ afs_int32 *isclone;
+{
+ afs_int32 code;
+
+ code = SVOTE_Debug(rxcall, aparm);
+ *isclone = amIClone;
+ return code;
+}
/* handle basic network debug command. This is the global state dumper */
SVOTE_Debug(rxcall, aparm)
char **argv;
{
register afs_int32 code;
- afs_int32 serverList[MAXSERVERS];
afs_int32 myHost;
struct rx_service *tservice;
struct rx_securityClass *sc[3];
int noAuth = 0, index, i;
extern int rx_extraPackets;
char commandLine[150];
-
+ char clones[MAXHOSTSPERCELL];
+
#ifdef AFS_AIX32_ENV
/*
* The following signal action for AIX is necessary so that in case of a
signal(SIGXCPU, CheckSignal_Signal);
#endif
/* get list of servers */
- code = afsconf_GetCellInfo(tdir,(char *)0, AFSCONF_VLDBSERVICE,&info);
+ code = afsconf_GetExtendedCellInfo(tdir,(char *)0, AFSCONF_VLDBSERVICE,
+ &info, &clones);
if (code) {
printf("vlserver: Couldn't get cell server list for 'afsvldb'.\n");
exit(2);
}
- for (index=0,i = 0;index<info.numServers;index++)
- if (info.hostAddr[index].sin_addr.s_addr != myHost) /* ubik already tacks myHost onto list */
- serverList[i++] = info.hostAddr[index].sin_addr.s_addr;
- serverList[i] = 0;
vldb_confdir = tdir; /* Preserve our configuration dir */
/* rxvab no longer supported */
ubik_SRXSecurityRock = (char *) tdir;
ubik_CheckRXSecurityProc = afsconf_CheckAuth;
ubik_CheckRXSecurityRock = (char *) tdir;
- code = ubik_ServerInit(myHost, htons(AFSCONF_VLDBPORT), serverList, vl_dbaseName, &VL_dbase);
+ code = ubik_ServerInitByInfo(myHost, htons(AFSCONF_VLDBPORT), &info,
+ &clones, vl_dbaseName, &VL_dbase);
if (code) {
printf("vlserver: Ubik init failed with code %d\n",code);
exit(2);