/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
+#include <roken.h>
#include <sys/types.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#include <time.h>
#include <netinet/in.h>
#include <netdb.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/rxkad.h>
#include <rx/rx_multi.h>
#include <afs/cellconfig.h>
#ifndef AFS_NT40_ENV
#include "ubik.h"
#include "ubik_int.h"
-/* statics used to determine if we're the sync site */
-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 */
+/*! \name statics used to determine if we're the sync site */
+static afs_int32 syncSiteUntil = 0; /*!< valid only if amSyncSite */
+int ubik_amSyncSite = 0; /*!< flag telling if I'm sync site */
+static int 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;
-int (*ubik_CRXSecurityProc) ();
-char *ubik_CRXSecurityRock;
+/*\}*/
+int (*ubik_CRXSecurityProc) (void *rock, struct rx_securityClass **,
+ afs_int32 *);
+void *ubik_CRXSecurityRock;
afs_int32 ubikSecIndex;
struct rx_securityClass *ubikSecClass;
-static verifyInterfaceAddress();
+static int ubeacon_InitServerListCommon(afs_uint32 ame,
+ struct afsconf_cell *info,
+ char clones[],
+ afs_uint32 aservers[]);
+static int verifyInterfaceAddress(afs_uint32 *ame, struct afsconf_cell *info,
+ afs_uint32 aservers[]);
+static int updateUbikNetworkAddress(afs_uint32 ubik_host[UBIK_MAX_INTERFACE_ADDR]);
-/* Module responsible for both deciding if we're currently the sync site,
+/*! \file
+ * Module responsible for both deciding if we're currently the sync site,
* and keeping collecting votes so as to stay sync site.
*
* The basic module contacts all of the servers it can, trying to get them to vote
* not to vote for someone else. This parameter (BIG seconds) is not actually passed in
* the interface (perhaps it should be?) but is instead a compile time constant that both
* sides know about.
-
+
* The beacon and vote modules work intimately together; the vote module decides how long
* it should promise the beacon module its vote, and the beacon module takes all of these
* votes and decides for how long it is the synchronization site.
*/
-/* procedure called from debug rpc call to get this module's state for debugging */
-ubeacon_Debug(aparm)
- register struct ubik_debug *aparm;
+/*! \brief procedure called from debug rpc call to get this module's state for debugging */
+void
+ubeacon_Debug(struct ubik_debug *aparm)
{
/* fill in beacon's state fields in the ubik_debug structure */
aparm->syncSiteUntil = syncSiteUntil;
aparm->nServers = nServers;
}
-/* procedure that determines whether this site has enough current votes to remain sync site.
- * called from higher-level modules (everything but the vote module).
+/*!
+ * \brief Procedure that determines whether this site has enough current votes to remain sync site.
*
- * If we're the sync site, check that our guarantees, obtained by the ubeacon_Interact
+ * Called from higher-level modules (everything but the vote module).
+ *
+ * If we're the sync site, check that our guarantees, obtained by the ubeacon_Interact()
* light-weight process, haven't expired. We're sync site as long as a majority of the
- * servers in existence have promised us unexpired guarantees. The variable ubik_syncSiteUntil
+ * servers in existence have promised us unexpired guarantees. The variable #ubik_syncSiteUntil
* contains the time at which the latest of the majority of the sync site guarantees expires
- * (if the variable ubik_amSyncSite is true)
+ * (if the variable #ubik_amSyncSite is true)
* This module also calls up to the recovery module if it thinks that the recovery module
- * may have to pick up a new database (which offucr sif we lose the sync site votes).
+ * may have to pick up a new database (which offucr sif [sic] we lose the sync site votes).
+ *
+ * \return 1 if local site is the sync site
+ * \return 0 if sync site is elsewhere
*/
-ubeacon_AmSyncSite()
+int
+ubeacon_AmSyncSite(void)
{
- register afs_int32 now;
- register afs_int32 rcode;
+ afs_int32 now;
+ afs_int32 rcode;
/* special case for fast startup */
if (nServers == 1 && !amIClone) {
return rcode;
}
-/* setup server list; called with two parms, first is my address, second is list of other servers
- * called only at initialization to set up the list of servers to contact for votes. Just creates
- * the server structure. Note that there are two connections in every server structure, one for
- * vote calls (which must always go through quickly) and one for database operations, which
- * are subject to waiting for locks. If we used only one, the votes would sometimes get
- * held up behind database operations, and the sync site guarantees would timeout
- * even though the host would be up for communication.
- *
- * The "magic" host is the one with the lowest internet address. It is
- * magic because its vote counts epsilon more than the others. This acts
- * as a tie-breaker when we have an even number of hosts in the system.
- * For example, if the "magic" host is up in a 2 site system, then it
- * is sync site. Without the magic host hack, if anyone crashed in a 2
- * site system, we'd be out of business.
+/*!
+ * \see ubeacon_InitServerListCommon()
*/
-ubeacon_InitServerListByInfo(ame, info, clones)
- afs_int32 ame;
- struct afsconf_cell *info;
- char clones[];
+int
+ubeacon_InitServerListByInfo(afs_uint32 ame, struct afsconf_cell *info,
+ char clones[])
{
afs_int32 code;
return code;
}
-ubeacon_InitServerList(ame, aservers)
- afs_int32 ame;
- register afs_int32 aservers[];
+/*!
+ * \param ame "address of me"
+ * \param aservers list of other servers
+ *
+ * \see ubeacon_InitServerListCommon()
+ */
+int
+ubeacon_InitServerList(afs_uint32 ame, afs_uint32 aservers[])
{
afs_int32 code;
return code;
}
-ubeacon_InitServerListCommon(ame, info, clones, aservers)
- afs_int32 ame;
- struct afsconf_cell *info;
- char clones[];
- register afs_int32 aservers[];
+void
+ubeacon_InitSecurityClass(void)
{
- 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, info, aservers)))
- return code;
-
+ int i;
/* get the security index to use, if we can */
if (ubik_CRXSecurityProc) {
i = (*ubik_CRXSecurityProc) (ubik_CRXSecurityRock, &ubikSecClass,
ubikSecIndex = 0;
ubikSecClass = rxnull_NewClientSecurityObject();
}
+}
+
+void
+ubeacon_ReinitServer(struct ubik_server *ts)
+{
+ if (!afsconf_UpToDate(ubik_CRXSecurityRock)) {
+ struct rx_connection *disk_rxcid;
+ struct rx_connection *vote_rxcid;
+ struct rx_connection *tmp;
+ ubeacon_InitSecurityClass();
+ disk_rxcid =
+ rx_NewConnection(rx_HostOf(rx_PeerOf(ts->disk_rxcid)),
+ ubik_callPortal, DISK_SERVICE_ID,
+ ubikSecClass, ubikSecIndex);
+ if (disk_rxcid) {
+ tmp = ts->disk_rxcid;
+ ts->disk_rxcid = disk_rxcid;
+ rx_PutConnection(tmp);
+ }
+ vote_rxcid =
+ rx_NewConnection(rx_HostOf(rx_PeerOf(ts->vote_rxcid)),
+ ubik_callPortal, VOTE_SERVICE_ID,
+ ubikSecClass, ubikSecIndex);
+ if (vote_rxcid) {
+ tmp = ts->vote_rxcid;
+ ts->vote_rxcid = vote_rxcid;
+ rx_PutConnection(tmp);
+ }
+ }
+}
+
+/*!
+ * \brief setup server list
+ *
+ * \param ame "address of me"
+ * \param aservers list of other servers
+ *
+ * called only at initialization to set up the list of servers to
+ * contact for votes. Just creates the server structure.
+ *
+ * The "magic" host is the one with the lowest internet address. It is
+ * magic because its vote counts epsilon more than the others. This acts
+ * as a tie-breaker when we have an even number of hosts in the system.
+ * For example, if the "magic" host is up in a 2 site system, then it
+ * is sync site. Without the magic host hack, if anyone crashed in a 2
+ * site system, we'd be out of business.
+ *
+ * \note There are two connections in every server structure, one for
+ * vote calls (which must always go through quickly) and one for database
+ * operations, which are subject to waiting for locks. If we used only
+ * one, the votes would sometimes get held up behind database operations,
+ * and the sync site guarantees would timeout even though the host would be
+ * up for communication.
+ *
+ * \see ubeacon_InitServerList(), ubeacon_InitServerListByInfo()
+ */
+int
+ubeacon_InitServerListCommon(afs_uint32 ame, struct afsconf_cell *info,
+ char clones[], afs_uint32 aservers[])
+{
+ struct ubik_server *ts;
+ afs_int32 me = -1;
+ afs_int32 servAddr;
+ afs_int32 i, code;
+ afs_int32 magicHost;
+ struct ubik_server *magicServer;
+
+ /* verify that the addresses passed in are correct */
+ if ((code = verifyInterfaceAddress(&ame, info, aservers)))
+ return code;
+
+ ubeacon_InitSecurityClass();
+
magicHost = ntohl(ame); /* do comparisons in host order */
magicServer = (struct ubik_server *)0;
return code;
/* Shoud we set some defaults for RX??
- r_retryInterval = 2;
+ r_retryInterval = 2;
r_nRetries = (RPCTIMEOUT/r_retryInterval);
*/
if (info) {
return 0;
}
-/* main lwp loop for code that sends out beacons. This code only runs while
- * we're sync site or we want to be the sync site. It runs in its very own light-weight
- * process.
+/*!
+ * \brief main lwp loop for code that sends out beacons.
+ *
+ * This code only runs while we're sync site or we want to be the sync site.
+ * It runs in its very own light-weight process.
*/
-ubeacon_Interact()
+void *
+ubeacon_Interact(void *dummy)
{
- register afs_int32 code;
+ afs_int32 code;
struct timeval tt;
struct rx_connection *connections[MAXSERVERS];
struct ubik_server *servers[MAXSERVERS];
- register afs_int32 i;
- register struct ubik_server *ts;
+ afs_int32 i;
+ struct ubik_server *ts;
afs_int32 temp, yesVotes, lastWakeupTime, oldestYesVote, syncsite;
struct ubik_tid ttid;
afs_int32 startTime;
temp = POLLTIME;
tt.tv_sec = temp;
tt.tv_usec = 0;
+#ifdef AFS_PTHREAD_ENV
+ code = select(0, 0, 0, 0, &tt);
+#else
code = IOMGR_Select(0, 0, 0, 0, &tt);
+#endif
} else
code = 0;
}
}
servers[i] = (struct ubik_server *)0; /* end of list */
- /* note that we assume in the vote module that we'll always get at least BIGTIME
+ /* note that we assume in the vote module that we'll always get at least BIGTIME
* seconds of vote from anyone who votes for us, which means we can conservatively
* assume we'll be fine until SMALLTIME seconds after we start collecting votes */
/* this next is essentially an expansion of rgen's ServBeacon routine */
ttid.counter = ubik_dbase->writeTidCounter;
} else
ttid.counter = ubik_dbase->tidCounter + 1;
-#if defined(UBIK_PAUSE)
- ubik_dbase->flags |= DBVOTING;
-#endif /* UBIK_PAUSE */
/* now analyze return codes, counting up our votes */
yesVotes = 0; /* count how many to ensure we have quorum */
- oldestYesVote = 0x3fffffff; /* time quorum expires */
+ oldestYesVote = 0x7fffffff; /* time quorum expires */
syncsite = ubeacon_AmSyncSite();
startTime = FT_ApproxTime();
/*
* Don't waste time using mult Rx calls if there are no connections out there
*/
if (i > 0) {
+ char hoststr[16];
multi_Rx(connections, i) {
multi_VOTE_Beacon(syncsite, startTime, &ubik_dbase->version,
&ttid);
* the vote was computed, *not* the time the vote expires. We compute
* the latter down below if we got enough votes to go with */
if (code > 0) {
- ts->lastVoteTime = code;
- if (code < oldestYesVote)
- oldestYesVote = code;
- ts->lastVote = 1;
- 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;
- ubik_dprint("yes vote from host %s\n",
- afs_inet_ntoa(ts->addr[0]));
+ if ((code & ~0xff) == ERROR_TABLE_BASE_RXK) {
+ ubik_dprint("token error %d from host %s\n",
+ code, afs_inet_ntoa_r(ts->addr[0], hoststr));
+ ts->up = 0;
+ ts->beaconSinceDown = 0;
+ urecovery_LostServer(ts);
+ } else {
+ ts->lastVoteTime = code;
+ if (code < oldestYesVote)
+ oldestYesVote = code;
+ ts->lastVote = 1;
+ 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;
+ ubik_dprint("yes vote from host %s\n",
+ afs_inet_ntoa_r(ts->addr[0], hoststr));
+ }
} else if (code == 0) {
ts->lastVoteTime = temp;
ts->lastVote = 0;
ts->beaconSinceDown = 1;
ubik_dprint("no vote from %s\n",
- afs_inet_ntoa(ts->addr[0]));
+ afs_inet_ntoa_r(ts->addr[0], hoststr));
} else if (code < 0) {
ts->up = 0;
ts->beaconSinceDown = 0;
- urecovery_LostServer();
+ urecovery_LostServer(ts);
ubik_dprint("time out from %s\n",
- afs_inet_ntoa(ts->addr[0]));
+ afs_inet_ntoa_r(ts->addr[0], hoststr));
}
}
multi_End;
if (i < oldestYesVote)
oldestYesVote = i;
}
-#if defined(UBIK_PAUSE)
- ubik_dbase->flags &= ~DBVOTING;
-#endif /* UBIK_PAUSE */
/* now decide if we have enough votes to become sync site.
* Note that we can still get enough votes even if we didn't for ourself. */
ubik_dprint("Ubik: I am the sync site\n");
ubik_amSyncSite = 1;
syncSiteUntil = oldestYesVote + SMALLTIME;
- LWP_NoYieldSignal(&ubik_amSyncSite);
+#ifndef AFS_PTHREAD_ENV
+ /* I did not find a corresponding LWP_WaitProcess(&ubik_amSyncSite) --
+ this may be a spurious signal call -- sjenkins */
+ LWP_NoYieldSignal(&ubik_amSyncSite);
+#endif
} else {
if (ubik_amSyncSite)
ubik_dprint("Ubik: I am no longer the sync site\n");
}
} /* while loop */
+ return NULL;
}
-/*
-* Input Param : ame is the pointer to my IP address specified in the
-* CellServDB file. aservers is an array containing IP
-* addresses of remote ubik servers. The array is
-* terminated by a zero address.
-*
-* Algorithm : Verify that my IP addresses 'ame' does actually exist
-* on this machine. If any of my IP addresses are there
-* in the remote server list 'aserver', remove them from
-* this list. Update global variable ubik_host[] with
-* my IP addresses.
-*
-* Return Values : 0 on success, non-zero on failure
-*/
-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 */
-{
+/*!
+ * \brief Verify that a given IP addresses does actually exist on this machine.
+ *
+ * \param ame the pointer to my IP address specified in the
+ * CellServDB file.
+ * \param aservers an array containing IP
+ * addresses of remote ubik servers. The array is
+ * terminated by a zero address.
+ *
+ * Algorithm : Verify that my IP addresses \p ame does actually exist
+ * on this machine. If any of my IP addresses are there
+ * in the remote server list \p aserver, remove them from
+ * this list. Update global variable \p ubik_host[] with
+ * my IP addresses.
+ *
+ * \return 0 on success, non-zero on failure
+ */
+static int
+verifyInterfaceAddress(afs_uint32 *ame, struct afsconf_cell *info,
+ afs_uint32 aservers[]) {
afs_uint32 myAddr[UBIK_MAX_INTERFACE_ADDR], *servList, tmpAddr;
afs_uint32 myAddr2[UBIK_MAX_INTERFACE_ADDR];
+ char hoststr[16];
int tcount, count, found, i, j, totalServers, start, end, usednetfiles =
0;
totalServers++;
}
-#ifdef AFS_NT40_ENV
- /* get all my interface addresses in net byte order */
- count = rx_getAllAddr(myAddr, UBIK_MAX_INTERFACE_ADDR);
-#else
if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) {
/*
* Find addresses we are supposed to register as per the netrestrict file
- * if it exists, else just register all the addresses we find on this
+ * if it exists, else just register all the addresses we find on this
* host as returned by rx_getAllAddr (in NBO)
*/
char reason[1024];
/* get all my interface addresses in net byte order */
count = rx_getAllAddr(myAddr, UBIK_MAX_INTERFACE_ADDR);
}
-#endif
if (count <= 0) { /* no address found */
ubik_print("ubik: No network addresses found, aborting..");
if (!found) {
ubik_print("ubik: primary address %s does not exist\n",
- afs_inet_ntoa(*ame));
+ afs_inet_ntoa_r(*ame, hoststr));
/* 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
}
/* if any of my addresses are there in serverList, then
- ** use that as my primary addresses : the higher level
+ ** use that as my primary addresses : the higher level
** application screwed up in dealing with multihomed concepts
*/
for (j = 0, found = 0; j < count; j++) {
for (i = 0; i < totalServers; i++) {
if (info)
- tmpAddr =
- ntohl((afs_uint32) info->hostAddr[i].sin_addr.s_addr);
+ tmpAddr = (afs_uint32) info->hostAddr[i].sin_addr.s_addr;
else
tmpAddr = aservers[i];
if (myAddr[j] == tmpAddr) {
}
}
if (found)
- ubik_print("Using %s as my primary address\n", afs_inet_ntoa(*ame));
+ ubik_print("Using %s as my primary address\n", afs_inet_ntoa_r(*ame, hoststr));
if (!info) {
- /* get rid of servers which were purged because all
- ** those interface addresses are myself
+ /* 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 */
}
}
- /* update all my addresses in ubik_host in such a way
- ** that ubik_host[0] has the primary address
+ /* update all my addresses in ubik_host in such a way
+ ** that ubik_host[0] has the primary address
*/
ubik_host[0] = *ame;
for (j = 0, i = 1; j < count; j++)
}
-/*
-* Input Param : ubik_host is an array containing all my IP addresses.
-*
-* Algorithm : Do an RPC to all remote ubik servers infroming them
-* about my IP addresses. Get their IP addresses and
-* update my linked list of ubik servers 'ubik_servers'
-*
-* Return Values : 0 on success, non-zero on failure
-*/
-int
-updateUbikNetworkAddress(ubik_host)
- afs_uint32 ubik_host[UBIK_MAX_INTERFACE_ADDR];
+/*!
+ * \brief Exchange IP address information with remote servers.
+ *
+ * \param ubik_host an array containing all my IP addresses.
+ *
+ * Algorithm : Do an RPC to all remote ubik servers infroming them
+ * about my IP addresses. Get their IP addresses and
+ * update my linked list of ubik servers \p ubik_servers
+ *
+ * \return 0 on success, non-zero on failure
+ */
+static int
+updateUbikNetworkAddress(afs_uint32 ubik_host[UBIK_MAX_INTERFACE_ADDR])
{
int j, count, code = 0;
UbikInterfaceAddr inAddr, outAddr;
struct rx_connection *conns[MAXSERVERS];
struct ubik_server *ts, *server[MAXSERVERS];
char buffer[32];
+ char hoststr[16];
for (count = 0, ts = ubik_servers; ts; count++, ts = ts->next) {
conns[count] = ts->disk_rxcid;
if (!multi_error) {
if (ts->addr[0] != htonl(outAddr.hostAddr[0])) {
code = UBADHOST;
- strcpy(buffer, (char *)afs_inet_ntoa(ts->addr[0]));
+ strcpy(buffer, afs_inet_ntoa_r(ts->addr[0], hoststr));
ubik_print("ubik:Two primary addresses for same server \
- %s %s\n", buffer, afs_inet_ntoa(htonl(outAddr.hostAddr[0])));
+ %s %s\n", buffer,
+ afs_inet_ntoa_r(htonl(outAddr.hostAddr[0]), hoststr));
} else {
for (j = 1; j < UBIK_MAX_INTERFACE_ADDR; j++)
ts->addr[j] = htonl(outAddr.hostAddr[j]);
} else if (multi_error == RXGEN_OPCODE) { /* pre 3.5 remote server */
ubik_print
("ubik server %s does not support UpdateInterfaceAddr RPC\n",
- afs_inet_ntoa(ts->addr[0]));
+ afs_inet_ntoa_r(ts->addr[0], hoststr));
} else if (multi_error == UBADHOST) {
code = UBADHOST; /* remote CellServDB inconsistency */
ubik_print("Inconsistent Cell Info on server: ");
for (j = 0; j < UBIK_MAX_INTERFACE_ADDR && ts->addr[j]; j++)
- ubik_print("%s ", afs_inet_ntoa(ts->addr[j]));
+ ubik_print("%s ", afs_inet_ntoa_r(ts->addr[j], hoststr));
ubik_print("\n");
} else {
ts->up = 0; /* mark the remote server as down */