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.6 (Berkeley) 06/01/90"; 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, &net->dest_addr, 47 sizeof(struct sockaddr_in)) < 0) { 48 syslog(LOG_ERR, "sendto: %m"); 49 exit(1); 50 } 51 52 do { 53 wait.tv_sec = ELECTIONWAIT; 54 wait.tv_usec = 0; 55 resp = readmsg(TSP_ANY, (char *)ANYADDR, &wait, net); 56 if (resp != NULL) { 57 switch (resp->tsp_type) { 58 59 case TSP_ACCEPT: 60 (void) addmach(resp->tsp_name, &from); 61 break; 62 63 case TSP_MASTERUP: 64 case TSP_MASTERREQ: 65 /* 66 * If a timedaemon is coming up at the same time, 67 * give up the candidature: it will be the master. 68 */ 69 ret = SLAVE; 70 break; 71 72 case TSP_QUIT: 73 case TSP_REFUSE: 74 /* 75 * Collision: change value of election timer 76 * using exponential backoff. 77 * The value of timer will be recomputed (in slave.c) 78 * using the original interval when election will 79 * be successfully completed. 80 */ 81 backoff *= 2; 82 delay2 = casual((long)MINTOUT, 83 (long)(MAXTOUT * backoff)); 84 ret = SLAVE; 85 break; 86 87 case TSP_ELECTION: 88 /* no master for another round */ 89 msg.tsp_type = TSP_REFUSE; 90 (void)strcpy(msg.tsp_name, hostname); 91 server = from; 92 answer = acksend(&msg, &server, resp->tsp_name, 93 TSP_ACK, (struct netinfo *)NULL); 94 if (answer == NULL) { 95 syslog(LOG_ERR, "error in election"); 96 } else { 97 (void) addmach(resp->tsp_name, &from); 98 } 99 break; 100 101 case TSP_SLAVEUP: 102 (void) addmach(resp->tsp_name, &from); 103 break; 104 105 case TSP_SETDATE: 106 case TSP_SETDATEREQ: 107 break; 108 109 default: 110 if (trace) { 111 fprintf(fd, "candidate: "); 112 print(resp, &from); 113 } 114 break; 115 } 116 } else { 117 break; 118 } 119 } while (ret == MASTER); 120 return(ret); 121 } 122