diff --git a/contrib/miscutil/misc_utils.c b/contrib/miscutil/misc_utils.c index 7518443971..d9237bd9db 100644 --- a/contrib/miscutil/misc_utils.c +++ b/contrib/miscutil/misc_utils.c @@ -89,9 +89,8 @@ active_listeners(text *relname) int ourpid = getpid(); char listen_name[NAMEDATALEN]; - lRel = heap_openr(ListenerRelationName); + lRel = heap_openr(ListenerRelationName, AccessShareLock); tdesc = RelationGetDescr(lRel); - LockRelation(lRel, AccessShareLock); if (relname && (VARSIZE(relname) > VARHDRSZ)) { len = MIN(VARSIZE(relname)-VARHDRSZ, NAMEDATALEN-1); @@ -110,19 +109,14 @@ active_listeners(text *relname) { d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull); pid = DatumGetInt32(d); -#ifdef HAVE_KILL if ((pid == ourpid) || (kill(pid, SIGTSTP) == 0)) { /* elog(NOTICE, "%d ok", pid); */ count++; } -#else - count++; -#endif } heap_endscan(sRel); - UnlockRelation(lRel, AccessShareLock); - heap_close(lRel); + heap_close(lRel, AccessShareLock); return count; } diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 3211134742..0535fd6278 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.44 1999/07/19 02:06:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.45 1999/09/18 19:05:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ #include "catalog/index.h" #include "catalog/pg_index.h" #include "executor/executor.h" +#include "miscadmin.h" #include "utils/syscache.h" @@ -88,8 +89,6 @@ gistbuild(Relation heap, TupleTableSlot *slot; #endif - Oid hrelid, - irelid; Node *pred, *oldPred; GISTSTATE giststate; @@ -271,28 +270,31 @@ gistbuild(Relation heap, } /* - * Since we just inted the tuples in the heap, we update its stats in - * pg_relation to guarantee that the planner takes advantage of the - * index we just created. UpdateStats() does a - * CommandinterIncrement(), which flushes changed entries from the - * system relcache. The act of constructing an index changes these - * heap and index tuples in the system catalogs, so they need to be - * flushed. We close them to guarantee that they will be. + * Since we just counted the tuples in the heap, we update its stats + * in pg_class to guarantee that the planner takes advantage of the + * index we just created. But, only update statistics during + * normal index definitions, not for indices on system catalogs + * created during bootstrap processing. We must close the relations + * before updating statistics to guarantee that the relcache entries + * are flushed when we increment the command counter in UpdateStats(). + * But we do not release any locks on the relations; those will be + * held until end of transaction. */ - - hrelid = RelationGetRelid(heap); - irelid = RelationGetRelid(index); - heap_close(heap); - index_close(index); - - UpdateStats(hrelid, nh, true); - UpdateStats(irelid, ni, false); - - if (oldPred != NULL) + if (IsNormalProcessingMode()) { - if (ni == nh) - pred = NULL; - UpdateIndexPredicate(irelid, oldPred, pred); + Oid hrelid = RelationGetRelid(heap); + Oid irelid = RelationGetRelid(index); + + heap_close(heap, NoLock); + index_close(index); + UpdateStats(hrelid, nh, true); + UpdateStats(irelid, ni, false); + if (oldPred != NULL) + { + if (ni == nh) + pred = NULL; + UpdateIndexPredicate(irelid, oldPred, pred); + } } /* be tidy */ diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 1130367b65..6e729008e8 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.30 1999/07/17 20:16:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.31 1999/09/18 19:05:52 tgl Exp $ * * NOTES * This file contains only the public interface routines. @@ -66,8 +66,6 @@ hashbuild(Relation heap, TupleTableSlot *slot; #endif - Oid hrelid, - irelid; Node *pred, *oldPred; @@ -232,17 +230,20 @@ hashbuild(Relation heap, /* * Since we just counted the tuples in the heap, we update its stats * in pg_class to guarantee that the planner takes advantage of the - * index we just created. Finally, only update statistics during + * index we just created. But, only update statistics during * normal index definitions, not for indices on system catalogs * created during bootstrap processing. We must close the relations - * before updatings statistics to guarantee that the relcache entries + * before updating statistics to guarantee that the relcache entries * are flushed when we increment the command counter in UpdateStats(). + * But we do not release any locks on the relations; those will be + * held until end of transaction. */ if (IsNormalProcessingMode()) { - hrelid = RelationGetRelid(heap); - irelid = RelationGetRelid(index); - heap_close(heap); + Oid hrelid = RelationGetRelid(heap); + Oid irelid = RelationGetRelid(index); + + heap_close(heap, NoLock); index_close(index); UpdateStats(hrelid, nhtups, true); UpdateStats(irelid, nitups, false); diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index d8dc24c41f..092a23cc0e 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.53 1999/07/19 07:07:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.54 1999/09/18 19:05:58 tgl Exp $ * * * INTERFACE ROUTINES @@ -486,15 +486,20 @@ heapgettup(Relation relation, /* ---------------- * heap_open - open a heap relation by relationId * - * presently the relcache routines do all the work we need - * to open/close heap relations. + * If lockmode is "NoLock", no lock is obtained on the relation, + * and the caller must check for a NULL return value indicating + * that no such relation exists. + * Otherwise, an error is raised if the relation does not exist, + * and the specified kind of lock is obtained on the relation. * ---------------- */ Relation -heap_open(Oid relationId) +heap_open(Oid relationId, LOCKMODE lockmode) { Relation r; + Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); + /* ---------------- * increment access statistics * ---------------- @@ -502,26 +507,41 @@ heap_open(Oid relationId) IncrHeapAccessStat(local_open); IncrHeapAccessStat(global_open); - r = (Relation) RelationIdGetRelation(relationId); + /* The relcache does all the real work... */ + r = RelationIdGetRelation(relationId); + /* Under no circumstances will we return an index as a relation. */ if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX) elog(ERROR, "%s is an index relation", r->rd_rel->relname.data); + if (lockmode == NoLock) + return r; /* caller must check RelationIsValid! */ + + if (! RelationIsValid(r)) + elog(ERROR, "Relation %u does not exist", relationId); + + LockRelation(r, lockmode); + return r; } /* ---------------- * heap_openr - open a heap relation by name * - * presently the relcache routines do all the work we need - * to open/close heap relations. + * If lockmode is "NoLock", no lock is obtained on the relation, + * and the caller must check for a NULL return value indicating + * that no such relation exists. + * Otherwise, an error is raised if the relation does not exist, + * and the specified kind of lock is obtained on the relation. * ---------------- */ Relation -heap_openr(char *relationName) +heap_openr(char *relationName, LOCKMODE lockmode) { Relation r; + Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); + /* ---------------- * increment access statistics * ---------------- @@ -529,24 +549,37 @@ heap_openr(char *relationName) IncrHeapAccessStat(local_openr); IncrHeapAccessStat(global_openr); + /* The relcache does all the real work... */ r = RelationNameGetRelation(relationName); + /* Under no circumstances will we return an index as a relation. */ if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX) elog(ERROR, "%s is an index relation", r->rd_rel->relname.data); + if (lockmode == NoLock) + return r; /* caller must check RelationIsValid! */ + + if (! RelationIsValid(r)) + elog(ERROR, "Relation '%s' does not exist", relationName); + + LockRelation(r, lockmode); + return r; } /* ---------------- * heap_close - close a heap relation * - * presently the relcache routines do all the work we need - * to open/close heap relations. + * If lockmode is not "NoLock", we first release the specified lock. + * Note that it is often sensible to hold a lock beyond heap_close; + * in that case, the lock is released automatically at xact end. * ---------------- */ void -heap_close(Relation relation) +heap_close(Relation relation, LOCKMODE lockmode) { + Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); + /* ---------------- * increment access statistics * ---------------- @@ -554,6 +587,10 @@ heap_close(Relation relation) IncrHeapAccessStat(local_close); IncrHeapAccessStat(global_close); + if (lockmode != NoLock) + UnlockRelation(relation, lockmode); + + /* The relcache does the real work... */ RelationClose(relation); } @@ -582,21 +619,29 @@ heap_beginscan(Relation relation, * sanity checks * ---------------- */ - if (RelationIsValid(relation) == false) + if (! RelationIsValid(relation)) elog(ERROR, "heap_beginscan: !RelationIsValid(relation)"); - LockRelation(relation, AccessShareLock); - - /* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */ - if (relation->rd_rel->relkind == RELKIND_UNCATALOGED) - snapshot = SnapshotSelf; - /* ---------------- * increment relation ref count while scanning relation * ---------------- */ RelationIncrementReferenceCount(relation); + /* ---------------- + * Acquire AccessShareLock for the duration of the scan + * + * Note: we could get an SI inval message here and consequently have + * to rebuild the relcache entry. The refcount increment above + * ensures that we will rebuild it and not just flush it... + * ---------------- + */ + LockRelation(relation, AccessShareLock); + + /* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */ + if (relation->rd_rel->relkind == RELKIND_UNCATALOGED) + snapshot = SnapshotSelf; + /* ---------------- * allocate and initialize scan descriptor * ---------------- @@ -683,15 +728,19 @@ heap_endscan(HeapScanDesc scan) */ unpinscan(scan); + /* ---------------- + * Release AccessShareLock acquired by heap_beginscan() + * ---------------- + */ + UnlockRelation(scan->rs_rd, AccessShareLock); + /* ---------------- * decrement relation reference count and free scan descriptor storage * ---------------- */ RelationDecrementReferenceCount(scan->rs_rd); - UnlockRelation(scan->rs_rd, AccessShareLock); - - pfree(scan); /* XXX */ + pfree(scan); } /* ---------------- diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 869e5e1e69..6ad242c0c3 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.35 1999/07/16 04:58:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.36 1999/09/18 19:06:04 tgl Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relationId @@ -129,26 +129,49 @@ * index_open - open an index relation by relationId * * presently the relcache routines do all the work we need - * to open/close index relations. + * to open/close index relations. However, callers of index_open + * expect it to succeed, so we need to check for a failure return. + * + * Note: we acquire no lock on the index. An AccessShareLock is + * acquired by index_beginscan (and released by index_endscan). * ---------------- */ Relation index_open(Oid relationId) { - return RelationIdGetRelation(relationId); + Relation r; + + r = RelationIdGetRelation(relationId); + + if (! RelationIsValid(r)) + elog(ERROR, "Index %u does not exist", relationId); + + if (r->rd_rel->relkind != RELKIND_INDEX) + elog(ERROR, "%s is not an index relation", r->rd_rel->relname.data); + + return r; } /* ---------------- * index_openr - open a index relation by name * - * presently the relcache routines do all the work we need - * to open/close index relations. + * As above, but lookup by name instead of OID. * ---------------- */ Relation index_openr(char *relationName) { - return RelationNameGetRelation(relationName); + Relation r; + + r = RelationNameGetRelation(relationName); + + if (! RelationIsValid(r)) + elog(ERROR, "Index '%s' does not exist", relationName); + + if (r->rd_rel->relkind != RELKIND_INDEX) + elog(ERROR, "%s is not an index relation", r->rd_rel->relname.data); + + return r; } /* ---------------- @@ -223,6 +246,16 @@ index_beginscan(Relation relation, RELATION_CHECKS; GET_REL_PROCEDURE(beginscan, ambeginscan); + RelationIncrementReferenceCount(relation); + + /* ---------------- + * Acquire AccessShareLock for the duration of the scan + * + * Note: we could get an SI inval message here and consequently have + * to rebuild the relcache entry. The refcount increment above + * ensures that we will rebuild it and not just flush it... + * ---------------- + */ LockRelation(relation, AccessShareLock); scandesc = (IndexScanDesc) @@ -260,7 +293,11 @@ index_endscan(IndexScanDesc scan) fmgr(procedure, scan); + /* Release lock and refcount acquired by index_beginscan */ + UnlockRelation(scan->relation, AccessShareLock); + + RelationDecrementReferenceCount(scan->relation); } /* ---------------- diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c index 1cdaadbc0c..cab6e58460 100644 --- a/src/backend/access/index/istrat.c +++ b/src/backend/access/index/istrat.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.35 1999/07/16 04:58:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.36 1999/09/18 19:06:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -558,7 +558,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy, F_OIDEQ, ObjectIdGetDatum(indexObjectId)); - relation = heap_openr(IndexRelationName); + relation = heap_openr(IndexRelationName, AccessShareLock); scan = heap_beginscan(relation, false, SnapshotNow, 1, entry); tuple = heap_getnext(scan, 0); } @@ -591,7 +591,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy, if (IsBootstrapProcessingMode()) { heap_endscan(scan); - heap_close(relation); + heap_close(relation, AccessShareLock); } /* if support routines exist for this access method, load them */ @@ -604,7 +604,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy, ScanKeyEntryInitialize(&entry[1], 0, Anum_pg_amproc_amopclaid, F_OIDEQ, 0); - relation = heap_openr(AccessMethodProcedureRelationName); + relation = heap_openr(AccessMethodProcedureRelationName, + AccessShareLock); for (attributeNumber = 1; attributeNumber <= maxAttributeNumber; attributeNumber++) @@ -631,7 +632,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy, heap_endscan(scan); } - heap_close(relation); + heap_close(relation, AccessShareLock); } ScanKeyEntryInitialize(&entry[0], 0, @@ -643,8 +644,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy, Anum_pg_amop_amopclaid, F_OIDEQ, 0); - relation = heap_openr(AccessMethodOperatorRelationName); - operatorRelation = heap_openr(OperatorRelationName); + relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock); + operatorRelation = heap_openr(OperatorRelationName, AccessShareLock); for (attributeNumber = maxAttributeNumber; attributeNumber > 0; attributeNumber--) @@ -676,8 +677,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy, heap_endscan(scan); } - heap_close(operatorRelation); - heap_close(relation); + heap_close(operatorRelation, AccessShareLock); + heap_close(relation, AccessShareLock); } /* ---------------- diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index c97273f10f..11f527fc3b 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.45 1999/07/17 20:16:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.46 1999/09/18 19:06:10 tgl Exp $ * * NOTES * This file contains only the public interface routines. @@ -74,8 +74,6 @@ btbuild(Relation heap, TupleTableSlot *slot = (TupleTableSlot *) NULL; #endif - Oid hrelid, - irelid; Node *pred, *oldPred; void *spool = (void *) NULL; @@ -301,17 +299,20 @@ btbuild(Relation heap, /* * Since we just counted the tuples in the heap, we update its stats * in pg_class to guarantee that the planner takes advantage of the - * index we just created. Finally, only update statistics during + * index we just created. But, only update statistics during * normal index definitions, not for indices on system catalogs * created during bootstrap processing. We must close the relations - * before updatings statistics to guarantee that the relcache entries + * before updating statistics to guarantee that the relcache entries * are flushed when we increment the command counter in UpdateStats(). + * But we do not release any locks on the relations; those will be + * held until end of transaction. */ if (IsNormalProcessingMode()) { - hrelid = RelationGetRelid(heap); - irelid = RelationGetRelid(index); - heap_close(heap); + Oid hrelid = RelationGetRelid(heap); + Oid irelid = RelationGetRelid(index); + + heap_close(heap, NoLock); index_close(index); UpdateStats(hrelid, nhtups, true); UpdateStats(irelid, nitups, false); diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c index 37da716df1..133bbdbc03 100644 --- a/src/backend/access/rtree/rtree.c +++ b/src/backend/access/rtree/rtree.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.36 1999/07/17 20:16:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.37 1999/09/18 19:06:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ #include "access/rtree.h" #include "catalog/index.h" #include "executor/executor.h" +#include "miscadmin.h" #include "utils/geo_decls.h" @@ -89,8 +90,6 @@ rtbuild(Relation heap, TupleTableSlot *slot; #endif - Oid hrelid, - irelid; Node *pred, *oldPred; RTSTATE rtState; @@ -248,27 +247,30 @@ rtbuild(Relation heap, /* * Since we just counted the tuples in the heap, we update its stats - * in pg_relation to guarantee that the planner takes advantage of the - * index we just created. UpdateStats() does a - * CommandCounterIncrement(), which flushes changed entries from the - * system relcache. The act of constructing an index changes these - * heap and index tuples in the system catalogs, so they need to be - * flushed. We close them to guarantee that they will be. + * in pg_class to guarantee that the planner takes advantage of the + * index we just created. But, only update statistics during + * normal index definitions, not for indices on system catalogs + * created during bootstrap processing. We must close the relations + * before updating statistics to guarantee that the relcache entries + * are flushed when we increment the command counter in UpdateStats(). + * But we do not release any locks on the relations; those will be + * held until end of transaction. */ - - hrelid = RelationGetRelid(heap); - irelid = RelationGetRelid(index); - heap_close(heap); - index_close(index); - - UpdateStats(hrelid, nh, true); - UpdateStats(irelid, ni, false); - - if (oldPred != NULL) + if (IsNormalProcessingMode()) { - if (ni == nh) - pred = NULL; - UpdateIndexPredicate(irelid, oldPred, pred); + Oid hrelid = RelationGetRelid(heap); + Oid irelid = RelationGetRelid(index); + + heap_close(heap, NoLock); + index_close(index); + UpdateStats(hrelid, nh, true); + UpdateStats(irelid, ni, false); + if (oldPred != NULL) + { + if (ni == nh) + pred = NULL; + UpdateIndexPredicate(irelid, oldPred, pred); + } } /* be tidy */ diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c index 1f44fb357a..b26243b425 100644 --- a/src/backend/access/transam/transam.c +++ b/src/backend/access/transam/transam.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.31 1999/08/08 20:12:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.32 1999/09/18 19:06:21 tgl Exp $ * * NOTES * This file contains the high level access-method interface to the @@ -405,8 +405,11 @@ InitializeTransactionLog(void) * (these are created by amiint so they are guaranteed to exist) * ---------------- */ - logRelation = heap_openr(LogRelationName); - VariableRelation = heap_openr(VariableRelationName); + logRelation = heap_openr(LogRelationName, NoLock); + Assert(logRelation != NULL); + VariableRelation = heap_openr(VariableRelationName, NoLock); + Assert(VariableRelation != NULL); + /* ---------------- * XXX TransactionLogUpdate requires that LogRelation * is valid so we temporarily set it so we can initialize diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index 135912e97d..989b506bb7 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.24 1999/07/15 23:03:03 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.25 1999/09/18 19:06:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -441,7 +441,7 @@ GetNewObjectId(Oid *oid_return) /* place to return the new object id */ * ---------------- */ if (!RelationIsValid(VariableRelation)) - VariableRelation = heap_openr(VariableRelationName); + VariableRelation = heap_openr(VariableRelationName, NoLock); /* ---------------- * get a new block of prefetched object ids. diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 8db37d0a08..18d9567ab8 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -7,7 +7,7 @@ * Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.66 1999/07/19 02:27:04 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.67 1999/09/18 19:06:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -396,7 +396,8 @@ boot_openrel(char *relname) if (Typ == (struct typmap **) NULL) { StartPortalAllocMode(DefaultAllocMode, 0); - rel = heap_openr(TypeRelationName); + rel = heap_openr(TypeRelationName, NoLock); + Assert(rel); scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL); i = 0; while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) @@ -416,7 +417,7 @@ boot_openrel(char *relname) sizeof((*app)->am_typ)); } heap_endscan(scan); - heap_close(rel); + heap_close(rel, NoLock); EndPortalAllocMode(); } @@ -427,7 +428,7 @@ boot_openrel(char *relname) printf("Amopen: relation %s. attrsize %d\n", relname ? relname : "(null)", (int) ATTRIBUTE_TUPLE_SIZE); - reldesc = heap_openr(relname); + reldesc = heap_openr(relname, NoLock); Assert(reldesc); numattr = reldesc->rd_rel->relnatts; for (i = 0; i < numattr; i++) @@ -490,7 +491,7 @@ closerel(char *name) { if (!Quiet) printf("Amclose: relation %s.\n", relname ? relname : "(null)"); - heap_close(reldesc); + heap_close(reldesc, NoLock); reldesc = (Relation) NULL; } } @@ -737,7 +738,7 @@ cleanup() proc_exit(1); } if (reldesc != (Relation) NULL) - heap_close(reldesc); + heap_close(reldesc, NoLock); CommitTransactionCommand(); proc_exit(Warnings); } @@ -775,7 +776,8 @@ gettype(char *type) } if (DebugMode) printf("bootstrap.c: External Type: %s\n", type); - rel = heap_openr(TypeRelationName); + rel = heap_openr(TypeRelationName, NoLock); + Assert(rel); scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL); i = 0; while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) @@ -795,7 +797,7 @@ gettype(char *type) sizeof((*app)->am_typ)); } heap_endscan(scan); - heap_close(rel); + heap_close(rel, NoLock); return gettype(type); } elog(ERROR, "Error: unknown type '%s'.\n", type); @@ -1106,11 +1108,16 @@ build_indices() for (; ILHead != (IndexList *) NULL; ILHead = ILHead->il_next) { - heap = heap_openr(ILHead->il_heap); + heap = heap_openr(ILHead->il_heap, NoLock); + Assert(heap); ind = index_openr(ILHead->il_ind); + Assert(ind); index_build(heap, ind, ILHead->il_natts, ILHead->il_attnos, ILHead->il_nparams, ILHead->il_params, ILHead->il_finfo, ILHead->il_predInfo); + /* In normal processing mode, index_build would close the heap + * and index, but in bootstrap mode it will not. + */ /* * All of the rest of this routine is needed only because in @@ -1128,9 +1135,9 @@ build_indices() * * -mer */ - heap = heap_openr(ILHead->il_heap); - if (!BootstrapAlreadySeen(RelationGetRelid(heap))) UpdateStats(RelationGetRelid(heap), 0, true); + + /* XXX Probably we ought to close the heap and index here? */ } } diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 186ecd07f3..33a589ec88 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.27 1999/07/30 18:09:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.28 1999/09/18 19:06:33 tgl Exp $ * * NOTES * See acl.h. @@ -105,19 +105,15 @@ ChangeAcl(char *relname, * We can't use the syscache here, since we need to do a heap_replace on * the tuple we find. */ - relation = heap_openr(RelationRelationName); - if (!RelationIsValid(relation)) - elog(ERROR, "ChangeAcl: could not open '%s'??", - RelationRelationName); + relation = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheTuple(RELNAME, PointerGetDatum(relname), 0, 0, 0); if (!HeapTupleIsValid(tuple)) { - heap_close(relation); + heap_close(relation, RowExclusiveLock); elog(ERROR, "ChangeAcl: class \"%s\" not found", relname); - return; } if (!heap_attisnull(tuple, Anum_pg_class_relacl)) @@ -164,7 +160,7 @@ ChangeAcl(char *relname, CatalogIndexInsert(idescs, Num_pg_class_indices, relation, tuple); CatalogCloseIndices(Num_pg_class_indices, idescs); - heap_close(relation); + heap_close(relation, RowExclusiveLock); if (free_old_acl) pfree(old_acl); pfree(new_acl); @@ -213,13 +209,7 @@ in_group(AclId uid, AclId gid) AclId *aidp; int32 found = 0; - relation = heap_openr(GroupRelationName); - if (!RelationIsValid(relation)) - { - elog(NOTICE, "in_group: could not open \"%s\"??", - GroupRelationName); - return 0; - } + relation = heap_openr(GroupRelationName, RowExclusiveLock); tuple = SearchSysCacheTuple(GROSYSID, ObjectIdGetDatum(gid), 0, 0, 0); @@ -242,7 +232,7 @@ in_group(AclId uid, AclId gid) } else elog(NOTICE, "in_group: group %d not found", gid); - heap_close(relation); + heap_close(relation, RowExclusiveLock); return found; } @@ -413,6 +403,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) } #ifndef ACLDEBUG + relation = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheTuple(RELNAME, PointerGetDatum(relname), 0, 0, 0); @@ -420,18 +411,15 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) { elog(ERROR, "pg_aclcheck: class \"%s\" not found", relname); - /* an elog(ERROR) kills us, so no need to return anything. */ } if (!heap_attisnull(tuple, Anum_pg_class_relacl)) { - relation = heap_openr(RelationRelationName); tmp = (Acl *) heap_getattr(tuple, Anum_pg_class_relacl, RelationGetDescr(relation), (bool *) NULL); acl = makeacl(ACL_NUM(tmp)); memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp)); - heap_close(relation); } else { @@ -442,42 +430,29 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) */ int4 ownerId; - relation = heap_openr(RelationRelationName); ownerId = (int4) heap_getattr(tuple, Anum_pg_class_relowner, RelationGetDescr(relation), (bool *) NULL); acl = aclownerdefault(relname, (AclId) ownerId); - heap_close(relation); } + heap_close(relation, RowExclusiveLock); #else - { /* This is why the syscache is great... */ - static ScanKeyData relkey[1] = { - {0, Anum_pg_class_relname, F_NAMEEQ} - }; - - relation = heap_openr(RelationRelationName); - if (!RelationIsValid(relation)) - { - elog(NOTICE, "pg_checkacl: could not open \"%-.*s\"??", - RelationRelationName); - return ACLCHECK_NO_CLASS; - } - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(relname), - 0, 0, 0); - if (HeapTupleIsValid(tuple) && - !heap_attisnull(tuple, Anum_pg_class_relacl)) - { - tmp = (Acl *) heap_getattr(tuple, - Anum_pg_class_relacl, - RelationGetDescr(relation), - (bool *) NULL); - acl = makeacl(ACL_NUM(tmp)); - memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp)); - } - heap_close(relation); + relation = heap_openr(RelationRelationName, RowExclusiveLock); + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(relname), + 0, 0, 0); + if (HeapTupleIsValid(tuple) && + !heap_attisnull(tuple, Anum_pg_class_relacl)) + { + tmp = (Acl *) heap_getattr(tuple, + Anum_pg_class_relacl, + RelationGetDescr(relation), + (bool *) NULL); + acl = makeacl(ACL_NUM(tmp)); + memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp)); } + heap_close(relation, RowExclusiveLock); #endif result = aclcheck(relname, acl, id, (AclIdType) ACL_IDTYPE_UID, mode); if (acl) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 561cb21a41..644f03eba8 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.95 1999/09/05 17:43:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.96 1999/09/18 19:06:33 tgl Exp $ * * * INTERFACE ROUTINES @@ -243,8 +243,6 @@ heap_create(char *relname, /* ---------------- * allocate a new relation descriptor. - * - * XXX the length computation may be incorrect, handle elsewhere * ---------------- */ len = sizeof(RelationData); @@ -474,7 +472,7 @@ RelnameFindRelid(char *relname) ScanKeyData key; HeapScanDesc pg_class_scan; - pg_class_desc = heap_openr(RelationRelationName); + pg_class_desc = heap_openr(RelationRelationName, AccessShareLock); /* ---------------- * At bootstrap time, we have to do this the hard way. Form the @@ -511,7 +509,7 @@ RelnameFindRelid(char *relname) heap_endscan(pg_class_scan); - heap_close(pg_class_desc); + heap_close(pg_class_desc, AccessShareLock); } return relid; } @@ -539,14 +537,12 @@ AddNewAttributeTuples(Oid new_rel_oid, * open pg_attribute * ---------------- */ - rel = heap_openr(AttributeRelationName); + rel = heap_openr(AttributeRelationName, RowExclusiveLock); /* ----------------- * Check if we have any indices defined on pg_attribute. * ----------------- */ - Assert(rel); - Assert(rel->rd_rel); hasindex = RelationGetForm(rel)->relhasindex; if (hasindex) CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs); @@ -607,7 +603,7 @@ AddNewAttributeTuples(Oid new_rel_oid, dpp++; } - heap_close(rel); + heap_close(rel, RowExclusiveLock); /* * close pg_attribute indices @@ -829,7 +825,7 @@ heap_create_with_catalog(char *relname, * now update the information in pg_class. * ---------------- */ - pg_class_desc = heap_openr(RelationRelationName); + pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock); AddNewRelationTuple(pg_class_desc, new_rel_desc, @@ -853,8 +849,8 @@ heap_create_with_catalog(char *relname, * SOMEDAY: fill the STATISTIC relation properly. * ---------------- */ - heap_close(new_rel_desc); - heap_close(pg_class_desc); + heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */ + heap_close(pg_class_desc, RowExclusiveLock); return new_rel_oid; } @@ -913,7 +909,7 @@ RelationRemoveInheritance(Relation relation) * open pg_inherits * ---------------- */ - catalogRelation = heap_openr(InheritsRelationName); + catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock); /* ---------------- * form a scan key for the subclasses of this class @@ -937,13 +933,15 @@ RelationRemoveInheritance(Relation relation) tuple = heap_getnext(scan, 0); if (HeapTupleIsValid(tuple)) { + Oid subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel; + heap_endscan(scan); - heap_close(catalogRelation); + heap_close(catalogRelation, RowExclusiveLock); elog(ERROR, "Relation '%u' inherits '%s'", - ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel, - RelationGetRelationName(relation)); + subclass, RelationGetRelationName(relation)); } + heap_endscan(scan); /* ---------------- * If we get here, it means the relation has no subclasses @@ -965,13 +963,14 @@ RelationRemoveInheritance(Relation relation) } heap_endscan(scan); - heap_close(catalogRelation); + heap_close(catalogRelation, RowExclusiveLock); /* ---------------- * now remove dead IPL tuples * ---------------- */ - catalogRelation = heap_openr(InheritancePrecidenceListRelationName); + catalogRelation = heap_openr(InheritancePrecidenceListRelationName, + RowExclusiveLock); entry.sk_attno = Anum_pg_ipl_iplrel; @@ -985,7 +984,7 @@ RelationRemoveInheritance(Relation relation) heap_delete(catalogRelation, &tuple->t_self, NULL); heap_endscan(scan); - heap_close(catalogRelation); + heap_close(catalogRelation, RowExclusiveLock); } /* -------------------------------- @@ -1001,7 +1000,7 @@ RelationRemoveIndexes(Relation relation) HeapScanDesc scan; ScanKeyData entry; - indexRelation = heap_openr(IndexRelationName); + indexRelation = heap_openr(IndexRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid, F_OIDEQ, @@ -1017,7 +1016,7 @@ RelationRemoveIndexes(Relation relation) index_destroy(((Form_pg_index) GETSTRUCT(tuple))->indexrelid); heap_endscan(scan); - heap_close(indexRelation); + heap_close(indexRelation, RowExclusiveLock); } /* -------------------------------- @@ -1035,14 +1034,14 @@ DeleteRelationTuple(Relation rel) * open pg_class * ---------------- */ - pg_class_desc = heap_openr(RelationRelationName); + pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock); tup = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid), 0, 0, 0); if (!HeapTupleIsValid(tup)) { - heap_close(pg_class_desc); + heap_close(pg_class_desc, RowExclusiveLock); elog(ERROR, "Relation '%s' does not exist", &rel->rd_rel->relname); } @@ -1054,7 +1053,7 @@ DeleteRelationTuple(Relation rel) heap_delete(pg_class_desc, &tup->t_self, NULL); pfree(tup); - heap_close(pg_class_desc); + heap_close(pg_class_desc, RowExclusiveLock); } /* -------------------------------- @@ -1073,13 +1072,7 @@ DeleteAttributeTuples(Relation rel) * open pg_attribute * ---------------- */ - pg_attribute_desc = heap_openr(AttributeRelationName); - - /* ----------------- - * Get a write lock _before_ getting the read lock in the scan - * ---------------- - */ - LockRelation(pg_attribute_desc, AccessExclusiveLock); + pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock); for (attnum = FirstLowInvalidHeapAttributeNumber + 1; attnum <= rel->rd_att->natts; @@ -1095,12 +1088,7 @@ DeleteAttributeTuples(Relation rel) } } - /* ---------------- - * Release the write lock - * ---------------- - */ - UnlockRelation(pg_attribute_desc, AccessExclusiveLock); - heap_close(pg_attribute_desc); + heap_close(pg_attribute_desc, RowExclusiveLock); } /* -------------------------------- @@ -1129,7 +1117,7 @@ DeleteTypeTuple(Relation rel) * open pg_type * ---------------- */ - pg_type_desc = heap_openr(TypeRelationName); + pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); /* ---------------- * create a scan key to locate the type tuple corresponding @@ -1157,7 +1145,7 @@ DeleteTypeTuple(Relation rel) if (!HeapTupleIsValid(tup)) { heap_endscan(pg_type_scan); - heap_close(pg_type_desc); + heap_close(pg_type_desc, RowExclusiveLock); elog(ERROR, "DeleteTypeTuple: %s type nonexistent", &rel->rd_rel->relname); } @@ -1171,7 +1159,7 @@ DeleteTypeTuple(Relation rel) */ typoid = tup->t_data->t_oid; - pg_attribute_desc = heap_openr(AttributeRelationName); + pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&attkey, 0, @@ -1197,16 +1185,16 @@ DeleteTypeTuple(Relation rel) { Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid; - heap_endscan(pg_type_scan); - heap_close(pg_type_desc); heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc); + heap_close(pg_attribute_desc, RowExclusiveLock); + heap_endscan(pg_type_scan); + heap_close(pg_type_desc, RowExclusiveLock); elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u", &rel->rd_rel->relname, relid); } heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc); + heap_close(pg_attribute_desc, RowExclusiveLock); /* ---------------- * Ok, it's safe so we delete the relation tuple @@ -1217,7 +1205,7 @@ DeleteTypeTuple(Relation rel) heap_delete(pg_type_desc, &tup->t_self, NULL); heap_endscan(pg_type_scan); - heap_close(pg_type_desc); + heap_close(pg_type_desc, RowExclusiveLock); } /* -------------------------------- @@ -1233,15 +1221,10 @@ heap_destroy_with_catalog(char *relname) bool istemp = (get_temp_rel_by_name(relname) != NULL); /* ---------------- - * first open the relation. if the relation doesn't exist, - * heap_openr() returns NULL. + * Open and lock the relation. * ---------------- */ - rel = heap_openr(relname); - if (rel == NULL) - elog(ERROR, "Relation '%s' does not exist", relname); - - LockRelation(rel, AccessExclusiveLock); + rel = heap_openr(relname, AccessExclusiveLock); rid = rel->rd_id; /* ---------------- @@ -1249,8 +1232,8 @@ heap_destroy_with_catalog(char *relname) * ---------------- */ /* allow temp of pg_class? Guess so. */ - if (!istemp && - !allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)->data)) + if (!istemp && !allowSystemTableMods && + IsSystemRelationName(RelationGetRelationName(rel)->data)) elog(ERROR, "System relation '%s' cannot be destroyed", &rel->rd_rel->relname); @@ -1330,9 +1313,12 @@ heap_destroy_with_catalog(char *relname) rel->rd_nonameunlinked = TRUE; - UnlockRelation(rel, AccessExclusiveLock); - - heap_close(rel); + /* + * Close relcache entry, but *keep* AccessExclusiveLock on the + * relation until transaction commit. This ensures no one else + * will try to do something with the doomed relation. + */ + heap_close(rel, NoLock); /* ---------------- * flush the relation from the relcache @@ -1354,7 +1340,7 @@ heap_destroy(Relation rel) if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked)) smgrunlink(DEFAULT_SMGR, rel); rel->rd_nonameunlinked = TRUE; - heap_close(rel); + heap_close(rel, NoLock); RemoveFromNoNameRelList(rel); } @@ -1542,13 +1528,13 @@ start: values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum; values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin)); values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc)); - adrel = heap_openr(AttrDefaultRelationName); + adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock); tuple = heap_formtuple(adrel->rd_att, values, nulls); CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs); heap_insert(adrel, tuple); CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple); CatalogCloseIndices(Num_pg_attrdef_indices, idescs); - heap_close(adrel); + heap_close(adrel, RowExclusiveLock); pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1])); pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1])); @@ -1605,20 +1591,18 @@ StoreRelCheck(Relation rel, ConstrCheck *check) values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(check->ccname)); values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin)); values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc)); - rcrel = heap_openr(RelCheckRelationName); + rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock); tuple = heap_formtuple(rcrel->rd_att, values, nulls); CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs); heap_insert(rcrel, tuple); CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple); CatalogCloseIndices(Num_pg_relcheck_indices, idescs); - heap_close(rcrel); + heap_close(rcrel, RowExclusiveLock); pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1])); pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1])); pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1])); pfree(tuple); - - return; } static void @@ -1653,23 +1637,18 @@ RemoveAttrDefault(Relation rel) ScanKeyData key; HeapTuple tup; - adrel = heap_openr(AttrDefaultRelationName); + adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid, F_OIDEQ, rel->rd_id); - LockRelation(adrel, AccessExclusiveLock); - adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key); while (HeapTupleIsValid(tup = heap_getnext(adscan, 0))) heap_delete(adrel, &tup->t_self, NULL); heap_endscan(adscan); - - UnlockRelation(adrel, AccessExclusiveLock); - heap_close(adrel); - + heap_close(adrel, RowExclusiveLock); } static void @@ -1680,23 +1659,18 @@ RemoveRelCheck(Relation rel) ScanKeyData key; HeapTuple tup; - rcrel = heap_openr(RelCheckRelationName); + rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid, F_OIDEQ, rel->rd_id); - LockRelation(rcrel, AccessExclusiveLock); - rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key); while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0))) heap_delete(rcrel, &tup->t_self, NULL); heap_endscan(rcscan); - - UnlockRelation(rcrel, AccessExclusiveLock); - heap_close(rcrel); - + heap_close(rcrel, RowExclusiveLock); } static void @@ -1712,6 +1686,4 @@ RemoveConstraints(Relation rel) if (constr->num_check > 0) RemoveRelCheck(rel); - - return; } diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index c90c27fd5d..912996fb1f 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.89 1999/09/05 17:43:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.90 1999/09/18 19:06:33 tgl Exp $ * * * INTERFACE ROUTINES @@ -378,7 +378,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId) * fetch the desired access method tuple * ---------------- */ - pg_am_desc = heap_openr(AccessMethodRelationName); + pg_am_desc = heap_openr(AccessMethodRelationName, AccessShareLock); pg_am_scan = heap_beginscan(pg_am_desc, 0, SnapshotNow, 1, &key); pg_am_tuple = heap_getnext(pg_am_scan, 0); @@ -390,7 +390,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId) if (!HeapTupleIsValid(pg_am_tuple)) { heap_endscan(pg_am_scan); - heap_close(pg_am_desc); + heap_close(pg_am_desc, AccessShareLock); return NULL; } @@ -402,7 +402,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId) memcpy(aform, GETSTRUCT(pg_am_tuple), sizeof *aform); heap_endscan(pg_am_scan); - heap_close(pg_am_desc); + heap_close(pg_am_desc, AccessShareLock); return aform; } @@ -456,7 +456,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname) Oid tupleOid; Relation idescs[Num_pg_class_indices]; - pg_class = heap_openr(RelationRelationName); + pg_class = heap_openr(RelationRelationName, RowExclusiveLock); /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */ tuple = heap_addheader(Natts_pg_class_fixed, @@ -491,7 +491,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname) tupleOid = tuple->t_data->t_oid; pfree(tuple); - heap_close(pg_class); + heap_close(pg_class, RowExclusiveLock); return tupleOid; } @@ -542,7 +542,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts) * XXX ADD INDEXING * ---------------- */ - pg_attribute = heap_openr(AttributeRelationName); + pg_attribute = heap_openr(AttributeRelationName, RowExclusiveLock); /* ---------------- * initialize *null, *replace and *value @@ -628,7 +628,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts) if (cur_tuple) pfree(cur_tuple); - heap_close(pg_attribute); + heap_close(pg_attribute, RowExclusiveLock); if (hasind) CatalogCloseIndices(Num_pg_attr_indices, idescs); @@ -734,7 +734,7 @@ UpdateIndexRelation(Oid indexoid, * open the system catalog index relation * ---------------- */ - pg_index = heap_openr(IndexRelationName); + pg_index = heap_openr(IndexRelationName, RowExclusiveLock); /* ---------------- * form a tuple to insert into pg_index @@ -755,7 +755,7 @@ UpdateIndexRelation(Oid indexoid, * close the relation and free the tuple * ---------------- */ - heap_close(pg_index); + heap_close(pg_index, RowExclusiveLock); pfree(predText); pfree(indexForm); pfree(tuple); @@ -810,7 +810,7 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate) predText = (text *) fmgr(F_TEXTIN, ""); /* open the index system catalog relation */ - pg_index = heap_openr(IndexRelationName); + pg_index = heap_openr(IndexRelationName, RowExclusiveLock); tuple = SearchSysCacheTuple(INDEXRELID, ObjectIdGetDatum(indexoid), @@ -832,7 +832,7 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate) heap_replace(pg_index, &newtup->t_self, newtup, NULL); pfree(newtup); - heap_close(pg_index); + heap_close(pg_index, RowExclusiveLock); pfree(predText); } @@ -956,12 +956,10 @@ index_create(char *heapRelationName, */ heapoid = GetHeapRelationOid(heapRelationName, indexRelationName, istemp); - heapRelation = heap_open(heapoid); - /* - * Only SELECT ... FOR UPDATE are allowed + * Only SELECT ... FOR UPDATE are allowed while doing this */ - LockRelation(heapRelation, ShareLock); + heapRelation = heap_open(heapoid, ShareLock); /* ---------------- * construct new tuple descriptor @@ -1070,16 +1068,20 @@ index_create(char *heapRelationName, * the index yet. We'll be creating more indices and classes later, * so we delay filling them in until just before we're done with * bootstrapping. Otherwise, we call the routine that constructs the - * index. The heap and index relations are closed by index_build(). + * index. + * + * In normal processing mode, the heap and index relations are closed + * by index_build() --- but we continue to hold the ShareLock on the + * heap that we acquired above, until end of transaction. */ if (IsBootstrapProcessingMode()) { index_register(heapRelationName, indexRelationName, numatts, attNums, parameterCount, parameter, funcInfo, predInfo); + /* XXX shouldn't we close the heap and index rels here? */ } else { - heapRelation = heap_openr(heapRelationName); index_build(heapRelation, indexRelation, numatts, attNums, parameterCount, parameter, funcInfo, predInfo); } @@ -1103,9 +1105,13 @@ index_destroy(Oid indexId) Assert(OidIsValid(indexId)); - /* Open now to obtain lock by referencing table? bjm */ userindexRelation = index_open(indexId); + /* + * Get exclusive lock to ensure no one else is scanning this index. + */ + LockRelation(userindexRelation, AccessExclusiveLock); + /* ---------------- * We do not allow DROP INDEX within a transaction block, because * if the transaction is later rolled back there would be no way to @@ -1121,7 +1127,7 @@ index_destroy(Oid indexId) * fix RELATION relation * ---------------- */ - relationRelation = heap_openr(RelationRelationName); + relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId), @@ -1131,13 +1137,13 @@ index_destroy(Oid indexId) heap_delete(relationRelation, &tuple->t_self, NULL); pfree(tuple); - heap_close(relationRelation); + heap_close(relationRelation, RowExclusiveLock); /* ---------------- * fix ATTRIBUTE relation * ---------------- */ - attributeRelation = heap_openr(AttributeRelationName); + attributeRelation = heap_openr(AttributeRelationName, RowExclusiveLock); attnum = 1; /* indexes start at 1 */ @@ -1150,7 +1156,7 @@ index_destroy(Oid indexId) pfree(tuple); attnum++; } - heap_close(attributeRelation); + heap_close(attributeRelation, RowExclusiveLock); /* does something only if it is a temp index */ remove_temp_relation(indexId); @@ -1159,16 +1165,16 @@ index_destroy(Oid indexId) * fix INDEX relation * ---------------- */ + indexRelation = heap_openr(IndexRelationName, RowExclusiveLock); + tuple = SearchSysCacheTupleCopy(INDEXRELID, ObjectIdGetDatum(indexId), 0, 0, 0); Assert(HeapTupleIsValid(tuple)); - indexRelation = heap_openr(IndexRelationName); - heap_delete(indexRelation, &tuple->t_self, NULL); pfree(tuple); - heap_close(indexRelation); + heap_close(indexRelation, RowExclusiveLock); /* * flush cache and physically remove the file @@ -1179,7 +1185,8 @@ index_destroy(Oid indexId) elog(ERROR, "index_destroy: unlink: %m"); index_close(userindexRelation); - RelationForgetRelation(RelationGetRelid(userindexRelation)); + + RelationForgetRelation(indexId); } /* ---------------------------------------------------------------- @@ -1264,16 +1271,21 @@ UpdateStats(Oid relid, long reltuples, bool hasindex) * ---------------- */ + /* + * Can't use heap_open here since we don't know if it's an index... + */ whichRel = RelationIdGetRelation(relid); if (!RelationIsValid(whichRel)) elog(ERROR, "UpdateStats: cannot open relation id %u", relid); + LockRelation(whichRel, ShareLock); + /* ---------------- * Find the RELATION relation tuple for the given relation. * ---------------- */ - pg_class = heap_openr(RelationRelationName); + pg_class = heap_openr(RelationRelationName, RowExclusiveLock); if (!RelationIsValid(pg_class)) elog(ERROR, "UpdateStats: could not open RELATION relation"); @@ -1300,7 +1312,7 @@ UpdateStats(Oid relid, long reltuples, bool hasindex) { if (IsBootstrapProcessingMode()) heap_endscan(pg_class_scan); - heap_close(pg_class); + heap_close(pg_class, RowExclusiveLock); elog(ERROR, "UpdateStats: cannot scan RELATION relation"); } @@ -1391,8 +1403,9 @@ UpdateStats(Oid relid, long reltuples, bool hasindex) else heap_endscan(pg_class_scan); - heap_close(pg_class); - heap_close(whichRel); + heap_close(pg_class, RowExclusiveLock); + /* Cheating a little bit since we didn't open it with heap_open... */ + heap_close(whichRel, ShareLock); } @@ -1600,20 +1613,31 @@ DefaultBuild(Relation heapRelation, pfree(datum); /* - * Okay, now update the reltuples and relpages statistics for both the - * heap relation and the index. These statistics are used by the - * planner to choose a scan type. They are maintained generally by - * the vacuum daemon, but we update them here to make the index useful - * as soon as possible. + * Since we just counted the tuples in the heap, we update its stats + * in pg_class to guarantee that the planner takes advantage of the + * index we just created. But, only update statistics during + * normal index definitions, not for indices on system catalogs + * created during bootstrap processing. We must close the relations + * before updating statistics to guarantee that the relcache entries + * are flushed when we increment the command counter in UpdateStats(). + * But we do not release any locks on the relations; those will be + * held until end of transaction. */ - UpdateStats(RelationGetRelid(heapRelation), reltuples, true); - UpdateStats(RelationGetRelid(indexRelation), indtuples, false); - if (oldPred != NULL) + if (IsNormalProcessingMode()) { - if (indtuples == reltuples) - predicate = NULL; - UpdateIndexPredicate(RelationGetRelid(indexRelation), - oldPred, predicate); + Oid hrelid = RelationGetRelid(heapRelation); + Oid irelid = RelationGetRelid(indexRelation); + + heap_close(heapRelation, NoLock); + index_close(indexRelation); + UpdateStats(hrelid, reltuples, true); + UpdateStats(irelid, indtuples, false); + if (oldPred != NULL) + { + if (indtuples == reltuples) + predicate = NULL; + UpdateIndexPredicate(irelid, oldPred, predicate); + } } } @@ -1715,7 +1739,7 @@ IndexIsUniqueNoCache(Oid indexId) Form_pg_index index; bool isunique; - pg_index = heap_openr(IndexRelationName); + pg_index = heap_openr(IndexRelationName, AccessShareLock); ScanKeyEntryInitialize(&skey[0], (bits16) 0x0, Anum_pg_index_indexrelid, @@ -1734,6 +1758,6 @@ IndexIsUniqueNoCache(Oid indexId) isunique = index->indisunique; heap_endscan(scandesc); - heap_close(pg_index); + heap_close(pg_index, AccessShareLock); return isunique; } diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index 9007258f2e..75799e5557 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.44 1999/09/04 22:00:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.45 1999/09/18 19:06:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -193,9 +193,9 @@ CatalogHasIndex(char *catName, Oid catId) return false; } - pg_class = heap_openr(RelationRelationName); + pg_class = heap_openr(RelationRelationName, AccessShareLock); htup = ClassOidIndexScan(pg_class, catId); - heap_close(pg_class); + heap_close(pg_class, AccessShareLock); if (!HeapTupleIsValid(htup)) { diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index c8f02287cb..0f2b98da90 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.24 1999/07/17 20:16:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.25 1999/09/18 19:06:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -234,10 +234,7 @@ AggregateCreate(char *aggName, else nulls[Anum_pg_aggregate_agginitval2 - 1] = 'n'; - if (!RelationIsValid(aggdesc = heap_openr(AggregateRelationName))) - elog(ERROR, "AggregateCreate: could not open '%s'", - AggregateRelationName); - + aggdesc = heap_openr(AggregateRelationName, RowExclusiveLock); tupDesc = aggdesc->rd_att; if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc, values, @@ -245,8 +242,7 @@ AggregateCreate(char *aggName, elog(ERROR, "AggregateCreate: heap_formtuple failed"); if (!OidIsValid(heap_insert(aggdesc, tup))) elog(ERROR, "AggregateCreate: heap_insert failed"); - heap_close(aggdesc); - + heap_close(aggdesc, RowExclusiveLock); } char * @@ -264,6 +260,14 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull) Assert(PointerIsValid(isNull)); Assert(xfuncno == 1 || xfuncno == 2); + /* + * since we will have to use fastgetattr (in case one or both init vals + * are NULL), we will need to open the relation. Do that first to + * ensure we don't get a stale tuple from the cache. + */ + + aggRel = heap_openr(AggregateRelationName, AccessShareLock); + tup = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggName), ObjectIdGetDatum(basetype), @@ -277,21 +281,12 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull) initValAttno = Anum_pg_aggregate_agginitval1; } else - /* can only be 1 or 2 */ { + /* can only be 1 or 2 */ transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype2; initValAttno = Anum_pg_aggregate_agginitval2; } - aggRel = heap_openr(AggregateRelationName); - if (!RelationIsValid(aggRel)) - elog(ERROR, "AggNameGetInitVal: could not open \"%-.*s\"", - AggregateRelationName); - - /* - * must use fastgetattr in case one or other of the init values is - * NULL - */ textInitVal = (text *) fastgetattr(tup, initValAttno, RelationGetDescr(aggRel), isNull); @@ -299,11 +294,12 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull) *isNull = true; if (*isNull) { - heap_close(aggRel); + heap_close(aggRel, AccessShareLock); return (char *) NULL; } strInitVal = textout(textInitVal); - heap_close(aggRel); + + heap_close(aggRel, AccessShareLock); tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(transtype), diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 8cab520f52..53b250fe3f 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.41 1999/07/17 20:16:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.42 1999/09/18 19:06:33 tgl Exp $ * * NOTES * these routines moved here from commands/define.c and somewhat cleaned up. @@ -199,7 +199,7 @@ OperatorGet(char *operatorName, * open the pg_operator relation * ---------------- */ - pg_operator_desc = heap_openr(OperatorRelationName); + pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock); /* ---------------- * get the oid for the operator with the appropriate name @@ -216,7 +216,7 @@ OperatorGet(char *operatorName, * close the relation and return the operator oid. * ---------------- */ - heap_close(pg_operator_desc); + heap_close(pg_operator_desc, AccessShareLock); return operatorObjectId; } @@ -341,7 +341,7 @@ OperatorShellMake(char *operatorName, * open pg_operator * ---------------- */ - pg_operator_desc = heap_openr(OperatorRelationName); + pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock); /* ---------------- * add a "shell" operator tuple to the operator relation @@ -356,7 +356,7 @@ OperatorShellMake(char *operatorName, * close the operator relation and return the oid. * ---------------- */ - heap_close(pg_operator_desc); + heap_close(pg_operator_desc, RowExclusiveLock); return operatorObjectId; } @@ -754,10 +754,11 @@ OperatorDef(char *operatorName, /* last three fields were filled in above */ + pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock); + /* * If we are adding to an operator shell, get its t_self */ - pg_operator_desc = heap_openr(OperatorRelationName); if (operatorObjectId) { @@ -798,7 +799,7 @@ OperatorDef(char *operatorName, operatorObjectId = tup->t_data->t_oid; } - heap_close(pg_operator_desc); + heap_close(pg_operator_desc, RowExclusiveLock); /* * If a commutator and/or negator link is provided, update the other @@ -853,7 +854,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId) nulls[i] = ' '; } - pg_operator_desc = heap_openr(OperatorRelationName); + pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock); /* check and update the commutator, if necessary */ opKey[0].sk_argument = ObjectIdGetDatum(commId); @@ -908,7 +909,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId) } heap_endscan(pg_operator_scan); - heap_close(pg_operator_desc); + heap_close(pg_operator_desc, RowExclusiveLock); return; } @@ -964,7 +965,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId) heap_endscan(pg_operator_scan); - heap_close(pg_operator_desc); + heap_close(pg_operator_desc, RowExclusiveLock); } diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index f0a10cf8f8..b71f36e661 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.33 1999/07/17 20:16:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.34 1999/09/18 19:06:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -277,7 +277,7 @@ ProcedureCreate(char *procedureName, values[i++] = (Datum) fmgr(F_TEXTIN, prosrc); /* prosrc */ values[i++] = (Datum) fmgr(F_TEXTIN, probin); /* probin */ - rel = heap_openr(ProcedureRelationName); + rel = heap_openr(ProcedureRelationName, RowExclusiveLock); tupDesc = rel->rd_att; tup = heap_formtuple(tupDesc, @@ -294,6 +294,6 @@ ProcedureCreate(char *procedureName, CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup); CatalogCloseIndices(Num_pg_proc_indices, idescs); } - heap_close(rel); + heap_close(rel, RowExclusiveLock); return tup->t_data->t_oid; } diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index a219767858..91c7cd995b 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.40 1999/07/17 20:16:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.41 1999/09/18 19:06:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -119,7 +119,7 @@ TypeGet(char *typeName, /* name of type to be fetched */ * open the pg_type relation * ---------------- */ - pg_type_desc = heap_openr(TypeRelationName); + pg_type_desc = heap_openr(TypeRelationName, AccessShareLock); /* ---------------- * scan the type relation for the information we want @@ -133,7 +133,7 @@ TypeGet(char *typeName, /* name of type to be fetched */ * close the type relation and return the type oid. * ---------------- */ - heap_close(pg_type_desc); + heap_close(pg_type_desc, AccessShareLock); return typeoid; } @@ -248,7 +248,7 @@ TypeShellMake(char *typeName) * open pg_type * ---------------- */ - pg_type_desc = heap_openr(TypeRelationName); + pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); /* ---------------- * insert the shell tuple @@ -260,7 +260,7 @@ TypeShellMake(char *typeName) * close pg_type and return the tuple's oid. * ---------------- */ - heap_close(pg_type_desc); + heap_close(pg_type_desc, RowExclusiveLock); return typoid; } @@ -457,14 +457,7 @@ TypeCreate(char *typeName, * open pg_type and begin a scan for the type name. * ---------------- */ - pg_type_desc = heap_openr(TypeRelationName); - - /* ----------------- - * Set a write lock initially so as not upgrade a read to a write - * when the heap_insert() or heap_replace() is called. - * ----------------- - */ - LockRelation(pg_type_desc, AccessExclusiveLock); + pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); typeKey[0].sk_argument = PointerGetDatum(typeName); pg_type_scan = heap_beginscan(pg_type_desc, @@ -521,8 +514,8 @@ TypeCreate(char *typeName, CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup); CatalogCloseIndices(Num_pg_type_indices, idescs); } - UnlockRelation(pg_type_desc, AccessExclusiveLock); - heap_close(pg_type_desc); + + heap_close(pg_type_desc, RowExclusiveLock); return typeObjectId; } @@ -541,7 +534,7 @@ TypeRename(char *oldTypeName, char *newTypeName) HeapTuple oldtup, newtup; - pg_type_desc = heap_openr(TypeRelationName); + pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); oldtup = SearchSysCacheTupleCopy(TYPNAME, PointerGetDatum(oldTypeName), @@ -549,7 +542,7 @@ TypeRename(char *oldTypeName, char *newTypeName) if (!HeapTupleIsValid(oldtup)) { - heap_close(pg_type_desc); + heap_close(pg_type_desc, RowExclusiveLock); elog(ERROR, "TypeRename: type %s not defined", oldTypeName); } @@ -559,7 +552,7 @@ TypeRename(char *oldTypeName, char *newTypeName) if (HeapTupleIsValid(newtup)) { pfree(oldtup); - heap_close(pg_type_desc); + heap_close(pg_type_desc, RowExclusiveLock); elog(ERROR, "TypeRename: type %s already defined", newTypeName); } @@ -575,7 +568,7 @@ TypeRename(char *oldTypeName, char *newTypeName) CatalogCloseIndices(Num_pg_type_indices, idescs); pfree(oldtup); - heap_close(pg_type_desc); + heap_close(pg_type_desc, RowExclusiveLock); } /* diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index ebdd045ce4..f8196f86ab 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -6,7 +6,7 @@ * Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.53 1999/07/18 18:03:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.54 1999/09/18 19:06:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,16 +51,9 @@ * transaction, since by assumption it is only called from outside any * transaction. * - * Note that the system's use of pg_listener is confined to very short - * intervals at the end of a transaction that contains NOTIFY statements, - * or during the transaction caused by an inbound SIGUSR2. So the fact that - * pg_listener is a global resource shouldn't cause too much performance - * problem. But application authors ought to be discouraged from doing - * LISTEN or UNLISTEN near the start of a long transaction --- that would - * result in holding the pg_listener write lock for a long time, possibly - * blocking unrelated activity. It could even lead to deadlock against another - * transaction that touches the same user tables and then tries to NOTIFY. - * Probably best to do LISTEN or UNLISTEN outside of transaction blocks. + * Although we grab AccessExclusiveLock on pg_listener for any operation, + * the lock is never held very long, so it shouldn't cause too much of + * a performance problem. * * An application that listens on the same relname it notifies will get * NOTIFY messages for its own NOTIFYs. These can be ignored, if not useful, @@ -155,26 +148,21 @@ Async_Notify(char *relname) TPRINTF(TRACE_NOTIFY, "Async_Notify: %s", relname); - /* - * We allocate list memory from the global malloc pool to ensure that - * it will live until we want to use it. This is probably not - * necessary any longer, since we will use it before the end of the - * transaction. DLList only knows how to use malloc() anyway, but we - * could probably palloc() the strings... - */ if (!pendingNotifies) pendingNotifies = DLNewList(); - notifyName = strdup(relname); - DLAddHead(pendingNotifies, DLNewElem(notifyName)); - - /* - * NOTE: we could check to see if pendingNotifies already has an entry - * for relname, and thus avoid making duplicate entries. However, - * most apps probably don't notify the same name multiple times per - * transaction, so we'd likely just be wasting cycles to make such a - * check. AsyncExistsPendingNotify() doesn't really care whether the - * list contains duplicates... - */ + /* no point in making duplicate entries in the list ... */ + if (!AsyncExistsPendingNotify(relname)) + { + /* + * We allocate list memory from the global malloc pool to ensure + * that it will live until we want to use it. This is probably not + * necessary any longer, since we will use it before the end of the + * transaction. DLList only knows how to use malloc() anyway, but we + * could probably palloc() the strings... + */ + notifyName = strdup(relname); + DLAddHead(pendingNotifies, DLNewElem(notifyName)); + } } /* @@ -212,8 +200,7 @@ Async_Listen(char *relname, int pid) TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname); - lRel = heap_openr(ListenerRelationName); - LockRelation(lRel, AccessExclusiveLock); + lRel = heap_openr(ListenerRelationName, AccessExclusiveLock); tdesc = RelationGetDescr(lRel); /* Detect whether we are already listening on this relname */ @@ -236,9 +223,8 @@ Async_Listen(char *relname, int pid) if (alreadyListener) { + heap_close(lRel, AccessExclusiveLock); elog(NOTICE, "Async_Listen: We are already listening on %s", relname); - UnlockRelation(lRel, AccessExclusiveLock); - heap_close(lRel); return; } @@ -262,8 +248,7 @@ Async_Listen(char *relname, int pid) heap_insert(lRel, newtup); pfree(newtup); - UnlockRelation(lRel, AccessExclusiveLock); - heap_close(lRel); + heap_close(lRel, AccessExclusiveLock); /* * now that we are listening, make sure we will unlisten before dying. @@ -308,18 +293,14 @@ Async_Unlisten(char *relname, int pid) TPRINTF(TRACE_NOTIFY, "Async_Unlisten %s", relname); + lRel = heap_openr(ListenerRelationName, AccessExclusiveLock); /* Note we assume there can be only one matching tuple. */ lTuple = SearchSysCacheTuple(LISTENREL, PointerGetDatum(relname), Int32GetDatum(pid), 0, 0); if (lTuple != NULL) - { - lRel = heap_openr(ListenerRelationName); - LockRelation(lRel, AccessExclusiveLock); heap_delete(lRel, &lTuple->t_self, NULL); - UnlockRelation(lRel, AccessExclusiveLock); - heap_close(lRel); - } + heap_close(lRel, AccessExclusiveLock); /* * We do not complain about unlistening something not being listened; @@ -354,8 +335,7 @@ Async_UnlistenAll() TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll"); - lRel = heap_openr(ListenerRelationName); - LockRelation(lRel, AccessExclusiveLock); + lRel = heap_openr(ListenerRelationName, AccessExclusiveLock); tdesc = RelationGetDescr(lRel); /* Find and delete all entries with my listenerPID */ @@ -369,8 +349,7 @@ Async_UnlistenAll() heap_delete(lRel, &lTuple->t_self, NULL); heap_endscan(sRel); - UnlockRelation(lRel, AccessExclusiveLock); - heap_close(lRel); + heap_close(lRel, AccessExclusiveLock); } /* @@ -462,8 +441,7 @@ AtCommit_Notify() TPRINTF(TRACE_NOTIFY, "AtCommit_Notify"); - lRel = heap_openr(ListenerRelationName); - LockRelation(lRel, AccessExclusiveLock); + lRel = heap_openr(ListenerRelationName, AccessExclusiveLock); tdesc = RelationGetDescr(lRel); sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL); @@ -542,10 +520,13 @@ AtCommit_Notify() heap_endscan(sRel); /* - * We do not do RelationUnsetLockForWrite(lRel) here, because the - * transaction is about to be committed anyway. + * We do NOT release the lock on pg_listener here; we need to hold it + * until end of transaction (which is about to happen, anyway) to + * ensure that notified backends see our tuple updates when they look. + * Else they might disregard the signal, which would make the + * application programmer very unhappy. */ - heap_close(lRel); + heap_close(lRel, NoLock); ClearPendingNotifies(); @@ -756,8 +737,7 @@ ProcessIncomingNotify(void) StartTransactionCommand(); - lRel = heap_openr(ListenerRelationName); - LockRelation(lRel, AccessExclusiveLock); + lRel = heap_openr(ListenerRelationName, AccessExclusiveLock); tdesc = RelationGetDescr(lRel); /* Scan only entries with my listenerPID */ @@ -794,10 +774,13 @@ ProcessIncomingNotify(void) heap_endscan(sRel); /* - * We do not do RelationUnsetLockForWrite(lRel) here, because the - * transaction is about to be committed anyway. + * We do NOT release the lock on pg_listener here; we need to hold it + * until end of transaction (which is about to happen, anyway) to + * ensure that other backends see our tuple updates when they look. + * Otherwise, a transaction started after this one might mistakenly + * think it doesn't need to send this backend a new NOTIFY. */ - heap_close(lRel); + heap_close(lRel, NoLock); CommitTransactionCommand(); diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 6f99a920f5..d578fc263f 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.44 1999/07/17 20:16:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.45 1999/09/18 19:06:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -101,29 +101,20 @@ cluster(char *oldrelname, char *oldindexname) /* * Like vacuum, cluster spans transactions, so I'm going to handle it - * in the same way. + * in the same way: commit and restart transactions where needed. + * + * We grab exclusive access to the target rel and index for the + * duration of the initial transaction. */ - /* matches the StartTransaction in PostgresMain() */ - - OldHeap = heap_openr(oldrelname); - if (!RelationIsValid(OldHeap)) - { - elog(ERROR, "cluster: unknown relation: \"%s\"", - oldrelname); - } - OIDOldHeap = RelationGetRelid(OldHeap); /* Get OID for the index - * scan */ + OldHeap = heap_openr(oldrelname, AccessExclusiveLock); + OIDOldHeap = RelationGetRelid(OldHeap); OldIndex = index_openr(oldindexname); /* Open old index relation */ - if (!RelationIsValid(OldIndex)) - { - elog(ERROR, "cluster: unknown index: \"%s\"", - oldindexname); - } - OIDOldIndex = RelationGetRelid(OldIndex); /* OID for the index scan */ + LockRelation(OldIndex, AccessExclusiveLock); + OIDOldIndex = RelationGetRelid(OldIndex); - heap_close(OldHeap); + heap_close(OldHeap, NoLock); /* do NOT give up the locks */ index_close(OldIndex); /* @@ -132,7 +123,7 @@ cluster(char *oldrelname, char *oldindexname) * will get the lock after being blocked and add rows which won't be * present in the new table. Bleagh! I'd be best to try and ensure * that no-one's in the tables for the entire duration of this process - * with a pg_vlock. + * with a pg_vlock. XXX Isn't the above comment now invalid? */ NewHeap = copy_heap(OIDOldHeap); OIDNewHeap = RelationGetRelid(NewHeap); @@ -171,7 +162,7 @@ cluster(char *oldrelname, char *oldindexname) renamerel(NewIndexName, saveoldindexname); /* - * Again flush all the buffers. + * Again flush all the buffers. XXX perhaps not needed? */ CommitTransactionCommand(); StartTransactionCommand(); @@ -193,7 +184,7 @@ copy_heap(Oid OIDOldHeap) */ snprintf(NewName, NAMEDATALEN, "temp_%x", OIDOldHeap); - OldHeap = heap_open(OIDOldHeap); + OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock); OldHeapDesc = RelationGetDescr(OldHeap); /* @@ -209,10 +200,11 @@ copy_heap(Oid OIDOldHeap) if (!OidIsValid(OIDNewHeap)) elog(ERROR, "clusterheap: cannot create temporary heap relation\n"); - NewHeap = heap_open(OIDNewHeap); + /* XXX why are we bothering to do this: */ + NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock); - heap_close(NewHeap); - heap_close(OldHeap); + heap_close(NewHeap, AccessExclusiveLock); + heap_close(OldHeap, AccessExclusiveLock); return NewHeap; } @@ -233,7 +225,7 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap) int natts; FuncIndexInfo *finfo; - NewHeap = heap_open(OIDNewHeap); + NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock); OldIndex = index_open(OIDOldIndex); /* @@ -305,8 +297,8 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap) Old_pg_index_Form->indisunique, Old_pg_index_Form->indisprimary); - heap_close(OldIndex); - heap_close(NewHeap); + index_close(OldIndex); + heap_close(NewHeap, AccessExclusiveLock); } @@ -326,8 +318,8 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex) * Open the relations I need. Scan through the OldHeap on the OldIndex * and insert each tuple into the NewHeap. */ - LocalNewHeap = (Relation) heap_open(OIDNewHeap); - LocalOldHeap = (Relation) heap_open(OIDOldHeap); + LocalNewHeap = heap_open(OIDNewHeap, AccessExclusiveLock); + LocalOldHeap = heap_open(OIDOldHeap, AccessExclusiveLock); LocalOldIndex = (Relation) index_open(OIDOldIndex); ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL); @@ -344,6 +336,6 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex) index_endscan(ScanDesc); index_close(LocalOldIndex); - heap_close(LocalOldHeap); - heap_close(LocalNewHeap); + heap_close(LocalOldHeap, AccessExclusiveLock); + heap_close(LocalNewHeap, AccessExclusiveLock); } diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 7fe62cf124..8872bcdfac 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.53 1999/09/04 21:19:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.54 1999/09/18 19:06:40 tgl Exp $ * * NOTES * The PortalExecutorHeapMemory crap needs to be eliminated @@ -283,6 +283,7 @@ PerformAddAttribute(char *relationName, { Relation rel, attrdesc; + Oid myrelid; HeapTuple reltup; HeapTuple attributeTuple; Form_pg_attribute attribute; @@ -310,6 +311,14 @@ PerformAddAttribute(char *relationName, relationName); #endif + /* + * Grab an exclusive lock on the target table, which we will NOT release + * until end of transaction. + */ + rel = heap_openr(relationName, AccessExclusiveLock); + myrelid = RelationGetRelid(rel); + heap_close(rel, NoLock); /* close rel but keep lock! */ + /* * we can't add a not null attribute */ @@ -331,20 +340,10 @@ PerformAddAttribute(char *relationName, { if (inherits) { - Oid myrelid, - childrelid; + Oid childrelid; List *child, *children; - rel = heap_openr(relationName); - if (!RelationIsValid(rel)) - { - elog(ERROR, "PerformAddAttribute: unknown relation: \"%s\"", - relationName); - } - myrelid = RelationGetRelid(rel); - heap_close(rel); - /* this routine is actually in the planner */ children = find_all_inheritors(lconsi(myrelid, NIL), NIL); @@ -358,31 +357,23 @@ PerformAddAttribute(char *relationName, childrelid = lfirsti(child); if (childrelid == myrelid) continue; - rel = heap_open(childrelid); - if (!RelationIsValid(rel)) - { - elog(ERROR, "PerformAddAttribute: can't find catalog entry for inheriting class with oid %u", - childrelid); - } + rel = heap_open(childrelid, AccessExclusiveLock); PerformAddAttribute((rel->rd_rel->relname).data, userName, false, colDef); - heap_close(rel); + heap_close(rel, AccessExclusiveLock); } } } - rel = heap_openr(RelationRelationName); + rel = heap_openr(RelationRelationName, RowExclusiveLock); reltup = SearchSysCacheTupleCopy(RELNAME, PointerGetDatum(relationName), 0, 0, 0); if (!HeapTupleIsValid(reltup)) - { - heap_close(rel); elog(ERROR, "PerformAddAttribute: relation \"%s\" not found", relationName); - } /* * XXX is the following check sufficient? @@ -391,23 +382,15 @@ PerformAddAttribute(char *relationName, { elog(ERROR, "PerformAddAttribute: index relation \"%s\" not changed", relationName); - return; } minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts; maxatts = minattnum + 1; if (maxatts > MaxHeapAttributeNumber) - { - pfree(reltup); - heap_close(rel); elog(ERROR, "PerformAddAttribute: relations limited to %d attributes", MaxHeapAttributeNumber); - } - attrdesc = heap_openr(AttributeRelationName); - - Assert(attrdesc); - Assert(RelationGetForm(attrdesc)); + attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock); /* * Open all (if any) pg_attribute indices @@ -438,12 +421,8 @@ PerformAddAttribute(char *relationName, 0, 0); if (HeapTupleIsValid(tup)) - { - heap_close(attrdesc); - heap_close(rel); elog(ERROR, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"", colDef->colname, relationName); - } /* * check to see if it is an array attribute. @@ -490,7 +469,8 @@ PerformAddAttribute(char *relationName, if (hasindex) CatalogCloseIndices(Num_pg_attr_indices, idescs); - heap_close(attrdesc); + + heap_close(attrdesc, RowExclusiveLock); ((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts; heap_replace(rel, &reltup->t_self, reltup, NULL); @@ -501,7 +481,7 @@ PerformAddAttribute(char *relationName, CatalogCloseIndices(Num_pg_class_indices, ridescs); pfree(reltup); - heap_close(rel); + heap_close(rel, RowExclusiveLock); } void @@ -510,9 +490,9 @@ LockTableCommand(LockStmt *lockstmt) Relation rel; int aclresult; - rel = heap_openr(lockstmt->relname); - if (rel == NULL) - elog(ERROR, "LOCK TABLE: relation %s can't be openned", lockstmt->relname); + rel = heap_openr(lockstmt->relname, NoLock); + if (! RelationIsValid(rel)) + elog(ERROR, "Relation '%s' does not exist", lockstmt->relname); if (lockstmt->mode == AccessShareLock) aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_RD); @@ -524,4 +504,5 @@ LockTableCommand(LockStmt *lockstmt) LockRelation(rel, lockstmt->mode); + heap_close(rel, NoLock); /* close rel, keep lock */ } diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 35f3d6da0b..493d2a170e 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.87 1999/09/11 22:28:11 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.88 1999/09/18 19:06:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -251,22 +251,22 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, Relation rel; extern char *UserName; /* defined in global.c */ const AclMode required_access = from ? ACL_WR : ACL_RD; + LOCKMODE required_lock = from ? AccessExclusiveLock : AccessShareLock; + /* Note: AccessExclusive is probably overkill for copying to a relation, + * but that's what the existing code grabs on the rel's indices. If + * this is relaxed then I think the index locks need relaxed also. + */ int result; - rel = heap_openr(relname); - if (rel == NULL) - elog(ERROR, "COPY command failed. Class %s " - "does not exist.", relname); + rel = heap_openr(relname, required_lock); result = pg_aclcheck(relname, UserName, required_access); if (result != ACLCHECK_OK) elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]); - /* Above should not return */ - else if (!superuser() && !pipe) + else if (!pipe && !superuser()) elog(ERROR, "You must have Postgres superuser privilege to do a COPY " "directly to or from a file. Anyone can COPY to stdout or " "from stdin. Psql's \\copy command also works for anyone."); - /* Above should not return. */ else { if (from) @@ -342,6 +342,8 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, pq_endcopyout(false); } } + + heap_close(rel, required_lock); } @@ -500,8 +502,6 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim) pfree(elements); pfree(typmod); } - - heap_close(rel); } static void @@ -905,20 +905,19 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim) pfree(typmod); } - /* comments in execUtils.c */ if (has_index) { for (i = 0; i < n_indices; i++) { if (index_rels[i] == NULL) continue; + /* see comments in ExecOpenIndices() in execUtils.c */ if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID && (index_rels[i])->rd_rel->relam != HASH_AM_OID) UnlockRelation(index_rels[i], AccessExclusiveLock); index_close(index_rels[i]); } } - heap_close(rel); } @@ -991,7 +990,7 @@ IsTypeByVal(Oid type) /* * Given the OID of a relation, return an array of index relation descriptors * and the number of index relations. These relation descriptors are open - * using heap_open(). + * using index_open(). * * Space for the array itself is palloc'ed. */ @@ -1017,7 +1016,7 @@ GetIndexRelations(Oid main_relation_oid, int i; bool isnull; - pg_index_rel = heap_openr(IndexRelationName); + pg_index_rel = heap_openr(IndexRelationName, AccessShareLock); scandesc = heap_beginscan(pg_index_rel, 0, SnapshotNow, 0, NULL); tupDesc = RelationGetDescr(pg_index_rel); @@ -1044,7 +1043,7 @@ GetIndexRelations(Oid main_relation_oid, } heap_endscan(scandesc); - heap_close(pg_index_rel); + heap_close(pg_index_rel, AccessShareLock); /* We cannot trust to relhasindex of the main_relation now, so... */ if (*n_indices == 0) @@ -1055,7 +1054,7 @@ GetIndexRelations(Oid main_relation_oid, for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next) { (*index_rels)[i] = index_open(scan->index_rel_oid); - /* comments in execUtils.c */ + /* see comments in ExecOpenIndices() in execUtils.c */ if ((*index_rels)[i] != NULL && ((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID && ((*index_rels)[i])->rd_rel->relam != HASH_AM_OID) diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index b93a40e7ba..c1069dd41e 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.45 1999/07/17 20:16:52 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.46 1999/09/18 19:06:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -202,14 +202,13 @@ MergeAttributes(List *schema, List *supers, List **supconstr) */ foreach(entry, schema) { - List *rest; ColumnDef *coldef = lfirst(entry); + List *rest; foreach(rest, lnext(entry)) { - /* - * check for duplicated relation names + * check for duplicated names within the new relation */ ColumnDef *restdef = lfirst(rest); @@ -246,17 +245,14 @@ MergeAttributes(List *schema, List *supers, List **supconstr) TupleDesc tupleDesc; TupleConstr *constr; - relation = heap_openr(name); - if (relation == NULL) - { - elog(ERROR, - "MergeAttr: Can't inherit from non-existent superclass '%s'", name); - } - if (relation->rd_rel->relkind == 'S') - elog(ERROR, "MergeAttr: Can't inherit from sequence superclass '%s'", name); + relation = heap_openr(name, AccessShareLock); tupleDesc = RelationGetDescr(relation); constr = tupleDesc->constr; + /* XXX shouldn't this test be stricter? No indexes, for example? */ + if (relation->rd_rel->relkind == 'S') + elog(ERROR, "MergeAttr: Can't inherit from sequence superclass '%s'", name); + for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--) { Form_pg_attribute attribute = tupleDesc->attrs[attrno]; @@ -340,9 +336,11 @@ MergeAttributes(List *schema, List *supers, List **supconstr) } /* - * iteration cleanup and result collection + * Close the parent rel, but keep our AccessShareLock on it until + * xact commit. That will prevent someone else from deleting or + * ALTERing the parent before the child is committed. */ - heap_close(relation); + heap_close(relation, NoLock); /* * wants the inherited schema to appear in the order they are @@ -386,7 +384,7 @@ StoreCatalogInheritance(Oid relationId, List *supers) * Catalog INHERITS information. * ---------------- */ - relation = heap_openr(InheritsRelationName); + relation = heap_openr(InheritsRelationName, RowExclusiveLock); desc = RelationGetDescr(relation); seqNumber = 1; @@ -422,7 +420,7 @@ StoreCatalogInheritance(Oid relationId, List *supers) seqNumber += 1; } - heap_close(relation); + heap_close(relation, RowExclusiveLock); /* ---------------- * Catalog IPL information. @@ -510,7 +508,7 @@ again: * 3. * ---------------- */ - relation = heap_openr(InheritancePrecidenceListRelationName); + relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock); desc = RelationGetDescr(relation); seqNumber = 1; @@ -537,7 +535,7 @@ again: seqNumber += 1; } - heap_close(relation); + heap_close(relation, RowExclusiveLock); } /* diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index b779715fe8..24eb5b531d 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.39 1999/07/17 20:16:52 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.40 1999/09/18 19:06:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -103,6 +103,8 @@ destroydb(char *dbname, CommandDest dest) /* stop the vacuum daemon */ stop_vacuum(dbpath, dbname); + /* XXX what about stopping backends connected to the target database? */ + path = ExpandDatabasePath(dbpath); if (path == NULL) elog(ERROR, "Unable to locate path '%s'" @@ -189,6 +191,7 @@ check_permissions(char *command, utup = SearchSysCacheTuple(USENAME, PointerGetDatum(userName), 0, 0, 0); + Assert(utup); *userIdP = ((Form_pg_shadow) GETSTRUCT(utup))->usesysid; use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper; use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb; @@ -211,22 +214,13 @@ check_permissions(char *command, /* Check to make sure database is owned by this user */ /* - * need the reldesc to get the database owner out of dbtup and to set - * a write lock on it. + * Acquire exclusive lock on pg_database from the beginning, even though + * we only need read access right here, to avoid potential deadlocks + * from upgrading our lock later. (Is this still necessary? Could we + * use something weaker than exclusive lock?) */ - dbrel = heap_openr(DatabaseRelationName); + dbrel = heap_openr(DatabaseRelationName, AccessExclusiveLock); - if (!RelationIsValid(dbrel)) - elog(FATAL, "%s: cannot open relation \"%-.*s\"", - command, DatabaseRelationName); - - /* - * Acquire a write lock on pg_database from the beginning to avoid - * upgrading a read lock to a write lock. Upgrading causes long - * delays when multiple 'createdb's or 'destroydb's are run simult. - * -mer 7/3/91 - */ - LockRelation(dbrel, AccessExclusiveLock); dbtup = get_pg_dbtup(command, dbname, dbrel); dbfound = HeapTupleIsValid(dbtup); @@ -248,7 +242,8 @@ check_permissions(char *command, else *dbIdP = InvalidOid; - heap_close(dbrel); + /* We will keep the lock on dbrel until end of transaction. */ + heap_close(dbrel, NoLock); /* * Now be sure that the user is allowed to do this. diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 3b1da18783..11e5c39423 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -4,7 +4,7 @@ * * Copyright (c) 1994-5, Regents of the University of California * - * $Id: explain.c,v 1.47 1999/09/11 19:06:36 tgl Exp $ + * $Id: explain.c,v 1.48 1999/09/18 19:06:40 tgl Exp $ * */ @@ -211,11 +211,14 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) i = 0; foreach(l, ((IndexScan *) plan)->indxid) { - relation = RelationIdCacheGetRelation((int) lfirst(l)); + relation = RelationIdGetRelation(lfirsti(l)); + Assert(relation); if (++i > 1) appendStringInfo(str, ", "); appendStringInfo(str, stringStringInfo((RelationGetRelationName(relation))->data)); + /* drop relcache refcount from RelationIdGetRelation */ + RelationDecrementReferenceCount(relation); } case T_SeqScan: if (((Scan *) plan)->scanrelid > 0) diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 31d3419bee..113854311d 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.10 1999/08/22 20:14:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.11 1999/09/18 19:06:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -324,15 +324,15 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) FIsetProcOid(funcInfo, tuple->t_data->t_oid); } - heapRelation = heap_open(relationId); + heapRelation = heap_open(relationId, ShareLock); indexRelation = index_open(indexId); - LockRelation(heapRelation, ShareLock); - InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId); index_build(heapRelation, indexRelation, numberOfAttributes, attributeNumberA, 0, NULL, funcInfo, predInfo); + + /* heap and index rels are closed as a side-effect of index_build */ } diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 21fde2af57..b2fc76f090 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -120,15 +120,14 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid); values[i++] = (Datum) fmgr(F_TEXTIN, stmt->plcompiler); - rel = heap_openr(LanguageRelationName); + rel = heap_openr(LanguageRelationName, RowExclusiveLock); tupDesc = rel->rd_att; tup = heap_formtuple(tupDesc, values, nulls); heap_insert(rel, tup); - heap_close(rel); - return; + heap_close(rel, RowExclusiveLock); } @@ -160,6 +159,8 @@ DropProceduralLanguage(DropPLangStmt *stmt) */ case_translate_language_name(stmt->plname, languageName); + rel = heap_openr(LanguageRelationName, RowExclusiveLock); + langTup = SearchSysCacheTupleCopy(LANNAME, PointerGetDatum(languageName), 0, 0, 0); @@ -167,14 +168,11 @@ DropProceduralLanguage(DropPLangStmt *stmt) elog(ERROR, "Language %s doesn't exist", languageName); if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl) - { elog(ERROR, "Language %s isn't a created procedural language", languageName); - } - rel = heap_openr(LanguageRelationName); heap_delete(rel, &langTup->t_self, NULL); pfree(langTup); - heap_close(rel); + heap_close(rel, RowExclusiveLock); } diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c index af20c79f17..a73964cb02 100644 --- a/src/backend/commands/remove.c +++ b/src/backend/commands/remove.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.36 1999/07/17 20:16:53 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.37 1999/09/18 19:06:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -75,13 +75,14 @@ RemoveOperator(char *operatorName, /* operator name */ else oprtype = 'r'; + relation = heap_openr(OperatorRelationName, RowExclusiveLock); + tup = SearchSysCacheTupleCopy(OPRNAME, PointerGetDatum(operatorName), ObjectIdGetDatum(typeId1), ObjectIdGetDatum(typeId2), CharGetDatum(oprtype)); - relation = heap_openr(OperatorRelationName); if (HeapTupleIsValid(tup)) { #ifndef NO_SECURITY @@ -117,7 +118,7 @@ RemoveOperator(char *operatorName, /* operator name */ } } pfree(tup); - heap_close(relation); + heap_close(relation, RowExclusiveLock); } #ifdef NOTYET @@ -141,7 +142,7 @@ SingleOpOperatorRemove(Oid typeOid) ScanKeyEntryInitialize(&key[0], 0, 0, F_OIDEQ, (Datum) typeOid); - rel = heap_openr(OperatorRelationName); + rel = heap_openr(OperatorRelationName, RowExclusiveLock); for (i = 0; i < 3; ++i) { key[0].sk_attno = attnums[i]; @@ -150,7 +151,7 @@ SingleOpOperatorRemove(Oid typeOid) heap_delete(rel, &tup->t_self, NULL); heap_endscan(scan); } - heap_close(rel); + heap_close(rel, RowExclusiveLock); } /* @@ -187,7 +188,7 @@ AttributeAndRelationRemove(Oid typeOid) oidptr = (struct oidlist *) palloc(sizeof(*oidptr)); oidptr->next = NULL; optr = oidptr; - rel = heap_openr(AttributeRelationName); + rel = heap_openr(AttributeRelationName, AccessShareLock); scan = heap_beginscan(rel, 0, SnapshotNow, 1, key); while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) { @@ -197,14 +198,15 @@ AttributeAndRelationRemove(Oid typeOid) } optr->next = NULL; heap_endscan(scan); - heap_close(rel); + heap_close(rel, AccessShareLock); + optr = oidptr; ScanKeyEntryInitialize(&key[0], 0, ObjectIdAttributeNumber, F_OIDEQ, (Datum) 0); - optr = oidptr; - rel = heap_openr(RelationRelationName); + /* get RowExclusiveLock because heap_destroy will need it */ + rel = heap_openr(RelationRelationName, RowExclusiveLock); while (PointerIsValid((char *) optr->next)) { key[0].sk_argument = (Datum) (optr++)->reloid; @@ -217,9 +219,9 @@ AttributeAndRelationRemove(Oid typeOid) name = (((Form_pg_class) GETSTRUCT(tup))->relname).data; heap_destroy_with_catalog(name); } + heap_endscan(scan); } - heap_endscan(scan); - heap_close(rel); + heap_close(rel, RowExclusiveLock); } #endif /* NOTYET */ @@ -245,18 +247,17 @@ RemoveType(char *typeName) /* type name to be removed */ typeName); #endif - relation = heap_openr(TypeRelationName); + relation = heap_openr(TypeRelationName, RowExclusiveLock); + tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName), 0, 0, 0); - if (!HeapTupleIsValid(tup)) { - heap_close(relation); + heap_close(relation, RowExclusiveLock); elog(ERROR, "RemoveType: type '%s' does not exist", typeName); } - relation = heap_openr(TypeRelationName); typeOid = tup->t_data->t_oid; heap_delete(relation, &tup->t_self, NULL); @@ -267,14 +268,13 @@ RemoveType(char *typeName) /* type name to be removed */ 0, 0, 0); if (!HeapTupleIsValid(tup)) { - heap_close(relation); - elog(ERROR, "RemoveType: type '%s' does not exist", typeName); + heap_close(relation, RowExclusiveLock); + elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type); } - typeOid = tup->t_data->t_oid; heap_delete(relation, &tup->t_self, NULL); - heap_close(relation); + heap_close(relation, RowExclusiveLock); } /* @@ -328,7 +328,7 @@ RemoveFunction(char *functionName, /* function name to be removed */ } #endif - relation = heap_openr(ProcedureRelationName); + relation = heap_openr(ProcedureRelationName, RowExclusiveLock); tup = SearchSysCacheTuple(PRONAME, PointerGetDatum(functionName), Int32GetDatum(nargs), @@ -337,19 +337,19 @@ RemoveFunction(char *functionName, /* function name to be removed */ if (!HeapTupleIsValid(tup)) { - heap_close(relation); + heap_close(relation, RowExclusiveLock); func_error("RemoveFunction", functionName, nargs, argList, NULL); } if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId) { - heap_close(relation); + heap_close(relation, RowExclusiveLock); elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName); } heap_delete(relation, &tup->t_self, NULL); - heap_close(relation); + heap_close(relation, RowExclusiveLock); } void @@ -398,7 +398,7 @@ RemoveAggregate(char *aggName, char *aggType) } #endif - relation = heap_openr(AggregateRelationName); + relation = heap_openr(AggregateRelationName, RowExclusiveLock); tup = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggName), ObjectIdGetDatum(basetypeID), @@ -406,7 +406,7 @@ RemoveAggregate(char *aggName, char *aggType) if (!HeapTupleIsValid(tup)) { - heap_close(relation); + heap_close(relation, RowExclusiveLock); if (aggType) { elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist", @@ -420,5 +420,5 @@ RemoveAggregate(char *aggName, char *aggType) } heap_delete(relation, &tup->t_self, NULL); - heap_close(relation); + heap_close(relation, RowExclusiveLock); } diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c index 1a93027b4a..3a822bd4e4 100644 --- a/src/backend/commands/rename.c +++ b/src/backend/commands/rename.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.32 1999/07/17 20:16:53 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.33 1999/09/18 19:06:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,6 +48,7 @@ renameatt(char *relname, char *userName, int recurse) { + Relation targetrelation; Relation attrelation; HeapTuple reltup, oldatttup, @@ -71,6 +72,14 @@ renameatt(char *relname, relname); #endif + /* + * Grab an exclusive lock on the target table, which we will NOT release + * until end of transaction. + */ + targetrelation = heap_openr(relname, AccessExclusiveLock); + relid = RelationGetRelid(targetrelation); + heap_close(targetrelation, NoLock); /* close rel but keep lock! */ + /* * if the 'recurse' flag is set then we are supposed to rename this * attribute in all classes that inherit from 'relname' (as well as in @@ -82,16 +91,11 @@ renameatt(char *relname, */ if (recurse) { - Oid myrelid, - childrelid; List *child, *children; - if ((myrelid = RelnameFindRelid(relname)) == InvalidOid) - elog(ERROR, "renameatt: unknown relation: \"%s\"", relname); - /* this routine is actually in the planner */ - children = find_all_inheritors(lconsi(myrelid, NIL), NIL); + children = find_all_inheritors(lconsi(relid, NIL), NIL); /* * find_all_inheritors does the recursive search of the @@ -100,10 +104,11 @@ renameatt(char *relname, */ foreach(child, children) { + Oid childrelid; char childname[NAMEDATALEN]; childrelid = lfirsti(child); - if (childrelid == myrelid) + if (childrelid == relid) continue; reltup = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(childrelid), @@ -117,14 +122,12 @@ renameatt(char *relname, StrNCpy(childname, ((Form_pg_class) GETSTRUCT(reltup))->relname.data, NAMEDATALEN); - /* no more recursion! */ + /* note we need not recurse again! */ renameatt(childname, oldattname, newattname, userName, 0); } } - - if ((relid = RelnameFindRelid(relname)) == InvalidOid) - elog(ERROR, "renameatt: relation \"%s\" nonexistent", relname); + attrelation = heap_openr(AttributeRelationName, RowExclusiveLock); oldatttup = SearchSysCacheTupleCopy(ATTNAME, ObjectIdGetDatum(relid), @@ -150,7 +153,6 @@ renameatt(char *relname, StrNCpy((((Form_pg_attribute) (GETSTRUCT(oldatttup)))->attname.data), newattname, NAMEDATALEN); - attrelation = heap_openr(AttributeRelationName); heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL); /* keep system catalog indices current */ @@ -159,7 +161,7 @@ renameatt(char *relname, CatalogCloseIndices(Num_pg_attr_indices, irelations); pfree(oldatttup); - heap_close(attrelation); + heap_close(attrelation, RowExclusiveLock); } /* @@ -182,6 +184,7 @@ void renamerel(char *oldrelname, char *newrelname) { int i; + Relation targetrelation; Relation relrelation; /* for RELATION relation */ HeapTuple oldreltup; char oldpath[MAXPGPATH], @@ -198,6 +201,15 @@ renamerel(char *oldrelname, char *newrelname) elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs", newrelname); + /* + * Grab an exclusive lock on the target table, which we will NOT release + * until end of transaction. + */ + targetrelation = heap_openr(oldrelname, AccessExclusiveLock); + heap_close(targetrelation, NoLock); /* close rel but keep lock! */ + + relrelation = heap_openr(RelationRelationName, RowExclusiveLock); + oldreltup = SearchSysCacheTupleCopy(RELNAME, PointerGetDatum(oldrelname), 0, 0, 0); @@ -207,12 +219,17 @@ renamerel(char *oldrelname, char *newrelname) if (RelnameFindRelid(newrelname) != InvalidOid) elog(ERROR, "renamerel: relation \"%s\" exists", newrelname); + /* + * XXX need to close relation and flush dirty buffers here! + */ + /* rename the path first, so if this fails the rename's not done */ strcpy(oldpath, relpath(oldrelname)); strcpy(newpath, relpath(newrelname)); if (rename(oldpath, newpath) < 0) elog(ERROR, "renamerel: unable to rename file: %s", oldpath); + /* rename additional segments of relation, too */ for (i = 1;; i++) { sprintf(toldpath, "%s.%d", oldpath, i); @@ -225,7 +242,6 @@ renamerel(char *oldrelname, char *newrelname) newrelname, NAMEDATALEN); /* insert fixed rel tuple */ - relrelation = heap_openr(RelationRelationName); heap_replace(relrelation, &oldreltup->t_self, oldreltup, NULL); /* keep the system catalog indices current */ @@ -233,5 +249,5 @@ renamerel(char *oldrelname, char *newrelname) CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup); CatalogCloseIndices(Num_pg_class_indices, irelations); - heap_close(relrelation); + heap_close(relrelation, RowExclusiveLock); } diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index b7f959cd65..be47d32f9f 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -153,10 +153,7 @@ DefineSequence(CreateSeqStmt *seq) DefineRelation(stmt, RELKIND_SEQUENCE); - rel = heap_openr(seq->seqname); - Assert(RelationIsValid(rel)); - - LockRelation(rel, AccessExclusiveLock); + rel = heap_openr(seq->seqname, AccessExclusiveLock); tupDesc = RelationGetDescr(rel); @@ -179,11 +176,7 @@ DefineSequence(CreateSeqStmt *seq) if (WriteBuffer(buf) == STATUS_ERROR) elog(ERROR, "DefineSequence: WriteBuffer failed"); - UnlockRelation(rel, AccessExclusiveLock); - heap_close(rel); - - return; - + heap_close(rel, AccessExclusiveLock); } @@ -422,12 +415,7 @@ init_sequence(char *caller, char *name) temp = elm; } - temp->rel = heap_openr(name); - - if (!RelationIsValid(temp->rel)) - elog(ERROR, "%s.%s: sequence does not exist", name, caller); - - LockRelation(temp->rel, AccessShareLock); + temp->rel = heap_openr(name, AccessShareLock); if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE) elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name); @@ -453,7 +441,6 @@ init_sequence(char *caller, char *name) } return elm; - } @@ -467,20 +454,15 @@ CloseSequences(void) SeqTable elm; Relation rel; - for (elm = seqtab; elm != (SeqTable) NULL;) + for (elm = seqtab; elm != (SeqTable) NULL; elm = elm->next) { if (elm->rel != (Relation) NULL) /* opened in current xact */ { rel = elm->rel; elm->rel = (Relation) NULL; - UnlockRelation(rel, AccessShareLock); - heap_close(rel); + heap_close(rel, AccessShareLock); } - elm = elm->next; } - - return; - } diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 55f67711c7..aa7a0b56c1 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -63,11 +63,7 @@ CreateTrigger(CreateTrigStmt *stmt) elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); #endif - rel = heap_openr(stmt->relname); - if (!RelationIsValid(rel)) - elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname); - - LockRelation(rel, AccessExclusiveLock); + rel = heap_openr(stmt->relname, AccessExclusiveLock); TRIGGER_CLEAR_TYPE(tgtype); if (stmt->before) @@ -103,8 +99,7 @@ CreateTrigger(CreateTrigStmt *stmt) } /* Scan pg_trigger */ - tgrel = heap_openr(TriggerRelationName); - LockRelation(tgrel, AccessExclusiveLock); + tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, F_OIDEQ, RelationGetRelid(rel)); tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key); @@ -203,20 +198,19 @@ CreateTrigger(CreateTrigStmt *stmt) CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple); CatalogCloseIndices(Num_pg_trigger_indices, idescs); pfree(tuple); - UnlockRelation(tgrel, AccessExclusiveLock); - heap_close(tgrel); + heap_close(tgrel, RowExclusiveLock); pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1])); pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1])); /* update pg_class */ + pgrel = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheTupleCopy(RELNAME, PointerGetDatum(stmt->relname), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname); - pgrel = heap_openr(RelationRelationName); ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1; RelationInvalidateHeapTuple(pgrel, tuple); heap_replace(pgrel, &tuple->t_self, tuple, NULL); @@ -224,7 +218,7 @@ CreateTrigger(CreateTrigStmt *stmt) CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple); CatalogCloseIndices(Num_pg_class_indices, ridescs); pfree(tuple); - heap_close(pgrel); + heap_close(pgrel, RowExclusiveLock); CommandCounterIncrement(); oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); @@ -232,8 +226,8 @@ CreateTrigger(CreateTrigStmt *stmt) rel->rd_rel->reltriggers = found + 1; RelationBuildTriggers(rel); MemoryContextSwitchTo(oldcxt); - heap_close(rel); - return; + /* Keep lock on target rel until end of xact */ + heap_close(rel, NoLock); } void @@ -255,14 +249,9 @@ DropTrigger(DropTrigStmt *stmt) elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); #endif - rel = heap_openr(stmt->relname); - if (!RelationIsValid(rel)) - elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname); + rel = heap_openr(stmt->relname, AccessExclusiveLock); - LockRelation(rel, AccessExclusiveLock); - - tgrel = heap_openr(TriggerRelationName); - LockRelation(tgrel, AccessExclusiveLock); + tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, F_OIDEQ, RelationGetRelid(rel)); tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key); @@ -282,20 +271,19 @@ DropTrigger(DropTrigStmt *stmt) elog(ERROR, "DropTrigger: there is no trigger %s on relation %s", stmt->trigname, stmt->relname); if (tgfound > 1) - elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s", + elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s", tgfound, stmt->trigname, stmt->relname); heap_endscan(tgscan); - UnlockRelation(tgrel, AccessExclusiveLock); - heap_close(tgrel); + heap_close(tgrel, RowExclusiveLock); + /* update pg_class */ + pgrel = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheTupleCopy(RELNAME, PointerGetDatum(stmt->relname), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "DropTrigger: relation %s not found in pg_class", stmt->relname); - /* update pg_class */ - pgrel = heap_openr(RelationRelationName); ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found; RelationInvalidateHeapTuple(pgrel, tuple); heap_replace(pgrel, &tuple->t_self, tuple, NULL); @@ -303,7 +291,7 @@ DropTrigger(DropTrigStmt *stmt) CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple); CatalogCloseIndices(Num_pg_class_indices, ridescs); pfree(tuple); - heap_close(pgrel); + heap_close(pgrel, RowExclusiveLock); CommandCounterIncrement(); oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); @@ -312,8 +300,8 @@ DropTrigger(DropTrigStmt *stmt) if (found > 0) RelationBuildTriggers(rel); MemoryContextSwitchTo(oldcxt); - heap_close(rel); - return; + /* Keep lock on target rel until end of xact */ + heap_close(rel, NoLock); } void @@ -324,8 +312,7 @@ RelationRemoveTriggers(Relation rel) ScanKeyData key; HeapTuple tup; - tgrel = heap_openr(TriggerRelationName); - LockRelation(tgrel, AccessExclusiveLock); + tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, F_OIDEQ, RelationGetRelid(rel)); @@ -335,9 +322,7 @@ RelationRemoveTriggers(Relation rel) heap_delete(tgrel, &tup->t_self, NULL); heap_endscan(tgscan); - UnlockRelation(tgrel, AccessExclusiveLock); - heap_close(tgrel); - + heap_close(tgrel, RowExclusiveLock); } void @@ -367,7 +352,7 @@ RelationBuildTriggers(Relation relation) (RegProcedure) F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); - tgrel = heap_openr(TriggerRelationName); + tgrel = heap_openr(TriggerRelationName, AccessShareLock); irel = index_openr(TriggerRelidIndex); sd = index_beginscan(irel, false, 1, &skey); @@ -441,7 +426,7 @@ RelationBuildTriggers(Relation relation) index_endscan(sd); pfree(sd); index_close(irel); - heap_close(tgrel); + heap_close(tgrel, AccessShareLock); /* Build trigdesc */ trigdesc->triggers = triggers; diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 1b0d972839..c05b6da585 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: user.c,v 1.33 1999/07/30 18:09:47 momjian Exp $ + * $Id: user.c,v 1.34 1999/09/18 19:06:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,13 +36,15 @@ static void CheckPgUserAclNotNull(void); * * copy the modified contents of pg_shadow to a file used by the postmaster * for user authentication. The file is stored as $PGDATA/pg_pwd. + * + * NB: caller is responsible for ensuring that only one backend can + * execute this routine at a time. Acquiring AccessExclusiveLock on + * pg_shadow is the standard way to do that. *--------------------------------------------------------------------- */ -static -void +static void UpdatePgPwdFile(char *sql, CommandDest dest) { - char *filename, *tempname; int bufsize; @@ -125,17 +127,13 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest) /* * Scan the pg_shadow relation to be certain the user doesn't already - * exist. + * exist. Note we secure exclusive lock, because we also need to be + * sure of what the next usesysid should be, and we need to protect + * our update of the flat password file. */ - pg_shadow_rel = heap_openr(ShadowRelationName); + pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock); pg_shadow_dsc = RelationGetDescr(pg_shadow_rel); - /* - * Secure a write lock on pg_shadow so we can be sure of what the next - * usesysid should be. - */ - LockRelation(pg_shadow_rel, AccessExclusiveLock); - scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL); while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) { @@ -152,8 +150,7 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest) if (exists) { - UnlockRelation(pg_shadow_rel, AccessExclusiveLock); - heap_close(pg_shadow_rel); + heap_close(pg_shadow_rel, AccessExclusiveLock); UserAbortTransactionBlock(); elog(ERROR, "defineUser: user \"%s\" has already been created", stmt->user); @@ -165,6 +162,12 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest) * * XXX Ugly as this code is, it still fails to cope with ' or \ in any of * the provided strings. + * + * XXX This routine would be *lots* better if it inserted the new + * tuple with formtuple/heap_insert. For one thing, all of the + * transaction-block gamesmanship could be eliminated, because + * it's only there to make the world safe for a recursive call + * to pg_exec_query_dest(). */ snprintf(sql, SQL_LENGTH, "insert into %s (usename,usesysid,usecreatedb,usetrace," @@ -189,17 +192,21 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest) pg_exec_query_dest(sql, dest, false); /* - * Add the stuff here for groups. + * Add stuff here for groups? */ + /* + * Write the updated pg_shadow data to the flat password file. + * Because we are still holding AccessExclusiveLock on pg_shadow, + * we can be sure no other backend will try to write the flat + * file at the same time. + */ UpdatePgPwdFile(sql, dest); /* - * This goes after the UpdatePgPwdFile to be certain that two backends - * to not attempt to write to the pg_pwd file at the same time. + * Now we can clean up. */ - UnlockRelation(pg_shadow_rel, AccessExclusiveLock); - heap_close(pg_shadow_rel); + heap_close(pg_shadow_rel, AccessExclusiveLock); if (IsTransactionBlock() && !inblock) EndTransactionBlock(); @@ -237,70 +244,79 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest) /* * Scan the pg_shadow relation to be certain the user exists. + * Note we secure exclusive lock to protect our update of the + * flat password file. */ - pg_shadow_rel = heap_openr(ShadowRelationName); + pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock); pg_shadow_dsc = RelationGetDescr(pg_shadow_rel); - /* - * Secure a write lock on pg_shadow so we can be sure that when the - * dump of the pg_pwd file is done, there is not another backend doing - * the same. - */ - LockRelation(pg_shadow_rel, AccessExclusiveLock); - tuple = SearchSysCacheTuple(USENAME, PointerGetDatum(stmt->user), 0, 0, 0); if (!HeapTupleIsValid(tuple)) { - UnlockRelation(pg_shadow_rel, AccessExclusiveLock); - heap_close(pg_shadow_rel); - UserAbortTransactionBlock(); /* needed? */ + heap_close(pg_shadow_rel, AccessExclusiveLock); + UserAbortTransactionBlock(); elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user); - return; } /* * Create the update statement to modify the user. + * + * XXX see diatribe in preceding routine. This code is just as bogus. */ snprintf(sql, SQL_LENGTH, "update %s set", ShadowRelationName); if (stmt->password) - snprintf(sql, SQL_LENGTH, "%s passwd = '%s'", pstrdup(sql), stmt->password); + snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql), + " passwd = '%s'", stmt->password); if (stmt->createdb) { - snprintf(sql, SQL_LENGTH, "%s %susecreatedb='%s'", - pstrdup(sql), stmt->password ? "," : "", + snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql), + "%s usecreatedb='%s'", + stmt->password ? "," : "", *stmt->createdb ? "t" : "f"); } if (stmt->createuser) { - snprintf(sql, SQL_LENGTH, "%s %susesuper='%s'", - pstrdup(sql), (stmt->password || stmt->createdb) ? "," : "", + snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql), + "%s usesuper='%s'", + (stmt->password || stmt->createdb) ? "," : "", *stmt->createuser ? "t" : "f"); } if (stmt->validUntil) { - snprintf(sql, SQL_LENGTH, "%s %svaluntil='%s'", - pstrdup(sql), + snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql), + "%s valuntil='%s'", (stmt->password || stmt->createdb || stmt->createuser) ? "," : "", stmt->validUntil); } - snprintf(sql, SQL_LENGTH, "%s where usename = '%s'", - pstrdup(sql), stmt->user); + snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql), + " where usename = '%s'", + stmt->user); pg_exec_query_dest(sql, dest, false); - /* do the pg_group stuff here */ + /* + * Add stuff here for groups? + */ + /* + * Write the updated pg_shadow data to the flat password file. + * Because we are still holding AccessExclusiveLock on pg_shadow, + * we can be sure no other backend will try to write the flat + * file at the same time. + */ UpdatePgPwdFile(sql, dest); - UnlockRelation(pg_shadow_rel, AccessExclusiveLock); - heap_close(pg_shadow_rel); + /* + * Now we can clean up. + */ + heap_close(pg_shadow_rel, AccessExclusiveLock); if (IsTransactionBlock() && !inblock) EndTransactionBlock(); @@ -310,7 +326,6 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest) extern void RemoveUser(char *user, CommandDest dest) { - char *pg_shadow; Relation pg_shadow_rel, pg_rel; @@ -318,7 +333,7 @@ RemoveUser(char *user, CommandDest dest) HeapScanDesc scan; HeapTuple tuple; Datum datum; - char sql[512]; + char sql[SQL_LENGTH]; bool n, inblock; int32 usesysid; @@ -341,27 +356,19 @@ RemoveUser(char *user, CommandDest dest) } /* - * Perform a scan of the pg_shadow relation to find the usesysid of - * the user to be deleted. If it is not found, then return a warning - * message. + * Scan the pg_shadow relation to find the usesysid of the user to be + * deleted. Note we secure exclusive lock, because we need to protect + * our update of the flat password file. */ - pg_shadow_rel = heap_openr(ShadowRelationName); + pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock); pg_dsc = RelationGetDescr(pg_shadow_rel); - /* - * Secure a write lock on pg_shadow so we can be sure that when the - * dump of the pg_pwd file is done, there is not another backend doing - * the same. - */ - LockRelation(pg_shadow_rel, AccessExclusiveLock); - tuple = SearchSysCacheTuple(USENAME, PointerGetDatum(user), 0, 0, 0); if (!HeapTupleIsValid(tuple)) { - UnlockRelation(pg_shadow_rel, AccessExclusiveLock); - heap_close(pg_shadow_rel); + heap_close(pg_shadow_rel, AccessExclusiveLock); UserAbortTransactionBlock(); elog(ERROR, "removeUser: user \"%s\" does not exist", user); } @@ -372,7 +379,7 @@ RemoveUser(char *user, CommandDest dest) * Perform a scan of the pg_database relation to find the databases * owned by usesysid. Then drop them. */ - pg_rel = heap_openr(DatabaseRelationName); + pg_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock); pg_dsc = RelationGetDescr(pg_rel); scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL); @@ -383,7 +390,7 @@ RemoveUser(char *user, CommandDest dest) if ((int) datum == usesysid) { datum = heap_getattr(tuple, Anum_pg_database_datname, pg_dsc, &n); - if (memcmp((void *) datum, "template1", 9)) + if (memcmp((void *) datum, "template1", 9) != 0) { dbase = (char **) repalloc((void *) dbase, sizeof(char *) * (ndbase + 1)); @@ -394,12 +401,12 @@ RemoveUser(char *user, CommandDest dest) } } heap_endscan(scan); - heap_close(pg_rel); + heap_close(pg_rel, AccessExclusiveLock); while (ndbase--) { elog(NOTICE, "Dropping database %s", dbase[ndbase]); - snprintf(sql, SQL_LENGTH, "drop database %s", dbase[ndbase]); + snprintf(sql, SQL_LENGTH, "DROP DATABASE %s", dbase[ndbase]); pfree((void *) dbase[ndbase]); pg_exec_query_dest(sql, dest, false); } @@ -431,10 +438,18 @@ RemoveUser(char *user, CommandDest dest) "delete from %s where usename = '%s'", ShadowRelationName, user); pg_exec_query_dest(sql, dest, false); + /* + * Write the updated pg_shadow data to the flat password file. + * Because we are still holding AccessExclusiveLock on pg_shadow, + * we can be sure no other backend will try to write the flat + * file at the same time. + */ UpdatePgPwdFile(sql, dest); - UnlockRelation(pg_shadow_rel, AccessExclusiveLock); - heap_close(pg_shadow_rel); + /* + * Now we can clean up. + */ + heap_close(pg_shadow_rel, AccessExclusiveLock); if (IsTransactionBlock() && !inblock) EndTransactionBlock(); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 55ec864fca..3027763b46 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.119 1999/08/25 12:20:57 ishii Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.120 1999/09/18 19:06:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -304,7 +304,7 @@ vc_getrels(NameData *VacRelP) portalmem = PortalGetVariableMemory(vc_portal); vrl = cur = (VRelList) NULL; - rel = heap_openr(RelationRelationName); + rel = heap_openr(RelationRelationName, AccessShareLock); tupdesc = RelationGetDescr(rel); scan = heap_beginscan(rel, false, SnapshotNow, 1, &key); @@ -343,9 +343,8 @@ vc_getrels(NameData *VacRelP) if (found == false) elog(NOTICE, "Vacuum: table not found"); - heap_endscan(scan); - heap_close(rel); + heap_close(rel, AccessShareLock); CommitTransactionCommand(); @@ -395,8 +394,10 @@ vc_vacone(Oid relid, bool analyze, List *va_cols) return; } - /* now open the class and vacuum it */ - onerel = heap_open(relid); + /* + * Open the class, get an exclusive lock on it, and vacuum it + */ + onerel = heap_open(relid, AccessExclusiveLock); vacrelstats = (VRelStats *) palloc(sizeof(VRelStats)); vacrelstats->relid = relid; @@ -509,9 +510,6 @@ vc_vacone(Oid relid, bool analyze, List *va_cols) vacrelstats->vacattrstats = (VacAttrStats *) NULL; } - /* we require the relation to be locked until the indices are cleaned */ - LockRelation(onerel, AccessExclusiveLock); - GetXmaxRecent(&XmaxRecent); /* scan it */ @@ -565,13 +563,13 @@ vc_vacone(Oid relid, bool analyze, List *va_cols) pfree(fraged_pages.vpl_pagedesc); } - /* all done with this class */ - heap_close(onerel); - /* update statistics in pg_class */ vc_updstats(vacrelstats->relid, vacrelstats->num_pages, vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats); + /* all done with this class, but hold lock until commit */ + heap_close(onerel, NoLock); + /* next command frees attribute stats */ CommitTransactionCommand(); } @@ -2281,6 +2279,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats * /* * update number of tuples and number of pages in pg_class */ + rd = heap_openr(RelationRelationName, RowExclusiveLock); + ctup = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(relid), 0, 0, 0); @@ -2288,8 +2288,6 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats * elog(ERROR, "pg_class entry for relid %u vanished during vacuuming", relid); - rd = heap_openr(RelationRelationName); - /* get the buffer cache tuple */ rtup.t_self = ctup->t_self; heap_fetch(rd, SnapshotNow, &rtup, &buffer); @@ -2306,8 +2304,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats * VacAttrStats *vacattrstats = vacrelstats->vacattrstats; int natts = vacrelstats->va_natts; - ad = heap_openr(AttributeRelationName); - sd = heap_openr(StatisticRelationName); + ad = heap_openr(AttributeRelationName, RowExclusiveLock); + sd = heap_openr(StatisticRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&askey, 0, Anum_pg_attribute_attrelid, F_INT4EQ, relid); @@ -2458,8 +2456,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats * } } heap_endscan(scan); - heap_close(ad); - heap_close(sd); + heap_close(ad, RowExclusiveLock); + heap_close(sd, RowExclusiveLock); } /* @@ -2469,7 +2467,7 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats * WriteBuffer(buffer); - heap_close(rd); + heap_close(rd, RowExclusiveLock); } /* @@ -2484,7 +2482,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums) HeapTuple tuple; ScanKeyData key; - pgstatistic = heap_openr(StatisticRelationName); + pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock); if (relid != InvalidOid) { @@ -2515,7 +2513,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums) } heap_endscan(scan); - heap_close(pgstatistic); + heap_close(pgstatistic, RowExclusiveLock); } /* @@ -2721,7 +2719,7 @@ vc_getindices(Oid relid, int *nindices, Relation **Irel) ioid = (Oid *) palloc(10 * sizeof(Oid)); /* prepare a heap scan on the pg_index relation */ - pgindex = heap_openr(IndexRelationName); + pgindex = heap_openr(IndexRelationName, AccessShareLock); tupdesc = RelationGetDescr(pgindex); ScanKeyEntryInitialize(&key, 0x0, Anum_pg_index_indrelid, @@ -2741,7 +2739,7 @@ vc_getindices(Oid relid, int *nindices, Relation **Irel) } heap_endscan(scan); - heap_close(pgindex); + heap_close(pgindex, AccessShareLock); if (i == 0) { /* No one index found */ diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 40a94fd02c..9c1b7b8bb4 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -1,11 +1,11 @@ /*------------------------------------------------------------------------- * * execAmi.c - * miscellanious executor access method routines + * miscellaneous executor access method routines * * Copyright (c) 1994, Regents of the University of California * - * $Id: execAmi.c,v 1.41 1999/07/17 20:16:56 momjian Exp $ + * $Id: execAmi.c,v 1.42 1999/09/18 19:06:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -52,7 +52,6 @@ static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys, bool isindex, ScanDirection dir, Snapshot snapshot); -static Relation ExecOpenR(Oid relationOid, bool isindex); /* ---------------------------------------------------------------- * ExecOpenScanR @@ -90,7 +89,22 @@ ExecOpenScanR(Oid relOid, * abstraction someday -cim 9/9/89 * ---------------- */ - relation = ExecOpenR(relOid, isindex); + + /* ---------------- + * open the relation with the correct call depending + * on whether this is a heap relation or an index relation. + * + * Do not lock the rel here; beginscan will acquire AccessShareLock. + * ---------------- + */ + if (isindex) + relation = index_open(relOid); + else + relation = heap_open(relOid, NoLock); + + if (relation == NULL) + elog(ERROR, "ExecOpenScanR: failed to open relation %u", relOid); + scanDesc = ExecBeginScan(relation, nkeys, skeys, @@ -104,35 +118,6 @@ ExecOpenScanR(Oid relOid, *returnScanDesc = scanDesc; } -/* ---------------------------------------------------------------- - * ExecOpenR - * - * returns a relation descriptor given an object id. - * ---------------------------------------------------------------- - */ -static Relation -ExecOpenR(Oid relationOid, bool isindex) -{ - Relation relation; - - relation = (Relation) NULL; - - /* ---------------- - * open the relation with the correct call depending - * on whether this is a heap relation or an index relation. - * ---------------- - */ - if (isindex) - relation = index_open(relationOid); - else - relation = heap_open(relationOid); - - if (relation == NULL) - elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed."); - - return relation; -} - /* ---------------------------------------------------------------- * ExecBeginScan * @@ -243,15 +228,20 @@ ExecCloseR(Plan *node) if (scanDesc != NULL) heap_endscan(scanDesc); + /* + * endscan released AccessShareLock acquired by beginscan. If we are + * holding any stronger locks on the rel, they should be held till end of + * xact. Therefore, we need only close the rel and not release locks. + */ if (relation != NULL) - heap_close(relation); + heap_close(relation, NoLock); /* ---------------- * if this is an index scan then we have to take care * of the index relations as well.. * ---------------- */ - if (nodeTag(node) == T_IndexScan) + if (IsA(node, IndexScan)) { IndexScan *iscan = (IndexScan *) node; IndexScanState *indexstate; diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 48c0a885f3..97dffe548f 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.93 1999/07/17 20:16:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.94 1999/09/18 19:06:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -587,14 +587,12 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) resultRelationIndex = resultRelation; rtentry = rt_fetch(resultRelationIndex, rangeTable); resultRelationOid = rtentry->relid; - resultRelationDesc = heap_open(resultRelationOid); + resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock); if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE) elog(ERROR, "You can't change sequence relation %s", resultRelationDesc->rd_rel->relname.data); - LockRelation(resultRelationDesc, RowExclusiveLock); - resultRelationInfo = makeNode(RelationInfo); resultRelationInfo->ri_RangeTableIndex = resultRelationIndex; resultRelationInfo->ri_RelationDesc = resultRelationDesc; @@ -636,8 +634,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) { rm = lfirst(l); relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid; - relation = heap_open(relid); - LockRelation(relation, RowShareLock); + relation = heap_open(relid, RowShareLock); if (!(rm->info & ROW_MARK_FOR_UPDATE)) continue; erm = (execRowMark *) palloc(sizeof(execRowMark)); @@ -758,7 +755,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) */ setheapoverride(true); - intoRelationDesc = heap_open(intoRelationId); + intoRelationDesc = heap_open(intoRelationId, + AccessExclusiveLock); setheapoverride(false); } @@ -809,14 +807,15 @@ EndPlan(Plan *plan, EState *estate) } /* - * close the result relations if necessary + * close the result relations if necessary, + * but hold locks on them until xact commit */ if (resultRelationInfo != NULL) { Relation resultRelationDesc; resultRelationDesc = resultRelationInfo->ri_RelationDesc; - heap_close(resultRelationDesc); + heap_close(resultRelationDesc, NoLock); /* * close indices on the result relation @@ -828,7 +827,7 @@ EndPlan(Plan *plan, EState *estate) * close the "into" relation if necessary */ if (intoRelationDesc != NULL) - heap_close(intoRelationDesc); + heap_close(intoRelationDesc, NoLock); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 4bacf3f7bd..197995c346 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.48 1999/07/16 04:58:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.49 1999/09/18 19:06:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -772,7 +772,7 @@ ExecOpenIndices(Oid resultRelationOid, * open pg_index * ---------------- */ - indexRd = heap_openr(IndexRelationName); + indexRd = heap_openr(IndexRelationName, AccessShareLock); /* ---------------- * form a scan key @@ -856,7 +856,7 @@ ExecOpenIndices(Oid resultRelationOid, * ---------------- */ heap_endscan(indexSd); - heap_close(indexRd); + heap_close(indexRd, AccessShareLock); /* ---------------- * Now that we've collected the index information into three @@ -913,7 +913,7 @@ ExecOpenIndices(Oid resultRelationOid, /* * Hack for not btree and hash indices: they use relation - * level exclusive locking on updation (i.e. - they are + * level exclusive locking on update (i.e. - they are * not ready for MVCC) and so we have to exclusively lock * indices here to prevent deadlocks if we will scan them * - index_beginscan places AccessShareLock, indices @@ -1010,7 +1010,7 @@ ExecCloseIndices(RelationInfo *resultRelationInfo) continue; /* - * Notes in ExecOpenIndices. + * See notes in ExecOpenIndices. */ if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID && relationDescs[i]->rd_rel->relam != HASH_AM_OID) diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 19a1e53b69..bd515d51f9 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.24 1999/07/17 19:01:21 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.25 1999/09/18 19:06:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -257,7 +257,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) reloid = rtentry->relid; rri = makeNode(RelationInfo); rri->ri_RangeTableIndex = es_rri->ri_RangeTableIndex; - rri->ri_RelationDesc = heap_open(reloid); + rri->ri_RelationDesc = heap_open(reloid, RowExclusiveLock); rri->ri_NumIndices = 0; rri->ri_IndexRelationDescs = NULL; /* index descs */ rri->ri_IndexRelationInfo = NULL; /* index key info */ @@ -484,7 +484,7 @@ ExecEndAppend(Append *node) resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList); resultRelationDesc = resultRelationInfo->ri_RelationDesc; - heap_close(resultRelationDesc); + heap_close(resultRelationDesc, NoLock); pfree(resultRelationInfo); resultRelationInfoList = lnext(resultRelationInfoList); } diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 68fb4eda07..3964d5d5bb 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.71 1999/09/13 00:17:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.72 1999/09/18 19:06:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1163,7 +1163,7 @@ clause_pred_clause_test(Expr *predicate, Node *clause) F_OIDEQ, ObjectIdGetDatum(pred_op)); - relation = heap_openr(AccessMethodOperatorRelationName); + relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock); /* * The following assumes that any given operator will only be in a @@ -1178,6 +1178,8 @@ clause_pred_clause_test(Expr *predicate, Node *clause) if (!HeapTupleIsValid(tuple)) { elog(DEBUG, "clause_pred_clause_test: unknown pred_op"); + heap_endscan(scan); + heap_close(relation, AccessShareLock); return false; } aform = (Form_pg_amop) GETSTRUCT(tuple); @@ -1209,6 +1211,8 @@ clause_pred_clause_test(Expr *predicate, Node *clause) if (!HeapTupleIsValid(tuple)) { elog(DEBUG, "clause_pred_clause_test: unknown clause_op"); + heap_endscan(scan); + heap_close(relation, AccessShareLock); return false; } aform = (Form_pg_amop) GETSTRUCT(tuple); @@ -1224,8 +1228,10 @@ clause_pred_clause_test(Expr *predicate, Node *clause) test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1]; if (test_strategy == 0) + { + heap_close(relation, AccessShareLock); return false; /* the implication cannot be determined */ - + } /* * 4. From the same opclass, find the operator for the test strategy @@ -1241,14 +1247,18 @@ clause_pred_clause_test(Expr *predicate, Node *clause) if (!HeapTupleIsValid(tuple)) { elog(DEBUG, "clause_pred_clause_test: unknown test_op"); + heap_endscan(scan); + heap_close(relation, AccessShareLock); return false; } aform = (Form_pg_amop) GETSTRUCT(tuple); /* Get the test operator */ test_op = aform->amopopr; + heap_endscan(scan); + heap_close(relation, AccessShareLock); /* * 5. Evaluate the test diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index a22d3ed43a..32a5bb52cd 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.67 1999/09/13 00:17:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.68 1999/09/18 19:07:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -627,7 +627,6 @@ pg_checkretval(Oid rettype, List *queryTreeList) Resdom *resnode; Relation reln; Oid relid; - Oid tletype; int relnatts; int i; @@ -713,11 +712,7 @@ pg_checkretval(Oid rettype, List *queryTreeList) * declared return type, and be sure that attributes 1 .. n in the * target list match the declared types. */ - reln = heap_open(typeTypeRelid(typ)); - - if (!RelationIsValid(reln)) - elog(ERROR, "cannot open relation relid %u", typeTypeRelid(typ)); - + reln = heap_open(typeTypeRelid(typ), AccessShareLock); relid = reln->rd_id; relnatts = reln->rd_rel->relnatts; @@ -729,41 +724,12 @@ pg_checkretval(Oid rettype, List *queryTreeList) { TargetEntry *tle = lfirst(tlist); Node *thenode = tle->expr; + Oid tletype = exprType(thenode); - tlist = lnext(tlist); - tletype = exprType(thenode); - -#ifdef NOT_USED /* fix me */ - /* this is tedious */ - if (IsA(thenode, Var)) - tletype = (Oid) ((Var *) thenode)->vartype; - else if (IsA(thenode, Const)) - tletype = (Oid) ((Const *) thenode)->consttype; - else if (IsA(thenode, Param)) - tletype = (Oid) ((Param *) thenode)->paramtype; - else if (IsA(thenode, Expr)) - tletype = Expr; - - else if (IsA(thenode, LispList)) - { - thenode = lfirst(thenode); - if (IsA(thenode, Oper)) - tletype = (Oid) get_opresulttype((Oper *) thenode); - else if (IsA(thenode, Func)) - tletype = (Oid) get_functype((Func *) thenode); - else - elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ)); - } - else - elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ)); -#endif - /* reach right in there, why don't you? */ if (tletype != reln->rd_att->attrs[i - 1]->atttypid) elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ)); + tlist = lnext(tlist); } - heap_close(reln); - - /* success */ - return; + heap_close(reln, AccessShareLock); } diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 9ca188bce6..ef120f8d2f 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.37 1999/09/09 02:35:53 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.38 1999/09/18 19:07:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -126,17 +126,19 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info) /* Find an index on the given relation */ if (first) { - if (RelationIsValid(relation)) - heap_close(relation); if (HeapScanIsValid(scan)) heap_endscan(scan); + scan = (HeapScanDesc) NULL; + if (RelationIsValid(relation)) + heap_close(relation, AccessShareLock); + relation = (Relation) NULL; ScanKeyEntryInitialize(&indexKey, 0, Anum_pg_index_indrelid, F_OIDEQ, ObjectIdGetDatum(indrelid)); - relation = heap_openr(IndexRelationName); + relation = heap_openr(IndexRelationName, AccessShareLock); scan = heap_beginscan(relation, 0, SnapshotNow, 1, &indexKey); } @@ -146,7 +148,7 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info) if (!HeapTupleIsValid(indexTuple)) { heap_endscan(scan); - heap_close(relation); + heap_close(relation, AccessShareLock); scan = (HeapScanDesc) NULL; relation = (Relation) NULL; return 0; @@ -190,7 +192,7 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info) info->relam = relam; info->pages = indexRelation->rd_rel->relpages; info->tuples = indexRelation->rd_rel->reltuples; - heap_close(indexRelation); + index_close(indexRelation); /* * Find the index ordering keys @@ -390,7 +392,7 @@ find_inheritance_children(Oid inhparent) key[0].sk_nargs = key[0].sk_func.fn_nargs; key[0].sk_argument = ObjectIdGetDatum((Oid) inhparent); - relation = heap_openr(InheritsRelationName); + relation = heap_openr(InheritsRelationName, AccessShareLock); scan = heap_beginscan(relation, 0, SnapshotNow, 1, key); while (HeapTupleIsValid(inheritsTuple = heap_getnext(scan, 0))) { @@ -398,7 +400,7 @@ find_inheritance_children(Oid inhparent) list = lappendi(list, inhrelid); } heap_endscan(scan); - heap_close(relation); + heap_close(relation, AccessShareLock); return list; } @@ -424,8 +426,8 @@ VersionGetParents(Oid verrelid) fmgr_info(F_OIDEQ, &key[0].sk_func); key[0].sk_nargs = key[0].sk_func.fn_nargs; - relation = heap_openr(VersionRelationName); key[0].sk_argument = ObjectIdGetDatum(verrelid); + relation = heap_openr(VersionRelationName, AccessShareLock); scan = heap_beginscan(relation, 0, SnapshotNow, 1, key); while (HeapTupleIsValid(versionTuple = heap_getnext(scan, 0))) { @@ -438,7 +440,7 @@ VersionGetParents(Oid verrelid) heap_rescan(scan, 0, key); } heap_endscan(scan); - heap_close(relation); + heap_close(relation, AccessShareLock); return list; } diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 2c4d1c7a7e..276d28b3aa 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.c,v 1.118 1999/08/21 03:48:55 tgl Exp $ + * $Id: analyze.c,v 1.119 1999/09/18 19:07:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -64,7 +64,7 @@ parse_analyze(List *pl, ParseState *parentParseState) parsetree = transformStmt(pstate, lfirst(pl)); if (pstate->p_target_relation != NULL) - heap_close(pstate->p_target_relation); + heap_close(pstate->p_target_relation, AccessShareLock); pstate->p_target_relation = NULL; pstate->p_target_rangetblentry = NULL; @@ -73,7 +73,7 @@ parse_analyze(List *pl, ParseState *parentParseState) result = lappend(result, transformStmt(pstate, lfirst(extras_before))); if (pstate->p_target_relation != NULL) - heap_close(pstate->p_target_relation); + heap_close(pstate->p_target_relation, AccessShareLock); pstate->p_target_relation = NULL; pstate->p_target_rangetblentry = NULL; extras_before = lnext(extras_before); @@ -86,7 +86,7 @@ parse_analyze(List *pl, ParseState *parentParseState) result = lappend(result, transformStmt(pstate, lfirst(extras_after))); if (pstate->p_target_relation != NULL) - heap_close(pstate->p_target_relation); + heap_close(pstate->p_target_relation, AccessShareLock); pstate->p_target_relation = NULL; pstate->p_target_rangetblentry = NULL; extras_after = lnext(extras_after); diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 234987fb5f..bae53ebbd8 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.44 1999/08/21 03:48:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.45 1999/09/18 19:07:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -75,11 +75,11 @@ setTargetTable(ParseState *pstate, char *relname) /* This could only happen for multi-action rules */ if (pstate->p_target_relation != NULL) - heap_close(pstate->p_target_relation); + heap_close(pstate->p_target_relation, AccessShareLock); pstate->p_target_rangetblentry = rte; - pstate->p_target_relation = heap_open(rte->relid); - /* will close relation later */ + pstate->p_target_relation = heap_open(rte->relid, AccessShareLock); + /* will close relation later, see analyze.c */ } /* diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 19a287d99e..15e63f7c98 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.54 1999/08/22 20:15:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.55 1999/09/18 19:07:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -139,7 +139,7 @@ agg_get_candidates(char *aggname, fmgr_info(F_NAMEEQ, (FmgrInfo *) &aggKey[0].sk_func); aggKey[0].sk_argument = NameGetDatum(aggname); - pg_aggregate_desc = heap_openr(AggregateRelationName); + pg_aggregate_desc = heap_openr(AggregateRelationName, AccessShareLock); pg_aggregate_scan = heap_beginscan(pg_aggregate_desc, 0, SnapshotSelf, /* ??? */ @@ -159,7 +159,7 @@ agg_get_candidates(char *aggname, } heap_endscan(pg_aggregate_scan); - heap_close(pg_aggregate_desc); + heap_close(pg_aggregate_desc, AccessShareLock); return ncandidates; } /* agg_get_candidates() */ @@ -310,11 +310,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, if (attisset) { toid = exprType(first_arg); - rd = heap_openr(typeidTypeName(toid)); + rd = heap_openr(typeidTypeName(toid), NoLock); if (RelationIsValid(rd)) { relname = RelationGetRelationName(rd)->data; - heap_close(rd); + heap_close(rd, NoLock); } else elog(ERROR, "Type '%s' is not a relation type", @@ -646,7 +646,7 @@ func_get_candidates(char *funcname, int nargs) CandidateList current_candidate; int i; - heapRelation = heap_openr(ProcedureRelationName); + heapRelation = heap_openr(ProcedureRelationName, AccessShareLock); ScanKeyEntryInitialize(&skey, (bits16) 0x0, (AttrNumber) 1, @@ -690,7 +690,7 @@ func_get_candidates(char *funcname, int nargs) index_endscan(sd); index_close(idesc); - heap_close(heapRelation); + heap_close(heapRelation, AccessShareLock); return candidates; } @@ -1086,7 +1086,7 @@ find_inheritors(Oid relid, Oid **supervec) visited = DLNewList(); - inhrel = heap_openr(InheritsRelationName); + inhrel = heap_openr(InheritsRelationName, AccessShareLock); inhtupdesc = RelationGetDescr(inhrel); /* @@ -1140,12 +1140,12 @@ find_inheritors(Oid relid, Oid **supervec) if (qentry != (SuperQE *) NULL) { - /* save the type id, rather than the relation id */ - if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL) + rd = heap_open(qentry->sqe_relid, NoLock); + if (! RelationIsValid(rd)) elog(ERROR, "Relid %u does not exist", qentry->sqe_relid); qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd)->data)); - heap_close(rd); + heap_close(rd, NoLock); DLAddTail(visited, qe); @@ -1153,7 +1153,7 @@ find_inheritors(Oid relid, Oid **supervec) } } while (qentry != (SuperQE *) NULL); - heap_close(inhrel); + heap_close(inhrel, AccessShareLock); if (nvisited > 0) { @@ -1370,16 +1370,13 @@ ParseComplexProjection(ParseState *pstate, */ /* add a tlist to the func node and return the Iter */ - rd = heap_openr(typeidTypeName(argtype)); + rd = heap_openr(typeidTypeName(argtype), NoLock); if (RelationIsValid(rd)) { relid = RelationGetRelid(rd); - heap_close(rd); - } - if (RelationIsValid(rd)) - { func->func_tlist = setup_tlist(funcname, argrelid); iter->itertype = attnumTypeId(rd, attnum); + heap_close(rd, NoLock); return (Node *) iter; } else @@ -1427,16 +1424,12 @@ ParseComplexProjection(ParseState *pstate, { /* add a tlist to the func node */ - rd = heap_openr(typeidTypeName(argtype)); - if (RelationIsValid(rd)) - { - relid = RelationGetRelid(rd); - heap_close(rd); - } + rd = heap_openr(typeidTypeName(argtype), NoLock); if (RelationIsValid(rd)) { Expr *newexpr; + relid = RelationGetRelid(rd); funcnode->func_tlist = setup_tlist(funcname, argrelid); funcnode->functype = attnumTypeId(rd, attnum); @@ -1446,8 +1439,11 @@ ParseComplexProjection(ParseState *pstate, newexpr->oper = (Node *) funcnode; newexpr->args = expr->args; + heap_close(rd, NoLock); + return (Node *) newexpr; } + /* XXX why not an error condition if it's not there? */ } @@ -1461,18 +1457,19 @@ ParseComplexProjection(ParseState *pstate, * If the Param is a complex type, this could be a * projection */ - rd = heap_openr(typeidTypeName(param->paramtype)); + rd = heap_openr(typeidTypeName(param->paramtype), NoLock); if (RelationIsValid(rd)) { relid = RelationGetRelid(rd); - heap_close(rd); if ((attnum = get_attnum(relid, funcname)) != InvalidAttrNumber) { param->paramtype = attnumTypeId(rd, attnum); param->param_tlist = setup_tlist(funcname, relid); + heap_close(rd, NoLock); return (Node *) param; } + heap_close(rd, NoLock); } break; } diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 8f82e58517..5a5c870996 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.31 1999/08/26 04:59:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.32 1999/09/18 19:07:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -75,7 +75,6 @@ binary_oper_get_candidates(char *opname, HeapScanDesc pg_operator_scan; HeapTuple tup; Form_pg_operator oper; - int nkeys; int ncandidates = 0; ScanKeyData opKey[3]; @@ -91,13 +90,11 @@ binary_oper_get_candidates(char *opname, F_CHAREQ, CharGetDatum('b')); - nkeys = 2; - - pg_operator_desc = heap_openr(OperatorRelationName); + pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock); pg_operator_scan = heap_beginscan(pg_operator_desc, 0, SnapshotSelf, /* ??? */ - nkeys, + 2, opKey); while (HeapTupleIsValid(tup = heap_getnext(pg_operator_scan, 0))) @@ -114,7 +111,7 @@ binary_oper_get_candidates(char *opname, } heap_endscan(pg_operator_scan); - heap_close(pg_operator_desc); + heap_close(pg_operator_desc, AccessShareLock); return ncandidates; } /* binary_oper_get_candidates() */ @@ -522,7 +519,7 @@ unary_oper_get_candidates(char *op, fmgr_info(F_CHAREQ, (FmgrInfo *) &opKey[1].sk_func); opKey[1].sk_argument = CharGetDatum(rightleft); - pg_operator_desc = heap_openr(OperatorRelationName); + pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock); pg_operator_scan = heap_beginscan(pg_operator_desc, 0, SnapshotSelf, /* ??? */ @@ -545,7 +542,7 @@ unary_oper_get_candidates(char *op, } heap_endscan(pg_operator_scan); - heap_close(pg_operator_desc); + heap_close(pg_operator_desc, AccessShareLock); return ncandidates; } /* unary_oper_get_candidates() */ diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 79b08635f0..af18087aa5 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.26 1999/07/19 00:26:20 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.27 1999/09/18 19:07:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -202,14 +202,9 @@ addRangeTableEntry(ParseState *pstate, rte->relname = pstrdup(relname); rte->refname = pstrdup(refname); - relation = heap_openr(relname); - if (relation == NULL) - elog(ERROR, "%s: %s", - relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]); - + relation = heap_openr(relname, AccessShareLock); rte->relid = RelationGetRelid(relation); - - heap_close(relation); + heap_close(relation, AccessShareLock); /* * Flags - zero or more from inheritance,union,version or recursive @@ -246,10 +241,7 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno) if (rte == NULL) rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE); - rel = heap_open(rte->relid); - if (rel == NULL) - elog(ERROR, "Unable to expand all -- heap_open failed on %s", - rte->refname); + rel = heap_open(rte->relid, AccessShareLock); maxattrs = RelationGetNumberOfAttributes(rel); @@ -278,7 +270,7 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno) te_list = lappend(te_list, te); } - heap_close(rel); + heap_close(rel, AccessShareLock); return te_list; } diff --git a/src/backend/rewrite/locks.c b/src/backend/rewrite/locks.c index c478a7face..ef96b85210 100644 --- a/src/backend/rewrite/locks.c +++ b/src/backend/rewrite/locks.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.21 1999/07/16 04:59:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.22 1999/09/18 19:07:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -184,7 +184,7 @@ checkLockPerms(List *locks, Query *parsetree, int rt_index) * Get the usename of the rules event relation owner */ rte = (RangeTblEntry *) nth(rt_index - 1, parsetree->rtable); - ev_rel = heap_openr(rte->relname); + ev_rel = heap_openr(rte->relname, AccessShareLock); usertup = SearchSysCacheTuple(USESYSID, ObjectIdGetDatum(ev_rel->rd_rel->relowner), 0, 0, 0); @@ -193,7 +193,7 @@ checkLockPerms(List *locks, Query *parsetree, int rt_index) elog(ERROR, "cache lookup for userid %d failed", ev_rel->rd_rel->relowner); } - heap_close(ev_rel); + heap_close(ev_rel, AccessShareLock); evowner = nameout(&(((Form_pg_shadow) GETSTRUCT(usertup))->usename)); /* diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index b118bf8de5..c9be17151a 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.35 1999/07/19 07:07:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.36 1999/09/18 19:07:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -78,9 +78,7 @@ InsertRule(char *rulname, extern void eval_as_new_xact(); char *template; - eventrel = heap_openr(evobj); - if (eventrel == NULL) - elog(ERROR, "rules cannot be defined on relations not in schema"); + eventrel = heap_openr(evobj, AccessShareLock); eventrel_oid = RelationGetRelid(eventrel); /* @@ -90,7 +88,7 @@ InsertRule(char *rulname, evslot_index = -1; else evslot_index = attnameAttNum(eventrel, (char *) evslot); - heap_close(eventrel); + heap_close(eventrel, AccessShareLock); if (evinstead) is_instead = "t"; @@ -258,9 +256,7 @@ DefineQueryRewrite(RuleStmt *stmt) * ... the targetlist of the SELECT action must exactly match the * event relation, ... */ - event_relation = heap_openr(event_obj->relname); - if (event_relation == NULL) - elog(ERROR, "virtual relations not supported yet"); + event_relation = heap_openr(event_obj->relname, AccessShareLock); if (event_relation->rd_att->natts != length(query->targetList)) elog(ERROR, "select rules target list must match event relations structure"); @@ -297,7 +293,7 @@ DefineQueryRewrite(RuleStmt *stmt) } } - heap_close(event_relation); + heap_close(event_relation, AccessShareLock); /* * LIMIT in view is not supported @@ -332,9 +328,7 @@ DefineQueryRewrite(RuleStmt *stmt) * This rule is allowed - install it. */ - event_relation = heap_openr(event_obj->relname); - if (event_relation == NULL) - elog(ERROR, "virtual relations not supported yet"); + event_relation = heap_openr(event_obj->relname, AccessShareLock); ev_relid = RelationGetRelid(event_relation); if (eslot_string == NULL) @@ -347,7 +341,7 @@ DefineQueryRewrite(RuleStmt *stmt) event_attno = attnameAttNum(event_relation, eslot_string); event_attype = attnumTypeId(event_relation, event_attno); } - heap_close(event_relation); + heap_close(event_relation, AccessShareLock); /* fix bug about instead nothing */ ValidateRule(event_type, event_obj->relname, diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 0fa7fd72d4..b13cb5e3ed 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.55 1999/08/25 23:21:43 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.56 1999/09/18 19:07:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2059,10 +2059,10 @@ fireRIRrules(Query *parsetree) continue; } - rel = heap_openr(rte->relname); + rel = heap_openr(rte->relname, AccessShareLock); if (rel->rd_rules == NULL) { - heap_close(rel); + heap_close(rel, AccessShareLock); continue; } @@ -2112,7 +2112,7 @@ fireRIRrules(Query *parsetree) &modified); } - heap_close(rel); + heap_close(rel, AccessShareLock); } fireRIRonSubselect((Node *) parsetree); @@ -2452,9 +2452,9 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products) * the statement is an update, insert or delete - fire rules on it. */ rt_entry = rt_fetch(result_relation, parsetree->rtable); - rt_entry_relation = heap_openr(rt_entry->relname); + rt_entry_relation = heap_openr(rt_entry->relname, AccessShareLock); rt_entry_locks = rt_entry_relation->rd_rules; - heap_close(rt_entry_relation); + heap_close(rt_entry_relation, AccessShareLock); if (rt_entry_locks != NULL) { @@ -2469,7 +2469,6 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products) } return product_queries; - } @@ -2585,7 +2584,7 @@ RewritePreprocessQuery(Query *parsetree) rte = (RangeTblEntry *) nth(parsetree->resultRelation - 1, parsetree->rtable); - rd = heap_openr(rte->relname); + rd = heap_openr(rte->relname, AccessShareLock); foreach(tl, parsetree->targetList) { @@ -2597,7 +2596,7 @@ RewritePreprocessQuery(Query *parsetree) tle->resdom->resno = 0; } - heap_close(rd); + heap_close(rd, AccessShareLock); } } diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index 14ceeead84..50e6c62c02 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.28 1999/07/17 20:17:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.29 1999/09/18 19:07:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -76,7 +76,7 @@ RemoveRewriteRule(char *ruleName) /* * Open the pg_rewrite relation. */ - RewriteRelation = heap_openr(RewriteRelationName); + RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock); /* * Scan the RuleRelation ('pg_rewrite') until we find a tuple @@ -90,7 +90,7 @@ RemoveRewriteRule(char *ruleName) */ if (!HeapTupleIsValid(tuple)) { - heap_close(RewriteRelation); + heap_close(RewriteRelation, RowExclusiveLock); elog(ERROR, "Rule '%s' not found\n", ruleName); } @@ -125,7 +125,7 @@ RemoveRewriteRule(char *ruleName) heap_delete(RewriteRelation, &tuple->t_self, NULL); pfree(tuple); - heap_close(RewriteRelation); + heap_close(RewriteRelation, RowExclusiveLock); } /* @@ -144,7 +144,7 @@ RelationRemoveRules(Oid relid) /* * Open the pg_rewrite relation. */ - RewriteRelation = heap_openr(RewriteRelationName); + RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock); /* * Scan the RuleRelation ('pg_rewrite') for all the tuples that has @@ -162,5 +162,5 @@ RelationRemoveRules(Oid relid) heap_delete(RewriteRelation, &tuple->t_self, NULL); heap_endscan(scanDesc); - heap_close(RewriteRelation); + heap_close(RewriteRelation, RowExclusiveLock); } diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index c8d9d023ef..c089be56d3 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.36 1999/07/16 04:59:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.37 1999/09/18 19:07:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -40,7 +40,7 @@ RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees) char *rule_evqual_string = NULL; Node *rule_evqual = NULL; - ruleRelation = heap_openr(RewriteRelationName); + ruleRelation = heap_openr(RewriteRelationName, AccessShareLock); ruleTupdesc = RelationGetDescr(ruleRelation); ruletuple = SearchSysCacheTuple(RULOID, ObjectIdGetDatum(ruleoid), @@ -68,7 +68,7 @@ RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees) ruleparse = (Query *) stringToNode(ruleaction); rule_evqual = (Node *) stringToNode(rule_evqual_string); - heap_close(ruleRelation); + heap_close(ruleRelation, AccessShareLock); *parseTrees = ruleparse; return rule_evqual; @@ -79,23 +79,11 @@ RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees) int IsDefinedRewriteRule(char *ruleName) { - Relation RewriteRelation = NULL; HeapTuple tuple; - - /* - * Open the pg_rewrite relation. - */ - RewriteRelation = heap_openr(RewriteRelationName); - tuple = SearchSysCacheTuple(REWRITENAME, PointerGetDatum(ruleName), 0, 0, 0); - - /* - * return whether or not the rewrite rule existed - */ - heap_close(RewriteRelation); return HeapTupleIsValid(tuple); } @@ -111,12 +99,12 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules) * pg_relation), find the appropriate tuple, and add the specified * lock to it. */ + relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(relationId), 0, 0, 0); Assert(HeapTupleIsValid(tuple)); - relationRelation = heap_openr(RelationRelationName); ((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relhasrules; heap_replace(relationRelation, &tuple->t_self, tuple, NULL); @@ -126,7 +114,7 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules) CatalogCloseIndices(Num_pg_class_indices, idescs); pfree(tuple); - heap_close(relationRelation); + heap_close(relationRelation, RowExclusiveLock); } void @@ -162,7 +150,7 @@ prs2_addToRelation(Oid relid, thisRule->actions = actions; thisRule->isInstead = isInstead; - relation = heap_open(relid); + relation = heap_open(relid, AccessShareLock); /* * modify or create a RuleLock cached by Relation @@ -200,9 +188,7 @@ prs2_addToRelation(Oid relid, rulelock->numLocks++; } - heap_close(relation); - - return; + heap_close(relation, AccessShareLock); } void @@ -214,7 +200,7 @@ prs2_deleteFromRelation(Oid relid, Oid ruleId) int i; MemoryContext oldcxt; - relation = heap_open(relid); + relation = heap_open(relid, AccessShareLock); rulelock = relation->rd_rules; Assert(rulelock != NULL); @@ -245,5 +231,5 @@ prs2_deleteFromRelation(Oid relid, Oid ruleId) rulelock->numLocks--; } - heap_close(relation); + heap_close(relation, AccessShareLock); } diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index de0d803efe..b435dd53ca 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.61 1999/07/17 20:17:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.62 1999/09/18 19:07:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -109,7 +109,7 @@ RelationGetBufferWithBuffer(Relation relation, { if (!BufferIsLocal(buffer)) { - LockRelId *lrelId = &(((LockInfo) (relation->lockInfo))->lockRelId); + LockRelId *lrelId = & relation->rd_lockInfo.lockRelId; bufHdr = &BufferDescriptors[buffer - 1]; SpinAcquire(BufMgrLock); @@ -813,6 +813,7 @@ FlushBuffer(Buffer buffer, bool release) status = smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum, (char *) MAKE_PTR(bufHdr->data)); + /* drop relcache refcount incremented by RelationIdCacheGetRelation */ RelationDecrementReferenceCount(bufrel); if (status == SM_FAIL) @@ -993,6 +994,7 @@ BufferSync() elog(ERROR, "BufferSync: write error %u for %s", bufHdr->tag.blockNum, bufHdr->sb_relname); } + /* drop refcount from RelationIdCacheGetRelation */ if (reln != (Relation) NULL) RelationDecrementReferenceCount(reln); continue; @@ -1047,6 +1049,7 @@ BufferSync() */ if (!(bufHdr->flags & BM_JUST_DIRTIED)) bufHdr->flags &= ~BM_DIRTY; + /* drop refcount from RelationIdCacheGetRelation */ if (reln != (Relation) NULL) RelationDecrementReferenceCount(reln); } @@ -1282,14 +1285,16 @@ BufferGetRelation(Buffer buffer) /* XXX should be a critical section */ relid = BufferDescriptors[buffer - 1].tag.relId.relId; relation = RelationIdGetRelation(relid); + Assert(relation); + /* drop relcache refcount incremented by RelationIdGetRelation */ RelationDecrementReferenceCount(relation); if (RelationHasReferenceCountZero(relation)) { /* - * elog(NOTICE, "BufferGetRelation: 0->1"); + * XXX why?? */ RelationIncrementReferenceCount(relation); @@ -1342,7 +1347,6 @@ BufferReplace(BufferDesc *bufHdr, bool bufferLockHeld) } else { - /* blind write always flushes */ status = smgrblindwrt(DEFAULT_SMGR, bufHdr->sb_dbname, bufHdr->sb_relname, bufdb, bufrel, @@ -1350,6 +1354,7 @@ BufferReplace(BufferDesc *bufHdr, bool bufferLockHeld) (char *) MAKE_PTR(bufHdr->data)); } + /* drop relcache refcount incremented by RelationIdCacheGetRelation */ if (reln != (Relation) NULL) RelationDecrementReferenceCount(reln); diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index a6a2d456b2..e003595bed 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.26 1999/07/17 20:17:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.27 1999/09/18 19:07:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -109,6 +109,8 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) smgrwrite(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum, (char *) MAKE_PTR(bufHdr->data)); LocalBufferFlushCount++; + + /* drop relcache refcount incremented by RelationIdCacheGetRelation */ RelationDecrementReferenceCount(bufrel); } @@ -187,6 +189,8 @@ FlushLocalBuffer(Buffer buffer, bool release) smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum, (char *) MAKE_PTR(bufHdr->data)); LocalBufferFlushCount++; + + /* drop relcache refcount incremented by RelationIdCacheGetRelation */ RelationDecrementReferenceCount(bufrel); Assert(LocalRefCount[bufid] > 0); @@ -260,6 +264,8 @@ LocalBufferSync(void) smgrwrite(DEFAULT_SMGR, bufrel, buf->tag.blockNum, (char *) MAKE_PTR(buf->data)); LocalBufferFlushCount++; + + /* drop relcache refcount from RelationIdCacheGetRelation */ RelationDecrementReferenceCount(bufrel); buf->tag.relId.relId = InvalidOid; diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index 6b8765bb81..f59e99d7fb 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.58 1999/07/19 07:07:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.59 1999/09/18 19:07:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -139,13 +139,16 @@ inv_create(int flags) /* make the relation visible in this transaction */ CommandCounterIncrement(); - r = heap_openr(objname); - if (!RelationIsValid(r)) - { - elog(ERROR, "cannot create large object on %s under inversion", - smgrout(DEFAULT_SMGR)); - } + /*-------------------- + * We hold AccessShareLock on any large object we have open + * by inv_create or inv_open; it is released by inv_close. + * Note this will not conflict with ExclusiveLock or ShareLock + * that we acquire when actually reading/writing; it just prevents + * deletion of the large object while we have it open. + *-------------------- + */ + r = heap_openr(objname, AccessShareLock); /* * Now create a btree index on the relation's olastbyte attribute to @@ -205,10 +208,7 @@ inv_open(Oid lobjId, int flags) char *indname; Relation indrel; - r = heap_open(lobjId); - - if (!RelationIsValid(r)) - return (LargeObjectDesc *) NULL; + r = heap_open(lobjId, AccessShareLock); indname = pstrdup((r->rd_rel->relname).data); @@ -262,8 +262,8 @@ inv_close(LargeObjectDesc *obj_desc) obj_desc->iscan = NULL; } - heap_close(obj_desc->heap_r); index_close(obj_desc->index_r); + heap_close(obj_desc->heap_r, AccessShareLock); pfree(obj_desc); } @@ -279,7 +279,7 @@ inv_destroy(Oid lobjId) Relation r; r = (Relation) RelationIdGetRelation(lobjId); - if (!RelationIsValid(r) || r->rd_rel->relkind == RELKIND_INDEX) + if (!RelationIsValid(r) || r->rd_rel->relkind != RELKIND_LOBJECT) return -1; heap_destroy_with_catalog(r->rd_rel->relname.data); @@ -497,7 +497,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes) if (!(obj_desc->flags & IFS_WRLOCK)) { - LockRelation(obj_desc->heap_r, ShareLock); + LockRelation(obj_desc->heap_r, ExclusiveLock); obj_desc->flags |= (IFS_WRLOCK | IFS_RDLOCK); } diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 839533952b..2aaaf69e83 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.34 1999/09/04 18:42:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.35 1999/09/18 19:07:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,11 +20,12 @@ #include "postgres.h" + #include "access/transam.h" #include "catalog/catalog.h" +#include "miscadmin.h" #include "utils/inval.h" -extern Oid MyDatabaseId; static LOCKMASK LockConflicts[] = { (int) NULL, @@ -106,37 +107,25 @@ InitLockTable() /* * RelationInitLockInfo * Initializes the lock information in a relation descriptor. + * + * relcache.c must call this during creation of any reldesc. */ void RelationInitLockInfo(Relation relation) { - LockInfo info; char *relname; - MemoryContext oldcxt; - extern Oid MyDatabaseId; /* XXX use include */ - extern GlobalMemory CacheCxt; Assert(RelationIsValid(relation)); Assert(OidIsValid(RelationGetRelid(relation))); - info = (LockInfo) relation->lockInfo; - - if (LockInfoIsValid(info)) - return; - relname = (char *) RelationGetRelationName(relation); - oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); - info = (LockInfo) palloc(sizeof(LockInfoData)); - MemoryContextSwitchTo(oldcxt); + relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation); - info->lockRelId.relId = RelationGetRelid(relation); if (IsSharedSystemRelationName(relname)) - info->lockRelId.dbId = InvalidOid; + relation->rd_lockInfo.lockRelId.dbId = InvalidOid; else - info->lockRelId.dbId = MyDatabaseId; - - relation->lockInfo = (Pointer) info; + relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId; } /* @@ -145,20 +134,14 @@ RelationInitLockInfo(Relation relation) void LockRelation(Relation relation, LOCKMODE lockmode) { - LockInfo lockinfo; LOCKTAG tag; if (LockingDisabled()) return; - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); - - lockinfo = (LockInfo) relation->lockInfo; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = lockinfo->lockRelId.relId; - tag.dbId = lockinfo->lockRelId.dbId; + tag.relId = relation->rd_lockInfo.lockRelId.relId; + tag.dbId = relation->rd_lockInfo.lockRelId.dbId; tag.objId.blkno = InvalidBlockNumber; LockAcquire(LockTableId, &tag, lockmode); @@ -180,28 +163,17 @@ LockRelation(Relation relation, LOCKMODE lockmode) void UnlockRelation(Relation relation, LOCKMODE lockmode) { - LockInfo lockinfo; LOCKTAG tag; if (LockingDisabled()) return; - lockinfo = (LockInfo) relation->lockInfo; - - if (!LockInfoIsValid(lockinfo)) - { - elog(ERROR, - "Releasing a lock on %s with invalid lock information", - RelationGetRelationName(relation)); - } - MemSet(&tag, 0, sizeof(tag)); - tag.relId = lockinfo->lockRelId.relId; - tag.dbId = lockinfo->lockRelId.dbId; + tag.relId = relation->rd_lockInfo.lockRelId.relId; + tag.dbId = relation->rd_lockInfo.lockRelId.dbId; tag.objId.blkno = InvalidBlockNumber; LockRelease(LockTableId, &tag, lockmode); - return; } /* @@ -210,24 +182,17 @@ UnlockRelation(Relation relation, LOCKMODE lockmode) void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) { - LockInfo lockinfo; LOCKTAG tag; if (LockingDisabled()) return; - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); - - lockinfo = (LockInfo) relation->lockInfo; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = lockinfo->lockRelId.relId; - tag.dbId = lockinfo->lockRelId.dbId; + tag.relId = relation->rd_lockInfo.lockRelId.relId; + tag.dbId = relation->rd_lockInfo.lockRelId.dbId; tag.objId.blkno = blkno; LockAcquire(LockTableId, &tag, lockmode); - return; } /* @@ -236,28 +201,17 @@ LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) { - LockInfo lockinfo; LOCKTAG tag; if (LockingDisabled()) return; - lockinfo = (LockInfo) relation->lockInfo; - - if (!LockInfoIsValid(lockinfo)) - { - elog(ERROR, - "Releasing a lock on %s with invalid lock information", - RelationGetRelationName(relation)); - } - MemSet(&tag, 0, sizeof(tag)); - tag.relId = lockinfo->lockRelId.relId; - tag.dbId = lockinfo->lockRelId.dbId; + tag.relId = relation->rd_lockInfo.lockRelId.relId; + tag.dbId = relation->rd_lockInfo.lockRelId.dbId; tag.objId.blkno = blkno; LockRelease(LockTableId, &tag, lockmode); - return; } void @@ -274,7 +228,6 @@ XactLockTableInsert(TransactionId xid) tag.objId.xid = xid; LockAcquire(LockTableId, &tag, ExclusiveLock); - return; } void @@ -291,7 +244,6 @@ XactLockTableDelete(TransactionId xid) tag.objId.xid = xid; LockRelease(LockTableId, &tag, ExclusiveLock); - return; } void @@ -316,6 +268,4 @@ XactLockTableWait(TransactionId xid) */ if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid)) TransactionIdAbort(xid); - - return; } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 427cc749c8..3f5322c9f0 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.61 1999/07/17 20:17:46 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.62 1999/09/18 19:07:38 tgl Exp $ * * NOTES * Outside modules can create a lock table and acquire/release @@ -596,7 +596,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode) if (!result) { elog(NOTICE, "LockAcquire: xid table corrupted"); - return STATUS_ERROR; + return FALSE; } /* @@ -1117,7 +1117,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode) TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag"); else #endif - elog(NOTICE, "LockReplace: xid table corrupted"); + elog(NOTICE, "LockRelease: xid table corrupted"); return FALSE; } XID_PRINT("LockRelease: found", result); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 8c1ac55614..29b4fb527c 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.64 1999/07/16 04:59:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.65 1999/09/18 19:07:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -165,38 +165,39 @@ ProcessUtility(Node *parsetree, case T_DestroyStmt: { DestroyStmt *stmt = (DestroyStmt *) parsetree; - List *arg; List *args = stmt->relNames; - Relation rel; + List *arg; PS_SET_STATUS(commandTag = "DROP"); CHECK_IF_ABORTED(); + /* check as much as we can before we start dropping ... */ foreach(arg, args) { + Relation rel; + relname = strVal(lfirst(arg)); if (!allowSystemTableMods && IsSystemRelationName(relname)) elog(ERROR, "class \"%s\" is a system catalog", relname); - rel = heap_openr(relname); - if (RelationIsValid(rel)) - { - if (stmt->sequence && - rel->rd_rel->relkind != RELKIND_SEQUENCE) - elog(ERROR, "Use DROP TABLE to drop table '%s'", - relname); - if (!(stmt->sequence) && - rel->rd_rel->relkind == RELKIND_SEQUENCE) - elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'", - relname); - heap_close(rel); - } + rel = heap_openr(relname, AccessExclusiveLock); + if (stmt->sequence && + rel->rd_rel->relkind != RELKIND_SEQUENCE) + elog(ERROR, "Use DROP TABLE to drop table '%s'", + relname); + if (!(stmt->sequence) && + rel->rd_rel->relkind == RELKIND_SEQUENCE) + elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'", + relname); + /* close rel, but keep lock until end of xact */ + heap_close(rel, NoLock); #ifndef NO_SECURITY if (!pg_ownercheck(userName, relname, RELNAME)) elog(ERROR, "you do not own class \"%s\"", relname); #endif } + /* OK, terminate 'em all */ foreach(arg, args) { relname = strVal(lfirst(arg)); diff --git a/src/backend/utils/adt/not_in.c b/src/backend/utils/adt/not_in.c index 2ef45f63e4..1a851cf7e5 100644 --- a/src/backend/utils/adt/not_in.c +++ b/src/backend/utils/adt/not_in.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.20 1999/07/17 20:17:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.21 1999/09/18 19:07:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -58,12 +58,7 @@ int4notin(int32 not_in_arg, char *relation_and_attr) /* Open the relation and get a relation descriptor */ - relation_to_scan = heap_openr(relation); - if (!RelationIsValid(relation_to_scan)) - { - elog(ERROR, "int4notin: unknown relation %s", - relation); - } + relation_to_scan = heap_openr(relation, AccessShareLock); /* Find the column to search */ @@ -95,7 +90,9 @@ int4notin(int32 not_in_arg, char *relation_and_attr) } /* close the relation */ - heap_close(relation_to_scan); + heap_endscan(scan_descriptor); + heap_close(relation_to_scan, AccessShareLock); + return retval; } diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 754eea3a96..b3179e864c 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.42 1999/07/17 20:17:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.43 1999/09/18 19:07:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -78,7 +78,7 @@ regprocin(char *pro_name_or_oid) (RegProcedure) F_NAMEEQ, PointerGetDatum(pro_name_or_oid)); - hdesc = heap_openr(ProcedureRelationName); + hdesc = heap_openr(ProcedureRelationName, AccessShareLock); idesc = index_openr(ProcedureNameIndex); sd = index_beginscan(idesc, false, 1, skey); @@ -102,6 +102,7 @@ regprocin(char *pro_name_or_oid) index_endscan(sd); pfree(sd); index_close(idesc); + heap_close(hdesc, AccessShareLock); if (matches > 1) elog(ERROR, "There is more than one procedure named %s.\n\tSupply the pg_proc oid inside single quotes.", pro_name_or_oid); @@ -116,13 +117,7 @@ regprocin(char *pro_name_or_oid) ScanKeyData key; bool isnull; - proc = heap_openr(ProcedureRelationName); - if (!RelationIsValid(proc)) - { - elog(ERROR, "regprocin: could not open %s", - ProcedureRelationName); - return 0; - } + proc = heap_openr(ProcedureRelationName, AccessShareLock); ScanKeyEntryInitialize(&key, (bits16) 0, (AttrNumber) 1, @@ -132,8 +127,8 @@ regprocin(char *pro_name_or_oid) procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key); if (!HeapScanIsValid(procscan)) { - heap_close(proc); - elog(ERROR, "regprocin: could not being scan of %s", + heap_close(proc, AccessShareLock); + elog(ERROR, "regprocin: could not begin scan of %s", ProcedureRelationName); return 0; } @@ -151,7 +146,7 @@ regprocin(char *pro_name_or_oid) result = (RegProcedure) 0; heap_endscan(procscan); - heap_close(proc); + heap_close(proc, AccessShareLock); } return (int32) result; @@ -193,12 +188,7 @@ regprocout(RegProcedure proid) HeapScanDesc procscan; ScanKeyData key; - proc = heap_openr(ProcedureRelationName); - if (!RelationIsValid(proc)) - { - elog(ERROR, "regprocout: could not open %s", ProcedureRelationName); - return 0; - } + proc = heap_openr(ProcedureRelationName, AccessShareLock); ScanKeyEntryInitialize(&key, (bits16) 0, (AttrNumber) ObjectIdAttributeNumber, @@ -208,8 +198,8 @@ regprocout(RegProcedure proid) procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key); if (!HeapScanIsValid(procscan)) { - heap_close(proc); - elog(ERROR, "regprocout: could not being scan of %s", + heap_close(proc, AccessShareLock); + elog(ERROR, "regprocout: could not begin scan of %s", ProcedureRelationName); return 0; } @@ -232,8 +222,7 @@ regprocout(RegProcedure proid) result[1] = '\0'; } heap_endscan(procscan); - heap_close(proc); - return result; + heap_close(proc, AccessShareLock); } return result; diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 1b2d58c075..e14e537555 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.40 1999/09/09 02:35:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.41 1999/09/18 19:07:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -598,7 +598,7 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid typid, int32 typmod, HeapTuple typeTuple; FmgrInfo inputproc; - rel = heap_openr(StatisticRelationName); + rel = heap_openr(StatisticRelationName, AccessShareLock); key[0].sk_argument = ObjectIdGetDatum(relid); key[1].sk_argument = Int16GetDatum((int16) attnum); @@ -609,7 +609,7 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid typid, int32 typmod, { /* no such stats entry */ heap_endscan(scan); - heap_close(rel); + heap_close(rel, AccessShareLock); return false; } @@ -694,7 +694,7 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid typid, int32 typmod, } heap_endscan(scan); - heap_close(rel); + heap_close(rel, AccessShareLock); return true; } diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c index 05bc16b92a..46dbca9d69 100644 --- a/src/backend/utils/adt/sets.c +++ b/src/backend/utils/adt/sets.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.25 1999/07/17 20:18:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.26 1999/09/18 19:07:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -100,8 +100,7 @@ SetDefine(char *querystr, char *typename) replNull[i] = ' '; /* change the pg_proc tuple */ - procrel = heap_openr(ProcedureRelationName); - LockRelation(procrel, AccessExclusiveLock); + procrel = heap_openr(ProcedureRelationName, RowExclusiveLock); tup = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(setoid), @@ -131,8 +130,7 @@ SetDefine(char *querystr, char *typename) CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup); CatalogCloseIndices(Num_pg_proc_indices, idescs); } - UnlockRelation(procrel, AccessExclusiveLock); - heap_close(procrel); + heap_close(procrel, RowExclusiveLock); } return setoid; } diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index f6ef0fecac..22d933bb37 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.48 1999/07/17 20:18:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.49 1999/09/18 19:07:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -130,7 +130,8 @@ CatalogCacheInitializeCache(struct catcache * cache, /* ---------------- * If no relation was passed we must open it to get access to * its fields. If one of the other caches has already opened - * it we use heap_open() instead of heap_openr() + * it we use heap_open() instead of heap_openr(). + * XXX is that really worth the trouble of checking? * ---------------- */ if (!RelationIsValid(relation)) @@ -155,9 +156,9 @@ CatalogCacheInitializeCache(struct catcache * cache, * ---------------- */ if (cp) - relation = heap_open(cp->relationId); + relation = heap_open(cp->relationId, NoLock); else - relation = heap_openr(cache->cc_relname); + relation = heap_openr(cache->cc_relname, NoLock); didopen = 1; } @@ -217,7 +218,7 @@ CatalogCacheInitializeCache(struct catcache * cache, * ---------------- */ if (didopen) - heap_close(relation); + heap_close(relation, NoLock); /* ---------------- * initialize index information for the cache. this @@ -891,10 +892,10 @@ SearchSysCache(struct catcache * cache, DLMoveToFront(elt); #ifdef CACHEDEBUG - relation = heap_open(cache->relationId); + relation = heap_open(cache->relationId, NoLock); CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", RelationGetRelationName(relation), hash); - heap_close(relation); + heap_close(relation, NoLock); #endif /* CACHEDEBUG */ return ct->ct_tup; @@ -925,7 +926,7 @@ SearchSysCache(struct catcache * cache, * open the relation associated with the cache * ---------------- */ - relation = heap_open(cache->relationId); + relation = heap_open(cache->relationId, AccessShareLock); CACHE2_elog(DEBUG, "SearchSysCache(%s)", RelationGetRelationName(relation)); @@ -1082,7 +1083,7 @@ SearchSysCache(struct catcache * cache, * and return the tuple we found (or NULL) * ---------------- */ - heap_close(relation); + heap_close(relation, AccessShareLock); MemoryContextSwitchTo(oldcxt); return ntp; @@ -1146,8 +1147,6 @@ RelationInvalidateCatalogCacheTuple(Relation relation, (*function) (ccp->id, CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), &tuple->t_self); - - heap_close(relation); } /* ---------------- diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index db685e751e..afba41db10 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.72 1999/09/06 19:33:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.73 1999/09/18 19:07:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -337,7 +337,7 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo) * open pg_class and fetch a tuple * ---------------- */ - pg_class_desc = heap_openr(RelationRelationName); + pg_class_desc = heap_openr(RelationRelationName, AccessShareLock); pg_class_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key); pg_class_tuple = heap_getnext(pg_class_scan, 0); @@ -361,7 +361,7 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo) /* all done */ heap_endscan(pg_class_scan); - heap_close(pg_class_desc); + heap_close(pg_class_desc, AccessShareLock); return return_tuple; } @@ -372,9 +372,7 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo) Relation pg_class_desc; HeapTuple return_tuple; - pg_class_desc = heap_openr(RelationRelationName); - if (!IsInitProcessingMode()) - LockRelation(pg_class_desc, AccessShareLock); + pg_class_desc = heap_openr(RelationRelationName, AccessShareLock); switch (buildinfo.infotype) { @@ -389,18 +387,10 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo) default: elog(ERROR, "ScanPgRelation: bad buildinfo"); - - /* - * XXX I hope this is right. It seems better than returning - * an uninitialized value - */ - return_tuple = NULL; + return_tuple = NULL; /* keep compiler quiet */ } - /* all done */ - if (!IsInitProcessingMode()) - UnlockRelation(pg_class_desc, AccessShareLock); - heap_close(pg_class_desc); + heap_close(pg_class_desc, AccessShareLock); return return_tuple; } @@ -508,7 +498,7 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo, * open pg_attribute and begin a scan * ---------------- */ - pg_attribute_desc = heap_openr(AttributeRelationName); + pg_attribute_desc = heap_openr(AttributeRelationName, AccessShareLock); pg_attribute_scan = heap_beginscan(pg_attribute_desc, 0, SnapshotNow, 1, &key); /* ---------------- @@ -544,7 +534,7 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo, * ---------------- */ heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc); + heap_close(pg_attribute_desc, AccessShareLock); } static void @@ -562,7 +552,7 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo, constr->has_not_null = false; - attrel = heap_openr(AttributeRelationName); + attrel = heap_openr(AttributeRelationName, AccessShareLock); for (i = 1; i <= relation->rd_rel->relnatts; i++) { @@ -597,7 +587,7 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo, } } - heap_close(attrel); + heap_close(attrel, AccessShareLock); if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks) { @@ -677,7 +667,7 @@ RelationBuildRuleLock(Relation relation) * open pg_attribute and begin a scan * ---------------- */ - pg_rewrite_desc = heap_openr(RewriteRelationName); + pg_rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock); pg_rewrite_scan = heap_beginscan(pg_rewrite_desc, 0, SnapshotNow, 1, &key); pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc); @@ -732,7 +722,7 @@ RelationBuildRuleLock(Relation relation) * ---------------- */ heap_endscan(pg_rewrite_scan); - heap_close(pg_rewrite_desc); + heap_close(pg_rewrite_desc, AccessShareLock); /* ---------------- * form a RuleLock and insert into relation @@ -765,9 +755,9 @@ RelationBuildRuleLock(Relation relation) * uint16 rd_refcnt; reference count * Form_pg_am rd_am; AM tuple * Form_pg_class rd_rel; RELATION tuple - * Oid rd_id; relations's object id - * Pointer lockInfo; ptr. to misc. info. - * TupleDesc rd_att; tuple desciptor + * Oid rd_id; relation's object id + * LockInfoData rd_lockInfo; lock manager's info + * TupleDesc rd_att; tuple descriptor * * Note: rd_ismem (rel is in-memory only) is currently unused * by any part of the system. someday this will indicate that @@ -1048,14 +1038,18 @@ formrdesc(char *relationName, */ RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid; + /* ---------------- + * initialize the relation lock manager information + * ---------------- + */ + RelationInitLockInfo(relation); /* see lmgr.c */ + /* ---------------- * add new reldesc to relcache * ---------------- */ RelationCacheInsert(relation); - RelationInitLockInfo(relation); - /* * Determining this requires a scan on pg_class, but to do the scan * the rdesc for pg_class must already exist. Therefore we must do @@ -1074,9 +1068,13 @@ formrdesc(char *relationName, /* -------------------------------- * RelationIdCacheGetRelation * - * only try to get the reldesc by looking up the cache - * do not go to the disk. this is used by BlockPrepareFile() - * and RelationIdGetRelation below. + * Lookup a reldesc by OID. + * Only try to get the reldesc by looking up the cache + * do not go to the disk. + * + * NB: relation ref count is incremented if successful. + * Caller should eventually decrement count. (Usually, + * that happens by calling RelationClose().) * -------------------------------- */ Relation @@ -1103,6 +1101,8 @@ RelationIdCacheGetRelation(Oid relationId) /* -------------------------------- * RelationNameCacheGetRelation + * + * As above, but lookup by name. * -------------------------------- */ static Relation @@ -1136,8 +1136,11 @@ RelationNameCacheGetRelation(char *relationName) /* -------------------------------- * RelationIdGetRelation * - * return a relation descriptor based on its id. - * return a cached value if possible + * Lookup a reldesc by OID; make one if not already in cache. + * + * NB: relation ref count is incremented, or set to 1 if new entry. + * Caller should eventually decrement count. (Usually, + * that happens by calling RelationClose().) * -------------------------------- */ Relation @@ -1176,8 +1179,7 @@ RelationIdGetRelation(Oid relationId) /* -------------------------------- * RelationNameGetRelation * - * return a relation descriptor based on its name. - * return a cached value if possible + * As above, but lookup by name. * -------------------------------- */ Relation @@ -1289,7 +1291,6 @@ RelationFlushRelation(Relation *relationPtr, /* Free all the subsidiary data structures of the relcache entry */ FreeTupleDesc(relation->rd_att); FreeTriggerDesc(relation); - pfree(RelationGetLockInfo(relation)); pfree(RelationGetForm(relation)); /* If we're really done with the relcache entry, blow it away. @@ -1530,10 +1531,10 @@ RelationRegisterRelation(Relation relation) if (oldcxt != (MemoryContext) CacheCxt) elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt"); - RelationCacheInsert(relation); - RelationInitLockInfo(relation); + RelationCacheInsert(relation); + /* * we've just created the relation. It is invisible to anyone else * before the transaction is committed. Setting rd_myxactonly allows @@ -1692,7 +1693,7 @@ AttrDefaultFetch(Relation relation) (RegProcedure) F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); - adrel = heap_openr(AttrDefaultRelationName); + adrel = heap_openr(AttrDefaultRelationName, AccessShareLock); irel = index_openr(AttrDefaultIndex); sd = index_beginscan(irel, false, 1, &skey); tuple.t_data = NULL; @@ -1754,7 +1755,7 @@ AttrDefaultFetch(Relation relation) index_endscan(sd); pfree(sd); index_close(irel); - heap_close(adrel); + heap_close(adrel, AccessShareLock); } static void @@ -1779,7 +1780,7 @@ RelCheckFetch(Relation relation) (RegProcedure) F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); - rcrel = heap_openr(RelCheckRelationName); + rcrel = heap_openr(RelCheckRelationName, AccessShareLock); irel = index_openr(RelCheckIndex); sd = index_beginscan(irel, false, 1, &skey); tuple.t_data = NULL; @@ -1834,8 +1835,7 @@ RelCheckFetch(Relation relation) index_endscan(sd); pfree(sd); index_close(irel); - heap_close(rcrel); - + heap_close(rcrel, AccessShareLock); } /* @@ -1929,9 +1929,6 @@ init_irels(void) /* the file descriptor is not yet opened */ ird->rd_fd = -1; - /* lock info is not initialized */ - ird->lockInfo = (char *) NULL; - /* next, read the access method tuple form */ if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len)) { @@ -2038,8 +2035,9 @@ init_irels(void) ird->rd_support = support; - RelationCacheInsert(ird); RelationInitLockInfo(ird); + + RelationCacheInsert(ird); } } diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index c9c7770f8c..204f13ffab 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.35 1999/09/04 22:00:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.36 1999/09/18 19:07:55 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -575,11 +575,19 @@ SearchSysCacheGetAttribute(int cacheId, Datum attributeValue; void *returnValue; - tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); + /* + * Open the relation first, to ensure we are in sync with SI inval + * events --- we don't want the tuple found in the cache to be + * invalidated out from under us. + */ cacheName = cacheinfo[cacheId].name; + relation = heap_openr(cacheName, AccessShareLock); + + tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); if (!HeapTupleIsValid(tp)) { + heap_close(relation, AccessShareLock); #ifdef CACHEDEBUG elog(DEBUG, "SearchSysCacheGetAttribute: Lookup in %s(%d) failed", @@ -588,8 +596,6 @@ SearchSysCacheGetAttribute(int cacheId, return NULL; } - relation = heap_openr(cacheName); - if (attributeNumber < 0 && attributeNumber > FirstLowInvalidHeapAttributeNumber) { @@ -604,6 +610,7 @@ SearchSysCacheGetAttribute(int cacheId, } else { + heap_close(relation, AccessShareLock); elog(ERROR, "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)", attributeNumber, cacheName, cacheId); @@ -617,11 +624,11 @@ SearchSysCacheGetAttribute(int cacheId, if (isNull) { - /* * Used to be an elog(DEBUG, ...) here and a claim that it should * be a FATAL error, I don't think either is warranted -mer 6/9/92 */ + heap_close(relation, AccessShareLock); return NULL; } @@ -639,6 +646,6 @@ SearchSysCacheGetAttribute(int cacheId, returnValue = (void *) tmp; } - heap_close(relation); + heap_close(relation, AccessShareLock); return returnValue; } diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index d48d8b8840..dcf2814171 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.31 1999/07/17 20:18:04 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.32 1999/09/18 19:08:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -56,8 +56,13 @@ fmgr_dynamic(Oid procedureId, int *pronargs) /* * The procedure isn't a builtin, so we'll have to do a catalog lookup - * to find its pg_proc entry. + * to find its pg_proc entry. Moreover, since probin is varlena, we're + * going to have to use heap_getattr, which means we need the reldesc, + * which means we need to open the relation. So we might as well do that + * first and get the benefit of SI inval if needed. */ + rel = heap_openr(ProcedureRelationName, AccessShareLock); + procedureTuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(procedureId), 0, 0, 0); @@ -71,36 +76,24 @@ fmgr_dynamic(Oid procedureId, int *pronargs) procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); proname = procedureStruct->proname.data; pronargs_save = *pronargs = procedureStruct->pronargs; - - /* - * Extract the procedure info from the pg_proc tuple. Since probin is - * varlena, do a amgetattr() on the procedure tuple. To do that, we - * need the rel for the procedure relation, so... - */ - - /* open pg_procedure */ - - rel = heap_openr(ProcedureRelationName); - if (!RelationIsValid(rel)) - { - elog(ERROR, "fmgr: Could not open relation %s", - ProcedureRelationName); - return (func_ptr) NULL; - } probinattr = heap_getattr(procedureTuple, Anum_pg_proc_probin, RelationGetDescr(rel), &isnull); if (!PointerIsValid(probinattr) /* || isnull */ ) { - heap_close(rel); + heap_close(rel, AccessShareLock); elog(ERROR, "fmgr: Could not extract probin for %u from %s", procedureId, ProcedureRelationName); return (func_ptr) NULL; } probinstring = textout((struct varlena *) probinattr); + heap_close(rel, AccessShareLock); + user_fn = handle_load(probinstring, proname); + pfree(probinstring); + procedureId_save = procedureId; user_fn_save = user_fn; diff --git a/src/backend/utils/misc/database.c b/src/backend/utils/misc/database.c index 39270f35c0..321ab943ae 100644 --- a/src/backend/utils/misc/database.c +++ b/src/backend/utils/misc/database.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.28 1999/07/17 20:18:11 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.29 1999/09/18 19:08:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,10 +43,7 @@ GetDatabaseInfo(char *name, int4 *owner, char *path) HeapScanDesc scan; ScanKeyData scanKey; - dbrel = heap_openr(DatabaseRelationName); - if (!RelationIsValid(dbrel)) - elog(FATAL, "GetDatabaseInfo: cannot open relation \"%-.*s\"", - DatabaseRelationName); + dbrel = heap_openr(DatabaseRelationName, AccessShareLock); ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname, F_NAMEEQ, NameGetDatum(name)); @@ -71,6 +68,7 @@ GetDatabaseInfo(char *name, int4 *owner, char *path) { elog(NOTICE, "GetDatabaseInfo: %s entry not found %s", DatabaseRelationName, name); + heap_close(dbrel, AccessShareLock); return TRUE; } @@ -88,7 +86,7 @@ GetDatabaseInfo(char *name, int4 *owner, char *path) memcpy(dbpath, VARDATA(dbtext), (VARSIZE(dbtext) - VARHDRSZ)); *(dbpath + (VARSIZE(dbtext) - VARHDRSZ)) = '\0'; - heap_close(dbrel); + heap_close(dbrel, AccessShareLock); owner = palloc(sizeof(Oid)); *owner = dbowner; diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 8c1461122f..b6dccc33fa 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: heapam.h,v 1.45 1999/07/16 17:07:26 momjian Exp $ + * $Id: heapam.h,v 1.46 1999/09/18 19:08:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,7 @@ #include "access/relscan.h" #include "access/tupmacs.h" #include "storage/block.h" +#include "storage/lmgr.h" #include "utils/rel.h" #include "utils/tqual.h" @@ -246,9 +247,9 @@ extern HeapAccessStatistics heap_access_stats; /* in stats.c */ /* heapam.c */ -extern Relation heap_open(Oid relationId); -extern Relation heap_openr(char *relationName); -extern void heap_close(Relation relation); +extern Relation heap_open(Oid relationId, LOCKMODE lockmode); +extern Relation heap_openr(char *relationName, LOCKMODE lockmode); +extern void heap_close(Relation relation, LOCKMODE lockmode); extern HeapScanDesc heap_beginscan(Relation relation, int atend, Snapshot snapshot, unsigned nkeys, ScanKey key); extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key); diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index 98d8be3369..b98f0fb820 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: buf_internals.h,v 1.31 1999/07/16 17:07:37 momjian Exp $ + * $Id: buf_internals.h,v 1.32 1999/09/18 19:08:18 tgl Exp $ * * NOTE * If BUFFERPAGE0 is defined, then 0 will be used as a @@ -64,8 +64,8 @@ struct buftag #define INIT_BUFFERTAG(a,xx_reln,xx_blockNum) \ ( \ - (a)->blockNum = xx_blockNum, \ - (a)->relId = ((LockInfo)(xx_reln->lockInfo))->lockRelId \ + (a)->blockNum = (xx_blockNum), \ + (a)->relId = (xx_reln)->rd_lockInfo.lockRelId \ ) #define BAD_BUFFER_ID(bid) ((bid<1) || (bid>(NBuffers))) diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h index 8903af8ec6..302bedb677 100644 --- a/src/include/storage/lmgr.h +++ b/src/include/storage/lmgr.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: lmgr.h,v 1.22 1999/07/15 23:04:11 momjian Exp $ + * $Id: lmgr.h,v 1.23 1999/09/18 19:08:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,11 @@ #include "storage/lock.h" #include "utils/rel.h" +/* These are the valid values of type LOCKMODE: */ + +/* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */ +#define NoLock 0 + #define AccessShareLock 1 /* SELECT */ #define RowShareLock 2 /* SELECT FOR UPDATE */ #define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */ @@ -27,21 +32,6 @@ extern LOCKMETHOD LockTableId; -typedef struct LockRelId -{ - Oid relId; /* a relation identifier */ - Oid dbId; /* a database identifier */ -} LockRelId; - -typedef struct LockInfoData -{ - LockRelId lockRelId; -} LockInfoData; - -typedef LockInfoData *LockInfo; - -#define LockInfoIsValid(lockinfo) PointerIsValid(lockinfo) - extern LOCKMETHOD InitLockTable(void); extern void RelationInitLockInfo(Relation relation); diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index c95f51e89d..f2789b39e0 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: rel.h,v 1.25 1999/07/16 17:07:40 momjian Exp $ + * $Id: rel.h,v 1.26 1999/09/18 19:08:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,26 @@ #include "rewrite/prs2lock.h" #include "storage/fd.h" + +/* + * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient + * to declare them here so we can have a LockInfoData field in a Relation. + */ + +typedef struct LockRelId +{ + Oid relId; /* a relation identifier */ + Oid dbId; /* a database identifier */ +} LockRelId; + +typedef struct LockInfoData +{ + LockRelId lockRelId; +} LockInfoData; + +typedef LockInfoData *LockInfo; + + typedef struct Trigger { char *tgname; @@ -44,20 +64,21 @@ typedef struct TriggerDesc Trigger *triggers; } TriggerDesc; + typedef struct RelationData { File rd_fd; /* open file descriptor */ int rd_nblocks; /* number of blocks in rel */ uint16 rd_refcnt; /* reference count */ - bool rd_myxactonly; /* uses the local buffer mgr */ + bool rd_myxactonly; /* rel uses the local buffer mgr */ bool rd_isnailed; /* rel is nailed in cache */ bool rd_isnoname; /* rel has no name */ bool rd_nonameunlinked; /* noname rel already unlinked */ Form_pg_am rd_am; /* AM tuple */ Form_pg_class rd_rel; /* RELATION tuple */ - Oid rd_id; /* relations's object id */ - Pointer lockInfo; /* ptr. to misc. info. */ - TupleDesc rd_att; /* tuple desciptor */ + Oid rd_id; /* relation's object id */ + LockInfoData rd_lockInfo; /* lock manager's info for locking relation */ + TupleDesc rd_att; /* tuple descriptor */ RuleLock *rd_rules; /* rewrite rules */ IndexStrategy rd_istrat; RegProcedure *rd_support; @@ -66,6 +87,7 @@ typedef struct RelationData typedef RelationData *Relation; + /* ---------------- * RelationPtr is used in the executor to support index scans * where we have to keep track of several index relations in an @@ -74,7 +96,6 @@ typedef RelationData *Relation; */ typedef Relation *RelationPtr; -#define InvalidRelation ((Relation)NULL) /* * RelationIsValid @@ -82,6 +103,8 @@ typedef Relation *RelationPtr; */ #define RelationIsValid(relation) PointerIsValid(relation) +#define InvalidRelation ((Relation) NULL) + /* * RelationGetSystemPort * Returns system port of a relation. @@ -91,13 +114,6 @@ typedef Relation *RelationPtr; */ #define RelationGetSystemPort(relation) ((relation)->rd_fd) -/* - * RelationGetLockInfo - * Returns the lock information structure in the reldesc - * - */ -#define RelationGetLockInfo(relation) ((relation)->lockInfo) - /* * RelationHasReferenceCountZero * True iff relation reference count is zero. @@ -112,13 +128,13 @@ typedef Relation *RelationPtr; * RelationSetReferenceCount * Sets relation reference count. */ -#define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = count) +#define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = (count)) /* * RelationIncrementReferenceCount * Increments relation reference count. */ -#define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1); +#define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1) /* * RelationDecrementReferenceCount @@ -135,7 +151,6 @@ typedef Relation *RelationPtr; */ #define RelationGetForm(relation) ((relation)->rd_rel) - /* * RelationGetRelid * @@ -151,7 +166,6 @@ typedef Relation *RelationPtr; */ #define RelationGetFile(relation) ((relation)->rd_fd) - /* * RelationGetRelationName * @@ -160,21 +174,19 @@ typedef Relation *RelationPtr; #define RelationGetRelationName(relation) (&(relation)->rd_rel->relname) /* - * RelationGetRelationName + * RelationGetNumberOfAttributes * - * Returns a the number of attributes. + * Returns the number of attributes. */ #define RelationGetNumberOfAttributes(relation) ((relation)->rd_rel->relnatts) /* * RelationGetDescr * Returns tuple descriptor for a relation. - * - * Note: - * Assumes relation descriptor is valid. */ #define RelationGetDescr(relation) ((relation)->rd_att) + extern IndexStrategy RelationGetIndexStrategy(Relation relation); extern void RelationSetIndexSupport(Relation relation, IndexStrategy strategy,