From dad07730989ae978739cb29a747a6642886887b0 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Tue, 28 Jun 2016 17:25:30 +0900
Subject: [PATCH 5/7] Add new fdwroutine AsyncConfigureWait and
 ShutdownForeignScan.

Async-capable nodes should handle AsyncConfigureWait and
ExecShutdownNode callbacks. This patch adds entries for FDWs in the
two functions and adds corresponding FdwRoutine entries.
---
 src/backend/executor/execAsync.c    | 14 ++++++++++++--
 src/backend/executor/execProcnode.c |  9 +++++++++
 src/include/foreign/fdwapi.h        |  8 ++++++++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/backend/executor/execAsync.c b/src/backend/executor/execAsync.c
index 51902e6..00de11b 100644
--- a/src/backend/executor/execAsync.c
+++ b/src/backend/executor/execAsync.c
@@ -25,6 +25,7 @@
 
 #include "executor/execAsync.h"
 #include "executor/executor.h"
+#include "foreign/fdwapi.h"
 #include "storage/latch.h"
 
 #define	EVENT_BUFFER_SIZE		16
@@ -289,8 +290,17 @@ ExecAsyncConfigureWait(PlanState *planstate, AsyncConfigMode config_mode)
 {
 	switch (nodeTag(planstate))
 	{
-		/* XXX: Add calls to per-nodetype handlers here. */
-		default:
+		/* Add calls to per-nodetype handlers here. */
+ 	case T_ForeignScanState:
+ 		{
+			ForeignScanState *node = (ForeignScanState *) planstate;
+			if (node->fdwroutine->AsyncConfigureWait)
+				return node->fdwroutine->AsyncConfigureWait(node, config_mode);
+		}
+		break;
+	default:
 			elog(ERROR, "unexpected node type: %d", nodeTag(planstate));
 	}
+
+	return false;
 }
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index 4f468c1..0e6ed39 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -115,6 +115,7 @@
 #include "executor/nodeValuesscan.h"
 #include "executor/nodeWindowAgg.h"
 #include "executor/nodeWorktablescan.h"
+#include "foreign/fdwapi.h"
 #include "nodes/nodeFuncs.h"
 #include "miscadmin.h"
 
@@ -890,6 +891,14 @@ ExecShutdownNode(PlanState *node)
 		case T_GatherState:
 			ExecShutdownGather((GatherState *) node);
 			break;
+		case T_ForeignScanState:
+			{
+				ForeignScanState *fsstate = (ForeignScanState *)node;
+				FdwRoutine *fdwroutine = fsstate->fdwroutine;
+				if (fdwroutine->ShutdownForeignScan)
+					fdwroutine->ShutdownForeignScan((ForeignScanState *) node);
+			}
+			break;
 		default:
 			break;
 	}
diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h
index e1b0d0d..8de44dd 100644
--- a/src/include/foreign/fdwapi.h
+++ b/src/include/foreign/fdwapi.h
@@ -13,6 +13,7 @@
 #define FDWAPI_H
 
 #include "access/parallel.h"
+#include "executor/execAsync.h"
 #include "nodes/execnodes.h"
 #include "nodes/relation.h"
 
@@ -154,6 +155,9 @@ typedef void (*InitializeWorkerForeignScan_function) (ForeignScanState *node,
 typedef bool (*IsForeignScanParallelSafe_function) (PlannerInfo *root,
 															 RelOptInfo *rel,
 														 RangeTblEntry *rte);
+typedef bool (*AsyncConfigureWait_function) (ForeignScanState *node,
+											 AsyncConfigMode config_mode);
+typedef void (*ShutdownForeignScan_function) (ForeignScanState *node);
 
 /*
  * FdwRoutine is the struct returned by a foreign-data wrapper's handler
@@ -224,6 +228,10 @@ typedef struct FdwRoutine
 	EstimateDSMForeignScan_function EstimateDSMForeignScan;
 	InitializeDSMForeignScan_function InitializeDSMForeignScan;
 	InitializeWorkerForeignScan_function InitializeWorkerForeignScan;
+
+	/* Support functions for asynchronous execution */
+	AsyncConfigureWait_function AsyncConfigureWait;
+	ShutdownForeignScan_function ShutdownForeignScan;
 } FdwRoutine;
 
 
-- 
1.8.3.1

