⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 master.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1985, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)master.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#ifdef sgi#ident "$Revision: 1.21 $"#endif#include "globals.h"#include <sys/file.h>#include <sys/types.h>#include <sys/times.h>#include <setjmp.h>#ifdef sgi#include <sys/schedctl.h>#endif /* sgi */#include <utmp.h>#include "pathnames.h"extern int measure_delta;extern jmp_buf jmpenv;extern int Mflag;extern int justquit;static int dictate;static int slvcount;			/* slaves listening to our clock */static void mchgdate __P((struct tsp *));#ifdef sgiextern void logwtmp __P((struct timeval *, struct timeval *));#elseextern void logwtmp __P((char *, char *, char *));#endif /* sgi *//* * The main function of `master' is to periodically compute the differences * (deltas) between its clock and the clocks of the slaves, to compute the * network average delta, and to send to the slaves the differences between * their individual deltas and the network delta. * While waiting, it receives messages from the slaves (i.e. requests for * master's name, remote requests to set the network time, ...), and * takes the appropriate action. */intmaster(){	struct hosttbl *htp;	long pollingtime;#define POLLRATE 4	int polls;	struct timeval wait, ntime;	struct tsp *msg, *answer, to;	char newdate[32];	struct sockaddr_in taddr;	char tname[MAXHOSTNAMELEN];	struct netinfo *ntp;	int i;	syslog(LOG_NOTICE, "This machine is master");	if (trace)		fprintf(fd, "This machine is master\n");	for (ntp = nettab; ntp != NULL; ntp = ntp->next) {		if (ntp->status == MASTER)			masterup(ntp);	}	(void)gettimeofday(&ntime, 0);	pollingtime = ntime.tv_sec+3;	if (justquit)		polls = 0;	else		polls = POLLRATE-1;/* Process all outstanding messages before spending the long time necessary *	to update all timers. */loop:	(void)gettimeofday(&ntime, 0);	wait.tv_sec = pollingtime - ntime.tv_sec;	if (wait.tv_sec < 0)		wait.tv_sec = 0;	wait.tv_usec = 0;	msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);	if (!msg) {		(void)gettimeofday(&ntime, 0);		if (ntime.tv_sec >= pollingtime) {			pollingtime = ntime.tv_sec + SAMPLEINTVL;			get_goodgroup(0);/* If a bogus master told us to quit, we can have decided to ignore a * network.  Therefore, periodically try to take over everything. */			polls = (polls + 1) % POLLRATE;			if (0 == polls && nignorednets > 0) {				trace_msg("Looking for nets to re-master\n");				for (ntp = nettab; ntp; ntp = ntp->next) {					if (ntp->status == IGNORE					    || ntp->status == NOMASTER) {						lookformaster(ntp);						if (ntp->status == MASTER) {							masterup(ntp);							polls = POLLRATE-1;						}					}					if (ntp->status == MASTER					    && --ntp->quit_count < 0)						ntp->quit_count = 0;				}				if (polls != 0)					setstatus();			}			synch(0L);			for (ntp = nettab; ntp != NULL; ntp = ntp->next) {				to.tsp_type = TSP_LOOP;				to.tsp_vers = TSPVERSION;				to.tsp_seq = sequence++;				to.tsp_hopcnt = MAX_HOPCNT;				(void)strcpy(to.tsp_name, hostname);				bytenetorder(&to);				if (sendto(sock, (char *)&to,					   sizeof(struct tsp), 0,					   (struct sockaddr*)&ntp->dest_addr,					   sizeof(ntp->dest_addr)) < 0) {				   trace_sendto_err(ntp->dest_addr.sin_addr);				}			}		}	} else {		switch (msg->tsp_type) {		case TSP_MASTERREQ:			break;		case TSP_SLAVEUP:			newslave(msg);			break;		case TSP_SETDATE:			/*			 * XXX check to see it is from ourself			 */#ifdef sgi			(void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);#else			(void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));#endif /* sgi */			if (!good_host_name(msg->tsp_name)) {				syslog(LOG_NOTICE,				       "attempted date change by %s to %s",				       msg->tsp_name, newdate);				spreadtime();				break;			}			mchgdate(msg);			(void)gettimeofday(&ntime, 0);			pollingtime = ntime.tv_sec + SAMPLEINTVL;			break;		case TSP_SETDATEREQ:			if (!fromnet || fromnet->status != MASTER)				break;#ifdef sgi			(void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);#else			(void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));#endif /* sgi */			htp = findhost(msg->tsp_name);			if (htp == 0) {				syslog(LOG_ERR,				       "attempted SET DATEREQ by uncontrolled %s to %s",				       msg->tsp_name, newdate);				break;			}			if (htp->seq == msg->tsp_seq)				break;			htp->seq = msg->tsp_seq;			if (!htp->good) {				syslog(LOG_NOTICE,				"attempted SET DATEREQ by untrusted %s to %s",				       msg->tsp_name, newdate);				spreadtime();				break;			}			mchgdate(msg);			(void)gettimeofday(&ntime, 0);			pollingtime = ntime.tv_sec + SAMPLEINTVL;			break;		case TSP_MSITE:			xmit(TSP_ACK, msg->tsp_seq, &from);			break;		case TSP_MSITEREQ:			break;		case TSP_TRACEON:			traceon();			break;		case TSP_TRACEOFF:			traceoff("Tracing ended at %s\n");			break;		case TSP_ELECTION:			if (!fromnet)				break;			if (fromnet->status == MASTER) {				pollingtime = 0;				(void)addmach(msg->tsp_name, &from,fromnet);			}			taddr = from;			(void)strcpy(tname, msg->tsp_name);			to.tsp_type = TSP_QUIT;			(void)strcpy(to.tsp_name, hostname);			answer = acksend(&to, &taddr, tname,					 TSP_ACK, 0, 1);			if (answer == NULL) {				syslog(LOG_ERR, "election error by %s",				       tname);			}			break;		case TSP_CONFLICT:			/*			 * After a network partition, there can be			 * more than one master: the first slave to			 * come up will notify here the situation.			 */			if (!fromnet || fromnet->status != MASTER)				break;			(void)strcpy(to.tsp_name, hostname);			/* The other master often gets into the same state,			 * with boring results if we stay at it forever.			 */			ntp = fromnet;	/* (acksend() can leave fromnet=0 */			for (i = 0; i < 3; i++) {				to.tsp_type = TSP_RESOLVE;				(void)strcpy(to.tsp_name, hostname);				answer = acksend(&to, &ntp->dest_addr,						 ANYADDR, TSP_MASTERACK,						 ntp, 0);				if (!answer)					break;				htp = addmach(answer->tsp_name,&from,ntp);				to.tsp_type = TSP_QUIT;				msg = acksend(&to, &htp->addr, htp->name,					      TSP_ACK, 0, htp->noanswer);				if (msg == NULL) {					syslog(LOG_ERR,				    "no response from %s to CONFLICT-QUIT",					       htp->name);				}			}			masterup(ntp);			pollingtime = 0;			break;		case TSP_RESOLVE:			if (!fromnet || fromnet->status != MASTER)				break;			/*			 * do not want to call synch() while waiting			 * to be killed!			 */			(void)gettimeofday(&ntime, (struct timezone *)0);			pollingtime = ntime.tv_sec + SAMPLEINTVL;			break;		case TSP_QUIT:			doquit(msg);		/* become a slave */			break;		case TSP_LOOP:			if (!fromnet || fromnet->status != MASTER			    || !strcmp(msg->tsp_name, hostname))				break;			/*			 * We should not have received this from a net			 * we are master on.  There must be two masters.			 */			htp = addmach(msg->tsp_name, &from,fromnet);			to.tsp_type = TSP_QUIT;			(void)strcpy(to.tsp_name, hostname);			answer = acksend(&to, &htp->addr, htp->name,					 TSP_ACK, 0, 1);			if (!answer) {				syslog(LOG_WARNING,				"loop breakage: no reply from %s=%s to QUIT",				    htp->name, inet_ntoa(htp->addr.sin_addr));				(void)remmach(htp);			}		case TSP_TEST:			if (trace) {				fprintf(fd,		"\tnets = %d, masters = %d, slaves = %d, ignored = %d\n",		nnets, nmasternets, nslavenets, nignorednets);				setstatus();			}			pollingtime = 0;			polls = POLLRATE-1;			break;		default:			if (trace) {				fprintf(fd, "garbage message: ");				print(msg, &from);			}			break;		}	}	goto loop;}/* * change the system date on the master */static voidmchgdate(msg)	struct tsp *msg;{	char tname[MAXHOSTNAMELEN];	char olddate[32];	struct timeval otime, ntime;	(void)strcpy(tname, msg->tsp_name);	xmit(TSP_DATEACK, msg->tsp_seq, &from);	(void)strcpy(olddate, date());	/* adjust time for residence on the queue */	(void)gettimeofday(&otime, 0);	adj_msg_time(msg,&otime);	timevalsub(&ntime, &msg->tsp_time, &otime);	if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {		/*		 * do not change the clock if we can adjust it		 */		dictate = 3;		synch(tvtomsround(ntime));	} else {#ifdef sgi		if (0 > settimeofday(&msg->tsp_time, 0)) {			syslog(LOG_ERR, "settimeofday(): %m");		}		logwtmp(&otime, &msg->tsp_time);#else		logwtmp("|", "date", "");		(void)settimeofday(&msg->tsp_time, 0);		logwtmp("}", "date", "");#endif /* sgi */		spreadtime();	}	syslog(LOG_NOTICE, "date changed by %s from %s",	       tname, olddate);}/* * synchronize all of the slaves */voidsynch(mydelta)	long mydelta;{	struct hosttbl *htp;	int measure_status;	struct timeval check, stop, wait;#ifdef sgi	int pri;#endif /* sgi */	if (slvcount > 0) {		if (trace)			fprintf(fd, "measurements starting at %s\n", date());		(void)gettimeofday(&check, 0);#ifdef sgi		/* run fast to get good time */		pri = schedctl(NDPRI,0,NDPHIMIN);		if (pri < 0)			syslog(LOG_ERR, "schedctl(): %m");#endif /* sgi */		for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {			if (htp->noanswer != 0) {				measure_status = measure(500, 100,							 htp->name,							 &htp->addr,0);			} else {				measure_status = measure(3000, 100,							 htp->name,							 &htp->addr,0);			}			if (measure_status != GOOD) {				/* The slave did not respond.  We have				 * just wasted lots of time on it.				 */				htp->delta = HOSTDOWN;				if (++htp->noanswer >= LOSTHOST) {					if (trace) {						fprintf(fd,					"purging %s for not answering ICMP\n",							htp->name);						(void)fflush(fd);					}					htp = remmach(htp);				}			} else {				htp->delta = measure_delta;			}			(void)gettimeofday(&stop, 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -