Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 24ff700

Browse files
committed
Code review for commit 05a7be9.
Avoid having walreceiver code know explicitly about the precision and underlying datatype of TimestampTz. (There is still one calculation that knows that, which should be replaced with use of TimestampDifferenceMilliseconds; but we need to figure out what to do about overflow cases first.) In support of this, provide a TimestampTzPlusSeconds macro, as well as TIMESTAMP_INFINITY and TIMESTAMP_MINUS_INFINITY macros. (We could have used the existing DT_NOEND and DT_NOBEGIN symbols, but I judged those too opaque and confusing.) Move GetCurrentTimestamp calls so that it's more obvious that we are not using stale values of "now" anyplace. This doesn't result in net more calls, and might indeed make for net fewer. Avoid having a dummy value in the WalRcvWakeupReason enum, so that we can hope for the compiler to catch overlooked switch cases. Nathan Bossart and Tom Lane Discussion: https://postgr.es/m/20230125235004.GA1327755@nathanxps13
1 parent e35bb9f commit 24ff700

File tree

3 files changed

+36
-26
lines changed

3 files changed

+36
-26
lines changed

src/backend/replication/walreceiver.c

+24-23
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ typedef enum WalRcvWakeupReason
122122
WALRCV_WAKEUP_TERMINATE,
123123
WALRCV_WAKEUP_PING,
124124
WALRCV_WAKEUP_REPLY,
125-
WALRCV_WAKEUP_HSFEEDBACK,
126-
NUM_WALRCV_WAKEUPS
125+
WALRCV_WAKEUP_HSFEEDBACK
126+
#define NUM_WALRCV_WAKEUPS (WALRCV_WAKEUP_HSFEEDBACK + 1)
127127
} WalRcvWakeupReason;
128128

129129
/*
@@ -206,8 +206,6 @@ WalReceiverMain(void)
206206
*/
207207
Assert(walrcv != NULL);
208208

209-
now = GetCurrentTimestamp();
210-
211209
/*
212210
* Mark walreceiver as running in shared memory.
213211
*
@@ -261,6 +259,7 @@ WalReceiverMain(void)
261259
Assert(!is_temp_slot || (slotname[0] == '\0'));
262260

263261
/* Initialise to a sanish value */
262+
now = GetCurrentTimestamp();
264263
walrcv->lastMsgSendTime =
265264
walrcv->lastMsgReceiptTime = walrcv->latestWalEndTime = now;
266265

@@ -464,6 +463,7 @@ WalReceiverMain(void)
464463
{
465464
ConfigReloadPending = false;
466465
ProcessConfigFile(PGC_SIGHUP);
466+
/* recompute wakeup times */
467467
now = GetCurrentTimestamp();
468468
for (int i = 0; i < NUM_WALRCV_WAKEUPS; ++i)
469469
WalRcvComputeNextWakeup(i, now);
@@ -472,7 +472,6 @@ WalReceiverMain(void)
472472

473473
/* See if we can read data immediately */
474474
len = walrcv_receive(wrconn, &buf, &wait_fd);
475-
now = GetCurrentTimestamp();
476475
if (len != 0)
477476
{
478477
/*
@@ -487,6 +486,7 @@ WalReceiverMain(void)
487486
* Something was received from primary, so adjust
488487
* the ping and terminate wakeup times.
489488
*/
489+
now = GetCurrentTimestamp();
490490
WalRcvComputeNextWakeup(WALRCV_WAKEUP_TERMINATE,
491491
now);
492492
WalRcvComputeNextWakeup(WALRCV_WAKEUP_PING, now);
@@ -506,7 +506,6 @@ WalReceiverMain(void)
506506
break;
507507
}
508508
len = walrcv_receive(wrconn, &buf, &wait_fd);
509-
now = GetCurrentTimestamp();
510509
}
511510

512511
/* Let the primary know that we received some data. */
@@ -525,7 +524,7 @@ WalReceiverMain(void)
525524
break;
526525

527526
/* Find the soonest wakeup time, to limit our nap. */
528-
nextWakeup = PG_INT64_MAX;
527+
nextWakeup = TIMESTAMP_INFINITY;
529528
for (int i = 0; i < NUM_WALRCV_WAKEUPS; ++i)
530529
nextWakeup = Min(wakeup[i], nextWakeup);
531530

@@ -536,6 +535,7 @@ WalReceiverMain(void)
536535
* millisecond to avoid waking up too early and spinning until
537536
* one of the wakeup times.
538537
*/
538+
now = GetCurrentTimestamp();
539539
nap = (int) Min(INT_MAX, Max(0, (nextWakeup - now + 999) / 1000));
540540

541541
/*
@@ -556,7 +556,6 @@ WalReceiverMain(void)
556556
wait_fd,
557557
nap,
558558
WAIT_EVENT_WAL_RECEIVER_MAIN);
559-
now = GetCurrentTimestamp();
560559
if (rc & WL_LATCH_SET)
561560
{
562561
ResetLatch(MyLatch);
@@ -592,19 +591,20 @@ WalReceiverMain(void)
592591
* Check if time since last receive from primary has
593592
* reached the configured limit.
594593
*/
594+
now = GetCurrentTimestamp();
595595
if (now >= wakeup[WALRCV_WAKEUP_TERMINATE])
596596
ereport(ERROR,
597597
(errcode(ERRCODE_CONNECTION_FAILURE),
598598
errmsg("terminating walreceiver due to timeout")));
599599

600600
/*
601-
* We didn't receive anything new, for half of receiver
602-
* replication timeout. Ping the server.
601+
* If we didn't receive anything new for half of receiver
602+
* replication timeout, then ping the server.
603603
*/
604604
if (now >= wakeup[WALRCV_WAKEUP_PING])
605605
{
606606
requestReply = true;
607-
wakeup[WALRCV_WAKEUP_PING] = PG_INT64_MAX;
607+
wakeup[WALRCV_WAKEUP_PING] = TIMESTAMP_INFINITY;
608608
}
609609

610610
XLogWalRcvSendReply(requestReply, requestReply);
@@ -1266,7 +1266,6 @@ static void
12661266
ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime)
12671267
{
12681268
WalRcvData *walrcv = WalRcv;
1269-
12701269
TimestampTz lastMsgReceiptTime = GetCurrentTimestamp();
12711270

12721271
/* Update shared-memory status */
@@ -1310,7 +1309,10 @@ ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime)
13101309
/*
13111310
* Compute the next wakeup time for a given wakeup reason. Can be called to
13121311
* initialize a wakeup time, to adjust it for the next wakeup, or to
1313-
* reinitialize it when GUCs have changed.
1312+
* reinitialize it when GUCs have changed. We ask the caller to pass in the
1313+
* value of "now" because this frequently avoids multiple calls of
1314+
* GetCurrentTimestamp(). It had better be a reasonably up-to-date value
1315+
* though.
13141316
*/
13151317
static void
13161318
WalRcvComputeNextWakeup(WalRcvWakeupReason reason, TimestampTz now)
@@ -1319,30 +1321,29 @@ WalRcvComputeNextWakeup(WalRcvWakeupReason reason, TimestampTz now)
13191321
{
13201322
case WALRCV_WAKEUP_TERMINATE:
13211323
if (wal_receiver_timeout <= 0)
1322-
wakeup[reason] = PG_INT64_MAX;
1324+
wakeup[reason] = TIMESTAMP_INFINITY;
13231325
else
1324-
wakeup[reason] = now + wal_receiver_timeout * INT64CONST(1000);
1326+
wakeup[reason] = TimestampTzPlusMilliseconds(now, wal_receiver_timeout);
13251327
break;
13261328
case WALRCV_WAKEUP_PING:
13271329
if (wal_receiver_timeout <= 0)
1328-
wakeup[reason] = PG_INT64_MAX;
1330+
wakeup[reason] = TIMESTAMP_INFINITY;
13291331
else
1330-
wakeup[reason] = now + (wal_receiver_timeout / 2) * INT64CONST(1000);
1332+
wakeup[reason] = TimestampTzPlusMilliseconds(now, wal_receiver_timeout / 2);
13311333
break;
13321334
case WALRCV_WAKEUP_HSFEEDBACK:
13331335
if (!hot_standby_feedback || wal_receiver_status_interval <= 0)
1334-
wakeup[reason] = PG_INT64_MAX;
1336+
wakeup[reason] = TIMESTAMP_INFINITY;
13351337
else
1336-
wakeup[reason] = now + wal_receiver_status_interval * INT64CONST(1000000);
1338+
wakeup[reason] = TimestampTzPlusSeconds(now, wal_receiver_status_interval);
13371339
break;
13381340
case WALRCV_WAKEUP_REPLY:
13391341
if (wal_receiver_status_interval <= 0)
1340-
wakeup[reason] = PG_INT64_MAX;
1342+
wakeup[reason] = TIMESTAMP_INFINITY;
13411343
else
1342-
wakeup[reason] = now + wal_receiver_status_interval * INT64CONST(1000000);
1343-
break;
1344-
default:
1344+
wakeup[reason] = TimestampTzPlusSeconds(now, wal_receiver_status_interval);
13451345
break;
1346+
/* there's intentionally no default: here */
13461347
}
13471348
}
13481349

src/include/datatype/timestamp.h

+10-3
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,17 @@ struct pg_itm_in
143143
#define TZDISP_LIMIT ((MAX_TZDISP_HOUR + 1) * SECS_PER_HOUR)
144144

145145
/*
146-
* DT_NOBEGIN represents timestamp -infinity; DT_NOEND represents +infinity
146+
* We reserve the minimum and maximum integer values to represent
147+
* timestamp (or timestamptz) -infinity and +infinity.
147148
*/
148-
#define DT_NOBEGIN PG_INT64_MIN
149-
#define DT_NOEND PG_INT64_MAX
149+
#define TIMESTAMP_MINUS_INFINITY PG_INT64_MIN
150+
#define TIMESTAMP_INFINITY PG_INT64_MAX
151+
152+
/*
153+
* Historically these alias for infinity have been used.
154+
*/
155+
#define DT_NOBEGIN TIMESTAMP_MINUS_INFINITY
156+
#define DT_NOEND TIMESTAMP_INFINITY
150157

151158
#define TIMESTAMP_NOBEGIN(j) \
152159
do {(j) = DT_NOBEGIN;} while (0)

src/include/utils/timestamp.h

+2
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ IntervalPGetDatum(const Interval *X)
8181
#define INTERVAL_PRECISION(t) ((t) & INTERVAL_PRECISION_MASK)
8282
#define INTERVAL_RANGE(t) (((t) >> 16) & INTERVAL_RANGE_MASK)
8383

84+
/* Macros for doing timestamp arithmetic without assuming timestamp's units */
8485
#define TimestampTzPlusMilliseconds(tz,ms) ((tz) + ((ms) * (int64) 1000))
86+
#define TimestampTzPlusSeconds(tz,s) ((tz) + ((s) * (int64) 1000000))
8587

8688

8789
/* Set at postmaster start */

0 commit comments

Comments
 (0)