candidate.c revision 1554
1327Sjkh/*- 2327Sjkh * Copyright (c) 1985, 1993 3327Sjkh * The Regents of the University of California. All rights reserved. 4327Sjkh * 5327Sjkh * Redistribution and use in source and binary forms, with or without 6327Sjkh * modification, are permitted provided that the following conditions 7327Sjkh * are met: 8327Sjkh * 1. Redistributions of source code must retain the above copyright 9327Sjkh * notice, this list of conditions and the following disclaimer. 10327Sjkh * 2. Redistributions in binary form must reproduce the above copyright 11327Sjkh * notice, this list of conditions and the following disclaimer in the 12327Sjkh * documentation and/or other materials provided with the distribution. 13327Sjkh * 3. All advertising materials mentioning features or use of this software 14327Sjkh * must display the following acknowledgement: 15327Sjkh * This product includes software developed by the University of 16327Sjkh * California, Berkeley and its contributors. 17327Sjkh * 4. Neither the name of the University nor the names of its contributors 1831997Shoek * may be used to endorse or promote products derived from this software 19327Sjkh * without specific prior written permission. 20327Sjkh * 21327Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2293520Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2393520Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2493520Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25327Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26327Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2774699Ssobomax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28327Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29103149Ssobomax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055567Sphantom * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31327Sjkh * SUCH DAMAGE. 3272174Ssobomax */ 33411Sjkh 3484745Ssobomax#ifndef lint 3511780Sjkhstatic char sccsid[] = "@(#)candidate.c 8.1 (Berkeley) 6/6/93"; 36392Sjkh#endif /* not lint */ 3796030Ssobomax 3874699Ssobomax#ifdef sgi 39327Sjkh#ident "$Revision: 1.9 $" 4030221Scharnier#endif 4130221Scharnier 42327Sjkh#include "globals.h" 43327Sjkh 44327Sjkh/* 45327Sjkh * `election' candidates a host as master: it is called by a slave 46327Sjkh * which runs with the -M option set when its election timeout expires. 4756001Sdan * Note the conservative approach: if a new timed comes up, or another 48327Sjkh * candidate sends an election request, the candidature is withdrawn. 4974699Ssobomax */ 5074699Ssobomaxint 5174699Ssobomaxelection(net) 5274699Ssobomax struct netinfo *net; 5374699Ssobomax{ 54327Sjkh struct tsp *resp, msg; 5546105Sjkh struct timeval then, wait; 5672174Ssobomax struct tsp *answer; 5746105Sjkh struct hosttbl *htp; 5846105Sjkh char loop_lim = 0; 5946105Sjkh 60327Sjkh/* This code can get totally confused if it gets slightly behind. For 61327Sjkh * example, if readmsg() has some QUIT messages waiting from the last 6272174Ssobomax * round, we would send an ELECTION message, get the stale QUIT, 63327Sjkh * and give up. This results in network storms when several machines 64327Sjkh * do it at once. 65327Sjkh */ 66327Sjkh wait.tv_sec = 0; 67327Sjkh wait.tv_usec = 0; 68327Sjkh while (0 != readmsg(TSP_REFUSE, ANYADDR, &wait, net)) { 694996Sjkh if (trace) 70327Sjkh fprintf(fd, "election: discarded stale REFUSE\n"); 71327Sjkh } 72327Sjkh while (0 != readmsg(TSP_QUIT, ANYADDR, &wait, net)) { 73327Sjkh if (trace) 74327Sjkh fprintf(fd, "election: discarded stale QUIT\n"); 75327Sjkh } 76327Sjkh 77327Sjkhagain: 78327Sjkh syslog(LOG_INFO, "This machine is a candidate time master"); 79327Sjkh if (trace) 80327Sjkh fprintf(fd, "This machine is a candidate time master\n"); 81327Sjkh msg.tsp_type = TSP_ELECTION; 82327Sjkh msg.tsp_vers = TSPVERSION; 83327Sjkh (void)strcpy(msg.tsp_name, hostname); 84327Sjkh bytenetorder(&msg); 85327Sjkh if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 86327Sjkh (struct sockaddr*)&net->dest_addr, 87327Sjkh sizeof(struct sockaddr)) < 0) { 884996Sjkh trace_sendto_err(net->dest_addr.sin_addr); 894996Sjkh return(SLAVE); 904996Sjkh } 914996Sjkh 92327Sjkh (void)gettimeofday(&then, 0); 93327Sjkh then.tv_sec += 3; 94327Sjkh for (;;) { 95327Sjkh (void)gettimeofday(&wait, 0); 9671965Sjkh timevalsub(&wait,&then,&wait); 9771965Sjkh resp = readmsg(TSP_ANY, ANYADDR, &wait, net); 9871965Sjkh if (!resp) 9971965Sjkh return(MASTER); 10072174Ssobomax 10172174Ssobomax switch (resp->tsp_type) { 10272174Ssobomax 10372174Ssobomax case TSP_ACCEPT: 104327Sjkh (void)addmach(resp->tsp_name, &from,fromnet); 105327Sjkh break; 106327Sjkh 107327Sjkh case TSP_MASTERUP: 108327Sjkh case TSP_MASTERREQ: 109327Sjkh /* 110327Sjkh * If another timedaemon is coming up at the same 111327Sjkh * time, give up, and let it be the master. 112327Sjkh */ 113327Sjkh if (++loop_lim < 5 114327Sjkh && !good_host_name(resp->tsp_name)) { 115327Sjkh (void)addmach(resp->tsp_name, &from,fromnet); 1164996Sjkh suppress(&from, resp->tsp_name, net); 1174996Sjkh goto again; 1184996Sjkh } 1194996Sjkh rmnetmachs(net); 120411Sjkh return(SLAVE); 121411Sjkh 122411Sjkh case TSP_QUIT: 123411Sjkh case TSP_REFUSE: 1244996Sjkh /* 1254996Sjkh * Collision: change value of election timer 1264996Sjkh * using exponential backoff. 1274996Sjkh * 12872174Ssobomax * Fooey. 12972174Ssobomax * An exponential backoff on a delay starting at 13072174Ssobomax * 6 to 15 minutes for a process that takes 13162775Ssobomax * milliseconds is silly. It is particularly 13267454Ssobomax * strange that the original code would increase 13367454Ssobomax * the backoff without bound. 13467454Ssobomax */ 13567454Ssobomax rmnetmachs(net); 13696030Ssobomax return(SLAVE); 13796030Ssobomax 13896030Ssobomax case TSP_ELECTION: 13996030Ssobomax /* no master for another round */ 14096030Ssobomax htp = addmach(resp->tsp_name,&from,fromnet); 14196030Ssobomax msg.tsp_type = TSP_REFUSE; 14284750Ssobomax (void)strcpy(msg.tsp_name, hostname); 14384750Ssobomax answer = acksend(&msg, &htp->addr, htp->name, 14484750Ssobomax TSP_ACK, 0, htp->noanswer); 14584750Ssobomax if (!answer) { 146379Sjkh syslog(LOG_ERR, "error in election from %s", 147379Sjkh htp->name); 148379Sjkh } 149379Sjkh break; 150411Sjkh 151411Sjkh case TSP_SLAVEUP: 152411Sjkh (void)addmach(resp->tsp_name, &from,fromnet); 153411Sjkh break; 154383Sjkh 15585019Ssobomax case TSP_SETDATE: 156383Sjkh case TSP_SETDATEREQ: 157383Sjkh break; 15872174Ssobomax 15972174Ssobomax default: 16072174Ssobomax if (trace) { 16172174Ssobomax fprintf(fd, "candidate: "); 162392Sjkh print(resp, &from); 163392Sjkh } 164392Sjkh break; 165392Sjkh } 16674699Ssobomax } 16774699Ssobomax} 16874699Ssobomax