1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)candidate.c 2.5 (Berkeley) 06/18/88"; 20 #endif /* not lint */ 21 22 #include "globals.h" 23 #include <protocols/timed.h> 24 25 #define ELECTIONWAIT 3 /* seconds */ 26 27 /* 28 * `election' candidates a host as master: it is called by a slave 29 * which runs with the -M option set when its election timeout expires. 30 * Note the conservative approach: if a new timed comes up, or another 31 * candidate sends an election request, the candidature is withdrawn. 32 */ 33 34 election(net) 35 struct netinfo *net; 36 { 37 int ret; 38 struct tsp *resp, msg, *readmsg(); 39 struct timeval wait; 40 struct tsp *answer, *acksend(); 41 long casual(); 42 struct sockaddr_in server; 43 44 syslog(LOG_INFO, "THIS MACHINE IS A CANDIDATE"); 45 if (trace) { 46 fprintf(fd, "THIS MACHINE IS A CANDIDATE\n"); 47 } 48 49 ret = MASTER; 50 slvcount = 1; 51 52 msg.tsp_type = TSP_ELECTION; 53 msg.tsp_vers = TSPVERSION; 54 (void)strcpy(msg.tsp_name, hostname); 55 bytenetorder(&msg); 56 if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, &net->dest_addr, 57 sizeof(struct sockaddr_in)) < 0) { 58 syslog(LOG_ERR, "sendto: %m"); 59 exit(1); 60 } 61 62 do { 63 wait.tv_sec = ELECTIONWAIT; 64 wait.tv_usec = 0; 65 resp = readmsg(TSP_ANY, (char *)ANYADDR, &wait, net); 66 if (resp != NULL) { 67 switch (resp->tsp_type) { 68 69 case TSP_ACCEPT: 70 (void) addmach(resp->tsp_name, &from); 71 break; 72 73 case TSP_MASTERUP: 74 case TSP_MASTERREQ: 75 /* 76 * If a timedaemon is coming up at the same time, 77 * give up the candidature: it will be the master. 78 */ 79 ret = SLAVE; 80 break; 81 82 case TSP_QUIT: 83 case TSP_REFUSE: 84 /* 85 * Collision: change value of election timer 86 * using exponential backoff. 87 * The value of timer will be recomputed (in slave.c) 88 * using the original interval when election will 89 * be successfully completed. 90 */ 91 backoff *= 2; 92 delay2 = casual((long)MINTOUT, 93 (long)(MAXTOUT * backoff)); 94 ret = SLAVE; 95 break; 96 97 case TSP_ELECTION: 98 /* no master for another round */ 99 msg.tsp_type = TSP_REFUSE; 100 (void)strcpy(msg.tsp_name, hostname); 101 server = from; 102 answer = acksend(&msg, &server, resp->tsp_name, 103 TSP_ACK, (struct netinfo *)NULL); 104 if (answer == NULL) { 105 syslog(LOG_ERR, "error in election"); 106 } else { 107 (void) addmach(resp->tsp_name, &from); 108 } 109 break; 110 111 case TSP_SLAVEUP: 112 (void) addmach(resp->tsp_name, &from); 113 break; 114 115 case TSP_SETDATE: 116 case TSP_SETDATEREQ: 117 break; 118 119 default: 120 if (trace) { 121 fprintf(fd, "candidate: "); 122 print(resp, &from); 123 } 124 break; 125 } 126 } else { 127 break; 128 } 129 } while (ret == MASTER); 130 return(ret); 131 } 132