diff options
Diffstat (limited to 'src/backend/access')
| -rw-r--r-- | src/backend/access/gin/ginvacuum.c | 17 | ||||
| -rw-r--r-- | src/backend/access/gist/gistvacuum.c | 13 | ||||
| -rw-r--r-- | src/backend/access/heap/heapam.c | 66 | ||||
| -rw-r--r-- | src/backend/access/heap/tuptoaster.c | 31 | ||||
| -rw-r--r-- | src/backend/access/index/genam.c | 9 | ||||
| -rw-r--r-- | src/backend/access/index/indexam.c | 110 |
6 files changed, 103 insertions, 143 deletions
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index c6551939a2..2bc80a2643 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.4 2006/07/14 14:52:16 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.5 2006/07/31 20:08:59 tgl Exp $ *------------------------------------------------------------------------- */ @@ -572,7 +572,7 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) { IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0); IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1); Relation index = info->index; - bool needLock = !RELATION_IS_LOCAL(index); + bool needLock; BlockNumber npages, blkno; BlockNumber nFreePages, @@ -591,10 +591,14 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) { */ stats->num_index_tuples = info->num_heap_tuples; - if (info->vacuum_full) { - LockRelation(index, AccessExclusiveLock); + /* + * If vacuum full, we already have exclusive lock on the index. + * Otherwise, need lock unless it's local to this backend. + */ + if (info->vacuum_full) needLock = false; - } + else + needLock = !RELATION_IS_LOCAL(index); if (needLock) LockRelationForExtension(index, ExclusiveLock); @@ -653,9 +657,6 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) { if (needLock) UnlockRelationForExtension(index, ExclusiveLock); - if (info->vacuum_full) - UnlockRelation(index, AccessExclusiveLock); - PG_RETURN_POINTER(stats); } diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index e3bff5147c..37b5631b28 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.25 2006/07/14 14:52:16 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.26 2006/07/31 20:08:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -517,7 +517,7 @@ gistvacuumcleanup(PG_FUNCTION_ARGS) GistVacuum gv; ArrayTuple res; - LockRelation(rel, AccessExclusiveLock); + /* note: vacuum.c already acquired AccessExclusiveLock on index */ gv.index = rel; initGISTstate(&(gv.giststate), rel); @@ -543,8 +543,12 @@ gistvacuumcleanup(PG_FUNCTION_ARGS) (errmsg("index \"%s\" needs VACUUM FULL or REINDEX to finish crash recovery", RelationGetRelationName(rel)))); + /* + * If vacuum full, we already have exclusive lock on the index. + * Otherwise, need lock unless it's local to this backend. + */ if (info->vacuum_full) - needLock = false; /* relation locked with AccessExclusiveLock */ + needLock = false; else needLock = !RELATION_IS_LOCAL(rel); @@ -613,9 +617,6 @@ gistvacuumcleanup(PG_FUNCTION_ARGS) if (needLock) UnlockRelationForExtension(rel, ExclusiveLock); - if (info->vacuum_full) - UnlockRelation(rel, AccessExclusiveLock); - PG_RETURN_POINTER(stats); } diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 91460410bf..f29407e8e5 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.217 2006/07/14 14:52:17 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.218 2006/07/31 20:08:59 tgl Exp $ * * * INTERFACE ROUTINES @@ -51,6 +51,7 @@ #include "pgstat.h" #include "storage/procarray.h" #include "utils/inval.h" +#include "utils/lsyscache.h" #include "utils/relcache.h" @@ -687,15 +688,16 @@ relation_open(Oid relationId, LOCKMODE lockmode) Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); + /* Get the lock before trying to open the relcache entry */ + if (lockmode != NoLock) + LockRelationOid(relationId, lockmode); + /* The relcache does all the real work... */ r = RelationIdGetRelation(relationId); if (!RelationIsValid(r)) elog(ERROR, "could not open relation with OID %u", relationId); - if (lockmode != NoLock) - LockRelation(r, lockmode); - return r; } @@ -713,26 +715,38 @@ conditional_relation_open(Oid relationId, LOCKMODE lockmode, bool nowait) Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); - /* The relcache does all the real work... */ - r = RelationIdGetRelation(relationId); - - if (!RelationIsValid(r)) - elog(ERROR, "could not open relation with OID %u", relationId); - + /* Get the lock before trying to open the relcache entry */ if (lockmode != NoLock) { if (nowait) { - if (!ConditionalLockRelation(r, lockmode)) - ereport(ERROR, - (errcode(ERRCODE_LOCK_NOT_AVAILABLE), - errmsg("could not obtain lock on relation \"%s\"", - RelationGetRelationName(r)))); + if (!ConditionalLockRelationOid(relationId, lockmode)) + { + /* try to throw error by name; relation could be deleted... */ + char *relname = get_rel_name(relationId); + + if (relname) + ereport(ERROR, + (errcode(ERRCODE_LOCK_NOT_AVAILABLE), + errmsg("could not obtain lock on relation \"%s\"", + relname))); + else + ereport(ERROR, + (errcode(ERRCODE_LOCK_NOT_AVAILABLE), + errmsg("could not obtain lock on relation with OID %u", + relationId))); + } } else - LockRelation(r, lockmode); + LockRelationOid(relationId, lockmode); } + /* The relcache does all the real work... */ + r = RelationIdGetRelation(relationId); + + if (!RelationIsValid(r)) + elog(ERROR, "could not open relation with OID %u", relationId); + return r; } @@ -749,12 +763,12 @@ relation_openrv(const RangeVar *relation, LOCKMODE lockmode) /* * Check for shared-cache-inval messages before trying to open the - * relation. This is needed to cover the case where the name identifies a - * rel that has been dropped and recreated since the start of our + * relation. This is needed to cover the case where the name identifies + * a rel that has been dropped and recreated since the start of our * transaction: if we don't flush the old syscache entry then we'll latch - * onto that entry and suffer an error when we do LockRelation. Note that - * relation_open does not need to do this, since a relation's OID never - * changes. + * onto that entry and suffer an error when we do RelationIdGetRelation. + * Note that relation_open does not need to do this, since a relation's + * OID never changes. * * We skip this if asked for NoLock, on the assumption that the caller has * already ensured some appropriate lock is held. @@ -772,7 +786,7 @@ relation_openrv(const RangeVar *relation, LOCKMODE lockmode) /* ---------------- * relation_close - close any relation * - * If lockmode is not "NoLock", we first release the specified lock. + * If lockmode is not "NoLock", we then release the specified lock. * * Note that it is often sensible to hold a lock beyond relation_close; * in that case, the lock is released automatically at xact end. @@ -781,13 +795,15 @@ relation_openrv(const RangeVar *relation, LOCKMODE lockmode) void relation_close(Relation relation, LOCKMODE lockmode) { - Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); + LockRelId relid = relation->rd_lockInfo.lockRelId; - if (lockmode != NoLock) - UnlockRelation(relation, lockmode); + Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); /* The relcache does the real work... */ RelationClose(relation); + + if (lockmode != NoLock) + UnlockRelationId(&relid, lockmode); } diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 11adf165c4..43ca366f0a 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.62 2006/07/14 14:52:17 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.63 2006/07/31 20:08:59 tgl Exp $ * * * INTERFACE ROUTINES @@ -1004,7 +1004,7 @@ toast_save_datum(Relation rel, Datum value) */ toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock); toasttupDesc = toastrel->rd_att; - toastidx = index_open(toastrel->rd_rel->reltoastidxid); + toastidx = index_open(toastrel->rd_rel->reltoastidxid, RowExclusiveLock); /* * Create the varattrib reference @@ -1044,12 +1044,6 @@ toast_save_datum(Relation rel, Datum value) data_todo = VARATT_SIZE(value) - VARHDRSZ; /* - * We must explicitly lock the toast index because we aren't using an - * index scan here. - */ - LockRelation(toastidx, RowExclusiveLock); - - /* * Split up the item into chunks */ while (data_todo > 0) @@ -1098,8 +1092,7 @@ toast_save_datum(Relation rel, Datum value) /* * Done - close toast relation and return the reference */ - UnlockRelation(toastidx, RowExclusiveLock); - index_close(toastidx); + index_close(toastidx, RowExclusiveLock); heap_close(toastrel, RowExclusiveLock); return PointerGetDatum(result); @@ -1130,7 +1123,7 @@ toast_delete_datum(Relation rel, Datum value) */ toastrel = heap_open(attr->va_content.va_external.va_toastrelid, RowExclusiveLock); - toastidx = index_open(toastrel->rd_rel->reltoastidxid); + toastidx = index_open(toastrel->rd_rel->reltoastidxid, RowExclusiveLock); /* * Setup a scan key to fetch from the index by va_valueid (we don't @@ -1144,7 +1137,7 @@ toast_delete_datum(Relation rel, Datum value) /* * Find the chunks by index */ - toastscan = index_beginscan(toastrel, toastidx, true, + toastscan = index_beginscan(toastrel, toastidx, SnapshotToast, 1, &toastkey); while ((toasttup = index_getnext(toastscan, ForwardScanDirection)) != NULL) { @@ -1158,7 +1151,7 @@ toast_delete_datum(Relation rel, Datum value) * End scan and close relations */ index_endscan(toastscan); - index_close(toastidx); + index_close(toastidx, RowExclusiveLock); heap_close(toastrel, RowExclusiveLock); } @@ -1202,7 +1195,7 @@ toast_fetch_datum(varattrib *attr) toastrel = heap_open(attr->va_content.va_external.va_toastrelid, AccessShareLock); toasttupDesc = toastrel->rd_att; - toastidx = index_open(toastrel->rd_rel->reltoastidxid); + toastidx = index_open(toastrel->rd_rel->reltoastidxid, AccessShareLock); /* * Setup a scan key to fetch from the index by va_valueid @@ -1221,7 +1214,7 @@ toast_fetch_datum(varattrib *attr) */ nextidx = 0; - toastscan = index_beginscan(toastrel, toastidx, true, + toastscan = index_beginscan(toastrel, toastidx, SnapshotToast, 1, &toastkey); while ((ttup = index_getnext(toastscan, ForwardScanDirection)) != NULL) { @@ -1282,7 +1275,7 @@ toast_fetch_datum(varattrib *attr) * End scan and close relations */ index_endscan(toastscan); - index_close(toastidx); + index_close(toastidx, AccessShareLock); heap_close(toastrel, AccessShareLock); return result; @@ -1355,7 +1348,7 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length) toastrel = heap_open(attr->va_content.va_external.va_toastrelid, AccessShareLock); toasttupDesc = toastrel->rd_att; - toastidx = index_open(toastrel->rd_rel->reltoastidxid); + toastidx = index_open(toastrel->rd_rel->reltoastidxid, AccessShareLock); /* * Setup a scan key to fetch from the index. This is either two keys or @@ -1396,7 +1389,7 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length) * The index is on (valueid, chunkidx) so they will come in order */ nextidx = startchunk; - toastscan = index_beginscan(toastrel, toastidx, true, + toastscan = index_beginscan(toastrel, toastidx, SnapshotToast, nscankeys, toastkey); while ((ttup = index_getnext(toastscan, ForwardScanDirection)) != NULL) { @@ -1461,7 +1454,7 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length) * End scan and close relations */ index_endscan(toastscan); - index_close(toastidx); + index_close(toastidx, AccessShareLock); heap_close(toastrel, AccessShareLock); return result; diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c index 399386c856..347d2b5365 100644 --- a/src/backend/access/index/genam.c +++ b/src/backend/access/index/genam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.57 2006/07/03 22:45:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.58 2006/07/31 20:08:59 tgl Exp $ * * NOTES * many of the old access method routines have been turned into @@ -87,7 +87,6 @@ RelationGetIndexScan(Relation indexRelation, scan->keyData = NULL; scan->is_multiscan = false; /* caller may change this */ - scan->have_lock = false; /* ditto */ scan->kill_prior_tuple = false; scan->ignore_killed_tuples = true; /* default setting */ @@ -182,7 +181,7 @@ systable_beginscan(Relation heapRelation, if (indexOK && !IgnoreSystemIndexes && !ReindexIsProcessingIndex(indexId)) - irel = index_open(indexId); + irel = index_open(indexId, AccessShareLock); else irel = NULL; @@ -207,7 +206,7 @@ systable_beginscan(Relation heapRelation, key[i].sk_attno = i + 1; } - sysscan->iscan = index_beginscan(heapRelation, irel, true, + sysscan->iscan = index_beginscan(heapRelation, irel, snapshot, nkeys, key); sysscan->scan = NULL; } @@ -253,7 +252,7 @@ systable_endscan(SysScanDesc sysscan) if (sysscan->irel) { index_endscan(sysscan->iscan); - index_close(sysscan->irel); + index_close(sysscan->irel, AccessShareLock); } else heap_endscan(sysscan->scan); diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 900b34263d..2663876f49 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -8,11 +8,10 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.93 2006/05/07 01:21:30 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.94 2006/07/31 20:08:59 tgl Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relation OID - * index_openrv - open an index relation specified by a RangeVar * index_close - close an index relation * index_beginscan - start a scan of an index with amgettuple * index_beginscan_multi - start a scan of an index with amgetmulti @@ -111,7 +110,6 @@ do { \ } while(0) static IndexScanDesc index_beginscan_internal(Relation indexRelation, - bool need_index_lock, int nkeys, ScanKey key); @@ -123,26 +121,23 @@ static IndexScanDesc index_beginscan_internal(Relation indexRelation, /* ---------------- * index_open - open an index relation by relation OID * - * Note: we acquire no lock on the index. A lock is not needed when - * simply examining the index reldesc; the index's schema information - * is considered to be protected by the lock that the caller had better - * be holding on the parent relation. Some type of lock should be - * obtained on the index before physically accessing it, however. - * This is handled automatically for most uses by index_beginscan - * and index_endscan for scan cases, or by ExecOpenIndices and - * ExecCloseIndices for update cases. Other callers will need to - * obtain their own locks. + * If lockmode is not "NoLock", the specified kind of lock is + * obtained on the index. (Generally, NoLock should only be + * used if the caller knows it has some appropriate lock on the + * index already.) + * + * An error is raised if the index does not exist. * * This is a convenience routine adapted for indexscan use. * Some callers may prefer to use relation_open directly. * ---------------- */ Relation -index_open(Oid relationId) +index_open(Oid relationId, LOCKMODE lockmode) { Relation r; - r = relation_open(relationId, NoLock); + r = relation_open(relationId, lockmode); if (r->rd_rel->relkind != RELKIND_INDEX) ereport(ERROR, @@ -156,41 +151,26 @@ index_open(Oid relationId) } /* ---------------- - * index_openrv - open an index relation specified - * by a RangeVar node + * index_close - close an index relation * - * As above, but relation is specified by a RangeVar. - * ---------------- - */ -Relation -index_openrv(const RangeVar *relation) -{ - Relation r; - - r = relation_openrv(relation, NoLock); - - if (r->rd_rel->relkind != RELKIND_INDEX) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not an index", - RelationGetRelationName(r)))); - - pgstat_initstats(&r->pgstat_info, r); - - return r; -} - -/* ---------------- - * index_close - close a index relation + * If lockmode is not "NoLock", we then release the specified lock. * - * presently the relcache routines do all the work we need - * to open/close index relations. + * Note that it is often sensible to hold a lock beyond index_close; + * in that case, the lock is released automatically at xact end. * ---------------- */ void -index_close(Relation relation) +index_close(Relation relation, LOCKMODE lockmode) { + LockRelId relid = relation->rd_lockInfo.lockRelId; + + Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); + + /* The relcache does the real work... */ RelationClose(relation); + + if (lockmode != NoLock) + UnlockRelationId(&relid, lockmode); } /* ---------------- @@ -229,24 +209,18 @@ index_insert(Relation indexRelation, * index_getnext on this scan; index_getnext_indexitem will not use the * heapRelation link (nor the snapshot). However, the caller had better * be holding some kind of lock on the heap relation in any case, to ensure - * no one deletes it (or the index) out from under us. - * - * Most callers should pass need_index_lock = true to cause the index code - * to take AccessShareLock on the index for the duration of the scan. But - * if it is known that a lock is already held on the index, pass false to - * skip taking an unnecessary lock. + * no one deletes it (or the index) out from under us. Caller must also + * be holding a lock on the index. */ IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, - bool need_index_lock, Snapshot snapshot, int nkeys, ScanKey key) { IndexScanDesc scan; - scan = index_beginscan_internal(indexRelation, need_index_lock, - nkeys, key); + scan = index_beginscan_internal(indexRelation, nkeys, key); /* * Save additional parameters into the scandesc. Everything else was set @@ -267,14 +241,12 @@ index_beginscan(Relation heapRelation, */ IndexScanDesc index_beginscan_multi(Relation indexRelation, - bool need_index_lock, Snapshot snapshot, int nkeys, ScanKey key) { IndexScanDesc scan; - scan = index_beginscan_internal(indexRelation, need_index_lock, - nkeys, key); + scan = index_beginscan_internal(indexRelation, nkeys, key); /* * Save additional parameters into the scandesc. Everything else was set @@ -291,33 +263,18 @@ index_beginscan_multi(Relation indexRelation, */ static IndexScanDesc index_beginscan_internal(Relation indexRelation, - bool need_index_lock, int nkeys, ScanKey key) { IndexScanDesc scan; FmgrInfo *procedure; RELATION_CHECKS; - - RelationIncrementReferenceCount(indexRelation); - - /* - * Acquire AccessShareLock for the duration of the scan, unless caller - * says it already has lock on the index. - * - * 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... - */ - if (need_index_lock) - LockRelation(indexRelation, AccessShareLock); + GET_REL_PROCEDURE(ambeginscan); /* - * LockRelation can clean rd_aminfo structure, so fill procedure after - * LockRelation + * We hold a reference count to the relcache entry throughout the scan. */ - - GET_REL_PROCEDURE(ambeginscan); + RelationIncrementReferenceCount(indexRelation); /* * Tell the AM to open a scan. @@ -328,9 +285,6 @@ index_beginscan_internal(Relation indexRelation, Int32GetDatum(nkeys), PointerGetDatum(key))); - /* Save flag to tell index_endscan whether to release lock */ - scan->have_lock = need_index_lock; - return scan; } @@ -390,11 +344,7 @@ index_endscan(IndexScanDesc scan) /* End the AM's scan */ FunctionCall1(procedure, PointerGetDatum(scan)); - /* Release index lock and refcount acquired by index_beginscan */ - - if (scan->have_lock) - UnlockRelation(scan->indexRelation, AccessShareLock); - + /* Release index refcount acquired by index_beginscan */ RelationDecrementReferenceCount(scan->indexRelation); /* Release the scan data structure itself */ |
