diff options
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/gist/gist.c | 48 | ||||
-rw-r--r-- | src/backend/access/hash/hash.c | 17 | ||||
-rw-r--r-- | src/backend/access/heap/heapam.c | 91 | ||||
-rw-r--r-- | src/backend/access/index/indexam.c | 49 | ||||
-rw-r--r-- | src/backend/access/index/istrat.c | 19 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtree.c | 17 | ||||
-rw-r--r-- | src/backend/access/rtree/rtree.c | 46 | ||||
-rw-r--r-- | src/backend/access/transam/transam.c | 9 | ||||
-rw-r--r-- | src/backend/access/transam/varsup.c | 4 |
9 files changed, 198 insertions, 102 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 32111347423..0535fd6278d 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 1130367b65d..6e729008e85 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 d8dc24c41f0..092a23cc0ec 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,15 +619,9 @@ 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 * ---------------- @@ -598,6 +629,20 @@ heap_beginscan(Relation 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 * ---------------- */ @@ -684,14 +729,18 @@ 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 869e5e1e690..6ad242c0c39 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 1cdaadbc0c3..cab6e584609 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 c97273f10f0..11f527fc3ba 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 37da716df1d..133bbdbc032 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 1f44fb357ac..b26243b4257 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 135912e97de..989b506bb7f 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. |