OSDN Git Service

pgindent run on all C files. Java run to follow. initdb/regression
[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.95 2001/10/25 05:49:51 momjian 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                 /*
225                  * Formerly we validated DataDir here, but now that's done
226                  * earlier.
227                  */
228
229                 /*
230                  * Find oid and path of the database we're about to open. Since
231                  * we're not yet up and running we have to use the hackish
232                  * GetRawDatabaseInfo.
233                  */
234                 GetRawDatabaseInfo(dbname, &MyDatabaseId, datpath);
235
236                 if (!OidIsValid(MyDatabaseId))
237                         elog(FATAL,
238                                  "Database \"%s\" does not exist in the system catalog.",
239                                  dbname);
240
241                 fullpath = GetDatabasePath(MyDatabaseId);
242
243                 /* Verify the database path */
244
245                 if (access(fullpath, F_OK) == -1)
246                         elog(FATAL, "Database \"%s\" does not exist.\n\t"
247                                  "The database subdirectory '%s' is missing.",
248                                  dbname, fullpath);
249
250                 ValidatePgVersion(fullpath);
251
252                 if (chdir(fullpath) == -1)
253                         elog(FATAL, "Unable to change directory to '%s': %m", fullpath);
254
255                 SetDatabasePath(fullpath);
256         }
257
258         /*
259          * Code after this point assumes we are in the proper directory!
260          */
261
262         /*
263          * Set up my per-backend PROC struct in shared memory.  (We need to
264          * know MyDatabaseId before we can do this, since it's entered into
265          * the PROC struct.)
266          */
267         InitProcess();
268
269         /*
270          * Initialize my entry in the shared-invalidation manager's array of
271          * per-backend data.  (Formerly this came before InitProcess, but now
272          * it must happen after, because it uses MyProc.)  Once I have done
273          * this, I am visible to other backends!
274          *
275          * Sets up MyBackendId, a unique backend identifier.
276          */
277         MyBackendId = InvalidBackendId;
278
279         InitBackendSharedInvalidationState();
280
281         if (MyBackendId > MaxBackends || MyBackendId <= 0)
282                 elog(FATAL, "InitPostgres: bad backend id %d", MyBackendId);
283
284         /*
285          * Initialize the transaction system override state.
286          */
287         AmiTransactionOverride(bootstrap);
288
289         /*
290          * Initialize the relation descriptor cache. The pre-allocated
291          * reldescs are created here.
292          */
293         RelationCacheInitialize();
294
295         /*
296          * Initialize the access methods. Does not touch files (?) - thomas
297          * 1997-11-01
298          */
299         initam();
300
301         /*
302          * Initialize all the system catalog caches.
303          *
304          * Does not touch files since all routines are builtins (?) - thomas
305          * 1997-11-01
306          */
307         InitCatalogCache();
308
309         /* Initialize portal manager */
310         EnablePortalManager();
311
312         /*
313          * Initialize the deferred trigger manager --- must happen before
314          * first transaction start.
315          */
316         DeferredTriggerInit();
317
318         /* start a new transaction here before access to db */
319         if (!bootstrap)
320                 StartTransactionCommand();
321
322         /* replace faked-up relcache entries with the real info */
323         RelationCacheInitializePhase2();
324
325         /*
326          * Figure out our postgres user id.  In standalone mode we use a fixed
327          * id, otherwise we figure it out from the authenticated user name.
328          */
329         if (bootstrap)
330                 InitializeSessionUserIdStandalone();
331         else if (!IsUnderPostmaster)
332         {
333                 InitializeSessionUserIdStandalone();
334                 if (!ThereIsAtLeastOneUser())
335                 {
336                         elog(NOTICE, "There are currently no users defined in this database system.");
337                         elog(NOTICE, "You should immediately run 'CREATE USER \"%s\" WITH SYSID %d CREATEUSER;'.",
338                                  username, BOOTSTRAP_USESYSID);
339                 }
340         }
341         else
342                 /* normal multiuser case */
343                 InitializeSessionUserId(username);
344
345         /*
346          * Unless we are bootstrapping, double-check that InitMyDatabaseInfo()
347          * got a correct result.  We can't do this until all the
348          * database-access infrastructure is up.
349          */
350         if (!bootstrap)
351                 ReverifyMyDatabase(dbname);
352
353 #ifdef MULTIBYTE
354         /* set default client encoding --- uses info from ReverifyMyDatabase */
355         set_default_client_encoding();
356 #endif
357
358         /*
359          * Set up process-exit callbacks to remove temp relations and then do
360          * pre-shutdown cleanup.  This should be last because we want
361          * shmem_exit to call these routines before the exit callbacks that
362          * are registered by buffer manager, lock manager, etc.  We need to
363          * run this code before we close down database access!
364          */
365         on_shmem_exit(ShutdownPostgres, 0);
366
367         /*
368          * because callbacks are called in reverse order, this gets done
369          * first:
370          */
371         on_shmem_exit(remove_all_temp_relations, 0);
372
373         /* close the transaction we started above */
374         if (!bootstrap)
375                 CommitTransactionCommand();
376 }
377
378 /*
379  * Backend-shutdown callback.  Do cleanup that we want to be sure happens
380  * before all the supporting modules begin to nail their doors shut via
381  * their own callbacks.  Note that because this has to be registered very
382  * late in startup, it will not get called if we suffer a failure *during*
383  * startup.
384  *
385  * User-level cleanup, such as temp-relation removal and UNLISTEN, happens
386  * via separate callbacks that execute before this one.  We don't combine the
387  * callbacks because we still want this one to happen if the user-level
388  * cleanup fails.
389  */
390 static void
391 ShutdownPostgres(void)
392 {
393         /*
394          * These operations are really just a minimal subset of
395          * AbortTransaction(). We don't want to do any inessential cleanup,
396          * since that just raises the odds of failure --- but there's some
397          * stuff we need to do.
398          *
399          * Release any LW locks and buffer context locks we might be holding.
400          * This is a kluge to improve the odds that we won't get into a
401          * self-made stuck-lock scenario while trying to shut down.
402          */
403         LWLockReleaseAll();
404         AbortBufferIO();
405         UnlockBuffers();
406
407         /*
408          * In case a transaction is open, delete any files it created.  This
409          * has to happen before bufmgr shutdown, so having smgr register a
410          * callback for it wouldn't work.
411          */
412         smgrDoPendingDeletes(false);            /* delete as though aborting xact */
413 }
414
415
416
417 /*
418  * Returns true if at least one user is defined in this database cluster.
419  */
420 static bool
421 ThereIsAtLeastOneUser(void)
422 {
423         Relation        pg_shadow_rel;
424         TupleDesc       pg_shadow_dsc;
425         HeapScanDesc scan;
426         bool            result;
427
428         pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
429         pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
430
431         scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, 0);
432         result = HeapTupleIsValid(heap_getnext(scan, 0));
433
434         heap_endscan(scan);
435         heap_close(pg_shadow_rel, AccessExclusiveLock);
436
437         return result;
438 }