PGPROC *parallel_master_pgproc;
pid_t parallel_master_pid;
BackendId parallel_master_backend_id;
+ TimestampTz xact_ts;
+ TimestampTz stmt_ts;
/* Mutex protects remaining fields. */
slock_t mutex;
fps->parallel_master_pgproc = MyProc;
fps->parallel_master_pid = MyProcPid;
fps->parallel_master_backend_id = MyBackendId;
+ fps->xact_ts = GetCurrentTransactionStartTimestamp();
+ fps->stmt_ts = GetCurrentStatementStartTimestamp();
SpinLockInit(&fps->mutex);
fps->last_xlog_end = 0;
shm_toc_insert(pcxt->toc, PARALLEL_KEY_FIXED, fps);
fps->parallel_master_pid))
return;
+ /*
+ * Restore transaction and statement start-time timestamps. This must
+ * happen before anything that would start a transaction, else asserts in
+ * xact.c will fire.
+ */
+ SetParallelStartTimestamps(fps->xact_ts, fps->stmt_ts);
+
/*
* Identify the entry point to be called. In theory this could result in
* loading an additional library, though most likely the entry point is in
return currentCommandId;
}
+/*
+ * SetParallelStartTimestamps
+ *
+ * In a parallel worker, we should inherit the parent transaction's
+ * timestamps rather than setting our own. The parallel worker
+ * infrastructure must call this to provide those values before
+ * calling StartTransaction() or SetCurrentStatementStartTimestamp().
+ */
+void
+SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
+{
+ Assert(IsParallelWorker());
+ xactStartTimestamp = xact_ts;
+ stmtStartTimestamp = stmt_ts;
+}
+
/*
* GetCurrentTransactionStartTimestamp
*/
/*
* SetCurrentStatementStartTimestamp
+ *
+ * In a parallel worker, this should already have been provided by a call
+ * to SetParallelStartTimestamps().
*/
void
SetCurrentStatementStartTimestamp(void)
{
- stmtStartTimestamp = GetCurrentTimestamp();
+ if (!IsParallelWorker())
+ stmtStartTimestamp = GetCurrentTimestamp();
+ else
+ Assert(stmtStartTimestamp != 0);
}
/*
/*
* set transaction_timestamp() (a/k/a now()). We want this to be the same
* as the first command's statement_timestamp(), so don't do a fresh
- * GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
- * xactStopTimestamp as unset.
+ * GetCurrentTimestamp() call (which'd be expensive anyway). In a
+ * parallel worker, this should already have been provided by a call to
+ * SetParallelStartTimestamps().
+ *
+ * Also, mark xactStopTimestamp as unset.
*/
- xactStartTimestamp = stmtStartTimestamp;
+ if (!IsParallelWorker())
+ xactStartTimestamp = stmtStartTimestamp;
+ else
+ Assert(xactStartTimestamp != 0);
xactStopTimestamp = 0;
pgstat_report_xact_timestamp(xactStartTimestamp);
extern void MarkCurrentTransactionIdLoggedIfAny(void);
extern bool SubTransactionIsActive(SubTransactionId subxid);
extern CommandId GetCurrentCommandId(bool used);
+extern void SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts);
extern TimestampTz GetCurrentTransactionStartTimestamp(void);
extern TimestampTz GetCurrentStatementStartTimestamp(void);
extern TimestampTz GetCurrentTransactionStopTimestamp(void);