*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.45 2004/08/29 05:06:40 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.46 2004/09/30 23:21:06 tgl Exp $
*
*
* INTERFACE ROUTINES
data_todo = VARATT_SIZE(value) - VARHDRSZ;
/*
- * Open the toast relation
+ * Open the toast relation. We must explicitly lock the toast index
+ * because we aren't using an index scan here.
*/
toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
toasttupDesc = toastrel->rd_att;
toastidx = index_open(toastrel->rd_rel->reltoastidxid);
+ LockRelation(toastidx, RowExclusiveLock);
/*
* Split up the item into chunks
/*
* Done - close toast relation and return the reference
*/
+ UnlockRelation(toastidx, RowExclusiveLock);
index_close(toastidx);
heap_close(toastrel, RowExclusiveLock);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.74 2004/08/29 04:12:20 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.75 2004/09/30 23:21:14 tgl Exp $
*
* INTERFACE ROUTINES
* index_open - open an index relation by relation OID
/* ----------------
* index_open - open an index relation by relation OID
*
- * Note: we acquire no lock on the index. An AccessShareLock is
- * acquired by index_beginscan (and released by index_endscan).
- * Generally, the caller should already hold some type of lock on
- * the parent relation to ensure that the index doesn't disappear.
+ * 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.
*
* This is a convenience routine adapted for indexscan use.
* Some callers may prefer to use relation_open directly.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.76 2004/08/29 05:06:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.77 2004/09/30 23:21:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* if there was an explicit column list in the ANALYZE command,
* however.
*/
- vac_open_indexes(onerel, &nindexes, &Irel);
+ vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
hasindex = (nindexes > 0);
indexdata = NULL;
analyzableindex = false;
*/
if (attr_cnt <= 0 && !analyzableindex)
{
- vac_close_indexes(nindexes, Irel);
+ vac_close_indexes(nindexes, Irel, AccessShareLock);
relation_close(onerel, AccessShareLock);
return;
}
}
/* Done with indexes */
- vac_close_indexes(nindexes, Irel);
+ vac_close_indexes(nindexes, Irel, NoLock);
/*
* Close source relation now, but keep lock so that no one deletes it
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.291 2004/09/13 20:06:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.292 2004/09/30 23:21:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
scan_heap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
/* Now open all indexes of the relation */
- vac_open_indexes(onerel, &nindexes, &Irel);
+ vac_open_indexes(onerel, AccessExclusiveLock, &nindexes, &Irel);
if (nindexes > 0)
vacrelstats->hasindex = true;
/* Try to shrink heap */
repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages,
nindexes, Irel);
- vac_close_indexes(nindexes, Irel);
+ vac_close_indexes(nindexes, Irel, NoLock);
}
else
{
- vac_close_indexes(nindexes, Irel);
+ vac_close_indexes(nindexes, Irel, NoLock);
if (vacuum_pages.num_pages > 0)
{
/* Clean pages from vacuum_pages list */
}
+/*
+ * Open all the indexes of the given relation, obtaining the specified kind
+ * of lock on each. Return an array of Relation pointers for the indexes
+ * into *Irel, and the number of indexes into *nindexes.
+ */
void
-vac_open_indexes(Relation relation, int *nindexes, Relation **Irel)
+vac_open_indexes(Relation relation, LOCKMODE lockmode,
+ int *nindexes, Relation **Irel)
{
List *indexoidlist;
ListCell *indexoidscan;
foreach(indexoidscan, indexoidlist)
{
Oid indexoid = lfirst_oid(indexoidscan);
+ Relation ind;
- (*Irel)[i] = index_open(indexoid);
- i++;
+ ind = index_open(indexoid);
+ (*Irel)[i++] = ind;
+ LockRelation(ind, lockmode);
}
list_free(indexoidlist);
}
-
+/*
+ * Release the resources acquired by vac_open_indexes. Optionally release
+ * the locks (say NoLock to keep 'em).
+ */
void
-vac_close_indexes(int nindexes, Relation *Irel)
+vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode)
{
if (Irel == NULL)
return;
while (nindexes--)
- index_close(Irel[nindexes]);
+ {
+ Relation ind = Irel[nindexes];
+
+ if (lockmode != NoLock)
+ UnlockRelation(ind, lockmode);
+ index_close(ind);
+ }
pfree(Irel);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.45 2004/08/29 05:06:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.46 2004/09/30 23:21:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
vacrelstats->threshold = GetAvgFSMRequestSize(&onerel->rd_node);
/* Open all indexes of the relation */
- vac_open_indexes(onerel, &nindexes, &Irel);
+ vac_open_indexes(onerel, ShareUpdateExclusiveLock, &nindexes, &Irel);
hasindex = (nindexes > 0);
/* Do the vacuuming */
lazy_scan_heap(onerel, vacrelstats, Irel, nindexes);
/* Done with indexes */
- vac_close_indexes(nindexes, Irel);
+ vac_close_indexes(nindexes, Irel, NoLock);
/*
* Optionally truncate the relation.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.115 2004/09/11 18:28:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.116 2004/09/30 23:21:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
IndexInfo *ii;
/*
- * Open (and lock, if necessary) the index relation
+ * Open and lock the index relation
+ *
+ * If the index AM supports concurrent updates, obtain RowExclusiveLock
+ * to signify that we are updating the index. This locks out only
+ * operations that need exclusive access, such as relocating the index
+ * to a new tablespace.
*
* If the index AM is not safe for concurrent updates, obtain an
* exclusive lock on the index to lock out other updaters as well
- * as readers (index_beginscan places AccessShareLock). We will
- * release this lock in ExecCloseIndices.
- *
- * If the index AM supports concurrent updates, we obtain no lock
- * here at all, which is a tad weird, but safe since any critical
- * operation on the index (like deleting it) will acquire
- * exclusive lock on the parent table. Perhaps someday we should
- * acquire RowExclusiveLock on the index here?
+ * as readers (index_beginscan places AccessShareLock).
*
* If there are multiple not-concurrent-safe indexes, all backends
- * must lock the indexes in the same order or we will get
- * deadlocks here during concurrent updates. This is guaranteed
- * by RelationGetIndexList(), which promises to return the index
- * list in OID order.
+ * must lock the indexes in the same order or we will get deadlocks
+ * here. This is guaranteed by RelationGetIndexList(), which promises
+ * to return the index list in OID order.
+ *
+ * The locks will be released in ExecCloseIndices.
*/
indexDesc = index_open(indexOid);
- if (!indexDesc->rd_am->amconcurrent)
+ if (indexDesc->rd_am->amconcurrent)
+ LockRelation(indexDesc, RowExclusiveLock);
+ else
LockRelation(indexDesc, AccessExclusiveLock);
/* extract index key information from the index's pg_index info */
for (i = 0; i < numIndices; i++)
{
if (indexDescs[i] == NULL)
- continue;
+ continue; /* shouldn't happen? */
- /* Drop lock, if one was acquired by ExecOpenIndices */
- if (!indexDescs[i]->rd_am->amconcurrent)
+ /* Drop lock acquired by ExecOpenIndices */
+ if (indexDescs[i]->rd_am->amconcurrent)
+ UnlockRelation(indexDescs[i], RowExclusiveLock);
+ else
UnlockRelation(indexDescs[i], AccessExclusiveLock);
index_close(indexDescs[i]);
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.57 2004/08/29 05:06:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.58 2004/09/30 23:21:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* in commands/vacuum.c */
extern void vacuum(VacuumStmt *vacstmt);
-extern void vac_open_indexes(Relation relation, int *nindexes,
- Relation **Irel);
-extern void vac_close_indexes(int nindexes, Relation *Irel);
+extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
+ int *nindexes, Relation **Irel);
+extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode);
extern void vac_update_relstats(Oid relid,
BlockNumber num_pages,
double num_tuples,