From a315b967cc1bd43ecf3c10ea48b44a4fb0ff8d45 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Sun, 26 Feb 2017 13:36:49 +0530 Subject: [PATCH] Allow custom and foreign scans to have shutdown callbacks. This is expected to be useful mostly when performing such scans in parallel, because in that case it allows (in combination with commit acf555bc53acb589b5a2827e65d655fa8c9adee0) nodes below a Gather to get control just before the DSM segment goes away. KaiGai Kohei, except that I rewrote the documentation. Reviewed by Claudio Freire. Discussion: http://postgr.es/m/CADyhKSXJK0jUJ8rWv4AmKDhsUh124_rEn39eqgfC5D8fu6xVuw@mail.gmail.com --- doc/src/sgml/custom-scan.sgml | 13 +++++++++++++ doc/src/sgml/fdwhandler.sgml | 14 ++++++++++++++ src/backend/executor/execProcnode.c | 6 ++++++ src/backend/executor/nodeCustom.c | 9 +++++++++ src/backend/executor/nodeForeignscan.c | 16 ++++++++++++++++ src/include/executor/nodeCustom.h | 1 + src/include/executor/nodeForeignscan.h | 1 + src/include/foreign/fdwapi.h | 2 ++ src/include/nodes/extensible.h | 1 + 9 files changed, 63 insertions(+) diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml index 1ca9247124..6159c3a24e 100644 --- a/doc/src/sgml/custom-scan.sgml +++ b/doc/src/sgml/custom-scan.sgml @@ -340,6 +340,19 @@ void (*InitializeWorkerCustomScan) (CustomScanState *node, +void (*ShutdownCustomScan) (CustomScanState *node); + + Release resources when it is anticipated the node will not be executed + to completion. This is not called in all cases; sometimes, + EndCustomScan may be called without this function having + been called first. Since the DSM segment used by parallel query is + destroyed just after this callback is invoked, custom scan providers that + wish to take some action before the DSM segment goes away should implement + this method. + + + + void (*ExplainCustomScan) (CustomScanState *node, List *ancestors, ExplainState *es); diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml index 0c1db070ed..dbeaab555d 100644 --- a/doc/src/sgml/fdwhandler.sgml +++ b/doc/src/sgml/fdwhandler.sgml @@ -1254,6 +1254,20 @@ InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc, This callback is optional, and needs only be supplied if this custom path supports parallel execution. + + + +void +ShutdownForeignScan(ForeignScanState *node); + + Release resources when it is anticipated the node will not be executed + to completion. This is not called in all cases; sometimes, + EndForeignScan may be called without this function having + been called first. Since the DSM segment used by parallel query is + destroyed just after this callback is invoked, foreign data wrappers that + wish to take some action before the DSM segment goes away should implement + this method. + diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 5ccc2e846d..ef6f35a5a0 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -822,6 +822,12 @@ ExecShutdownNode(PlanState *node) case T_GatherState: ExecShutdownGather((GatherState *) node); break; + case T_ForeignScanState: + ExecShutdownForeignScan((ForeignScanState *) node); + break; + case T_CustomScanState: + ExecShutdownCustomScan((CustomScanState *) node); + break; default: break; } diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c index 16343a56df..d464748290 100644 --- a/src/backend/executor/nodeCustom.c +++ b/src/backend/executor/nodeCustom.c @@ -202,3 +202,12 @@ ExecCustomScanInitializeWorker(CustomScanState *node, shm_toc *toc) methods->InitializeWorkerCustomScan(node, toc, coordinate); } } + +void +ExecShutdownCustomScan(CustomScanState *node) +{ + const CustomExecMethods *methods = node->methods; + + if (methods->ShutdownCustomScan) + methods->ShutdownCustomScan(node); +} diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index 86a77e356c..3b6d1390eb 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -353,3 +353,19 @@ ExecForeignScanInitializeWorker(ForeignScanState *node, shm_toc *toc) fdwroutine->InitializeWorkerForeignScan(node, toc, coordinate); } } + +/* ---------------------------------------------------------------- + * ExecShutdownForeignScan + * + * Gives FDW chance to stop asynchronous resource consumption + * and release any resources still held. + * ---------------------------------------------------------------- + */ +void +ExecShutdownForeignScan(ForeignScanState *node) +{ + FdwRoutine *fdwroutine = node->fdwroutine; + + if (fdwroutine->ShutdownForeignScan) + fdwroutine->ShutdownForeignScan(node); +} diff --git a/src/include/executor/nodeCustom.h b/src/include/executor/nodeCustom.h index 19d5d047b5..c2f2ca1eed 100644 --- a/src/include/executor/nodeCustom.h +++ b/src/include/executor/nodeCustom.h @@ -37,5 +37,6 @@ extern void ExecCustomScanInitializeDSM(CustomScanState *node, ParallelContext *pcxt); extern void ExecCustomScanInitializeWorker(CustomScanState *node, shm_toc *toc); +extern void ExecShutdownCustomScan(CustomScanState *node); #endif /* NODECUSTOM_H */ diff --git a/src/include/executor/nodeForeignscan.h b/src/include/executor/nodeForeignscan.h index f0e942a8bc..1b167b8143 100644 --- a/src/include/executor/nodeForeignscan.h +++ b/src/include/executor/nodeForeignscan.h @@ -28,5 +28,6 @@ extern void ExecForeignScanInitializeDSM(ForeignScanState *node, ParallelContext *pcxt); extern void ExecForeignScanInitializeWorker(ForeignScanState *node, shm_toc *toc); +extern void ExecShutdownForeignScan(ForeignScanState *node); #endif /* NODEFOREIGNSCAN_H */ diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h index 523d415575..6ca44f734f 100644 --- a/src/include/foreign/fdwapi.h +++ b/src/include/foreign/fdwapi.h @@ -151,6 +151,7 @@ typedef void (*InitializeDSMForeignScan_function) (ForeignScanState *node, typedef void (*InitializeWorkerForeignScan_function) (ForeignScanState *node, shm_toc *toc, void *coordinate); +typedef void (*ShutdownForeignScan_function) (ForeignScanState *node); typedef bool (*IsForeignScanParallelSafe_function) (PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); @@ -224,6 +225,7 @@ typedef struct FdwRoutine EstimateDSMForeignScan_function EstimateDSMForeignScan; InitializeDSMForeignScan_function InitializeDSMForeignScan; InitializeWorkerForeignScan_function InitializeWorkerForeignScan; + ShutdownForeignScan_function ShutdownForeignScan; } FdwRoutine; diff --git a/src/include/nodes/extensible.h b/src/include/nodes/extensible.h index 7e860b0dca..0b02cc18e9 100644 --- a/src/include/nodes/extensible.h +++ b/src/include/nodes/extensible.h @@ -139,6 +139,7 @@ typedef struct CustomExecMethods void (*InitializeWorkerCustomScan) (CustomScanState *node, shm_toc *toc, void *coordinate); + void (*ShutdownCustomScan) (CustomScanState *node); /* Optional: print additional information in EXPLAIN */ void (*ExplainCustomScan) (CustomScanState *node, -- 2.40.0