ubik-clone-support-20010212
authorHartmut Reuter <reuter@rzg.mpg.de>
Mon, 12 Feb 2001 21:57:57 +0000 (21:57 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 12 Feb 2001 21:57:57 +0000 (21:57 +0000)
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

13 files changed:
src/auth/cellconfig.c
src/auth/writeconfig.c
src/bozo/bos.c
src/kauth/kaserver.c
src/ptserver/ptserver.c
src/ubik/beacon.c
src/ubik/recovery.c
src/ubik/ubik.c
src/ubik/ubik.p.h
src/ubik/ubik_int.xg
src/ubik/udebug.c
src/ubik/vote.c
src/vlserver/vlserver.c

index 4a31cac..81f78dd 100644 (file)
@@ -218,7 +218,7 @@ register char *adir; {
     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];
 
@@ -272,7 +272,7 @@ register char *adir; {
        }
        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);
@@ -322,8 +322,11 @@ static int GetCellNT(struct afsconf_dir *adir)
 #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;
@@ -409,7 +412,10 @@ register struct afsconf_dir *adir; {
                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 */
@@ -442,17 +448,26 @@ register struct afsconf_dir *adir; {
 }
 
 /* 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;
@@ -501,6 +516,30 @@ char *arock; {
 }
 
 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;
@@ -520,8 +559,8 @@ struct afsconf_cell *acellInfo; {
        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) {
@@ -643,7 +682,7 @@ register struct afsconf_dir *adir; {
     register afs_int32 code;
     code = afsconf_CloseInternal(adir);
     if (code) return code;
-    code = afsconf_OpenInternal(adir);
+    code = afsconf_OpenInternal(adir, 0, 0);
     return code;
 }
 
index 925cf99..9e0d81f 100644 (file)
@@ -74,7 +74,20 @@ register struct afsconf_cell *aci; {
 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];
@@ -121,7 +134,10 @@ struct afsconf_cell *acellInfo; {
        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);
index f6c1085..f487335 100644 (file)
@@ -707,10 +707,21 @@ register struct cmd_syndesc *as; {
     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));
     }
@@ -1885,6 +1896,7 @@ main(argc, argv)
     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,
index e3374ee..3bb2cf3 100644 (file)
@@ -156,6 +156,8 @@ main (argc, argv)
     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];
@@ -282,15 +284,21 @@ main (argc, argv)
     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));
@@ -313,8 +321,13 @@ main (argc, argv)
     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);
index 291251f..e29fe7c 100644 (file)
@@ -64,7 +64,6 @@ void main (argc, argv)
   char **argv;
 {
     register afs_int32 code;
-    afs_int32 serverList[MAXSERVERS];
     afs_int32 myHost;
     register struct hostent *th;
     char hostname[64];
@@ -81,6 +80,7 @@ void main (argc, argv)
     int kerberosKeys;                  /* set if found some keys */
     afs_int32 i,j;
     int lwps = 3;
+    char clones[MAXHOSTSPERCELL];
 
     const char *pr_dbaseName;
     char *whoami = "ptserver";
@@ -189,7 +189,8 @@ void main (argc, argv)
     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);
@@ -197,11 +198,6 @@ void main (argc, argv)
     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);
@@ -234,8 +230,8 @@ void main (argc, argv)
      * 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);
index 63687fa..59fb4c8 100644 (file)
@@ -24,6 +24,7 @@
 #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>
@@ -38,6 +39,8 @@ static afs_int32 syncSiteUntil = 0;       /* valid only if amSyncSite */
 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;
@@ -91,11 +94,11 @@ ubeacon_AmSyncSite() {
     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 */
@@ -127,17 +130,43 @@ ubeacon_AmSyncSite() {
  * 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 */
@@ -150,28 +179,79 @@ ubeacon_InitServerList(ame, aservers)
        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);
@@ -182,7 +262,19 @@ ubeacon_InitServerList(ame, aservers)
     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 */
@@ -222,7 +314,7 @@ ubeacon_Interact() {
 
        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 */
 
@@ -233,7 +325,7 @@ ubeacon_Interact() {
            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;
            }
@@ -279,7 +371,8 @@ ubeacon_Interact() {
                    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;
@@ -340,16 +433,20 @@ ubeacon_Interact() {
 *
 * 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 */
@@ -407,34 +504,41 @@ afs_uint32 aservers[];    /* list of all possible server addresses */
     */
     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 
index c3aa09c..6de9dcc 100644 (file)
@@ -425,6 +425,7 @@ urecovery_Interact() {
            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 */
index 4b6618d..7911633 100644 (file)
@@ -20,6 +20,7 @@
 #include <lock.h>
 #include <rx/xdr.h>
 #include <rx/rx.h>
+#include <afs/cellconfig.h>
 
 #define UBIK_INTERNALS
 #include "ubik.h"
@@ -145,7 +146,8 @@ afs_int32 ContactQuorum(aproc, atrans, aflags, aparm0, aparm1, aparm2, aparm3, a
            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;
            }
@@ -161,12 +163,43 @@ afs_int32 ContactQuorum(aproc, atrans, aflags, aparm0, aparm1, aparm2, aparm3, a
     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;
@@ -245,7 +278,10 @@ int ubik_ServerInit(myHost, myPort, serverList, pathName, dbase)
     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 */
index e0c681a..bf75fbc 100644 (file)
@@ -248,6 +248,7 @@ struct ubik_server {
     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 */
@@ -258,6 +259,7 @@ struct ubik_server {
 
 /* list of all servers in the system */
 extern struct ubik_server *ubik_servers;
+extern char amIClone;
 
 /* network port info */
 extern short ubik_callPortal;
index 36bde69..df8e7f7 100644 (file)
@@ -167,6 +167,8 @@ statindex 11
 #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,
@@ -186,6 +188,13 @@ Debug              (OUT ubik_debug *db) = VOTE_DEBUG;
 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
index 71602b1..2586248 100644 (file)
@@ -86,6 +86,7 @@ struct cmd_syndesc *as; {
     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);
 
@@ -128,7 +129,8 @@ struct cmd_syndesc *as; {
     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 */
@@ -205,7 +207,10 @@ struct cmd_syndesc *as; {
                   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);
@@ -239,13 +244,16 @@ struct cmd_syndesc *as; {
     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);
@@ -253,12 +261,15 @@ struct cmd_syndesc *as; {
            }
            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");
index 1739fe5..3d9eb89 100644 (file)
@@ -172,6 +172,8 @@ SVOTE_Beacon(rxcall, astate, astart, avers, atid)
     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 */
@@ -188,8 +190,15 @@ SVOTE_Beacon(rxcall, astate, astart, avers, atid)
                                        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));
@@ -211,8 +220,11 @@ SVOTE_Beacon(rxcall, astate, astart, avers, atid)
        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;
     }
@@ -223,8 +235,9 @@ SVOTE_Beacon(rxcall, astate, astart, avers, atid)
        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];
     }
@@ -261,7 +274,18 @@ SVOTE_Beacon(rxcall, astate, astart, avers, atid)
        /* 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. */
@@ -293,7 +317,19 @@ SVOTE_Beacon(rxcall, astate, astart, avers, atid)
 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) {
@@ -309,12 +345,24 @@ SVOTE_SDebug(rxcall, awhich, aparm)
            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)
index e57e410..6f17df5 100644 (file)
@@ -106,7 +106,6 @@ int argc;
 char   **argv;
 {
     register afs_int32   code;
-    afs_int32      serverList[MAXSERVERS];
     afs_int32              myHost;
     struct rx_service      *tservice;
     struct rx_securityClass *sc[3];
@@ -121,7 +120,8 @@ char        **argv;
     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 
@@ -214,15 +214,12 @@ char      **argv;
     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 */
@@ -237,7 +234,8 @@ char        **argv;
     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);