doc/src/sgml/custom-scan.sgml | 44 ++++++++++++++++++++++++++++++++++ doc/src/sgml/fdwhandler.sgml | 11 +++++++++ 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, 91 insertions(+) diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml index 1ca9247..ef8a57c 100644 --- a/doc/src/sgml/custom-scan.sgml +++ b/doc/src/sgml/custom-scan.sgml @@ -240,6 +240,40 @@ typedef struct CustomScanState structure embedding the above as its first member. + + The simplest execution life-cycle of CustomScanState has + three basic steps. First, executor calls BeginCustomScan with + CustomScanState object allocated by + by CreateCustomScanState. Next, ExecCustomScan + shall be called repeatedly until it returns valid tuples. + Last, EndCustomScan shall be called. + + + + According to the type of upper plan node, it may call + ReScanCustomScan, MarkPosCustomScan or + RestrPosCustomScan during execution on demand. + + + + If custom-scan works under CPU parallel, some more interaction with + executor are required. + Prior to launch of background workers, EstimateDSMCustomScan + is called next to creation of the CustomScanState, to + inform amount of the DSM segment required by the custom-scan node. + Then, InitializeDSMCustomScan is called to initialize the + DSM area which is allocated for the custom-scan node. + Once execution gets started, Gather node kicks background + worker processes, then InitializeWorkerCustomScan is called + on the worker process's context, to initialize extra stuff based on the + DSM contents. + After the execution of worker process, Gather synchronizes + its completion, then ShutdownCustomScan is called, but + prior to release of the DSM segment. So, if custom-scan node wants to + return its own extra information using DSM, it has to be retrieved at + this point. + + Custom Scan Execution Callbacks @@ -340,6 +374,16 @@ void (*InitializeWorkerCustomScan) (CustomScanState *node, +void (*ShutdownCustomScan) (CustomScanState *node); + + Stops asynchronous resource consumption, retrieves contents on the + DSM segment, or release any resources still held. + This callback is optional, and makes sense only if this custom path + works under parallel execution. + + + + void (*ExplainCustomScan) (CustomScanState *node, List *ancestors, ExplainState *es); diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml index 0c1db07..b51a2ac 100644 --- a/doc/src/sgml/fdwhandler.sgml +++ b/doc/src/sgml/fdwhandler.sgml @@ -1254,6 +1254,17 @@ 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); + + Stops asynchronous resource consumption, retrieves contents on the + DSM segment, or release any resources still held. + This callback is optional, and makes sense only if this custom path + works under parallel execution. + diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 5ccc2e8..ef6f35a 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 16343a5..d464748 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 86a77e3..3b6d139 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 19d5d04..c2f2ca1 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 f0e942a..1b167b8 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 523d415..6ca44f7 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 7e860b0..0b02cc1 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,