summaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorTom Lane2017-08-30 17:18:16 +0000
committerTom Lane2017-08-30 17:18:16 +0000
commit41b0dd987d44089dc48e9c70024277e253b396b7 (patch)
treec42eeeb2f175764a9b1ad9c095f8a46057078eb3 /doc/src
parent6c2c5bea3cec4c874d1ee225bb6e222055c03d75 (diff)
Separate reinitialization of shared parallel-scan state from ExecReScan.
Previously, the parallel executor logic did reinitialization of shared state within the ExecReScan code for parallel-aware scan nodes. This is problematic, because it means that the ExecReScan call has to occur synchronously (ie, during the parent Gather node's ReScan call). That is swimming very much against the tide so far as the ExecReScan machinery is concerned; the fact that it works at all today depends on a lot of fragile assumptions, such as that no plan node between Gather and a parallel-aware scan node is parameterized. Another objection is that because ExecReScan might be called in workers as well as the leader, hacky extra tests are needed in some places to prevent unwanted shared-state resets. Hence, let's separate this code into two functions, a ReInitializeDSM call and the ReScan call proper. ReInitializeDSM is called only in the leader and is guaranteed to run before we start new workers. ReScan is returned to its traditional function of resetting only local state, which means that ExecReScan's usual habits of delaying or eliminating child rescan calls are safe again. As with the preceding commit 7df2c1f8d, it doesn't seem to be necessary to make these changes in 9.6, which is a good thing because the FDW and CustomScan APIs are impacted. Discussion: https://postgr.es/m/CAA4eK1JkByysFJNh9M349u_nNjqETuEnY_y1VUc_kJiU0bxtaQ@mail.gmail.com
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/custom-scan.sgml29
-rw-r--r--doc/src/sgml/fdwhandler.sgml43
2 files changed, 54 insertions, 18 deletions
diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml
index 6159c3a24eb..9d1ca7bfe16 100644
--- a/doc/src/sgml/custom-scan.sgml
+++ b/doc/src/sgml/custom-scan.sgml
@@ -320,22 +320,39 @@ void (*InitializeDSMCustomScan) (CustomScanState *node,
void *coordinate);
</programlisting>
Initialize the dynamic shared memory that will be required for parallel
- operation; <literal>coordinate</> points to an amount of allocated space
- equal to the return value of <function>EstimateDSMCustomScan</>.
+ operation. <literal>coordinate</> points to a shared memory area of
+ size equal to the return value of <function>EstimateDSMCustomScan</>.
This callback is optional, and need only be supplied if this custom
scan provider supports parallel execution.
</para>
<para>
<programlisting>
+void (*ReInitializeDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt,
+ void *coordinate);
+</programlisting>
+ Re-initialize the dynamic shared memory required for parallel operation
+ when the custom-scan plan node is about to be re-scanned.
+ This callback is optional, and need only be supplied if this custom
+ scan provider supports parallel execution.
+ Recommended practice is that this callback reset only shared state,
+ while the <function>ReScanCustomScan</> callback resets only local
+ state. Currently, this callback will be called
+ before <function>ReScanCustomScan</>, but it's best not to rely on
+ that ordering.
+ </para>
+
+ <para>
+<programlisting>
void (*InitializeWorkerCustomScan) (CustomScanState *node,
shm_toc *toc,
void *coordinate);
</programlisting>
- Initialize a parallel worker's custom state based on the shared state
- set up in the leader by <literal>InitializeDSMCustomScan</>.
- This callback is optional, and needs only be supplied if this
- custom path supports parallel execution.
+ Initialize a parallel worker's local state based on the shared state
+ set up by the leader during <function>InitializeDSMCustomScan</>.
+ This callback is optional, and need only be supplied if this custom
+ scan provider supports parallel execution.
</para>
<para>
diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml
index dbeaab555db..cfa68084179 100644
--- a/doc/src/sgml/fdwhandler.sgml
+++ b/doc/src/sgml/fdwhandler.sgml
@@ -1191,12 +1191,12 @@ ImportForeignSchema (ImportForeignSchemaStmt *stmt, Oid serverOid);
<para>
A <structname>ForeignScan</> node can, optionally, support parallel
execution. A parallel <structname>ForeignScan</> will be executed
- in multiple processes and should return each row only once across
+ in multiple processes and must return each row exactly once across
all cooperating processes. To do this, processes can coordinate through
- fixed size chunks of dynamic shared memory. This shared memory is not
- guaranteed to be mapped at the same address in every process, so pointers
- may not be used. The following callbacks are all optional in general,
- but required if parallel execution is to be supported.
+ fixed-size chunks of dynamic shared memory. This shared memory is not
+ guaranteed to be mapped at the same address in every process, so it
+ must not contain pointers. The following functions are all optional,
+ but most are required if parallel execution is to be supported.
</para>
<para>
@@ -1215,7 +1215,7 @@ IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
</para>
<para>
- If this callback is not defined, it is assumed that the scan must take
+ If this function is not defined, it is assumed that the scan must take
place within the parallel leader. Note that returning true does not mean
that the scan itself can be done in parallel, only that the scan can be
performed within a parallel worker. Therefore, it can be useful to define
@@ -1230,6 +1230,9 @@ EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);
Estimate the amount of dynamic shared memory that will be required
for parallel operation. This may be higher than the amount that will
actually be used, but it must not be lower. The return value is in bytes.
+ This function is optional, and can be omitted if not needed; but if it
+ is omitted, the next three functions must be omitted as well, because
+ no shared memory will be allocated for the FDW's use.
</para>
<para>
@@ -1239,8 +1242,25 @@ InitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
void *coordinate);
</programlisting>
Initialize the dynamic shared memory that will be required for parallel
- operation; <literal>coordinate</> points to an amount of allocated space
- equal to the return value of <function>EstimateDSMForeignScan</>.
+ operation. <literal>coordinate</> points to a shared memory area of
+ size equal to the return value of <function>EstimateDSMForeignScan</>.
+ This function is optional, and can be omitted if not needed.
+ </para>
+
+ <para>
+<programlisting>
+void
+ReInitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
+ void *coordinate);
+</programlisting>
+ Re-initialize the dynamic shared memory required for parallel operation
+ when the foreign-scan plan node is about to be re-scanned.
+ This function is optional, and can be omitted if not needed.
+ Recommended practice is that this function reset only shared state,
+ while the <function>ReScanForeignScan</> function resets only local
+ state. Currently, this function will be called
+ before <function>ReScanForeignScan</>, but it's best not to rely on
+ that ordering.
</para>
<para>
@@ -1249,10 +1269,9 @@ void
InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc,
void *coordinate);
</programlisting>
- Initialize a parallel worker's custom state based on the shared state
- set up in the leader by <literal>InitializeDSMForeignScan</>.
- This callback is optional, and needs only be supplied if this
- custom path supports parallel execution.
+ Initialize a parallel worker's local state based on the shared state
+ set up by the leader during <function>InitializeDSMForeignScan</>.
+ This function is optional, and can be omitted if not needed.
</para>
<para>