OSDN Git Service

In the continuing saga of FE/BE protocol revisions, add reporting of
[pg-rex/syncrep.git] / src / backend / utils / init / postinit.c
1 /*-------------------------------------------------------------------------
2  *
3  * postinit.c
4  *        postgres initialization utilities
5  *
6  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.120 2003/04/25 19:45:08 tgl Exp $
12  *
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17
18 #include <fcntl.h>
19 #include <sys/file.h>
20 #include <math.h>
21 #include <unistd.h>
22
23 #include "catalog/catalog.h"
24 #include "access/heapam.h"
25 #include "catalog/catname.h"
26 #include "catalog/namespace.h"
27 #include "catalog/pg_database.h"
28 #include "catalog/pg_shadow.h"
29 #include "commands/trigger.h"
30 #include "mb/pg_wchar.h"
31 #include "miscadmin.h"
32 #include "storage/backendid.h"
33 #include "storage/ipc.h"
34 #include "storage/proc.h"
35 #include "storage/sinval.h"
36 #include "storage/smgr.h"
37 #include "utils/fmgroids.h"
38 #include "utils/guc.h"
39 #include "utils/portal.h"
40 #include "utils/relcache.h"
41 #include "utils/syscache.h"
42
43
44 static void ReverifyMyDatabase(const char *name);
45 static void InitCommunication(void);
46 static void ShutdownPostgres(void);
47 static bool ThereIsAtLeastOneUser(void);
48
49
50 /*** InitPostgres support ***/
51
52
53 /* --------------------------------
54  *              ReverifyMyDatabase
55  *
56  * Since we are forced to fetch the database OID out of pg_database without
57  * benefit of locking or transaction ID checking (see utils/misc/database.c),
58  * we might have gotten a wrong answer.  Or, we might have attached to a
59  * database that's in process of being destroyed by destroydb().  This
60  * routine is called after we have all the locking and other infrastructure
61  * running --- now we can check that we are really attached to a valid
62  * database.
63  *
64  * In reality, if destroydb() is running in parallel with our startup,
65  * it's pretty likely that we will have failed before now, due to being
66  * unable to read some of the system tables within the doomed database.
67  * This routine just exists to make *sure* we have not started up in an
68  * invalid database.  If we quit now, we should have managed to avoid
69  * creating any serious problems.
70  *
71  * This is also a handy place to fetch the database encoding info out
72  * of pg_database.
73  *
74  * To avoid having to read pg_database more times than necessary
75  * during session startup, this place is also fitting to set up any
76  * database-specific configuration variables.
77  * --------------------------------
78  */
79 static void
80 ReverifyMyDatabase(const char *name)
81 {
82         Relation        pgdbrel;
83         HeapScanDesc pgdbscan;
84         ScanKeyData key;
85         HeapTuple       tup;
86         Form_pg_database dbform;
87
88         /*
89          * Because we grab AccessShareLock here, we can be sure that destroydb
90          * is not running in parallel with us (any more).
91          */
92         pgdbrel = heap_openr(DatabaseRelationName, AccessShareLock);
93
94         ScanKeyEntryInitialize(&key, 0, Anum_pg_database_datname,
95                                                    F_NAMEEQ, NameGetDatum(name));
96
97         pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);
98
99         tup = heap_getnext(pgdbscan, ForwardScanDirection);
100         if (!HeapTupleIsValid(tup) ||
101                 HeapTupleGetOid(tup) != MyDatabaseId)
102         {
103                 /* OOPS */
104                 heap_close(pgdbrel, AccessShareLock);
105
106                 /*
107                  * The only real problem I could have created is to load dirty
108                  * buffers for the dead database into shared buffer cache; if I
109                  * did, some other backend will eventually try to write them and
110                  * die in mdblindwrt.  Flush any such pages to forestall trouble.
111                  */
112                 DropBuffers(MyDatabaseId);
113                 /* Now I can commit hara-kiri with a clear conscience... */
114                 elog(FATAL, "Database \"%s\", OID %u, has disappeared from pg_database",
115                          name, MyDatabaseId);
116         }
117
118         /*
119          * Also check that the database is currently allowing connections.
120          */
121         dbform = (Form_pg_database) GETSTRUCT(tup);
122         if (!dbform->datallowconn)
123                 elog(FATAL, "Database \"%s\" is not currently accepting connections",
124                          name);
125
126         /*
127          * OK, we're golden.  Only other to-do item is to save the encoding
128          * info out of the pg_database tuple.
129          */
130         SetDatabaseEncoding(dbform->encoding);
131         /* Record it as a GUC internal option, too */
132         SetConfigOption("server_encoding", GetDatabaseEncodingName(),
133                                         PGC_INTERNAL, PGC_S_OVERRIDE);
134         /* If we have no other source of client_encoding, use server encoding */
135         SetConfigOption("client_encoding", GetDatabaseEncodingName(),
136                                         PGC_BACKEND, PGC_S_DEFAULT);
137
138         /*
139          * Set up database-specific configuration variables.
140          */
141         if (IsUnderPostmaster)
142         {
143                 Datum           datum;
144                 bool            isnull;
145
146                 datum = heap_getattr(tup, Anum_pg_database_datconfig,
147                                                          RelationGetDescr(pgdbrel), &isnull);
148                 if (!isnull)
149                 {
150                         ArrayType  *a = DatumGetArrayTypeP(datum);
151
152                         ProcessGUCArray(a, PGC_S_DATABASE);
153                 }
154         }
155
156         heap_endscan(pgdbscan);
157         heap_close(pgdbrel, AccessShareLock);
158 }
159
160
161
162 /* --------------------------------
163  *              InitCommunication
164  *
165  *              This routine initializes stuff needed for ipc, locking, etc.
166  *              it should be called something more informative.
167  * --------------------------------
168  */
169 static void
170 InitCommunication(void)
171 {
172         /*
173          * initialize shared memory and semaphores appropriately.
174          */
175         if (!IsUnderPostmaster)         /* postmaster already did this */
176         {
177                 /*
178                  * We're running a postgres bootstrap process or a standalone backend.
179                  * Create private "shmem" and semaphores.  Force MaxBackends to 1 so
180                  * that we don't allocate more resources than necessary.
181                  */
182                 SetConfigOption("max_connections", "1",
183                                                 PGC_POSTMASTER, PGC_S_OVERRIDE);
184
185                 CreateSharedMemoryAndSemaphores(true, MaxBackends, 0);
186         }
187 }
188
189
190 /*
191  * Early initialization of a backend (either standalone or under postmaster).
192  * This happens even before InitPostgres.
193  *
194  * If you're wondering why this is separate from InitPostgres at all:
195  * the critical distinction is that this stuff has to happen before we can
196  * run XLOG-related initialization, which is done before InitPostgres --- in
197  * fact, for cases such as checkpoint creation processes, InitPostgres may
198  * never be done at all.
199  */
200 void
201 BaseInit(void)
202 {
203         /*
204          * Attach to shared memory and semaphores, and initialize our
205          * input/output/debugging file descriptors.
206          */
207         InitCommunication();
208         DebugFileOpen();
209
210         /* Do local initialization of storage and buffer managers */
211         smgrinit();
212         InitBufferPoolAccess();
213         InitLocalBuffer();
214 }
215
216
217 /* --------------------------------
218  * InitPostgres
219  *              Initialize POSTGRES.
220  *
221  * Note:
222  *              Be very careful with the order of calls in the InitPostgres function.
223  * --------------------------------
224  */
225 void
226 InitPostgres(const char *dbname, const char *username)
227 {
228         bool            bootstrap = IsBootstrapProcessingMode();
229
230         /*
231          * Set up the global variables holding database name, id, and path.
232          *
233          * We take a shortcut in the bootstrap case, otherwise we have to look up
234          * the db name in pg_database.
235          */
236         SetDatabaseName(dbname);
237
238         if (bootstrap)
239         {
240                 MyDatabaseId = TemplateDbOid;
241                 SetDatabasePath(GetDatabasePath(MyDatabaseId));
242         }
243         else
244         {
245                 char       *fullpath,
246                                         datpath[MAXPGPATH];
247
248                 /*
249                  * Formerly we validated DataDir here, but now that's done
250                  * earlier.
251                  */
252
253                 /*
254                  * Find oid and path of the database we're about to open. Since
255                  * we're not yet up and running we have to use the hackish
256                  * GetRawDatabaseInfo.
257                  */
258                 GetRawDatabaseInfo(dbname, &MyDatabaseId, datpath);
259
260                 if (!OidIsValid(MyDatabaseId))
261                         elog(FATAL,
262                                  "Database \"%s\" does not exist in the system catalog.",
263                                  dbname);
264
265                 fullpath = GetDatabasePath(MyDatabaseId);
266
267                 /* Verify the database path */
268
269                 if (access(fullpath, F_OK) == -1)
270                         elog(FATAL, "Database \"%s\" does not exist.\n\t"
271                                  "The database subdirectory '%s' is missing.",
272                                  dbname, fullpath);
273
274                 ValidatePgVersion(fullpath);
275
276                 if (chdir(fullpath) == -1)
277                         elog(FATAL, "Unable to change directory to '%s': %m", fullpath);
278
279                 SetDatabasePath(fullpath);
280         }
281
282         /*
283          * Code after this point assumes we are in the proper directory!
284          */
285
286         /*
287          * Set up my per-backend PGPROC struct in shared memory.        (We need
288          * to know MyDatabaseId before we can do this, since it's entered into
289          * the PGPROC struct.)
290          */
291         InitProcess();
292
293         /*
294          * Initialize my entry in the shared-invalidation manager's array of
295          * per-backend data.  (Formerly this came before InitProcess, but now
296          * it must happen after, because it uses MyProc.)  Once I have done
297          * this, I am visible to other backends!
298          *
299          * Sets up MyBackendId, a unique backend identifier.
300          */
301         MyBackendId = InvalidBackendId;
302
303         InitBackendSharedInvalidationState();
304
305         if (MyBackendId > MaxBackends || MyBackendId <= 0)
306                 elog(FATAL, "InitPostgres: bad backend id %d", MyBackendId);
307
308         /*
309          * Initialize the transaction system override state.
310          */
311         AmiTransactionOverride(bootstrap);
312
313         /*
314          * Initialize the relation descriptor cache.  This must create at
315          * least the minimum set of "nailed-in" cache entries.  No catalog
316          * access happens here.
317          */
318         RelationCacheInitialize();
319
320         /*
321          * Initialize all the system catalog caches.  Note that no catalog
322          * access happens here; we only set up the cache structure.
323          */
324         InitCatalogCache();
325
326         /* Initialize portal manager */
327         EnablePortalManager();
328
329         /*
330          * Initialize the deferred trigger manager --- must happen before
331          * first transaction start.
332          */
333         DeferredTriggerInit();
334
335         /* start a new transaction here before access to db */
336         if (!bootstrap)
337                 StartTransactionCommand(true);
338
339         /*
340          * It's now possible to do real access to the system catalogs.
341          *
342          * Replace faked-up relcache entries with correct info.
343          */
344         RelationCacheInitializePhase2();
345
346         /*
347          * Figure out our postgres user id.  In standalone mode we use a fixed
348          * id, otherwise we figure it out from the authenticated user name.
349          */
350         if (bootstrap)
351                 InitializeSessionUserIdStandalone();
352         else if (!IsUnderPostmaster)
353         {
354                 InitializeSessionUserIdStandalone();
355                 if (!ThereIsAtLeastOneUser())
356                 {
357                         elog(WARNING, "There are currently no users defined in this database system.");
358                         elog(WARNING, "You should immediately run 'CREATE USER \"%s\" WITH SYSID %d CREATEUSER;'.",
359                                  username, BOOTSTRAP_USESYSID);
360                 }
361         }
362         else
363         {
364                 /* normal multiuser case */
365                 InitializeSessionUserId(username);
366         }
367
368         /*
369          * Unless we are bootstrapping, double-check that InitMyDatabaseInfo()
370          * got a correct result.  We can't do this until all the
371          * database-access infrastructure is up.
372          */
373         if (!bootstrap)
374                 ReverifyMyDatabase(dbname);
375
376         /*
377          * Final phase of relation cache startup: write a new cache file if
378          * necessary.  This is done after ReverifyMyDatabase to avoid writing
379          * a cache file into a dead database.
380          */
381         RelationCacheInitializePhase3();
382
383         /*
384          * Check a normal user hasn't connected to a superuser reserved slot.
385          * We can't do this till after we've read the user information, and
386          * we must do it inside a transaction since checking superuserness
387          * may require database access.  The superuser check is probably the
388          * most expensive part; don't do it until necessary.
389          */
390         if (ReservedBackends > 0 &&
391                 CountEmptyBackendSlots() < ReservedBackends &&
392                 !superuser())
393                 elog(FATAL, "Non-superuser connection limit exceeded");
394
395         /*
396          * Initialize various default states that can't be set up until we've
397          * selected the active user and done ReverifyMyDatabase.
398          */
399
400         /* set default namespace search path */
401         InitializeSearchPath();
402
403         /* initialize client encoding */
404         InitializeClientEncoding();
405
406         /*
407          * Now all default states are fully set up.  Report them to client
408          * if appropriate.
409          */
410         BeginReportingGUCOptions();
411
412         /*
413          * Set up process-exit callback to do pre-shutdown cleanup.  This
414          * should be last because we want shmem_exit to call this routine
415          * before the exit callbacks that are registered by buffer manager,
416          * lock manager, etc. We need to run this code before we close down
417          * database access!
418          */
419         on_shmem_exit(ShutdownPostgres, 0);
420
421         /* close the transaction we started above */
422         if (!bootstrap)
423                 CommitTransactionCommand(true);
424 }
425
426 /*
427  * Backend-shutdown callback.  Do cleanup that we want to be sure happens
428  * before all the supporting modules begin to nail their doors shut via
429  * their own callbacks.  Note that because this has to be registered very
430  * late in startup, it will not get called if we suffer a failure *during*
431  * startup.
432  *
433  * User-level cleanup, such as temp-relation removal and UNLISTEN, happens
434  * via separate callbacks that execute before this one.  We don't combine the
435  * callbacks because we still want this one to happen if the user-level
436  * cleanup fails.
437  */
438 static void
439 ShutdownPostgres(void)
440 {
441         /*
442          * These operations are really just a minimal subset of
443          * AbortTransaction(). We don't want to do any inessential cleanup,
444          * since that just raises the odds of failure --- but there's some
445          * stuff we need to do.
446          *
447          * Release any LW locks and buffer context locks we might be holding.
448          * This is a kluge to improve the odds that we won't get into a
449          * self-made stuck-lock scenario while trying to shut down.
450          */
451         LWLockReleaseAll();
452         AbortBufferIO();
453         UnlockBuffers();
454
455         /*
456          * In case a transaction is open, delete any files it created.  This
457          * has to happen before bufmgr shutdown, so having smgr register a
458          * callback for it wouldn't work.
459          */
460         smgrDoPendingDeletes(false);    /* delete as though aborting xact */
461 }
462
463
464
465 /*
466  * Returns true if at least one user is defined in this database cluster.
467  */
468 static bool
469 ThereIsAtLeastOneUser(void)
470 {
471         Relation        pg_shadow_rel;
472         TupleDesc       pg_shadow_dsc;
473         HeapScanDesc scan;
474         bool            result;
475
476         pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
477         pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
478
479         scan = heap_beginscan(pg_shadow_rel, SnapshotNow, 0, NULL);
480         result = (heap_getnext(scan, ForwardScanDirection) != NULL);
481
482         heap_endscan(scan);
483         heap_close(pg_shadow_rel, AccessExclusiveLock);
484
485         return result;
486 }