Skip to content

Commit e997a0c

Browse files
committed
Remove all use of ThisTimeLineID global variable outside of xlog.c
All such code deals with this global variable in one of three ways. Sometimes the same functions use it in more than one of these ways at the same time. First, sometimes it's an implicit argument to one or more functions being called in xlog.c or elsewhere, and must be set to the appropriate value before calling those functions lest they misbehave. In those cases, it is now passed as an explicit argument instead. Second, sometimes it's used to obtain the current timeline after the end of recovery, i.e. the timeline to which WAL is being written and flushed. Such code now calls GetWALInsertionTimeLine() or relies on the new out parameter added to GetFlushRecPtr(). Third, sometimes it's used during recovery to store the current replay timeline. That can change, so such code must generally update the value before each use. It can still do that, but must now use a local variable instead. The net effect of these changes is to reduce by a fair amount the amount of code that is directly accessing this global variable. That's good, because history has shown that we don't always think clearly about which timeline ID it's supposed to contain at any given point in time, or indeed, whether it has been or needs to be initialized at any given point in the code. Patch by me, reviewed and tested by Michael Paquier, Amul Sul, and Álvaro Herrera. Discussion: https://postgr.es/m/CA+TgmobfAAqhfWa1kaFBBFvX+5CjM=7TE=n4r4Q1o2bjbGYBpA@mail.gmail.com
1 parent caf1f67 commit e997a0c

File tree

13 files changed

+169
-132
lines changed

13 files changed

+169
-132
lines changed

src/backend/access/transam/twophase.c

+1-13
Original file line numberDiff line numberDiff line change
@@ -1373,19 +1373,14 @@ ReadTwoPhaseFile(TransactionId xid, bool missing_ok)
13731373
* twophase files and ReadTwoPhaseFile should be used instead.
13741374
*
13751375
* Note clearly that this function can access WAL during normal operation,
1376-
* similarly to the way WALSender or Logical Decoding would do. While
1377-
* accessing WAL, read_local_xlog_page() may change ThisTimeLineID,
1378-
* particularly if this routine is called for the end-of-recovery checkpoint
1379-
* in the checkpointer itself, so save the current timeline number value
1380-
* and restore it once done.
1376+
* similarly to the way WALSender or Logical Decoding would do.
13811377
*/
13821378
static void
13831379
XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
13841380
{
13851381
XLogRecord *record;
13861382
XLogReaderState *xlogreader;
13871383
char *errormsg;
1388-
TimeLineID save_currtli = ThisTimeLineID;
13891384

13901385
xlogreader = XLogReaderAllocate(wal_segment_size, NULL,
13911386
XL_ROUTINE(.page_read = &read_local_xlog_page,
@@ -1401,13 +1396,6 @@ XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
14011396
XLogBeginRead(xlogreader, lsn);
14021397
record = XLogReadRecord(xlogreader, &errormsg);
14031398

1404-
/*
1405-
* Restore immediately the timeline where it was previously, as
1406-
* read_local_xlog_page() could have changed it if the record was read
1407-
* while recovery was finishing or if the timeline has jumped in-between.
1408-
*/
1409-
ThisTimeLineID = save_currtli;
1410-
14111399
if (record == NULL)
14121400
ereport(ERROR,
14131401
(errcode_for_file_access(),

src/backend/access/transam/xlog.c

+55-23
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ CheckpointStatsData CheckpointStats;
192192
* ThisTimeLineID will be same in all backends --- it identifies current
193193
* WAL timeline for the database system.
194194
*/
195-
TimeLineID ThisTimeLineID = 0;
195+
static TimeLineID ThisTimeLineID = 0;
196196

197197
static XLogRecPtr LastRec;
198198

@@ -917,7 +917,8 @@ static void AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic);
917917
static bool XLogCheckpointNeeded(XLogSegNo new_segno);
918918
static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible);
919919
static bool InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
920-
bool find_free, XLogSegNo max_segno);
920+
bool find_free, XLogSegNo max_segno,
921+
TimeLineID tli);
921922
static int XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
922923
XLogSource source, bool notfoundOk);
923924
static int XLogFileReadAnyTLI(XLogSegNo segno, int emode, XLogSource source);
@@ -2518,7 +2519,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
25182519
wal_segment_size);
25192520

25202521
/* create/use new log file */
2521-
openLogFile = XLogFileInit(openLogSegNo);
2522+
openLogFile = XLogFileInit(openLogSegNo, ThisTimeLineID);
25222523
ReserveExternalFD();
25232524
}
25242525

@@ -2633,15 +2634,15 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
26332634
*/
26342635
if (finishing_seg)
26352636
{
2636-
issue_xlog_fsync(openLogFile, openLogSegNo);
2637+
issue_xlog_fsync(openLogFile, openLogSegNo, ThisTimeLineID);
26372638

26382639
/* signal that we need to wakeup walsenders later */
26392640
WalSndWakeupRequest();
26402641

26412642
LogwrtResult.Flush = LogwrtResult.Write; /* end of page */
26422643

26432644
if (XLogArchivingActive())
2644-
XLogArchiveNotifySeg(openLogSegNo);
2645+
XLogArchiveNotifySeg(openLogSegNo, ThisTimeLineID);
26452646

26462647
XLogCtl->lastSegSwitchTime = (pg_time_t) time(NULL);
26472648
XLogCtl->lastSegSwitchLSN = LogwrtResult.Flush;
@@ -2704,7 +2705,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
27042705
ReserveExternalFD();
27052706
}
27062707

2707-
issue_xlog_fsync(openLogFile, openLogSegNo);
2708+
issue_xlog_fsync(openLogFile, openLogSegNo, ThisTimeLineID);
27082709
}
27092710

27102711
/* signal that we need to wakeup walsenders later */
@@ -3296,7 +3297,8 @@ XLogNeedsFlush(XLogRecPtr record)
32963297
* succeed. (This is weird, but it's efficient for the callers.)
32973298
*/
32983299
static int
3299-
XLogFileInitInternal(XLogSegNo logsegno, bool *added, char *path)
3300+
XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli,
3301+
bool *added, char *path)
33003302
{
33013303
char tmppath[MAXPGPATH];
33023304
PGAlignedXLogBlock zbuffer;
@@ -3305,7 +3307,9 @@ XLogFileInitInternal(XLogSegNo logsegno, bool *added, char *path)
33053307
int fd;
33063308
int save_errno;
33073309

3308-
XLogFilePath(path, ThisTimeLineID, logsegno, wal_segment_size);
3310+
Assert(logtli != 0);
3311+
3312+
XLogFilePath(path, logtli, logsegno, wal_segment_size);
33093313

33103314
/*
33113315
* Try to use existent file (checkpoint maker may have created it already)
@@ -3449,7 +3453,8 @@ XLogFileInitInternal(XLogSegNo logsegno, bool *added, char *path)
34493453
* CheckPointSegments.
34503454
*/
34513455
max_segno = logsegno + CheckPointSegments;
3452-
if (InstallXLogFileSegment(&installed_segno, tmppath, true, max_segno))
3456+
if (InstallXLogFileSegment(&installed_segno, tmppath, true, max_segno,
3457+
logtli))
34533458
{
34543459
*added = true;
34553460
elog(DEBUG2, "done creating and filling new WAL file");
@@ -3481,13 +3486,15 @@ XLogFileInitInternal(XLogSegNo logsegno, bool *added, char *path)
34813486
* in a critical section.
34823487
*/
34833488
int
3484-
XLogFileInit(XLogSegNo logsegno)
3489+
XLogFileInit(XLogSegNo logsegno, TimeLineID logtli)
34853490
{
34863491
bool ignore_added;
34873492
char path[MAXPGPATH];
34883493
int fd;
34893494

3490-
fd = XLogFileInitInternal(logsegno, &ignore_added, path);
3495+
Assert(logtli != 0);
3496+
3497+
fd = XLogFileInitInternal(logsegno, logtli, &ignore_added, path);
34913498
if (fd >= 0)
34923499
return fd;
34933500

@@ -3629,7 +3636,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
36293636
/*
36303637
* Now move the segment into place with its final name.
36313638
*/
3632-
if (!InstallXLogFileSegment(&destsegno, tmppath, false, 0))
3639+
if (!InstallXLogFileSegment(&destsegno, tmppath, false, 0, ThisTimeLineID))
36333640
elog(ERROR, "InstallXLogFileSegment should not have failed");
36343641
}
36353642

@@ -3653,18 +3660,22 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
36533660
* free slot is found between *segno and max_segno. (Ignored when find_free
36543661
* is false.)
36553662
*
3663+
* tli: The timeline on which the new segment should be installed.
3664+
*
36563665
* Returns true if the file was installed successfully. false indicates that
36573666
* max_segno limit was exceeded, the startup process has disabled this
36583667
* function for now, or an error occurred while renaming the file into place.
36593668
*/
36603669
static bool
36613670
InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
3662-
bool find_free, XLogSegNo max_segno)
3671+
bool find_free, XLogSegNo max_segno, TimeLineID tli)
36633672
{
36643673
char path[MAXPGPATH];
36653674
struct stat stat_buf;
36663675

3667-
XLogFilePath(path, ThisTimeLineID, *segno, wal_segment_size);
3676+
Assert(tli != 0);
3677+
3678+
XLogFilePath(path, tli, *segno, wal_segment_size);
36683679

36693680
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
36703681
if (!XLogCtl->InstallXLogFileSegmentActive)
@@ -3690,7 +3701,7 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
36903701
return false;
36913702
}
36923703
(*segno)++;
3693-
XLogFilePath(path, ThisTimeLineID, *segno, wal_segment_size);
3704+
XLogFilePath(path, tli, *segno, wal_segment_size);
36943705
}
36953706
}
36963707

@@ -3987,7 +3998,7 @@ PreallocXlogFiles(XLogRecPtr endptr)
39873998
if (offset >= (uint32) (0.75 * wal_segment_size))
39883999
{
39894000
_logSegNo++;
3990-
lf = XLogFileInitInternal(_logSegNo, &added, path);
4001+
lf = XLogFileInitInternal(_logSegNo, ThisTimeLineID, &added, path);
39914002
if (lf >= 0)
39924003
close(lf);
39934004
if (added)
@@ -4266,7 +4277,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
42664277
XLogCtl->InstallXLogFileSegmentActive && /* callee rechecks this */
42674278
lstat(path, &statbuf) == 0 && S_ISREG(statbuf.st_mode) &&
42684279
InstallXLogFileSegment(endlogSegNo, path,
4269-
true, recycleSegNo))
4280+
true, recycleSegNo, ThisTimeLineID))
42704281
{
42714282
ereport(DEBUG2,
42724283
(errmsg_internal("recycled write-ahead log file \"%s\"",
@@ -5401,7 +5412,7 @@ BootStrapXLOG(void)
54015412
record->xl_crc = crc;
54025413

54035414
/* Create first XLOG segment file */
5404-
openLogFile = XLogFileInit(1);
5415+
openLogFile = XLogFileInit(1, ThisTimeLineID);
54055416

54065417
/*
54075418
* We needn't bother with Reserve/ReleaseExternalFD here, since we'll
@@ -5709,7 +5720,7 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
57095720
*/
57105721
int fd;
57115722

5712-
fd = XLogFileInit(startLogSegNo);
5723+
fd = XLogFileInit(startLogSegNo, ThisTimeLineID);
57135724

57145725
if (close(fd) != 0)
57155726
{
@@ -8706,15 +8717,35 @@ GetInsertRecPtr(void)
87068717
* position known to be fsync'd to disk.
87078718
*/
87088719
XLogRecPtr
8709-
GetFlushRecPtr(void)
8720+
GetFlushRecPtr(TimeLineID *insertTLI)
87108721
{
87118722
SpinLockAcquire(&XLogCtl->info_lck);
87128723
LogwrtResult = XLogCtl->LogwrtResult;
87138724
SpinLockRelease(&XLogCtl->info_lck);
87148725

8726+
/*
8727+
* If we're writing and flushing WAL, the time line can't be changing,
8728+
* so no lock is required.
8729+
*/
8730+
if (insertTLI)
8731+
*insertTLI = XLogCtl->ThisTimeLineID;
8732+
87158733
return LogwrtResult.Flush;
87168734
}
87178735

8736+
/*
8737+
* GetWALInsertionTimeLine -- Returns the current timeline of a system that
8738+
* is not in recovery.
8739+
*/
8740+
TimeLineID
8741+
GetWALInsertionTimeLine(void)
8742+
{
8743+
Assert(XLogCtl->SharedRecoveryState == RECOVERY_STATE_DONE);
8744+
8745+
/* Since the value can't be changing, no lock is required. */
8746+
return XLogCtl->ThisTimeLineID;
8747+
}
8748+
87188749
/*
87198750
* GetLastImportantRecPtr -- Returns the LSN of the last important record
87208751
* inserted. All records not explicitly marked as unimportant are considered
@@ -10849,11 +10880,13 @@ assign_xlog_sync_method(int new_sync_method, void *extra)
1084910880
* 'segno' is for error reporting purposes.
1085010881
*/
1085110882
void
10852-
issue_xlog_fsync(int fd, XLogSegNo segno)
10883+
issue_xlog_fsync(int fd, XLogSegNo segno, TimeLineID tli)
1085310884
{
1085410885
char *msg = NULL;
1085510886
instr_time start;
1085610887

10888+
Assert(tli != 0);
10889+
1085710890
/*
1085810891
* Quick exit if fsync is disabled or write() has already synced the WAL
1085910892
* file.
@@ -10902,8 +10935,7 @@ issue_xlog_fsync(int fd, XLogSegNo segno)
1090210935
char xlogfname[MAXFNAMELEN];
1090310936
int save_errno = errno;
1090410937

10905-
XLogFileName(xlogfname, ThisTimeLineID, segno,
10906-
wal_segment_size);
10938+
XLogFileName(xlogfname, tli, segno, wal_segment_size);
1090710939
errno = save_errno;
1090810940
ereport(PANIC,
1090910941
(errcode_for_file_access(),

src/backend/access/transam/xlogarchive.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -498,11 +498,13 @@ XLogArchiveNotify(const char *xlog)
498498
* Convenience routine to notify using segment number representation of filename
499499
*/
500500
void
501-
XLogArchiveNotifySeg(XLogSegNo segno)
501+
XLogArchiveNotifySeg(XLogSegNo segno, TimeLineID tli)
502502
{
503503
char xlog[MAXFNAMELEN];
504504

505-
XLogFileName(xlog, ThisTimeLineID, segno, wal_segment_size);
505+
Assert(tli != 0);
506+
507+
XLogFileName(xlog, tli, segno, wal_segment_size);
506508
XLogArchiveNotify(xlog);
507509
}
508510

src/backend/access/transam/xlogfuncs.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ pg_current_wal_flush_lsn(PG_FUNCTION_ARGS)
382382
errmsg("recovery is in progress"),
383383
errhint("WAL control functions cannot be executed during recovery.")));
384384

385-
current_recptr = GetFlushRecPtr();
385+
current_recptr = GetFlushRecPtr(NULL);
386386

387387
PG_RETURN_LSN(current_recptr);
388388
}
@@ -469,7 +469,8 @@ pg_walfile_name_offset(PG_FUNCTION_ARGS)
469469
* xlogfilename
470470
*/
471471
XLByteToPrevSeg(locationpoint, xlogsegno, wal_segment_size);
472-
XLogFileName(xlogfilename, ThisTimeLineID, xlogsegno, wal_segment_size);
472+
XLogFileName(xlogfilename, GetWALInsertionTimeLine(), xlogsegno,
473+
wal_segment_size);
473474

474475
values[0] = CStringGetTextDatum(xlogfilename);
475476
isnull[0] = false;
@@ -511,7 +512,8 @@ pg_walfile_name(PG_FUNCTION_ARGS)
511512
"pg_walfile_name()")));
512513

513514
XLByteToPrevSeg(locationpoint, xlogsegno, wal_segment_size);
514-
XLogFileName(xlogfilename, ThisTimeLineID, xlogsegno, wal_segment_size);
515+
XLogFileName(xlogfilename, GetWALInsertionTimeLine(), xlogsegno,
516+
wal_segment_size);
515517

516518
PG_RETURN_TEXT_P(cstring_to_text(xlogfilename));
517519
}

0 commit comments

Comments
 (0)