v7-0003-Add-skip_locked-argument-to-vac_open_indexes.patch

application/octet-stream

Filename: v7-0003-Add-skip_locked-argument-to-vac_open_indexes.patch
Type: application/octet-stream
Part: 2
Message: Re: BUG #14941: Vacuum crashes

Patch

Format: format-patch
Series: patch v7-0003
Subject: Add skip_locked argument to vac_open_indexes().
File+
src/backend/commands/analyze.c 1 1
src/backend/commands/vacuum.c 25 2
src/backend/commands/vacuumlazy.c 1 1
src/include/commands/vacuum.h 2 1
From ac8708a0f9c65f7cee4898aa8d83d09294e2fa0d Mon Sep 17 00:00:00 2001
From: Nathan Bossart <bossartn@amazon.com>
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