📄 master.c
字号:
timevalsub(&stop, &stop, &check); if (stop.tv_sec >= 1) { if (trace) (void)fflush(fd); /* * ack messages periodically */ wait.tv_sec = 0; wait.tv_usec = 0; if (0 != readmsg(TSP_TRACEON,ANYADDR, &wait,0)) traceon(); (void)gettimeofday(&check, 0); } }#ifdef sgi if (pri >= 0) (void)schedctl(NDPRI,0,pri);#endif /* sgi */ if (trace) fprintf(fd, "measurements finished at %s\n", date()); } if (!(status & SLAVE)) { if (!dictate) { mydelta = networkdelta(); } else { dictate--; } } if (trace && (mydelta != 0 || (status & SLAVE))) fprintf(fd,"local correction of %ld ms.\n", mydelta); correct(mydelta);}/* * sends the time to each slave after the master * has received the command to set the network time */voidspreadtime(){ struct hosttbl *htp; struct tsp to; struct tsp *answer;/* Do not listen to the consensus after forcing the time. This is because * the consensus takes a while to reach the time we are dictating. */ dictate = 2; for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { to.tsp_type = TSP_SETTIME; (void)strcpy(to.tsp_name, hostname); (void)gettimeofday(&to.tsp_time, 0); answer = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer); if (answer == 0) { /* We client does not respond, then we have * just wasted lots of time on it. */ syslog(LOG_WARNING, "no reply to SETTIME from %s", htp->name); if (++htp->noanswer >= LOSTHOST) { if (trace) { fprintf(fd, "purging %s for not answering", htp->name); (void)fflush(fd); } htp = remmach(htp); } } }}voidprthp(delta) clock_t delta;{ static time_t next_time; time_t this_time; struct tms tm; struct hosttbl *htp; int length, l; int i; if (!fd) /* quit if tracing already off */ return; this_time = times(&tm); if (this_time + delta < next_time) return; next_time = this_time + CLK_TCK; fprintf(fd, "host table: %d entries at %s\n", slvcount, date()); htp = self.l_fwd; length = 1; for (i = 1; i <= slvcount; i++, htp = htp->l_fwd) { l = strlen(htp->name) + 1; if (length+l >= 80) { fprintf(fd, "\n"); length = 0; } length += l; fprintf(fd, " %s", htp->name); } fprintf(fd, "\n");}static struct hosttbl *newhost_hash;static struct hosttbl *lasthfree = &hosttbl[0];struct hosttbl * /* answer or 0 */findhost(name) char *name;{ int i, j; struct hosttbl *htp; char *p; j= 0; for (p = name, i = 0; i < 8 && *p != '\0'; i++, p++) j = (j << 2) ^ *p; newhost_hash = &hosttbl[j % NHOSTS]; htp = newhost_hash; if (htp->name[0] == '\0') return(0); do { if (!strcmp(name, htp->name)) return(htp); htp = htp->h_fwd; } while (htp != newhost_hash); return(0);}/* * add a host to the list of controlled machines if not already there */struct hosttbl *addmach(name, addr, ntp) char *name; struct sockaddr_in *addr; struct netinfo *ntp;{ struct hosttbl *ret, *p, *b, *f; ret = findhost(name); if (ret == 0) { if (slvcount >= NHOSTS) { if (trace) { fprintf(fd, "no more slots in host table\n"); prthp(CLK_TCK); } syslog(LOG_ERR, "no more slots in host table"); Mflag = 0; longjmp(jmpenv, 2); /* give up and be a slave */ } /* if our home hash slot is occupied, find a free entry * in the hash table */ if (newhost_hash->name[0] != '\0') { do { ret = lasthfree; if (++lasthfree > &hosttbl[NHOSTS]) lasthfree = &hosttbl[1]; } while (ret->name[0] != '\0'); if (!newhost_hash->head) { /* Move an interloper using our home. Use * scratch pointers in case the new head is * pointing to itself. */ f = newhost_hash->h_fwd; b = newhost_hash->h_bak; f->h_bak = ret; b->h_fwd = ret; f = newhost_hash->l_fwd; b = newhost_hash->l_bak; f->l_bak = ret; b->l_fwd = ret; bcopy(newhost_hash,ret,sizeof(*ret)); ret = newhost_hash; ret->head = 1; ret->h_fwd = ret; ret->h_bak = ret; } else { /* link to an existing chain in our home */ ret->head = 0; p = newhost_hash->h_bak; ret->h_fwd = newhost_hash; ret->h_bak = p; p->h_fwd = ret; newhost_hash->h_bak = ret; } } else { ret = newhost_hash; ret->head = 1; ret->h_fwd = ret; ret->h_bak = ret; } ret->addr = *addr; ret->ntp = ntp; (void)strncpy(ret->name, name, sizeof(ret->name)); ret->good = good_host_name(name); ret->l_fwd = &self; ret->l_bak = self.l_bak; self.l_bak->l_fwd = ret; self.l_bak = ret; slvcount++; ret->noanswer = 0; ret->need_set = 1; } else { ret->noanswer = (ret->noanswer != 0); } /* need to clear sequence number anyhow */ ret->seq = 0; return(ret);}/* * remove the machine with the given index in the host table. */struct hosttbl *remmach(htp) struct hosttbl *htp;{ struct hosttbl *lprv, *hnxt, *f, *b; if (trace) fprintf(fd, "remove %s\n", htp->name); /* get out of the lists */ htp->l_fwd->l_bak = lprv = htp->l_bak; htp->l_bak->l_fwd = htp->l_fwd; htp->h_fwd->h_bak = htp->h_bak; htp->h_bak->h_fwd = hnxt = htp->h_fwd; /* If we are in the home slot, pull up the chain */ if (htp->head && hnxt != htp) { if (lprv == hnxt) lprv = htp; /* Use scratch pointers in case the new head is pointing to * itself. */ f = hnxt->h_fwd; b = hnxt->h_bak; f->h_bak = htp; b->h_fwd = htp; f = hnxt->l_fwd; b = hnxt->l_bak; f->l_bak = htp; b->l_fwd = htp; hnxt->head = 1; bcopy(hnxt, htp, sizeof(*htp)); lasthfree = hnxt; } else { lasthfree = htp; } lasthfree->name[0] = '\0'; lasthfree->h_fwd = 0; lasthfree->l_fwd = 0; slvcount--; return lprv;}/* * Remove all the machines from the host table that exist on the given * network. This is called when a master transitions to a slave on a * given network. */voidrmnetmachs(ntp) struct netinfo *ntp;{ struct hosttbl *htp; if (trace) prthp(CLK_TCK); for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { if (ntp == htp->ntp) htp = remmach(htp); } if (trace) prthp(CLK_TCK);}voidmasterup(net) struct netinfo *net;{ xmit(TSP_MASTERUP, 0, &net->dest_addr); /* * Do not tell new slaves our time for a while. This ensures * we do not tell them to start using our time, before we have * found a good master. */ (void)gettimeofday(&net->slvwait, 0);}voidnewslave(msg) struct tsp *msg;{ struct hosttbl *htp; struct tsp *answer, to; struct timeval now; if (!fromnet || fromnet->status != MASTER) return; htp = addmach(msg->tsp_name, &from,fromnet); htp->seq = msg->tsp_seq; if (trace) prthp(0); /* * If we are stable, send our time to the slave. * Do not go crazy if the date has been changed. */ (void)gettimeofday(&now, 0); if (now.tv_sec >= fromnet->slvwait.tv_sec+3 || now.tv_sec < fromnet->slvwait.tv_sec) { to.tsp_type = TSP_SETTIME; (void)strcpy(to.tsp_name, hostname); (void)gettimeofday(&to.tsp_time, 0); answer = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer); if (answer) { htp->need_set = 0; } else { syslog(LOG_WARNING, "no reply to initial SETTIME from %s", htp->name); htp->noanswer = LOSTHOST; } }}/* * react to a TSP_QUIT: */voiddoquit(msg) struct tsp *msg;{ if (fromnet->status == MASTER) { if (!good_host_name(msg->tsp_name)) { if (fromnet->quit_count <= 0) { syslog(LOG_NOTICE,"untrusted %s told us QUIT", msg->tsp_name); suppress(&from, msg->tsp_name, fromnet); fromnet->quit_count = 1; return; } syslog(LOG_NOTICE, "untrusted %s told us QUIT twice", msg->tsp_name); fromnet->quit_count = 2; fromnet->status = NOMASTER; } else { fromnet->status = SLAVE; } rmnetmachs(fromnet); longjmp(jmpenv, 2); /* give up and be a slave */ } else { if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "untrusted %s told us QUIT", msg->tsp_name); fromnet->quit_count = 2; } }}voidtraceon(){ if (!fd) { fd = fopen(_PATH_TIMEDLOG, "w"); if (!fd) { trace = 0; return; } fprintf(fd,"Tracing started at %s\n", date()); } trace = 1; get_goodgroup(1); setstatus(); prthp(CLK_TCK);}voidtraceoff(msg) char *msg;{ get_goodgroup(1); setstatus(); prthp(CLK_TCK); if (trace) { fprintf(fd, msg, date()); (void)fclose(fd); fd = 0; }#ifdef GPROF moncontrol(0); _mcleanup(); moncontrol(1);#endif trace = OFF;}#ifdef sgivoidlogwtmp(otime, ntime) struct timeval *otime, *ntime;{ static struct utmp wtmp[2] = { {"","",OTIME_MSG,0,OLD_TIME,0,0,0}, {"","",NTIME_MSG,0,NEW_TIME,0,0,0} }; static char *wtmpfile = WTMP_FILE; int f; wtmp[0].ut_time = otime->tv_sec + (otime->tv_usec + 500000) / 1000000; wtmp[1].ut_time = ntime->tv_sec + (ntime->tv_usec + 500000) / 1000000; if (wtmp[0].ut_time == wtmp[1].ut_time) return; setutent(); (void)pututline(&wtmp[0]); (void)pututline(&wtmp[1]); endutent(); if ((f = open(wtmpfile, O_WRONLY|O_APPEND)) >= 0) { (void) write(f, (char *)wtmp, sizeof(wtmp)); (void) close(f); }}#endif /* sgi */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -