summaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/gin/ginvacuum.c17
-rw-r--r--src/backend/access/gist/gistvacuum.c13
-rw-r--r--src/backend/access/heap/heapam.c66
-rw-r--r--src/backend/access/heap/tuptoaster.c31
-rw-r--r--src/backend/access/index/genam.c9
-rw-r--r--src/backend/access/index/indexam.c110
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 */