diff options
author | Alexander Korotkov <akorotkov@postgresql.org> | 2020-04-08 11:37:27 +0300 |
---|---|---|
committer | Alexander Korotkov <akorotkov@postgresql.org> | 2020-04-08 11:37:27 +0300 |
commit | 1aac32df89eb19949050f6f27c268122833ad036 (patch) | |
tree | 7f1b7d61e1bdb19a5f9437d5198b63e4be4e2ecb /src/backend/commands | |
parent | 02a2e8b442002a698336954633b0ccc4e30061e6 (diff) | |
download | postgresql-1aac32df89eb19949050f6f27c268122833ad036.tar.gz postgresql-1aac32df89eb19949050f6f27c268122833ad036.zip |
Revert 0f5ca02f53
0f5ca02f53 introduces 3 new keywords. It appears to be too much for relatively
small feature. Given now we past feature freeze, it's already late for
discussion of the new syntax. So, revert.
Discussion: https://postgr.es/m/28209.1586294824%40sss.pgh.pa.us
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/Makefile | 3 | ||||
-rw-r--r-- | src/backend/commands/wait.c | 295 |
2 files changed, 1 insertions, 297 deletions
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile index 9b310926c12..d4815d3ce65 100644 --- a/src/backend/commands/Makefile +++ b/src/backend/commands/Makefile @@ -57,7 +57,6 @@ OBJS = \ user.o \ vacuum.o \ variable.o \ - view.o \ - wait.o + view.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/commands/wait.c b/src/backend/commands/wait.c deleted file mode 100644 index b7aee5b794b..00000000000 --- a/src/backend/commands/wait.c +++ /dev/null @@ -1,295 +0,0 @@ -/*------------------------------------------------------------------------- - * - * wait.c - * Implements WAIT FOR clause for BEGIN and START TRANSACTION commands. - * This clause allows waiting for given LSN to be replayed on standby. - * - * Copyright (c) 2020, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/backend/commands/wait.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include <math.h> - -#include "access/xlog.h" -#include "access/xlogdefs.h" -#include "commands/wait.h" -#include "funcapi.h" -#include "miscadmin.h" -#include "pgstat.h" -#include "storage/backendid.h" -#include "storage/pmsignal.h" -#include "storage/proc.h" -#include "storage/shmem.h" -#include "storage/sinvaladt.h" -#include "storage/spin.h" -#include "utils/builtins.h" -#include "utils/pg_lsn.h" -#include "utils/timestamp.h" - -/* - * Shared memory structure representing information about LSNs, which backends - * are waiting for replay. - */ -typedef struct -{ - slock_t mutex; /* mutex protecting the fields below */ - int max_backend_id; /* max backend_id present in lsns[] */ - pg_atomic_uint64 min_lsn; /* minimal waited LSN */ - /* per-backend array of waited LSNs */ - XLogRecPtr lsns[FLEXIBLE_ARRAY_MEMBER]; -} WaitLSNState; - -static WaitLSNState * state; - -/* - * Add the wait event of the current backend to shared memory array - */ -static void -WaitLSNAdd(XLogRecPtr lsn_to_wait) -{ - SpinLockAcquire(&state->mutex); - if (state->max_backend_id < MyBackendId) - state->max_backend_id = MyBackendId; - - state->lsns[MyBackendId] = lsn_to_wait; - - if (lsn_to_wait < state->min_lsn.value) - state->min_lsn.value = lsn_to_wait; - SpinLockRelease(&state->mutex); -} - -/* - * Delete wait event of the current backend from the shared memory array. - */ -void -WaitLSNDelete(void) -{ - int i; - XLogRecPtr deleted_lsn; - - SpinLockAcquire(&state->mutex); - - deleted_lsn = state->lsns[MyBackendId]; - state->lsns[MyBackendId] = InvalidXLogRecPtr; - - /* If we are deleting the minimal LSN, then choose the next min_lsn */ - if (!XLogRecPtrIsInvalid(deleted_lsn) && - deleted_lsn == state->min_lsn.value) - { - state->min_lsn.value = InvalidXLogRecPtr; - for (i = 2; i <= state->max_backend_id; i++) - { - if (!XLogRecPtrIsInvalid(state->lsns[i]) && - (state->lsns[i] < state->min_lsn.value || - XLogRecPtrIsInvalid(state->min_lsn.value))) - { - state->min_lsn.value = state->lsns[i]; - } - } - } - - /* If deleting from the end of the array, shorten the array's used part */ - if (state->max_backend_id == MyBackendId) - { - for (i = (MyBackendId); i >= 2; i--) - if (!XLogRecPtrIsInvalid(state->lsns[i])) - { - state->max_backend_id = i; - break; - } - } - - SpinLockRelease(&state->mutex); -} - -/* - * Report amount of shared memory space needed for WaitLSNState - */ -Size -WaitLSNShmemSize(void) -{ - Size size; - - size = offsetof(WaitLSNState, lsns); - size = add_size(size, mul_size(MaxBackends + 1, sizeof(XLogRecPtr))); - return size; -} - -/* - * Initialize an shared memory structure for waiting for LSN - */ -void -WaitLSNShmemInit(void) -{ - bool found; - uint32 i; - - state = (WaitLSNState *) ShmemInitStruct("pg_wait_lsn", - WaitLSNShmemSize(), - &found); - if (!found) - { - SpinLockInit(&state->mutex); - - for (i = 0; i < (MaxBackends + 1); i++) - state->lsns[i] = InvalidXLogRecPtr; - - state->max_backend_id = 0; - pg_atomic_init_u64(&state->min_lsn, InvalidXLogRecPtr); - } -} - -/* - * Set latches in shared memory to signal that new LSN has been replayed - */ -void -WaitLSNSetLatch(XLogRecPtr cur_lsn) -{ - uint32 i; - int max_backend_id; - PGPROC *backend; - - SpinLockAcquire(&state->mutex); - max_backend_id = state->max_backend_id; - - for (i = 2; i <= max_backend_id; i++) - { - backend = BackendIdGetProc(i); - - if (backend && state->lsns[i] != 0 && - state->lsns[i] <= cur_lsn) - { - SetLatch(&backend->procLatch); - } - } - SpinLockRelease(&state->mutex); -} - -/* - * Get minimal LSN that some backend is waiting for - */ -XLogRecPtr -WaitLSNGetMin(void) -{ - return state->min_lsn.value; -} - -/* - * On WAIT use a latch to wait till LSN is replayed, postmaster dies or timeout - * happens. Timeout is specified in milliseconds. Returns true if LSN was - * reached and false otherwise. - */ -bool -WaitLSNUtility(XLogRecPtr target_lsn, const int timeout_ms) -{ - XLogRecPtr cur_lsn; - int latch_events; - float8 endtime; - bool res = false; - bool wait_forever = (timeout_ms <= 0); - - endtime = GetNowFloat() + timeout_ms / 1000.0; - - latch_events = WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH; - - /* Check if we already reached the needed LSN */ - cur_lsn = GetXLogReplayRecPtr(NULL); - if (cur_lsn >= target_lsn) - return true; - - WaitLSNAdd(target_lsn); - ResetLatch(MyLatch); - - /* Recheck if LSN was reached while WaitLSNAdd() and ResetLatch() */ - cur_lsn = GetXLogReplayRecPtr(NULL); - if (cur_lsn >= target_lsn) - return true; - - for (;;) - { - int rc; - float8 time_left = 0; - long time_left_ms = 0; - - time_left = endtime - GetNowFloat(); - - /* Use 1 second as the default timeout to check for interrupts */ - if (wait_forever || time_left < 0 || time_left > 1.0) - time_left_ms = 1000; - else - time_left_ms = (long) ceil(time_left * 1000.0); - - /* If interrupt, LockErrorCleanup() will do WaitLSNDelete() for us */ - CHECK_FOR_INTERRUPTS(); - - /* If postmaster dies, finish immediately */ - if (!PostmasterIsAlive()) - break; - - rc = WaitLatch(MyLatch, latch_events, time_left_ms, - WAIT_EVENT_CLIENT_READ); - - ResetLatch(MyLatch); - - if (rc & WL_LATCH_SET) - cur_lsn = GetXLogReplayRecPtr(NULL); - - if (rc & WL_TIMEOUT) - { - time_left = endtime - GetNowFloat(); - /* If the time specified by user has passed, stop waiting */ - if (!wait_forever && time_left <= 0.0) - break; - cur_lsn = GetXLogReplayRecPtr(NULL); - } - - /* If LSN has been replayed */ - if (target_lsn <= cur_lsn) - break; - } - - WaitLSNDelete(); - - if (cur_lsn < target_lsn) - ereport(WARNING, - (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), - errmsg("didn't start transaction because LSN was not reached"), - errhint("Try to increase wait timeout."))); - else - res = true; - - return res; -} - -/* - * Implementation of WAIT FOR clause for BEGIN and START TRANSACTION commands - */ -int -WaitLSNMain(WaitClause *stmt, DestReceiver *dest) -{ - TupleDesc tupdesc; - TupOutputState *tstate; - XLogRecPtr target_lsn; - bool res = false; - - target_lsn = DatumGetLSN(DirectFunctionCall1(pg_lsn_in, - CStringGetDatum(stmt->lsn))); - res = WaitLSNUtility(target_lsn, stmt->timeout); - - /* Need a tuple descriptor representing a single TEXT column */ - tupdesc = CreateTemplateTupleDesc(1); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "LSN reached", TEXTOID, -1, 0); - - /* Prepare for projection of tuples */ - tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsMinimalTuple); - - /* Send the result */ - do_text_output_oneline(tstate, res ? "t" : "f"); - end_tup_output(tstate); - return res; -} |