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

📄 postinit.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * postinit.c *	  postgres initialization utilities * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.158.2.1 2005/11/22 18:23:24 momjian Exp $ * * *------------------------------------------------------------------------- */#include "postgres.h"#include <fcntl.h>#include <sys/file.h>#include <math.h>#include <unistd.h>#include "access/genam.h"#include "access/heapam.h"#include "catalog/catalog.h"#include "catalog/indexing.h"#include "catalog/namespace.h"#include "catalog/pg_authid.h"#include "catalog/pg_database.h"#include "catalog/pg_tablespace.h"#include "libpq/hba.h"#include "mb/pg_wchar.h"#include "miscadmin.h"#include "postmaster/autovacuum.h"#include "postmaster/postmaster.h"#include "storage/backendid.h"#include "storage/fd.h"#include "storage/ipc.h"#include "storage/proc.h"#include "storage/procarray.h"#include "storage/sinval.h"#include "storage/smgr.h"#include "utils/acl.h"#include "utils/flatfiles.h"#include "utils/fmgroids.h"#include "utils/guc.h"#include "utils/portal.h"#include "utils/relcache.h"#include "utils/syscache.h"#include "pgstat.h"static bool FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace);static void ReverifyMyDatabase(const char *name);static void InitCommunication(void);static void ShutdownPostgres(int code, Datum arg);static bool ThereIsAtLeastOneRole(void);/*** InitPostgres support ***//* * FindMyDatabase -- get the critical info needed to locate my database * * Find the named database in pg_database, return its database OID and the * OID of its default tablespace.  Return TRUE if found, FALSE if not. * * Since we are not yet up and running as a backend, we cannot look directly * at pg_database (we can't obtain locks nor participate in transactions). * So to get the info we need before starting up, we must look at the "flat * file" copy of pg_database that is helpfully maintained by flatfiles.c. * This is subject to various race conditions, so after we have the * transaction infrastructure started, we have to recheck the information; * see ReverifyMyDatabase. */static boolFindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace){	bool		result = false;	char	   *filename;	FILE	   *db_file;	char		thisname[NAMEDATALEN];	TransactionId dummyxid;	filename = database_getflatfilename();	db_file = AllocateFile(filename, "r");	if (db_file == NULL)		ereport(FATAL,				(errcode_for_file_access(),				 errmsg("could not open file \"%s\": %m", filename)));	while (read_pg_database_line(db_file, thisname, db_id,								 db_tablespace, &dummyxid,								 &dummyxid))	{		if (strcmp(thisname, name) == 0)		{			result = true;			break;		}	}	FreeFile(db_file);	pfree(filename);	return result;}/* * ReverifyMyDatabase -- recheck info obtained by FindMyDatabase * * Since FindMyDatabase cannot lock pg_database, the information it read * could be stale; for example we might have attached to a database that's in * process of being destroyed by dropdb().	This routine is called after * we have all the locking and other infrastructure running --- now we can * check that we are really attached to a valid database. * * In reality, if dropdb() is running in parallel with our startup, * it's pretty likely that we will have failed before now, due to being * unable to read some of the system tables within the doomed database. * This routine just exists to make *sure* we have not started up in an * invalid database.  If we quit now, we should have managed to avoid * creating any serious problems. * * This is also a handy place to fetch the database encoding info out * of pg_database. * * To avoid having to read pg_database more times than necessary * during session startup, this place is also fitting to set up any * database-specific configuration variables. */static voidReverifyMyDatabase(const char *name){	Relation	pgdbrel;	SysScanDesc pgdbscan;	ScanKeyData key;	HeapTuple	tup;	Form_pg_database dbform;	/*	 * Because we grab RowShareLock here, we can be sure that dropdb() is not	 * running in parallel with us (any more).	 */	pgdbrel = heap_open(DatabaseRelationId, RowShareLock);	ScanKeyInit(&key,				Anum_pg_database_datname,				BTEqualStrategyNumber, F_NAMEEQ,				NameGetDatum(name));	pgdbscan = systable_beginscan(pgdbrel, DatabaseNameIndexId, true,								  SnapshotNow, 1, &key);	tup = systable_getnext(pgdbscan);	if (!HeapTupleIsValid(tup) ||		HeapTupleGetOid(tup) != MyDatabaseId)	{		/* OOPS */		heap_close(pgdbrel, RowShareLock);		/*		 * The only real problem I could have created is to load dirty buffers		 * for the dead database into shared buffer cache; if I did, some		 * other backend will eventually try to write them and die in		 * mdblindwrt.	Flush any such pages to forestall trouble.		 */		DropBuffers(MyDatabaseId);		/* Now I can commit hara-kiri with a clear conscience... */		ereport(FATAL,				(errcode(ERRCODE_UNDEFINED_DATABASE),		  errmsg("database \"%s\", OID %u, has disappeared from pg_database",				 name, MyDatabaseId)));	}	dbform = (Form_pg_database) GETSTRUCT(tup);	/*	 * These next checks are not enforced when in standalone mode, so that	 * there is a way to recover from disabling all access to all databases,	 * for example "UPDATE pg_database SET datallowconn = false;".	 *	 * We do not enforce them for the autovacuum process either.	 */	if (IsUnderPostmaster && !IsAutoVacuumProcess())	{		/*		 * Check that the database is currently allowing connections.		 */		if (!dbform->datallowconn)			ereport(FATAL,					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),			 errmsg("database \"%s\" is not currently accepting connections",					name)));		/*		 * Check connection limit for this database.		 *		 * There is a race condition here --- we create our PGPROC before		 * checking for other PGPROCs.	If two backends did this at about the		 * same time, they might both think they were over the limit, while		 * ideally one should succeed and one fail.  Getting that to work		 * exactly seems more trouble than it is worth, however; instead we		 * just document that the connection limit is approximate.		 */		if (dbform->datconnlimit >= 0 &&			!superuser() &&			CountDBBackends(MyDatabaseId) > dbform->datconnlimit)			ereport(FATAL,					(errcode(ERRCODE_TOO_MANY_CONNECTIONS),					 errmsg("too many connections for database \"%s\"",							name)));	}	/*	 * OK, we're golden.  Next to-do item is to save the encoding info out of	 * the pg_database tuple.	 */	SetDatabaseEncoding(dbform->encoding);	/* Record it as a GUC internal option, too */	SetConfigOption("server_encoding", GetDatabaseEncodingName(),					PGC_INTERNAL, PGC_S_OVERRIDE);	/* If we have no other source of client_encoding, use server encoding */	SetConfigOption("client_encoding", GetDatabaseEncodingName(),					PGC_BACKEND, PGC_S_DEFAULT);	/*	 * Lastly, set up any database-specific configuration variables.	 */	if (IsUnderPostmaster)	{		Datum		datum;		bool		isnull;		datum = heap_getattr(tup, Anum_pg_database_datconfig,							 RelationGetDescr(pgdbrel), &isnull);		if (!isnull)		{			ArrayType  *a = DatumGetArrayTypeP(datum);			ProcessGUCArray(a, PGC_S_DATABASE);		}	}	systable_endscan(pgdbscan);	heap_close(pgdbrel, RowShareLock);}/* -------------------------------- *		InitCommunication * *		This routine initializes stuff needed for ipc, locking, etc. *		it should be called something more informative. * -------------------------------- */static voidInitCommunication(void){	/*	 * initialize shared memory and semaphores appropriately.	 */	if (!IsUnderPostmaster)		/* postmaster already did this */	{		/*		 * We're running a postgres bootstrap process or a standalone backend.		 * Create private "shmem" and semaphores.		 */		CreateSharedMemoryAndSemaphores(true, 0);	}}/* * Early initialization of a backend (either standalone or under postmaster). * This happens even before InitPostgres. * * If you're wondering why this is separate from InitPostgres at all: * the critical distinction is that this stuff has to happen before we can * run XLOG-related initialization, which is done before InitPostgres --- in * fact, for cases such as checkpoint creation processes, InitPostgres may * never be done at all. */voidBaseInit(void){	/*	 * Attach to shared memory and semaphores, and initialize our	 * input/output/debugging file descriptors.	 */	InitCommunication();

⌨️ 快捷键说明

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