diff options
Diffstat (limited to 'src/backend/access/index/indexam.c')
-rw-r--r-- | src/backend/access/index/indexam.c | 110 |
1 files changed, 30 insertions, 80 deletions
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 900b34263d8..2663876f494 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 */ |