1 /*-------------------------------------------------------------------------
4 * postgres initialization utilities
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.73 2000/11/28 23:27:57 tgl Exp $
14 *-------------------------------------------------------------------------
20 #include <sys/types.h>
24 #ifndef OLD_FILE_NAMING
25 #include "catalog/catalog.h"
28 #include "access/heapam.h"
29 #include "catalog/catname.h"
30 #include "catalog/pg_database.h"
31 #include "miscadmin.h"
32 #include "storage/backendid.h"
33 #include "storage/proc.h"
34 #include "storage/sinval.h"
35 #include "storage/smgr.h"
36 #include "utils/fmgroids.h"
37 #include "utils/portal.h"
38 #include "utils/relcache.h"
39 #include "utils/syscache.h"
42 #include "mb/pg_wchar.h"
45 static void ReverifyMyDatabase(const char *name);
46 static void InitCommunication(void);
49 /*** InitPostgres support ***/
52 /* --------------------------------
55 * Since we are forced to fetch the database OID out of pg_database without
56 * benefit of locking or transaction ID checking (see utils/misc/database.c),
57 * we might have gotten a wrong answer. Or, we might have attached to a
58 * database that's in process of being destroyed by destroydb(). This
59 * routine is called after we have all the locking and other infrastructure
60 * running --- now we can check that we are really attached to a valid
63 * In reality, if destroydb() is running in parallel with our startup,
64 * it's pretty likely that we will have failed before now, due to being
65 * unable to read some of the system tables within the doomed database.
66 * This routine just exists to make *sure* we have not started up in an
67 * invalid database. If we quit now, we should have managed to avoid
68 * creating any serious problems.
70 * This is also a handy place to fetch the database encoding info out
71 * of pg_database, if we are in MULTIBYTE mode.
72 * --------------------------------
75 ReverifyMyDatabase(const char *name)
78 HeapScanDesc pgdbscan;
81 Form_pg_database dbform;
84 * Because we grab AccessShareLock here, we can be sure that destroydb
85 * is not running in parallel with us (any more).
87 pgdbrel = heap_openr(DatabaseRelationName, AccessShareLock);
89 ScanKeyEntryInitialize(&key, 0, Anum_pg_database_datname,
90 F_NAMEEQ, NameGetDatum(name));
92 pgdbscan = heap_beginscan(pgdbrel, 0, SnapshotNow, 1, &key);
94 tup = heap_getnext(pgdbscan, 0);
95 if (!HeapTupleIsValid(tup) ||
96 tup->t_data->t_oid != MyDatabaseId)
99 heap_close(pgdbrel, AccessShareLock);
102 * The only real problem I could have created is to load dirty
103 * buffers for the dead database into shared buffer cache; if I
104 * did, some other backend will eventually try to write them and
105 * die in mdblindwrt. Flush any such pages to forestall trouble.
107 DropBuffers(MyDatabaseId);
108 /* Now I can commit hara-kiri with a clear conscience... */
109 elog(FATAL, "Database \"%s\", OID %u, has disappeared from pg_database",
114 * Also check that the database is currently allowing connections.
116 dbform = (Form_pg_database) GETSTRUCT(tup);
117 if (! dbform->datallowconn)
118 elog(FATAL, "Database \"%s\" is not currently accepting connections",
122 * OK, we're golden. Only other to-do item is to save the MULTIBYTE
123 * encoding info out of the pg_database tuple.
126 SetDatabaseEncoding(dbform->encoding);
129 heap_endscan(pgdbscan);
130 heap_close(pgdbrel, AccessShareLock);
135 /* --------------------------------
138 * This routine initializes stuff needed for ipc, locking, etc.
139 * it should be called something more informative.
140 * --------------------------------
143 InitCommunication(void)
146 * initialize shared memory and semaphores appropriately.
149 if (!IsUnderPostmaster) /* postmaster already did this */
152 * we're running a postgres backend by itself with
153 * no front end or postmaster. Create private "shmem"
154 * and semaphores. Setting MaxBackends = 16 is arbitrary.
157 CreateSharedMemoryAndSemaphores(true, 16);
163 /* --------------------------------
165 * Initialize POSTGRES.
168 * Be very careful with the order of calls in the InitPostgres function.
169 * --------------------------------
171 int lockingOff = 0; /* backend -L switch */
176 InitPostgres(const char *dbname, const char *username)
178 bool bootstrap = IsBootstrapProcessingMode();
181 if (!TransactionFlushEnabled())
182 on_shmem_exit(FlushBufferPool, 0);
185 SetDatabaseName(dbname);
187 * initialize the database id used for system caches and lock tables
192 MyDatabaseId = TemplateDbOid;
193 #ifdef OLD_FILE_NAMING
194 SetDatabasePath(ExpandDatabasePath(dbname));
196 SetDatabasePath(GetDatabasePath(MyDatabaseId));
205 /* Verify if DataDir is ok */
206 if (access(DataDir, F_OK) == -1)
207 elog(FATAL, "Database system not found. Data directory '%s' does not exist.",
210 ValidatePgVersion(DataDir);
213 * Find oid and path of the database we're about to open. Since we're
214 * not yet up and running we have to use the hackish GetRawDatabaseInfo.
217 * The database's oid forms half of the unique key for the system
218 * caches and lock tables. We therefore want it initialized before
219 * we open any relations, since opening relations puts things in the
220 * cache. To get around this problem, this code opens and scans the
221 * pg_database relation by hand.
224 GetRawDatabaseInfo(dbname, &MyDatabaseId, datpath);
226 if (!OidIsValid(MyDatabaseId))
228 "Database \"%s\" does not exist in the system catalog.",
231 #ifdef OLD_FILE_NAMING
232 fullpath = ExpandDatabasePath(datpath);
234 elog(FATAL, "Database path could not be resolved.");
236 fullpath = GetDatabasePath(MyDatabaseId);
239 /* Verify the database path */
241 if (access(fullpath, F_OK) == -1)
242 elog(FATAL, "Database \"%s\" does not exist. The data directory '%s' is missing.",
245 ValidatePgVersion(fullpath);
247 if (chdir(fullpath) == -1)
248 elog(FATAL, "Unable to change directory to '%s': %s", fullpath, strerror(errno));
250 SetDatabasePath(fullpath);
254 * Code after this point assumes we are in the proper directory!
258 * Initialize the transaction system and the relation descriptor
259 * cache. Note we have to make certain the lock manager is off while
262 AmiTransactionOverride(IsBootstrapProcessingMode());
266 * Part of the initialization processing done here sets a read lock on
267 * pg_log. Since locking is disabled the set doesn't have intended
268 * effect of locking out writers, but this is ok, since we only lock
269 * it to examine AMI transaction status, and this is never written
270 * after initdb is done. -mer 15 June 1992
272 RelationCacheInitialize(); /* pre-allocated reldescs created here */
274 InitializeTransactionSystem(); /* pg_log,etc init/crash recovery
280 * Set up my per-backend PROC struct in shared memory.
285 * Initialize my entry in the shared-invalidation manager's array of
286 * per-backend data. (Formerly this came before InitProcess, but now
287 * it must happen after, because it uses MyProc.) Once I have done
288 * this, I am visible to other backends!
290 * Sets up MyBackendId, a unique backend identifier.
292 MyBackendId = InvalidBackendId;
294 InitBackendSharedInvalidationState();
296 if (MyBackendId > MAXBACKENDS || MyBackendId <= 0)
297 elog(FATAL, "cinit2: bad backend id %d", MyBackendId);
300 * Initialize the access methods. Does not touch files (?) - thomas
306 * Initialize all the system catalog caches.
308 * Does not touch files since all routines are builtins (?) - thomas
313 /* start a new transaction here before access to db */
315 StartTransactionCommand();
317 /* replace faked-up relcache entries with the real info */
318 RelationCacheInitializePhase2();
324 * Set ourselves to the proper user id and figure out our postgres
328 SetSessionUserId(geteuid());
330 SetSessionUserIdFromUserName(username);
335 * Unless we are bootstrapping, double-check that InitMyDatabaseInfo()
336 * got a correct result. We can't do this until essentially all the
337 * infrastructure is up, so just do it at the end.
340 ReverifyMyDatabase(dbname);
347 * Attach to shared memory and semaphores, and initialize our
348 * input/output/debugging file descriptors.
355 EnablePortalManager(); /* memory for portal/transaction stuff */
357 /* initialize the local buffer manager */