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

📄 postmaster.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * This check is an essential part of the interlock that prevents two	 * postmasters from starting in the same directory (see CreateLockFile()).	 * Do not remove or weaken it.	 *	 * XXX can we safely enable this check on Windows?	 */#if !defined(WIN32) && !defined(__CYGWIN__)	if (stat_buf.st_uid != geteuid())		ereport(FATAL,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("data directory \"%s\" has wrong ownership",						DataDir),				 errhint("The server must be started by the user that owns the data directory.")));#endif	/*	 * Check if the directory has group or world access.  If so, reject.	 *	 * It would be possible to allow weaker constraints (for example, allow	 * group access) but we cannot make a general assumption that that is	 * okay; for example there are platforms where nearly all users	 * customarily belong to the same group.  Perhaps this test should be	 * configurable.	 *	 * XXX temporarily suppress check when on Windows, because there may not	 * be proper support for Unix-y file permissions.  Need to think of a	 * reasonable check to apply on Windows.	 */#if !defined(WIN32) && !defined(__CYGWIN__)	if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))		ereport(FATAL,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("data directory \"%s\" has group or world access",						DataDir),				 errdetail("Permissions should be u=rwx (0700).")));#endif	/* Look for PG_VERSION before looking for pg_control */	ValidatePgVersion(DataDir);	snprintf(path, sizeof(path), "%s/global/pg_control", DataDir);	fp = AllocateFile(path, PG_BINARY_R);	if (fp == NULL)	{		write_stderr("%s: could not find the database system\n"					 "Expected to find it in the directory \"%s\",\n"					 "but could not open file \"%s\": %s\n",					 progname, DataDir, path, strerror(errno));		ExitPostmaster(2);	}	FreeFile(fp);}#ifdef USE_BONJOUR/* * empty callback function for DNSServiceRegistrationCreate() */static voidreg_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context){}#endif   /* USE_BONJOUR *//* * Fork away from the controlling terminal (-S option) */static voidpmdaemonize(void){#ifndef WIN32	int			i;	pid_t		pid;	pid = fork_process();	if (pid == (pid_t) -1)	{		write_stderr("%s: could not fork background process: %s\n",					 progname, strerror(errno));		ExitPostmaster(1);	}	else if (pid)	{							/* parent */		/* Parent should just exit, without doing any atexit cleanup */		_exit(0);	}	MyProcPid = PostmasterPid = getpid();		/* reset PID vars to child *//* GH: If there's no setsid(), we hopefully don't need silent mode. * Until there's a better solution. */#ifdef HAVE_SETSID	if (setsid() < 0)	{		write_stderr("%s: could not dissociate from controlling TTY: %s\n",					 progname, strerror(errno));		ExitPostmaster(1);	}#endif	i = open(NULL_DEV, O_RDWR);	dup2(i, 0);	dup2(i, 1);	dup2(i, 2);	close(i);#else							/* WIN32 */	/* not supported */	elog(FATAL, "SilentMode not supported under WIN32");#endif   /* WIN32 */}/* * Print out help message */static voidusage(const char *progname){	printf(_("%s is the PostgreSQL server.\n\n"), progname);	printf(_("Usage:\n  %s [OPTION]...\n\n"), progname);	printf(_("Options:\n"));#ifdef USE_ASSERT_CHECKING	printf(_("  -A 1|0          enable/disable run-time assert checking\n"));#endif	printf(_("  -B NBUFFERS     number of shared buffers\n"));	printf(_("  -c NAME=VALUE   set run-time parameter\n"));	printf(_("  -d 1-5          debugging level\n"));	printf(_("  -D DATADIR      database directory\n"));	printf(_("  -F              turn fsync off\n"));	printf(_("  -h HOSTNAME     host name or IP address to listen on\n"));	printf(_("  -i              enable TCP/IP connections\n"));	printf(_("  -k DIRECTORY    Unix-domain socket location\n"));#ifdef USE_SSL	printf(_("  -l              enable SSL connections\n"));#endif	printf(_("  -N MAX-CONNECT  maximum number of allowed connections\n"));	printf(_("  -o OPTIONS      pass \"OPTIONS\" to each server process\n"));	printf(_("  -p PORT         port number to listen on\n"));	printf(_("  -S              silent mode (start in background without logging output)\n"));	printf(_("  --help          show this help, then exit\n"));	printf(_("  --version       output version information, then exit\n"));	printf(_("\nDeveloper options:\n"));	printf(_("  -n              do not reinitialize shared memory after abnormal exit\n"));	printf(_("  -s              send SIGSTOP to all backend servers if one dies\n"));	printf(_("\nPlease read the documentation for the complete list of run-time\n"	 "configuration settings and how to set them on the command line or in\n"			 "the configuration file.\n\n"			 "Report bugs to <pgsql-bugs@postgresql.org>.\n"));}/* * Main idle loop of postmaster */static intServerLoop(void){	fd_set		readmask;	int			nSockets;	time_t		now,				last_touch_time;	struct timeval earlier,				later;	gettimeofday(&earlier, NULL);	last_touch_time = time(NULL);	nSockets = initMasks(&readmask);	for (;;)	{		Port	   *port;		fd_set		rmask;		struct timeval timeout;		int			selres;		int			i;		/*		 * Wait for something to happen.		 *		 * We wait at most one minute, or the minimum autovacuum delay, to		 * ensure that the other background tasks handled below get done even		 * when no requests are arriving.		 */		memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set));		timeout.tv_sec = Min(60, autovacuum_naptime);		timeout.tv_usec = 0;		PG_SETMASK(&UnBlockSig);		selres = select(nSockets, &rmask, NULL, NULL, &timeout);		/*		 * Block all signals until we wait again.  (This makes it safe for our		 * signal handlers to do nontrivial work.)		 */		PG_SETMASK(&BlockSig);		if (selres < 0)		{			if (errno != EINTR && errno != EWOULDBLOCK)			{				ereport(LOG,						(errcode_for_socket_access(),						 errmsg("select() failed in postmaster: %m")));				return STATUS_ERROR;			}		}		/*		 * New connection pending on any of our sockets? If so, fork a child		 * process to deal with it.		 */		if (selres > 0)		{			/*			 * Select a random seed at the time of first receiving a request.			 */			while (random_seed == 0)			{				gettimeofday(&later, NULL);				/*				 * We are not sure how much precision is in tv_usec, so we				 * swap the high and low 16 bits of 'later' and XOR them with				 * 'earlier'. On the off chance that the result is 0, we loop				 * until it isn't.				 */				random_seed = earlier.tv_usec ^					((later.tv_usec << 16) |					 ((later.tv_usec >> 16) & 0xffff));			}			for (i = 0; i < MAXLISTEN; i++)			{				if (ListenSocket[i] == -1)					break;				if (FD_ISSET(ListenSocket[i], &rmask))				{					port = ConnCreate(ListenSocket[i]);					if (port)					{						BackendStartup(port);						/*						 * We no longer need the open socket or port structure						 * in this process						 */						StreamClose(port->sock);						ConnFree(port);					}				}			}		}		/* If we have lost the system logger, try to start a new one */		if (SysLoggerPID == 0 && Redirect_stderr)			SysLoggerPID = SysLogger_Start();		/*		 * If no background writer process is running, and we are not in a		 * state that prevents it, start one.  It doesn't matter if this		 * fails, we'll just try again later.		 */		if (BgWriterPID == 0 && StartupPID == 0 && !FatalError)		{			BgWriterPID = StartBackgroundWriter();			/* If shutdown is pending, set it going */			if (Shutdown > NoShutdown && BgWriterPID != 0)				kill(BgWriterPID, SIGUSR2);		}		/*		 * Start a new autovacuum process, if there isn't one running already.		 * (It'll die relatively quickly.)  We check that it's not started too		 * frequently in autovac_start.		 */		if (AutoVacuumingActive() && AutoVacPID == 0 &&			StartupPID == 0 && !FatalError && Shutdown == NoShutdown)			AutoVacPID = autovac_start();		/* If we have lost the archiver, try to start a new one */		if (XLogArchivingActive() && PgArchPID == 0 &&			StartupPID == 0 && !FatalError && Shutdown == NoShutdown)			PgArchPID = pgarch_start();		/* If we have lost the stats collector, try to start a new one */		if (PgStatPID == 0 &&			StartupPID == 0 && !FatalError && Shutdown == NoShutdown)			PgStatPID = pgstat_start();		/*		 * Touch the socket and lock file every 58 minutes, to ensure that		 * they are not removed by overzealous /tmp-cleaning tasks.  We assume		 * no one runs cleaners with cutoff times of less than an hour ...		 */		now = time(NULL);		if (now - last_touch_time >= 58 * SECS_PER_MINUTE)		{			TouchSocketFile();			TouchSocketLockFile();			last_touch_time = now;		}	}}/* * Initialise the masks for select() for the ports we are listening on. * Return the number of sockets to listen on. */static intinitMasks(fd_set *rmask){	int			nsocks = -1;	int			i;	FD_ZERO(rmask);	for (i = 0; i < MAXLISTEN; i++)	{		int			fd = ListenSocket[i];		if (fd == -1)			break;		FD_SET(fd, rmask);		if (fd > nsocks)			nsocks = fd;	}	return nsocks + 1;}/* * Read the startup packet and do something according to it. * * Returns STATUS_OK or STATUS_ERROR, or might call ereport(FATAL) and * not return at all. * * (Note that ereport(FATAL) stuff is sent to the client, so only use it * if that's what you want.  Return STATUS_ERROR if you don't want to * send anything to the client, which would typically be appropriate * if we detect a communications failure.) */static intProcessStartupPacket(Port *port, bool SSLdone){	int32		len;	void	   *buf;	ProtocolVersion proto;	MemoryContext oldcontext;	if (pq_getbytes((char *) &len, 4) == EOF)	{		/*		 * EOF after SSLdone probably means the client didn't like our		 * response to NEGOTIATE_SSL_CODE.	That's not an error condition, so		 * don't clutter the log with a complaint.		 */		if (!SSLdone)			ereport(COMMERROR,					(errcode(ERRCODE_PROTOCOL_VIOLATION),					 errmsg("incomplete startup packet")));		return STATUS_ERROR;	}	len = ntohl(len);	len -= 4;	if (len < (int32) sizeof(ProtocolVersion) ||		len > MAX_STARTUP_PACKET_LENGTH)	{		ereport(COMMERROR,				(errcode(ERRCODE_PROTOCOL_VIOLATION),				 errmsg("invalid length of startup packet")));		return STATUS_ERROR;	}	/*	 * Allocate at least the size of an old-style startup packet, plus one	 * extra byte, and make sure all are zeroes.  This ensures we will have	 * null termination of all strings, in both fixed- and variable-length	 * packet layouts.	 */	if (len <= (int32) sizeof(StartupPacket))		buf = palloc0(sizeof(StartupPacket) + 1);	else		buf = palloc0(len + 1);	if (pq_getbytes(buf, len) == EOF)	{		ereport(COMMERROR,				(errcode(ERRCODE_PROTOCOL_VIOLATION),				 errmsg("incomplete startup packet")));		return STATUS_ERROR;	}	/*	 * The first field is either a protocol version number or a special	 * request code.	 */	port->proto = proto = ntohl(*((ProtocolVersion *) buf));	if (proto == CANCEL_REQUEST_CODE)	{		processCancelRequest(port, buf);		return 127;				/* XXX */	}	if (proto == NEGOTIATE_SSL_CODE && !SSLdone)	{		char		SSLok;#ifdef USE_SSL		/* No SSL when disabled or on Unix sockets */		if (!EnableSSL || IS_AF_UNIX(port->laddr.addr.ss_family))			SSLok = 'N';		else			SSLok = 'S';		/* Support for SSL */#else		SSLok = 'N';			/* No support for SSL */#endif		if (send(port->sock, &SSLok, 1, 0) != 1)		{			ereport(COMMERROR,					(errcode_for_socket_access(),					 errmsg("failed to send SSL negotiation response: %m")));			return STATUS_ERROR;	/* close the connection */		}#ifdef USE_SSL		if (SSLok == 'S' && secure_open_server(port) == -1)			return STATUS_ERROR;#endif		/* regular startup packet, cancel, etc packet should follow... */		/* but not another SSL negotiation request */		return ProcessStartupPacket(port, true);	}	/* Could add additional special packet types here */	/*	 * Set FrontendProtocol now so that ereport() knows what format to send if	 * we fail during startup.	 */	FrontendProtocol = proto;	/* Check we can handle the protocol the frontend is using. */	if (PG_PROTOCOL_MAJOR(proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||		PG_PROTOCOL_MAJOR(proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||		(PG_PROTOCOL_MAJOR(proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&		 PG_PROTOCOL_MINOR(proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))		ereport(FATAL,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u",						PG_PROTOCOL_MAJOR(proto), PG_PROTOCOL_MINOR(proto),						PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST),						PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST),						PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST))));	/*	 * Now fetch parameters out of startup packet and save them into the Port	 * structure.  All data structures attached to the Port struct must be	 * allocated in TopMemoryContext so that they won't disappear when we pass	 * them to PostgresMain (see BackendRun).  We need not worry about leaking	 * this storage on failure, since we aren't in the postmaster process	 * anymore.	 */	oldcontext = MemoryContextSwitchTo(TopMemoryContext);	if (PG_PROTOCOL_MAJOR(proto) >= 3)	{		int32		offset = sizeof(ProtocolVersion);		/*		 * Scan packet body for name/option pairs.	We can assume any string		 * beginning within the packet body is null-terminated, thanks to		 * zeroing extra byte above.		 */		port->guc_options = NIL;

⌨️ 快捷键说明

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