OSDN Git Service

Implement new 'lightweight lock manager' that's intermediate between
[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-2001, 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.93 2001/09/29 04:02:25 tgl Exp $
12  *
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17
18 #include <fcntl.h>
19 #include <sys/file.h>
20 #include <sys/types.h>
21 #include <math.h>
22 #include <unistd.h>
23
24 #include "catalog/catalog.h"
25 #include "access/heapam.h"
26 #include "catalog/catname.h"
27 #include "catalog/pg_database.h"
28 #include "catalog/pg_shadow.h"
29 #include "commands/trigger.h"
30 #include "commands/variable.h"  /* for set_default_client_encoding() */
31 #include "mb/pg_wchar.h"
32 #include "miscadmin.h"
33 #include "storage/backendid.h"
34 #include "storage/proc.h"
35 #include "storage/sinval.h"
36 #include "storage/smgr.h"
37 #include "utils/fmgroids.h"
38 #include "utils/portal.h"
39 #include "utils/relcache.h"
40 #include "utils/syscache.h"
41 #include "utils/temprel.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, if we are in MULTIBYTE mode.
73  * --------------------------------
74  */
75 static void
76 ReverifyMyDatabase(const char *name)
77 {
78         Relation        pgdbrel;
79         HeapScanDesc pgdbscan;
80         ScanKeyData key;
81         HeapTuple       tup;
82         Form_pg_database dbform;
83
84         /*
85          * Because we grab AccessShareLock here, we can be sure that destroydb
86          * is not running in parallel with us (any more).
87          */
88         pgdbrel = heap_openr(DatabaseRelationName, AccessShareLock);
89
90         ScanKeyEntryInitialize(&key, 0, Anum_pg_database_datname,
91                                                    F_NAMEEQ, NameGetDatum(name));
92
93         pgdbscan = heap_beginscan(pgdbrel, 0, SnapshotNow, 1, &key);
94
95         tup = heap_getnext(pgdbscan, 0);
96         if (!HeapTupleIsValid(tup) ||
97                 tup->t_data->t_oid != MyDatabaseId)
98         {
99                 /* OOPS */
100                 heap_close(pgdbrel, AccessShareLock);
101
102                 /*
103                  * The only real problem I could have created is to load dirty
104                  * buffers for the dead database into shared buffer cache; if I
105                  * did, some other backend will eventually try to write them and
106                  * die in mdblindwrt.  Flush any such pages to forestall trouble.
107                  */
108                 DropBuffers(MyDatabaseId);
109                 /* Now I can commit hara-kiri with a clear conscience... */
110                 elog(FATAL, "Database \"%s\", OID %u, has disappeared from pg_database",
111                          name, MyDatabaseId);
112         }
113
114         /*
115          * Also check that the database is currently allowing connections.
116          */
117         dbform = (Form_pg_database) GETSTRUCT(tup);
118         if (!dbform->datallowconn)
119                 elog(FATAL, "Database \"%s\" is not currently accepting connections",
120                          name);
121
122         /*
123          * OK, we're golden.  Only other to-do item is to save the MULTIBYTE
124          * encoding info out of the pg_database tuple --- or complain, if we
125          * can't support it.
126          */
127 #ifdef MULTIBYTE
128         SetDatabaseEncoding(dbform->encoding);
129 #else
130         if (dbform->encoding != PG_SQL_ASCII)
131                 elog(FATAL, "database was initialized with MULTIBYTE encoding %d,\n\tbut the backend was compiled without multibyte support.\n\tlooks like you need to initdb or recompile.",
132                          dbform->encoding);
133 #endif
134
135         heap_endscan(pgdbscan);
136         heap_close(pgdbrel, AccessShareLock);
137 }
138
139
140
141 /* --------------------------------
142  *              InitCommunication
143  *
144  *              This routine initializes stuff needed for ipc, locking, etc.
145  *              it should be called something more informative.
146  * --------------------------------
147  */
148 static void
149 InitCommunication(void)
150 {
151         /*
152          * initialize shared memory and semaphores appropriately.
153          */
154         if (!IsUnderPostmaster)         /* postmaster already did this */
155         {
156                 /*
157                  * we're running a postgres backend by itself with no front end or
158                  * postmaster.  Create private "shmem" and semaphores.  Setting
159                  * MaxBackends = 16 is arbitrary.
160                  */
161                 CreateSharedMemoryAndSemaphores(true, 16);
162         }
163 }
164
165
166 /*
167  * Early initialization of a backend (either standalone or under postmaster).
168  * This happens even before InitPostgres.
169  *
170  * If you're wondering why this is separate from InitPostgres at all:
171  * the critical distinction is that this stuff has to happen before we can
172  * run XLOG-related initialization, which is done before InitPostgres --- in
173  * fact, for cases such as checkpoint creation processes, InitPostgres may
174  * never be done at all.
175  */
176 void
177 BaseInit(void)
178 {
179         /*
180          * Attach to shared memory and semaphores, and initialize our
181          * input/output/debugging file descriptors.
182          */
183         InitCommunication();
184         DebugFileOpen();
185
186         /* Do local initialization of storage and buffer managers */
187         smgrinit();
188         InitBufferPoolAccess();
189         InitLocalBuffer();
190 }
191
192
193 /* --------------------------------
194  * InitPostgres
195  *              Initialize POSTGRES.
196  *
197  * Note:
198  *              Be very careful with the order of calls in the InitPostgres function.
199  * --------------------------------
200  */
201 void
202 InitPostgres(const char *dbname, const char *username)
203 {
204         bool            bootstrap = IsBootstrapProcessingMode();
205
206         /*
207          * Set up the global variables holding database name, id, and path.
208          *
209          * We take a shortcut in the bootstrap case, otherwise we have to look up
210          * the db name in pg_database.
211          */
212         SetDatabaseName(dbname);
213
214         if (bootstrap)
215         {
216                 MyDatabaseId = TemplateDbOid;
217                 SetDatabasePath(GetDatabasePath(MyDatabaseId));
218         }
219         else
220         {
221                 char       *fullpath,
222                                         datpath[MAXPGPATH];
223
224                 /* Verify if DataDir is ok */
225                 if (access(DataDir, F_OK) == -1)
226                         elog(FATAL, "Database system not found.\n\t"
227                                  "Data directory '%s' does not exist.",
228                                  DataDir);
229
230                 ValidatePgVersion(DataDir);
231
232                 /*
233                  * Find oid and path of the database we're about to open. Since
234                  * we're not yet up and running we have to use the hackish
235                  * GetRawDatabaseInfo.
236                  */
237                 GetRawDatabaseInfo(dbname, &MyDatabaseId, datpath);
238
239                 if (!OidIsValid(MyDatabaseId))
240                         elog(FATAL,
241                                  "Database \"%s\" does not exist in the system catalog.",
242                                  dbname);
243
244                 fullpath = GetDatabasePath(MyDatabaseId);
245
246                 /* Verify the database path */
247
248                 if (access(fullpath, F_OK) == -1)
249                         elog(FATAL, "Database \"%s\" does not exist.\n\t"
250                                  "The database subdirectory '%s' is missing.",
251                                  dbname, fullpath);
252
253                 ValidatePgVersion(fullpath);
254
255                 if (chdir(fullpath) == -1)
256                         elog(FATAL, "Unable to change directory to '%s': %m", fullpath);
257
258                 SetDatabasePath(fullpath);
259         }
260
261         /*
262          * Code after this point assumes we are in the proper directory!
263          */
264
265         /*
266          * Set up my per-backend PROC struct in shared memory.  (We need to
267          * know MyDatabaseId before we can do this, since it's entered into
268          * the PROC struct.)
269          */
270         InitProcess();
271
272         /*
273          * Initialize my entry in the shared-invalidation manager's array of
274          * per-backend data.  (Formerly this came before InitProcess, but now
275          * it must happen after, because it uses MyProc.)  Once I have done
276          * this, I am visible to other backends!
277          *
278          * Sets up MyBackendId, a unique backend identifier.
279          */
280         MyBackendId = InvalidBackendId;
281
282         InitBackendSharedInvalidationState();
283
284         if (MyBackendId > MaxBackends || MyBackendId <= 0)
285                 elog(FATAL, "InitPostgres: bad backend id %d", MyBackendId);
286
287         /*
288          * Initialize the transaction system override state.
289          */
290         AmiTransactionOverride(bootstrap);
291
292         /*
293          * Initialize the relation descriptor cache.
294          * The pre-allocated reldescs are created here.
295          */
296         RelationCacheInitialize();
297
298         /*
299          * Initialize the access methods. Does not touch files (?) - thomas
300          * 1997-11-01
301          */
302         initam();
303
304         /*
305          * Initialize all the system catalog caches.
306          *
307          * Does not touch files since all routines are builtins (?) - thomas
308          * 1997-11-01
309          */
310         InitCatalogCache();
311
312         /* Initialize portal manager */
313         EnablePortalManager();
314
315         /*
316          * Initialize the deferred trigger manager --- must happen before
317          * first transaction start.
318          */
319         DeferredTriggerInit();
320
321         /* start a new transaction here before access to db */
322         if (!bootstrap)
323                 StartTransactionCommand();
324
325         /* replace faked-up relcache entries with the real info */
326         RelationCacheInitializePhase2();
327
328         /*
329          * Figure out our postgres user id.  In standalone mode we use a
330          * fixed id, otherwise we figure it out from the authenticated
331          * user name.
332          */
333         if (bootstrap)
334                 InitializeSessionUserIdStandalone();
335         else if (!IsUnderPostmaster)
336         {
337                 InitializeSessionUserIdStandalone();
338                 if (!ThereIsAtLeastOneUser())
339                 {
340                         elog(NOTICE, "There are currently no users defined in this database system.");
341                         elog(NOTICE, "You should immediately run 'CREATE USER \"%s\" WITH SYSID %d CREATEUSER;'.",
342                                  username, BOOTSTRAP_USESYSID);
343                 }
344         }
345         else
346                 /* normal multiuser case */
347                 InitializeSessionUserId(username);
348
349         /*
350          * Unless we are bootstrapping, double-check that InitMyDatabaseInfo()
351          * got a correct result.  We can't do this until all the
352          * database-access infrastructure is up.
353          */
354         if (!bootstrap)
355                 ReverifyMyDatabase(dbname);
356
357 #ifdef MULTIBYTE
358         /* set default client encoding --- uses info from ReverifyMyDatabase */
359         set_default_client_encoding();
360 #endif
361
362         /*
363          * Set up process-exit callbacks to remove temp relations and then do
364          * pre-shutdown cleanup.  This should be last because we want
365          * shmem_exit to call these routines before the exit callbacks that
366          * are registered by buffer manager, lock manager, etc.  We need to
367          * run this code before we close down database access!
368          */
369         on_shmem_exit(ShutdownPostgres, 0);
370
371         /*
372          * because callbacks are called in reverse order, this gets done
373          * first:
374          */
375         on_shmem_exit(remove_all_temp_relations, 0);
376
377         /* close the transaction we started above */
378         if (!bootstrap)
379                 CommitTransactionCommand();
380 }
381
382 /*
383  * Backend-shutdown callback.  Do cleanup that we want to be sure happens
384  * before all the supporting modules begin to nail their doors shut via
385  * their own callbacks.  Note that because this has to be registered very
386  * late in startup, it will not get called if we suffer a failure *during*
387  * startup.
388  *
389  * User-level cleanup, such as temp-relation removal and UNLISTEN, happens
390  * via separate callbacks that execute before this one.  We don't combine the
391  * callbacks because we still want this one to happen if the user-level
392  * cleanup fails.
393  */
394 static void
395 ShutdownPostgres(void)
396 {
397
398         /*
399          * These operations are really just a minimal subset of
400          * AbortTransaction(). We don't want to do any inessential cleanup,
401          * since that just raises the odds of failure --- but there's some
402          * stuff we need to do.
403          *
404          * Release any LW locks and buffer context locks we might be holding.
405          * This is a kluge to improve the odds that we won't get into a
406          * self-made stuck-lock scenario while trying to shut down.
407          */
408         LWLockReleaseAll();
409         AbortBufferIO();
410         UnlockBuffers();
411
412         /*
413          * In case a transaction is open, delete any files it created.  This
414          * has to happen before bufmgr shutdown, so having smgr register a
415          * callback for it wouldn't work.
416          */
417         smgrDoPendingDeletes(false);/* delete as though aborting xact */
418 }
419
420
421
422 /*
423  * Returns true if at least one user is defined in this database cluster.
424  */
425 static bool
426 ThereIsAtLeastOneUser(void)
427 {
428         Relation        pg_shadow_rel;
429         TupleDesc       pg_shadow_dsc;
430         HeapScanDesc scan;
431         bool            result;
432
433         pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
434         pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
435
436         scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, 0);
437         result = HeapTupleIsValid(heap_getnext(scan, 0));
438
439         heap_endscan(scan);
440         heap_close(pg_shadow_rel, AccessExclusiveLock);
441
442         return result;
443 }