Commit a315b967 authored by Robert Haas's avatar Robert Haas

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
acf555bc) 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
parent 285ca261
......@@ -340,6 +340,19 @@ void (*InitializeWorkerCustomScan) (CustomScanState *node,
<para>
<programlisting>
void (*ShutdownCustomScan) (CustomScanState *node);
</programlisting>
Release resources when it is anticipated the node will not be executed
to completion. This is not called in all cases; sometimes,
<literal>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.
</para>
<para>
<programlisting>
void (*ExplainCustomScan) (CustomScanState *node,
List *ancestors,
ExplainState *es);
......
......@@ -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.
</para>
<para>
<programlisting>
void
ShutdownForeignScan(ForeignScanState *node);
</programlisting>
Release resources when it is anticipated the node will not be executed
to completion. This is not called in all cases; sometimes,
<literal>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.
</para>
</sect2>
</sect1>
......
......@@ -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;
}
......
......@@ -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);
}
......@@ -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);
}
......@@ -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 */
......@@ -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 */
......@@ -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;
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment