* directory or online at http://www.openafs.org/dl/license10.html
*/
+#include <afsconfig.h>
#include <afs/param.h>
+
+RCSID("$Header$");
+
#include <sys/types.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#endif
#include <errno.h>
#include <lock.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
#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;
afs_int32 ubikSecIndex;
struct rx_securityClass *ubikSecClass;
+static verifyInterfaceAddress();
/* Module responsible for both deciding if we're currently the sync site,
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));
+ memset(ts, 0, 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;
+ }
+ /* for vote reqs */
+ ts->vote_rxcid = rx_NewConnection(info->hostAddr[i].sin_addr.s_addr,
+ ubik_callPortal,
+ VOTE_SERVICE_ID,
+ ubikSecClass, ubikSecIndex);
+ /* for disk reqs */
+ ts->disk_rxcid = rx_NewConnection(info->hostAddr[i].sin_addr.s_addr,
+ ubik_callPortal,
+ DISK_SERVICE_ID, ubikSecClass,
+ ubikSecIndex);
+ 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));
+ memset(ts, 0, 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;
/* now call our own voter module to see if we'll vote for ourself. Note that
the same restrictions apply for our voting for ourself as for our voting
for anyone else. */
- i = SVOTE_Beacon((struct rx_connection *) 0, ubeacon_AmSyncSite(), startTime, &ubik_dbase->version, &ttid);
+ i = SVOTE_Beacon((struct rx_call *) 0, ubeacon_AmSyncSite(), startTime, &ubik_dbase->version, &ttid);
if (i) {
yesVotes += 2;
if (amIMagic) yesVotes++; /* extra epsilon */
*
* 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)
+ afs_uint32 *ame; /* one of my interface addr in net byte order */
+ struct afsconf_cell *info;
+ afs_uint32 aservers[]; /* list of all possible server addresses */
{
- afs_uint32 myAddr[UBIK_MAX_INTERFACE_ADDR], *servList;
- int count, index, found, i, j, totalServers, start, end;
-
- /* count the number of servers */
- for ( totalServers=0, servList = aservers; *servList; servList++)
- totalServers++;
+ afs_uint32 myAddr[UBIK_MAX_INTERFACE_ADDR], *servList, tmpAddr;
+ afs_uint32 myAddr2[UBIK_MAX_INTERFACE_ADDR];
+ int count, found, i, j, totalServers, start, end, usednetfiles = 0;
+
+ 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 */
ubik_print("Aborting..\n");
return UBADHOST;
}
+ usednetfiles++;
}
else {
/* get all my interface addresses in net byte order */
{
ubik_print("ubik: primary address %s does not exist\n",
afs_inet_ntoa(*ame));
- return UBADHOST;
+ /* if we had the result of rx_getAllAddr already, avoid subverting
+ the "is gethostbyname(gethostname()) us" check. If we're
+ using NetInfo/NetRestrict, we assume they have enough clue
+ to avoid that big hole in their foot from the loaded gun. */
+ if (usednetfiles) {
+ /* take the address we did get, then see if ame was masked */
+ *ame=myAddr[0];
+ count = rx_getAllAddr(myAddr2, UBIK_MAX_INTERFACE_ADDR);
+ if ( count <= 0 ) /* no address found */
+ {
+ ubik_print("ubik: No network addresses found, aborting..");
+ return UBADHOST;
+ }
+
+ /* verify that the My-address passed in by ubik is correct */
+ for ( j=0, found = 0; j < count; j++)
+ {
+ if ( *ame == myAddr2[j] ) /* both in net byte order */
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+ if ( !found )
+ return UBADHOST;
}
/* if any of my addresses are there in serverList, then
*/
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
updateUbikNetworkAddress(ubik_host)
afs_uint32 ubik_host[UBIK_MAX_INTERFACE_ADDR];
{
- int j, count, found, index, code = 0;
+ int j, count, code = 0;
UbikInterfaceAddr inAddr, outAddr;
struct rx_connection *conns[MAXSERVERS];
struct ubik_server *ts, *server[MAXSERVERS];
code = UBADHOST; /* remote CellServDB inconsistency */
ubik_print("Inconsistent Cell Info on server: ");
for ( j=0; j < UBIK_MAX_INTERFACE_ADDR && ts->addr[j]; j++)
- printf("%s ", afs_inet_ntoa(ts->addr[j]));
- printf("\n");
- fflush(stdout); fflush(stderr);
+ ubik_print("%s ", afs_inet_ntoa(ts->addr[j]));
+ ubik_print("\n");
}
else {
ts->up= 0; /* mark the remote server as down */