aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/dbcommands.c89
-rw-r--r--src/backend/commands/vacuum.c7
-rw-r--r--src/backend/libpq/hba.c50
-rw-r--r--src/backend/utils/init/flatfiles.c20
-rw-r--r--src/backend/utils/init/postinit.c88
-rw-r--r--src/backend/utils/misc/Makefile14
-rw-r--r--src/backend/utils/misc/database.c189
-rw-r--r--src/bin/initdb/initdb.c17
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/pg_proc.h6
-rw-r--r--src/include/libpq/hba.h11
-rw-r--r--src/include/miscadmin.h5
12 files changed, 184 insertions, 316 deletions
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 0962e32c5e1..474701fa573 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -3,13 +3,19 @@
* dbcommands.c
* Database management commands (create/drop database).
*
+ * Note: database creation/destruction commands take ExclusiveLock on
+ * pg_database to ensure that no two proceed in parallel. We must use
+ * at least this level of locking to ensure that no two backends try to
+ * write the flat-file copy of pg_database at once. We avoid using
+ * AccessExclusiveLock since there's no need to lock out ordinary readers
+ * of pg_database.
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.150 2005/02/20 02:21:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.151 2005/02/26 18:43:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -446,13 +452,13 @@ createdb(const CreatedbStmt *stmt)
/*
* Now OK to grab exclusive lock on pg_database.
*/
- pg_database_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
+ pg_database_rel = heap_openr(DatabaseRelationName, ExclusiveLock);
/* Check to see if someone else created same DB name meanwhile. */
if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
{
/* Don't hold lock while doing recursive remove */
- heap_close(pg_database_rel, AccessExclusiveLock);
+ heap_close(pg_database_rel, ExclusiveLock);
remove_dbtablespaces(dboid);
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_DATABASE),
@@ -498,13 +504,6 @@ createdb(const CreatedbStmt *stmt)
/* Update indexes */
CatalogUpdateIndexes(pg_database_rel, tuple);
- /*
- * Force dirty buffers out to disk, so that newly-connecting backends
- * will see the new database in pg_database right away. (They'll see
- * an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
- */
- FlushRelationBuffers(pg_database_rel, MaxBlockNumber);
-
/* Close pg_database, but keep exclusive lock till commit */
heap_close(pg_database_rel, NoLock);
@@ -542,12 +541,15 @@ dropdb(const char *dbname)
* Obtain exclusive lock on pg_database. We need this to ensure that
* no new backend starts up in the target database while we are
* deleting it. (Actually, a new backend might still manage to start
- * up, because it will read pg_database without any locking to
- * discover the database's OID. But it will detect its error in
- * ReverifyMyDatabase and shut down before any serious damage is done.
- * See postinit.c.)
+ * up, because it isn't able to lock pg_database while starting. But
+ * it will detect its error in ReverifyMyDatabase and shut down before
+ * any serious damage is done. See postinit.c.)
+ *
+ * An ExclusiveLock, rather than AccessExclusiveLock, is sufficient
+ * since ReverifyMyDatabase takes RowShareLock. This allows ordinary
+ * readers of pg_database to proceed in parallel.
*/
- pgdbrel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
+ pgdbrel = heap_openr(DatabaseRelationName, ExclusiveLock);
if (!get_db_info(dbname, &db_id, &db_owner, NULL,
&db_istemplate, NULL, NULL, NULL, NULL))
@@ -638,14 +640,6 @@ dropdb(const char *dbname)
*/
remove_dbtablespaces(db_id);
- /*
- * Force dirty buffers out to disk, so that newly-connecting backends
- * will see the database tuple marked dead in pg_database right away.
- * (They'll see an uncommitted deletion, but they don't care; see
- * GetRawDatabaseInfo.)
- */
- FlushRelationBuffers(pgdbrel, MaxBlockNumber);
-
/* Close pg_database, but keep exclusive lock till commit */
heap_close(pgdbrel, NoLock);
@@ -671,10 +665,10 @@ RenameDatabase(const char *oldname, const char *newname)
key2;
/*
- * Obtain AccessExclusiveLock so that no new session gets started
+ * Obtain ExclusiveLock so that no new session gets started
* while the rename is in progress.
*/
- rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
+ rel = heap_openr(DatabaseRelationName, ExclusiveLock);
ScanKeyInit(&key,
Anum_pg_database_datname,
@@ -742,14 +736,6 @@ RenameDatabase(const char *oldname, const char *newname)
systable_endscan(scan);
- /*
- * Force dirty buffers out to disk, so that newly-connecting backends
- * will see the renamed database in pg_database right away. (They'll
- * see an uncommitted tuple, but they don't care; see
- * GetRawDatabaseInfo.)
- */
- FlushRelationBuffers(rel, MaxBlockNumber);
-
/* Close pg_database, but keep exclusive lock till commit */
heap_close(rel, NoLock);
@@ -779,9 +765,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
valuestr = flatten_set_variable_args(stmt->variable, stmt->value);
/*
- * We need AccessExclusiveLock so we can safely do FlushRelationBuffers.
+ * We don't need ExclusiveLock since we aren't updating the
+ * flat file.
*/
- rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
+ rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
ScanKeyInit(&scankey,
Anum_pg_database_datname,
BTEqualStrategyNumber, F_NAMEEQ,
@@ -840,15 +827,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
systable_endscan(scan);
- /*
- * Force dirty buffers out to disk, so that newly-connecting backends
- * will see the altered row in pg_database right away. (They'll
- * see an uncommitted tuple, but they don't care; see
- * GetRawDatabaseInfo.)
- */
- FlushRelationBuffers(rel, MaxBlockNumber);
-
- /* Close pg_database, but keep exclusive lock till commit */
+ /* Close pg_database, but keep lock till commit */
heap_close(rel, NoLock);
/*
@@ -871,9 +850,10 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
Form_pg_database datForm;
/*
- * We need AccessExclusiveLock so we can safely do FlushRelationBuffers.
+ * We don't need ExclusiveLock since we aren't updating the
+ * flat file.
*/
- rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
+ rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
ScanKeyInit(&scankey,
Anum_pg_database_datname,
BTEqualStrategyNumber, F_NAMEEQ,
@@ -937,22 +917,11 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
CatalogUpdateIndexes(rel, newtuple);
heap_freetuple(newtuple);
-
- /* must release buffer pins before FlushRelationBuffers */
- systable_endscan(scan);
-
- /*
- * Force dirty buffers out to disk, so that newly-connecting backends
- * will see the altered row in pg_database right away. (They'll
- * see an uncommitted tuple, but they don't care; see
- * GetRawDatabaseInfo.)
- */
- FlushRelationBuffers(rel, MaxBlockNumber);
}
- else
- systable_endscan(scan);
- /* Close pg_database, but keep exclusive lock till commit */
+ systable_endscan(scan);
+
+ /* Close pg_database, but keep lock till commit */
heap_close(rel, NoLock);
/*
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index c818d8f9667..f4fbbae2ec8 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.301 2005/02/20 02:21:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.302 2005/02/26 18:43:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -704,11 +704,12 @@ vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples,
* We violate no-overwrite semantics here by storing new values for the
* statistics columns directly into the tuple that's already on the page.
* As with vac_update_relstats, this avoids leaving dead tuples behind
- * after a VACUUM; which is good since GetRawDatabaseInfo
- * can get confused by finding dead tuples in pg_database.
+ * after a VACUUM.
*
* This routine is shared by full and lazy VACUUM. Note that it is only
* applied after a database-wide VACUUM operation.
+ *
+ * Note that we don't bother to update the flat-file copy of pg_database.
*/
static void
vac_update_dbstats(Oid dbid,
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 9a65ee1610c..658b42bbfac 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -10,12 +10,13 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.139 2005/02/20 04:45:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.140 2005/02/26 18:43:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include <ctype.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/param.h>
@@ -37,6 +38,8 @@
#include "utils/guc.h"
+#define atooid(x) ((Oid) strtoul((x), NULL, 10))
+
/* Max size of username ident server can return */
#define IDENT_USERNAME_MAX 512
@@ -1059,6 +1062,51 @@ load_hba(void)
FreeFile(file);
}
+/*
+ * Read and parse one line from the flat pg_database file.
+ *
+ * Returns TRUE on success, FALSE if EOF; bad data causes elog(FATAL).
+ *
+ * Output parameters:
+ * dbname: gets database name (must be of size NAMEDATALEN bytes)
+ * dboid: gets database OID
+ * dbtablespace: gets database's default tablespace's OID
+ *
+ * This is not much related to the other functions in hba.c, but we put it
+ * here because it uses the next_token() infrastructure.
+ */
+bool
+read_pg_database_line(FILE *fp, char *dbname,
+ Oid *dboid, Oid *dbtablespace)
+{
+ char buf[MAX_TOKEN];
+
+ if (feof(fp))
+ return false;
+ next_token(fp, buf, sizeof(buf));
+ if (!buf[0])
+ return false;
+ if (strlen(buf) >= NAMEDATALEN)
+ elog(FATAL, "bad data in flat pg_database file");
+ strcpy(dbname, buf);
+ next_token(fp, buf, sizeof(buf));
+ if (!isdigit((unsigned char) buf[0]))
+ elog(FATAL, "bad data in flat pg_database file");
+ *dboid = atooid(buf);
+ next_token(fp, buf, sizeof(buf));
+ if (!isdigit((unsigned char) buf[0]))
+ elog(FATAL, "bad data in flat pg_database file");
+ *dbtablespace = atooid(buf);
+ /* discard datfrozenxid */
+ next_token(fp, buf, sizeof(buf));
+ if (!isdigit((unsigned char) buf[0]))
+ elog(FATAL, "bad data in flat pg_database file");
+ /* expect EOL next */
+ next_token(fp, buf, sizeof(buf));
+ if (buf[0])
+ elog(FATAL, "bad data in flat pg_database file");
+ return true;
+}
/*
* Process one line from the ident config file.
diff --git a/src/backend/utils/init/flatfiles.c b/src/backend/utils/init/flatfiles.c
index 8968d572c88..e7ddd0a42c1 100644
--- a/src/backend/utils/init/flatfiles.c
+++ b/src/backend/utils/init/flatfiles.c
@@ -22,7 +22,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.3 2005/02/20 22:02:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.4 2005/02/26 18:43:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -243,10 +243,12 @@ write_database_file(Relation drel)
Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);
char *datname;
Oid datoid;
+ Oid dattablespace;
TransactionId datfrozenxid;
datname = NameStr(dbform->datname);
datoid = HeapTupleGetOid(tuple);
+ dattablespace = dbform->dattablespace;
datfrozenxid = dbform->datfrozenxid;
/*
@@ -276,13 +278,13 @@ write_database_file(Relation drel)
}
/*
- * The file format is: "dbname" oid frozenxid
+ * The file format is: "dbname" oid tablespace frozenxid
*
* The xid is not needed for backend startup, but may be of use
* for forensic purposes.
*/
fputs_quote(datname, fp);
- fprintf(fp, " %u %u\n", datoid, datfrozenxid);
+ fprintf(fp, " %u %u %u\n", datoid, dattablespace, datfrozenxid);
}
heap_endscan(scan);
@@ -830,15 +832,3 @@ flatfile_update_trigger(PG_FUNCTION_ARGS)
return PointerGetDatum(NULL);
}
-
-
-/*
- * Old version of trigger --- remove after we can force an initdb
- */
-extern Datum update_pg_pwd_and_pg_group(PG_FUNCTION_ARGS);
-
-Datum
-update_pg_pwd_and_pg_group(PG_FUNCTION_ARGS)
-{
- return flatfile_update_trigger(fcinfo);
-}
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 53eb47a97ec..d1479bbab77 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.140 2005/02/20 21:46:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.141 2005/02/26 18:43:33 tgl Exp $
*
*
*-------------------------------------------------------------------------
@@ -27,14 +27,16 @@
#include "catalog/pg_database.h"
#include "catalog/pg_shadow.h"
#include "catalog/pg_tablespace.h"
+#include "libpq/hba.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "postmaster/postmaster.h"
-#include "storage/backendid.h"
+#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
+#include "utils/flatfiles.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/portal.h"
@@ -42,6 +44,7 @@
#include "utils/syscache.h"
+static bool FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace);
static void ReverifyMyDatabase(const char *name);
static void InitCommunication(void);
static void ShutdownPostgres(int code, Datum arg);
@@ -51,18 +54,60 @@ static bool ThereIsAtLeastOneUser(void);
/*** InitPostgres support ***/
-/* --------------------------------
- * ReverifyMyDatabase
+/*
+ * FindMyDatabase -- get the critical info needed to locate my database
*
- * Since we are forced to fetch the database OID out of pg_database without
- * benefit of locking or transaction ID checking (see utils/misc/database.c),
- * we might have gotten a wrong answer. Or, we might have attached to a
- * database that's in process of being destroyed by destroydb(). This
- * routine is called after we have all the locking and other infrastructure
- * running --- now we can check that we are really attached to a valid
- * database.
+ * Find the named database in pg_database, return its database OID and the
+ * OID of its default tablespace. Return TRUE if found, FALSE if not.
*
- * In reality, if destroydb() is running in parallel with our startup,
+ * Since we are not yet up and running as a backend, we cannot look directly
+ * at pg_database (we can't obtain locks nor participate in transactions).
+ * So to get the info we need before starting up, we must look at the "flat
+ * file" copy of pg_database that is helpfully maintained by flatfiles.c.
+ * This is subject to various race conditions, so after we have the
+ * transaction infrastructure started, we have to recheck the information;
+ * see ReverifyMyDatabase.
+ */
+static bool
+FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
+{
+ bool result = false;
+ char *filename;
+ FILE *db_file;
+ char thisname[NAMEDATALEN];
+
+ filename = database_getflatfilename();
+ db_file = AllocateFile(filename, "r");
+ if (db_file == NULL)
+ ereport(FATAL,
+ (errcode_for_file_access(),
+ errmsg("could not open file \"%s\": %m", filename)));
+
+ while (read_pg_database_line(db_file, thisname, db_id, db_tablespace))
+ {
+ if (strcmp(thisname, name) == 0)
+ {
+ result = true;
+ break;
+ }
+ }
+
+ FreeFile(db_file);
+ pfree(filename);
+
+ return result;
+}
+
+/*
+ * ReverifyMyDatabase -- recheck info obtained by FindMyDatabase
+ *
+ * Since FindMyDatabase cannot lock pg_database, the information it read
+ * could be stale; for example we might have attached to a database that's in
+ * process of being destroyed by dropdb(). This routine is called after
+ * we have all the locking and other infrastructure running --- now we can
+ * check that we are really attached to a valid database.
+ *
+ * In reality, if dropdb() is running in parallel with our startup,
* it's pretty likely that we will have failed before now, due to being
* unable to read some of the system tables within the doomed database.
* This routine just exists to make *sure* we have not started up in an
@@ -75,7 +120,6 @@ static bool ThereIsAtLeastOneUser(void);
* To avoid having to read pg_database more times than necessary
* during session startup, this place is also fitting to set up any
* database-specific configuration variables.
- * --------------------------------
*/
static void
ReverifyMyDatabase(const char *name)
@@ -87,10 +131,10 @@ ReverifyMyDatabase(const char *name)
Form_pg_database dbform;
/*
- * Because we grab AccessShareLock here, we can be sure that destroydb
+ * Because we grab RowShareLock here, we can be sure that dropdb()
* is not running in parallel with us (any more).
*/
- pgdbrel = heap_openr(DatabaseRelationName, AccessShareLock);
+ pgdbrel = heap_openr(DatabaseRelationName, RowShareLock);
ScanKeyInit(&key,
Anum_pg_database_datname,
@@ -104,7 +148,7 @@ ReverifyMyDatabase(const char *name)
HeapTupleGetOid(tup) != MyDatabaseId)
{
/* OOPS */
- heap_close(pgdbrel, AccessShareLock);
+ heap_close(pgdbrel, RowShareLock);
/*
* The only real problem I could have created is to load dirty
@@ -131,7 +175,7 @@ ReverifyMyDatabase(const char *name)
name)));
/*
- * OK, we're golden. Only other to-do item is to save the encoding
+ * OK, we're golden. Next to-do item is to save the encoding
* info out of the pg_database tuple.
*/
SetDatabaseEncoding(dbform->encoding);
@@ -143,7 +187,7 @@ ReverifyMyDatabase(const char *name)
PGC_BACKEND, PGC_S_DEFAULT);
/*
- * Set up database-specific configuration variables.
+ * Lastly, set up any database-specific configuration variables.
*/
if (IsUnderPostmaster)
{
@@ -161,7 +205,7 @@ ReverifyMyDatabase(const char *name)
}
heap_endscan(pgdbscan);
- heap_close(pgdbrel, AccessShareLock);
+ heap_close(pgdbrel, RowShareLock);
}
@@ -261,11 +305,9 @@ InitPostgres(const char *dbname, const char *username)
/*
* 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
- * GetRawDatabaseInfo.
+ * FindMyDatabase.
*/
- GetRawDatabaseInfo(dbname, &MyDatabaseId, &MyDatabaseTableSpace);
-
- if (!OidIsValid(MyDatabaseId))
+ if (!FindMyDatabase(dbname, &MyDatabaseId, &MyDatabaseTableSpace))
ereport(FATAL,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" does not exist",
diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile
index f907f22d16e..afa3216558a 100644
--- a/src/backend/utils/misc/Makefile
+++ b/src/backend/utils/misc/Makefile
@@ -1,4 +1,12 @@
-# $PostgreSQL: pgsql/src/backend/utils/misc/Makefile,v 1.22 2003/11/29 19:52:03 pgsql Exp $
+#-------------------------------------------------------------------------
+#
+# Makefile--
+# Makefile for utils/misc
+#
+# IDENTIFICATION
+# $PostgreSQL: pgsql/src/backend/utils/misc/Makefile,v 1.23 2005/02/26 18:43:33 tgl Exp $
+#
+#-------------------------------------------------------------------------
subdir = src/backend/utils/misc
top_builddir = ../../../..
@@ -6,10 +14,10 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
-OBJS = database.o superuser.o guc.o help_config.o ps_status.o
+OBJS = guc.o help_config.o ps_status.o superuser.o
# This location might depend on the installation directories. Therefore
-# we can't subsitute it into config.h.
+# we can't subsitute it into pg_config.h.
ifdef krb_srvtab
override CPPFLAGS += -DPG_KRB_SRVTAB='"$(krb_srvtab)"'
endif
diff --git a/src/backend/utils/misc/database.c b/src/backend/utils/misc/database.c
deleted file mode 100644
index 66ea6dbed79..00000000000
--- a/src/backend/utils/misc/database.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * database.c
- * miscellaneous initialization support stuff
- *
- * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/database.c,v 1.63 2004/12/31 22:02:45 pgsql Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "access/xact.h"
-#include "catalog/catname.h"
-#include "catalog/catalog.h"
-#include "catalog/pg_database.h"
-#include "catalog/pg_tablespace.h"
-#include "miscadmin.h"
-#include "utils/syscache.h"
-
-
-static bool PhonyHeapTupleSatisfiesNow(HeapTupleHeader tuple);
-
-
-/* --------------------------------
- * GetRawDatabaseInfo() -- Find the OID and tablespace of the database.
- *
- * We need both the OID and the default tablespace in order to find
- * the database's system catalogs. Moreover the database's OID forms
- * half of the unique key for the system caches and lock tables, so
- * we must have it before we can use any of the cache mechanisms.
- * To get around these problems, this code opens and scans the
- * pg_database relation by hand.
- *
- * This code knows way more than it should about the layout of
- * tuples on disk, but there seems to be no help for that.
- * We're pulling ourselves up by the bootstraps here...
- * --------------------------------
- */
-void
-GetRawDatabaseInfo(const char *name, Oid *db_id, Oid *db_tablespace)
-{
- int dbfd;
- int nbytes;
- HeapTupleData tup;
- Form_pg_database tup_db;
- Page pg;
- char *dbfname;
- RelFileNode rnode;
-
- /* hard-wired path to pg_database */
- rnode.spcNode = GLOBALTABLESPACE_OID;
- rnode.dbNode = 0;
- rnode.relNode = RelOid_pg_database;
-
- dbfname = relpath(rnode);
-
- if ((dbfd = open(dbfname, O_RDONLY | PG_BINARY, 0)) < 0)
- ereport(FATAL,
- (errcode_for_file_access(),
- errmsg("could not open file \"%s\": %m", dbfname)));
-
- pfree(dbfname);
-
- /*
- * read and examine every page in pg_database
- *
- * Raw I/O! Read those tuples the hard way! Yow!
- *
- * Why don't we use the access methods or move this code someplace else?
- * This is really pg_database schema dependent code. Perhaps it
- * should go in lib/catalog/pg_database? -cim 10/3/90
- *
- * mao replies 4 apr 91: yeah, maybe this should be moved to
- * lib/catalog. however, we CANNOT use the access methods since those
- * use the buffer cache, which uses the relation cache, which requires
- * that the dbid be set, which is what we're trying to do here.
- *
- */
- pg = (Page) palloc(BLCKSZ);
-
- while ((nbytes = read(dbfd, pg, BLCKSZ)) == BLCKSZ)
- {
- OffsetNumber max = PageGetMaxOffsetNumber(pg);
- OffsetNumber lineoff;
-
- /* look at each tuple on the page */
- for (lineoff = FirstOffsetNumber; lineoff <= max; lineoff++)
- {
- ItemId lpp = PageGetItemId(pg, lineoff);
-
- /* if it's a freed tuple, ignore it */
- if (!ItemIdIsUsed(lpp))
- continue;
-
- /* get a pointer to the tuple itself */
- tup.t_datamcxt = NULL;
- tup.t_data = (HeapTupleHeader) PageGetItem(pg, lpp);
-
- /*
- * Check to see if tuple is valid (committed).
- *
- * XXX warning, will robinson: violation of transaction semantics
- * happens right here. We cannot really determine if the
- * tuple is valid without checking transaction commit status,
- * and the only way to do that at init time is to paw over
- * pg_clog by hand, too. Instead of checking, we assume that
- * the inserting transaction committed, and that any deleting
- * transaction did also, unless shown otherwise by on-row
- * commit status bits.
- *
- * All in all, this code is pretty shaky. We will cross-check
- * our result in ReverifyMyDatabase() in postinit.c.
- *
- * NOTE: if a bogus tuple in pg_database prevents connection to a
- * valid database, a fix is to connect to another database and
- * do "select * from pg_database". That should cause
- * committed and dead tuples to be marked with correct states.
- *
- * XXX wouldn't it be better to let new backends read the
- * database info from a flat file, handled the same way we
- * handle the password relation?
- */
- if (!PhonyHeapTupleSatisfiesNow(tup.t_data))
- continue;
-
- /*
- * Okay, see if this is the one we want.
- */
- tup_db = (Form_pg_database) GETSTRUCT(&tup);
-
- if (strcmp(name, NameStr(tup_db->datname)) == 0)
- {
- /* Found it; extract the db's OID and tablespace. */
- *db_id = HeapTupleGetOid(&tup);
- *db_tablespace = tup_db->dattablespace;
- goto done;
- }
- }
- }
-
- /* failed to find it... */
- *db_id = InvalidOid;
- *db_tablespace = InvalidOid;
-
-done:
- close(dbfd);
- pfree(pg);
-}
-
-/*
- * PhonyHeapTupleSatisfiesNow --- cut-down tuple time qual test
- *
- * This is a simplified version of HeapTupleSatisfiesNow() that does not
- * depend on having transaction commit info available. Any transaction
- * that touched the tuple is assumed committed unless later marked invalid.
- * (While we could think about more complex rules, this seems appropriate
- * for examining pg_database, since both CREATE DATABASE and DROP DATABASE
- * are non-roll-back-able.)
- */
-static bool
-PhonyHeapTupleSatisfiesNow(HeapTupleHeader tuple)
-{
- if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
- {
- if (tuple->t_infomask & HEAP_XMIN_INVALID)
- return false;
-
- if (tuple->t_infomask & HEAP_MOVED_OFF)
- return false;
- /* else assume committed */
- }
-
- if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
- return true;
-
- /* assume xmax transaction committed */
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
- return true;
-
- return false;
-}
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 5d8338f5ac4..e6cfc05d205 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -39,7 +39,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
* Portions taken from FreeBSD.
*
- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.75 2005/02/22 04:38:22 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.76 2005/02/26 18:43:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1319,15 +1319,18 @@ setup_shadow(void)
char **line;
static char *pg_shadow_setup[] = {
/*
- * Create a trigger so that direct updates to pg_shadow will be
- * written to the flat password/group files pg_pwd and pg_group
+ * Create triggers to ensure manual updates to shared catalogs
+ * will be reflected into their "flat file" copies.
*/
- "CREATE TRIGGER pg_sync_pg_pwd "
- " AFTER INSERT OR UPDATE OR DELETE ON pg_shadow "
- " FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd_and_pg_group();\n",
+ "CREATE TRIGGER pg_sync_pg_database "
+ " AFTER INSERT OR UPDATE OR DELETE ON pg_database "
+ " FOR EACH STATEMENT EXECUTE PROCEDURE flatfile_update_trigger();\n",
"CREATE TRIGGER pg_sync_pg_group "
" AFTER INSERT OR UPDATE OR DELETE ON pg_group "
- " FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd_and_pg_group();\n",
+ " FOR EACH STATEMENT EXECUTE PROCEDURE flatfile_update_trigger();\n",
+ "CREATE TRIGGER pg_sync_pg_pwd "
+ " AFTER INSERT OR UPDATE OR DELETE ON pg_shadow "
+ " FOR EACH STATEMENT EXECUTE PROCEDURE flatfile_update_trigger();\n",
/*
* needs to be done before alter user, because alter user checks
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index e4f6a74ea34..ca44b24b2c4 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.254 2005/02/25 16:13:29 teodor Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.255 2005/02/26 18:43:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200502251
+#define CATALOG_VERSION_NO 200502261
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 16867cb992c..e456e96bba6 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.349 2004/12/31 22:03:25 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.350 2005/02/26 18:43:34 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2133,8 +2133,8 @@ DESCR("matches LIKE expression, case-insensitive");
DATA(insert OID = 1661 ( bpcharicnlike PGNSP PGUID 12 f f t f i 2 16 "1042 25" _null_ texticnlike - _null_ ));
DESCR("does not match LIKE expression, case-insensitive");
-DATA(insert OID = 1689 ( update_pg_pwd_and_pg_group PGNSP PGUID 12 f f t f v 0 2279 "" _null_ update_pg_pwd_and_pg_group - _null_ ));
-DESCR("update pg_pwd and pg_group files");
+DATA(insert OID = 1689 ( flatfile_update_trigger PGNSP PGUID 12 f f t f v 0 2279 "" _null_ flatfile_update_trigger - _null_ ));
+DESCR("update flat-file copy of a shared catalog");
/* Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de> */
DATA(insert OID = 868 ( strpos PGNSP PGUID 12 f f t f i 2 23 "25 25" _null_ textpos - _null_ ));
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index a284edf3967..0656e6a4e82 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -4,19 +4,16 @@
* Interface to hba.c
*
*
- * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.35 2004/02/02 16:58:30 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.36 2005/02/26 18:43:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef HBA_H
#define HBA_H
-#ifndef WIN32
-#include <netinet/in.h>
-#endif
-
#include "nodes/pg_list.h"
+
typedef enum UserAuth
{
uaReject,
@@ -41,5 +38,7 @@ extern void load_user(void);
extern void load_group(void);
extern int hba_getauthmethod(hbaPort *port);
extern int authident(hbaPort *port);
+extern bool read_pg_database_line(FILE *fp, char *dbname,
+ Oid *dboid, Oid *dbtablespace);
-#endif
+#endif /* HBA_H */
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index e5333977c09..3e9b7d912a4 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.174 2004/12/31 22:03:19 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.175 2005/02/26 18:43:34 tgl Exp $
*
* NOTES
* some of the information in this file should be moved to other files.
@@ -225,9 +225,6 @@ extern void check_stack_depth(void);
extern char *DatabasePath;
-/* in utils/misc/database.c */
-extern void GetRawDatabaseInfo(const char *name, Oid *db_id, Oid *db_tablespace);
-
/* now in utils/init/miscinit.c */
extern void SetDatabasePath(const char *path);