From ac8708a0f9c65f7cee4898aa8d83d09294e2fa0d Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 5 Apr 2018 16:58:27 +0000 Subject: [PATCH v7 03/12] Add skip_locked argument to vac_open_indexes(). --- src/backend/commands/analyze.c | 2 +- src/backend/commands/vacuum.c | 27 +++++++++++++++++++++++++-- src/backend/commands/vacuumlazy.c | 2 +- src/include/commands/vacuum.h | 3 ++- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 451e923132..5fdbbd630e 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -468,7 +468,7 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params, * all. */ if (!inh) - vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel); + vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel, false, NULL); else { Irel = NULL; diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index db1b6e2d26..3ccf6cf98d 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1603,14 +1603,19 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) * vacuum even if the index isn't indisvalid; this is important because in a * unique index, uniqueness checks will be performed anyway and had better not * hit dangling index pointers. + * + * If skip_locked is true and an index cannot be locked immediately without + * waiting, *Irel will be set to NULL and nindexes will be set to 0. If skipped + * is provided, it will be set to true if an index was skipped (false otherwise). */ void vac_open_indexes(Relation relation, LOCKMODE lockmode, - int *nindexes, Relation **Irel) + int *nindexes, Relation **Irel, bool skip_locked, bool *skipped) { List *indexoidlist; ListCell *indexoidscan; int i; + bool did_skip = false; Assert(lockmode != NoLock); @@ -1631,13 +1636,31 @@ vac_open_indexes(Relation relation, LOCKMODE lockmode, Oid indexoid = lfirst_oid(indexoidscan); Relation indrel; - indrel = index_open(indexoid, lockmode); + if (skip_locked && !ConditionalLockRelationOid(indexoid, lockmode)) + { + did_skip = true; + break; + } + + indrel = index_open(indexoid, skip_locked ? NoLock : lockmode); if (IndexIsReady(indrel->rd_index)) (*Irel)[i++] = indrel; else index_close(indrel, lockmode); } + if (did_skip) + { + vac_close_indexes(i, *Irel, lockmode); + + /* clear all return values */ + *Irel = NULL; + i = 0; + } + + if (skipped != NULL) + *skipped = did_skip; + *nindexes = i; list_free(indexoidlist); diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index d2a006671a..13e5bd452f 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -259,7 +259,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, vacrelstats->lock_waiter_detected = false; /* Open all indexes of the relation */ - vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel); + vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel, false, NULL); vacrelstats->hasindex = (nindexes > 0); /* Do the vacuuming */ diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 85d472f0a5..69b1e384ef 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -160,7 +160,8 @@ extern void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel); extern void vacuum(int options, List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, bool isTopLevel); extern void vac_open_indexes(Relation relation, LOCKMODE lockmode, - int *nindexes, Relation **Irel); + int *nindexes, Relation **Irel, + bool skip_locked, bool *skipped); extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode); extern double vac_estimate_reltuples(Relation relation, BlockNumber total_pages, -- 2.16.2