Finish up the flat-files project: get rid of GetRawDatabaseInfo() hack

in favor of looking at the flat file copy of pg_database during backend
startup.  This should finally eliminate the various corner cases in which
backend startup fails unexpectedly because it isn't able to distinguish
live and dead tuples in pg_database.  Simplify locking on pg_database
to be similar to the rules used with pg_shadow and pg_group, and eliminate
FlushRelationBuffers operations that were used only to reduce the odds
of failure of GetRawDatabaseInfo.
initdb forced due to addition of a trigger to pg_database.
This commit is contained in:
Tom Lane 2005-02-26 18:43:34 +00:00
parent ffef9a9de4
commit 0fc4ecf935
12 changed files with 184 additions and 316 deletions

View File

@ -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);
/*

View File

@ -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,

View File

@ -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.

View File

@ -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);
}

View File

@ -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",

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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_ ));

View File

@ -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 */

View File

@ -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);