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