candidate.c revision 1553
11553Srgrimes/*- 21553Srgrimes * Copyright (c) 1985, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 3. All advertising materials mentioning features or use of this software 141553Srgrimes * must display the following acknowledgement: 151553Srgrimes * This product includes software developed by the University of 161553Srgrimes * California, Berkeley and its contributors. 171553Srgrimes * 4. Neither the name of the University nor the names of its contributors 181553Srgrimes * may be used to endorse or promote products derived from this software 191553Srgrimes * without specific prior written permission. 201553Srgrimes * 211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311553Srgrimes * SUCH DAMAGE. 321553Srgrimes */ 331553Srgrimes 341553Srgrimes#ifndef lint 351553Srgrimesstatic char sccsid[] = "@(#)candidate.c 8.1 (Berkeley) 6/6/93"; 361553Srgrimes#endif /* not lint */ 371553Srgrimes 381553Srgrimes#ifdef sgi 391553Srgrimes#ident "$Revision: 1.9 $" 401553Srgrimes#endif 411553Srgrimes 421553Srgrimes#include "globals.h" 431553Srgrimes 441553Srgrimes/* 451553Srgrimes * `election' candidates a host as master: it is called by a slave 461553Srgrimes * which runs with the -M option set when its election timeout expires. 471553Srgrimes * Note the conservative approach: if a new timed comes up, or another 481553Srgrimes * candidate sends an election request, the candidature is withdrawn. 491553Srgrimes */ 501553Srgrimesint 511553Srgrimeselection(net) 521553Srgrimes struct netinfo *net; 531553Srgrimes{ 541553Srgrimes struct tsp *resp, msg; 551553Srgrimes struct timeval then, wait; 561553Srgrimes struct tsp *answer; 571553Srgrimes struct hosttbl *htp; 581553Srgrimes char loop_lim = 0; 591553Srgrimes 601553Srgrimes/* This code can get totally confused if it gets slightly behind. For 611553Srgrimes * example, if readmsg() has some QUIT messages waiting from the last 621553Srgrimes * round, we would send an ELECTION message, get the stale QUIT, 631553Srgrimes * and give up. This results in network storms when several machines 641553Srgrimes * do it at once. 651553Srgrimes */ 661553Srgrimes wait.tv_sec = 0; 671553Srgrimes wait.tv_usec = 0; 681553Srgrimes while (0 != readmsg(TSP_REFUSE, ANYADDR, &wait, net)) { 691553Srgrimes if (trace) 701553Srgrimes fprintf(fd, "election: discarded stale REFUSE\n"); 711553Srgrimes } 721553Srgrimes while (0 != readmsg(TSP_QUIT, ANYADDR, &wait, net)) { 731553Srgrimes if (trace) 741553Srgrimes fprintf(fd, "election: discarded stale QUIT\n"); 751553Srgrimes } 761553Srgrimes 771553Srgrimesagain: 781553Srgrimes syslog(LOG_INFO, "This machine is a candidate time master"); 791553Srgrimes if (trace) 801553Srgrimes fprintf(fd, "This machine is a candidate time master\n"); 811553Srgrimes msg.tsp_type = TSP_ELECTION; 821553Srgrimes msg.tsp_vers = TSPVERSION; 831553Srgrimes (void)strcpy(msg.tsp_name, hostname); 841553Srgrimes bytenetorder(&msg); 851553Srgrimes if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 861553Srgrimes (struct sockaddr*)&net->dest_addr, 871553Srgrimes sizeof(struct sockaddr)) < 0) { 881553Srgrimes trace_sendto_err(net->dest_addr.sin_addr); 891553Srgrimes return(SLAVE); 901553Srgrimes } 911553Srgrimes 921553Srgrimes (void)gettimeofday(&then, 0); 931553Srgrimes then.tv_sec += 3; 941553Srgrimes for (;;) { 951553Srgrimes (void)gettimeofday(&wait, 0); 961553Srgrimes timevalsub(&wait,&then,&wait); 971553Srgrimes resp = readmsg(TSP_ANY, ANYADDR, &wait, net); 981553Srgrimes if (!resp) 991553Srgrimes return(MASTER); 1001553Srgrimes 1011553Srgrimes switch (resp->tsp_type) { 1021553Srgrimes 1031553Srgrimes case TSP_ACCEPT: 1041553Srgrimes (void)addmach(resp->tsp_name, &from,fromnet); 1051553Srgrimes break; 1061553Srgrimes 1071553Srgrimes case TSP_MASTERUP: 1081553Srgrimes case TSP_MASTERREQ: 1091553Srgrimes /* 1101553Srgrimes * If another timedaemon is coming up at the same 1111553Srgrimes * time, give up, and let it be the master. 1121553Srgrimes */ 1131553Srgrimes if (++loop_lim < 5 1141553Srgrimes && !good_host_name(resp->tsp_name)) { 1151553Srgrimes (void)addmach(resp->tsp_name, &from,fromnet); 1161553Srgrimes suppress(&from, resp->tsp_name, net); 1171553Srgrimes goto again; 1181553Srgrimes } 1191553Srgrimes rmnetmachs(net); 1201553Srgrimes return(SLAVE); 1211553Srgrimes 1221553Srgrimes case TSP_QUIT: 1231553Srgrimes case TSP_REFUSE: 1241553Srgrimes /* 1251553Srgrimes * Collision: change value of election timer 1261553Srgrimes * using exponential backoff. 1271553Srgrimes * 1281553Srgrimes * Fooey. 1291553Srgrimes * An exponential backoff on a delay starting at 1301553Srgrimes * 6 to 15 minutes for a process that takes 1311553Srgrimes * milliseconds is silly. It is particularly 1321553Srgrimes * strange that the original code would increase 1331553Srgrimes * the backoff without bound. 1341553Srgrimes */ 1351553Srgrimes rmnetmachs(net); 1361553Srgrimes return(SLAVE); 1371553Srgrimes 1381553Srgrimes case TSP_ELECTION: 1391553Srgrimes /* no master for another round */ 1401553Srgrimes htp = addmach(resp->tsp_name,&from,fromnet); 1411553Srgrimes msg.tsp_type = TSP_REFUSE; 1421553Srgrimes (void)strcpy(msg.tsp_name, hostname); 1431553Srgrimes answer = acksend(&msg, &htp->addr, htp->name, 1441553Srgrimes TSP_ACK, 0, htp->noanswer); 1451553Srgrimes if (!answer) { 1461553Srgrimes syslog(LOG_ERR, "error in election from %s", 1471553Srgrimes htp->name); 1481553Srgrimes } 1491553Srgrimes break; 1501553Srgrimes 1511553Srgrimes case TSP_SLAVEUP: 1521553Srgrimes (void)addmach(resp->tsp_name, &from,fromnet); 1531553Srgrimes break; 1541553Srgrimes 1551553Srgrimes case TSP_SETDATE: 1561553Srgrimes case TSP_SETDATEREQ: 1571553Srgrimes break; 1581553Srgrimes 1591553Srgrimes default: 1601553Srgrimes if (trace) { 1611553Srgrimes fprintf(fd, "candidate: "); 1621553Srgrimes print(resp, &from); 1631553Srgrimes } 1641553Srgrimes break; 1651553Srgrimes } 1661553Srgrimes } 1671553Srgrimes} 168