📄 postinit.c
字号:
DebugFileOpen(); /* Do local initialization of file, storage and buffer managers */ InitFileAccess(); smgrinit(); InitBufferPoolAccess();}/* -------------------------------- * InitPostgres * Initialize POSTGRES. * * In bootstrap mode neither of the parameters are used. In autovacuum * mode, the username parameter is not used. * * The return value indicates whether the userID is a superuser. (That * can only be tested inside a transaction, so we want to do it during * the startup transaction rather than doing a separate one in postgres.c.) * * Note: * Be very careful with the order of calls in the InitPostgres function. * -------------------------------- */boolInitPostgres(const char *dbname, const char *username){ bool bootstrap = IsBootstrapProcessingMode(); bool autovacuum = IsAutoVacuumProcess(); bool am_superuser; /* * Set up the global variables holding database id and path. * * We take a shortcut in the bootstrap case, otherwise we have to look up * the db name in pg_database. */ if (bootstrap) { MyDatabaseId = TemplateDbOid; MyDatabaseTableSpace = DEFAULTTABLESPACE_OID; SetDatabasePath(GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace)); } else { char *fullpath; /* * Formerly we validated DataDir here, but now that's done earlier. */ /* * Find oid and tablespace of the database we're about to open. Since * we're not yet up and running we have to use the hackish * FindMyDatabase. */ if (!FindMyDatabase(dbname, &MyDatabaseId, &MyDatabaseTableSpace)) ereport(FATAL, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%s\" does not exist", dbname))); fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace); /* Verify the database path */ if (access(fullpath, F_OK) == -1) { if (errno == ENOENT) ereport(FATAL, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%s\" does not exist", dbname), errdetail("The database subdirectory \"%s\" is missing.", fullpath))); else ereport(FATAL, (errcode_for_file_access(), errmsg("could not access directory \"%s\": %m", fullpath))); } ValidatePgVersion(fullpath); SetDatabasePath(fullpath); } /* * Code after this point assumes we are in the proper directory! */ /* * Set up my per-backend PGPROC struct in shared memory. (We need to * know MyDatabaseId before we can do this, since it's entered into the * PGPROC struct.) */ InitProcess(); /* * Initialize my entry in the shared-invalidation manager's array of * per-backend data. (Formerly this came before InitProcess, but now it * must happen after, because it uses MyProc.) Once I have done this, I * am visible to other backends! * * Sets up MyBackendId, a unique backend identifier. */ MyBackendId = InvalidBackendId; InitBackendSharedInvalidationState(); if (MyBackendId > MaxBackends || MyBackendId <= 0) elog(FATAL, "bad backend id: %d", MyBackendId); /* * bufmgr needs another initialization call too */ InitBufferPoolBackend(); /* * Initialize local process's access to XLOG. In bootstrap case we may * skip this since StartupXLOG() was run instead. */ if (!bootstrap) InitXLOGAccess(); /* * Initialize the relation descriptor cache. This must create at least * the minimum set of "nailed-in" cache entries. No catalog access * happens here. */ RelationCacheInitialize(); /* * Initialize all the system catalog caches. Note that no catalog access * happens here; we only set up the cache structure. */ InitCatalogCache(); /* Initialize portal manager */ EnablePortalManager(); /* * Set up process-exit callback to do pre-shutdown cleanup. This has to * be after we've initialized all the low-level modules like the buffer * manager, because during shutdown this has to run before the low-level * modules start to close down. On the other hand, we want it in place * before we begin our first transaction --- if we fail during the * initialization transaction, as is entirely possible, we need the * AbortTransaction call to clean up. */ on_shmem_exit(ShutdownPostgres, 0); /* start a new transaction here before access to db */ if (!bootstrap) StartTransactionCommand(); /* * It's now possible to do real access to the system catalogs. * * Replace faked-up relcache entries with correct info. */ RelationCacheInitializePhase2(); /* * Figure out our postgres user id. In standalone mode and in the * autovacuum process, we use a fixed id, otherwise we figure it out from * the authenticated user name. */ if (bootstrap || autovacuum) InitializeSessionUserIdStandalone(); else if (!IsUnderPostmaster) { InitializeSessionUserIdStandalone(); if (!ThereIsAtLeastOneRole()) ereport(WARNING, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("no roles are defined in this database system"), errhint("You should immediately run CREATE USER \"%s\" CREATEUSER;.", username))); } else { /* normal multiuser case */ InitializeSessionUserId(username); } /* * Unless we are bootstrapping, double-check that InitMyDatabaseInfo() got * a correct result. We can't do this until all the database-access * infrastructure is up. (Also, it wants to know if the user is a * superuser, so the above stuff has to happen first.) */ if (!bootstrap) ReverifyMyDatabase(dbname); /* * Final phase of relation cache startup: write a new cache file if * necessary. This is done after ReverifyMyDatabase to avoid writing a * cache file into a dead database. */ RelationCacheInitializePhase3(); /* * Check if user is a superuser. */ if (bootstrap || autovacuum) am_superuser = true; else am_superuser = superuser(); /* * Check a normal user hasn't connected to a superuser reserved slot. */ if (!am_superuser && ReservedBackends > 0 && !HaveNFreeProcs(ReservedBackends)) ereport(FATAL, (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("connection limit exceeded for non-superusers"))); /* * Initialize various default states that can't be set up until we've * selected the active user and done ReverifyMyDatabase. */ /* set default namespace search path */ InitializeSearchPath(); /* set up ACL framework (currently just sets RolMemCache callback) */ initialize_acl(); /* initialize client encoding */ InitializeClientEncoding(); /* initialize statistics collection for this backend */ if (IsUnderPostmaster) pgstat_bestart(); /* close the transaction we started above */ if (!bootstrap) CommitTransactionCommand(); return am_superuser;}/* * Backend-shutdown callback. Do cleanup that we want to be sure happens * before all the supporting modules begin to nail their doors shut via * their own callbacks. * * User-level cleanup, such as temp-relation removal and UNLISTEN, happens * via separate callbacks that execute before this one. We don't combine the * callbacks because we still want this one to happen if the user-level * cleanup fails. */static voidShutdownPostgres(int code, Datum arg){ /* Make sure we've killed any active transaction */ AbortOutOfAnyTransaction(); /* * User locks are not released by transaction end, so be sure to release * them explicitly. */#ifdef USER_LOCKS LockReleaseAll(USER_LOCKMETHOD, true);#endif}/* * Returns true if at least one role is defined in this database cluster. */static boolThereIsAtLeastOneRole(void){ Relation pg_authid_rel; HeapScanDesc scan; bool result; pg_authid_rel = heap_open(AuthIdRelationId, AccessExclusiveLock); scan = heap_beginscan(pg_authid_rel, SnapshotNow, 0, NULL); result = (heap_getnext(scan, ForwardScanDirection) != NULL); heap_endscan(scan); heap_close(pg_authid_rel, AccessExclusiveLock); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -