Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit32f4de0

Browse files
committed
Write exact xlog position of timeline switch in the timeline history file.
This allows us to do some more rigorous sanity checking for variousincorrect point-in-time recovery scenarios, and provides more informationfor debugging purposes. It will also come handy in the upcoming patch toallow timeline switches to be replicated by streaming replication.
1 parenta84c30d commit32f4de0

File tree

3 files changed

+247
-90
lines changed

3 files changed

+247
-90
lines changed

‎src/backend/access/transam/timeline.c

Lines changed: 120 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
*
1313
* Each line in the file represents a timeline switch:
1414
*
15-
* <parentTLI> <xlogfname> <reason>
15+
* <parentTLI> <switchpoint> <reason>
1616
*
1717
*parentTLIID of the parent timeline
18-
*xlogfnamefilename of the WALsegment where the switch happened
18+
*switchpointXLogRecPtr of the WALposition where the switch happened
1919
*reasonhuman-readable explanation of why the timeline was changed
2020
*
2121
* The fields are separated by tabs. Lines beginning with # are comments, and
@@ -56,10 +56,18 @@ readTimeLineHistory(TimeLineID targetTLI)
5656
charhistfname[MAXFNAMELEN];
5757
charfline[MAXPGPATH];
5858
FILE*fd;
59+
TimeLineHistoryEntry*entry;
60+
TimeLineIDlasttli=0;
61+
XLogRecPtrprevend;
5962

6063
/* Timeline 1 does not have a history file, so no need to check */
6164
if (targetTLI==1)
62-
returnlist_make1_int((int)targetTLI);
65+
{
66+
entry= (TimeLineHistoryEntry*)palloc(sizeof(TimeLineHistoryEntry));
67+
entry->tli=targetTLI;
68+
entry->begin=entry->end=InvalidXLogRecPtr;
69+
returnlist_make1(entry);
70+
}
6371

6472
if (InArchiveRecovery)
6573
{
@@ -77,20 +85,26 @@ readTimeLineHistory(TimeLineID targetTLI)
7785
(errcode_for_file_access(),
7886
errmsg("could not open file \"%s\": %m",path)));
7987
/* Not there, so assume no parents */
80-
returnlist_make1_int((int)targetTLI);
88+
entry= (TimeLineHistoryEntry*)palloc(sizeof(TimeLineHistoryEntry));
89+
entry->tli=targetTLI;
90+
entry->begin=entry->end=InvalidXLogRecPtr;
91+
returnlist_make1(entry);
8192
}
8293

8394
result=NIL;
8495

8596
/*
8697
* Parse the file...
8798
*/
99+
prevend=InvalidXLogRecPtr;
88100
while (fgets(fline,sizeof(fline),fd)!=NULL)
89101
{
90102
/* skip leading whitespace and check for # comment */
91103
char*ptr;
92-
char*endptr;
93104
TimeLineIDtli;
105+
uint32switchpoint_hi;
106+
uint32switchpoint_lo;
107+
intnfields;
94108

95109
for (ptr=fline;*ptr;ptr++)
96110
{
@@ -100,38 +114,56 @@ readTimeLineHistory(TimeLineID targetTLI)
100114
if (*ptr=='\0'||*ptr=='#')
101115
continue;
102116

103-
/* expect a numeric timeline ID as first field of line */
104-
tli= (TimeLineID)strtoul(ptr,&endptr,0);
105-
if (endptr==ptr)
117+
nfields=sscanf(fline,"%u\t%X/%X",&tli,&switchpoint_hi,&switchpoint_lo);
118+
119+
if (nfields<1)
120+
{
121+
/* expect a numeric timeline ID as first field of line */
106122
ereport(FATAL,
107123
(errmsg("syntax error in history file: %s",fline),
108124
errhint("Expected a numeric timeline ID.")));
125+
}
126+
if (nfields!=3)
127+
ereport(FATAL,
128+
(errmsg("syntax error in history file: %s",fline),
129+
errhint("Expected an XLOG switchpoint location.")));
109130

110-
if (result&&
111-
tli <= (TimeLineID)linitial_int(result))
131+
if (result&&tli <=lasttli)
112132
ereport(FATAL,
113133
(errmsg("invalid data in history file: %s",fline),
114134
errhint("Timeline IDs must be in increasing sequence.")));
115135

136+
lasttli=tli;
137+
138+
entry= (TimeLineHistoryEntry*)palloc(sizeof(TimeLineHistoryEntry));
139+
entry->tli=tli;
140+
entry->begin=prevend;
141+
entry->end= ((uint64) (switchpoint_hi)) <<32 | (uint64)switchpoint_lo;
142+
prevend=entry->end;
143+
116144
/* Build list with newest item first */
117-
result=lcons_int((int)tli,result);
145+
result=lcons(entry,result);
118146

119147
/* we ignore the remainder of each line */
120148
}
121149

122150
FreeFile(fd);
123151

124-
if (result&&
125-
targetTLI <= (TimeLineID)linitial_int(result))
152+
if (result&&targetTLI <=lasttli)
126153
ereport(FATAL,
127154
(errmsg("invalid data in history file \"%s\"",path),
128155
errhint("Timeline IDs must be less than child timeline's ID.")));
129156

130-
result=lcons_int((int)targetTLI,result);
157+
/*
158+
* Create one more entry for the "tip" of the timeline, which has no
159+
* entry in the history file.
160+
*/
161+
entry= (TimeLineHistoryEntry*)palloc(sizeof(TimeLineHistoryEntry));
162+
entry->tli=targetTLI;
163+
entry->begin=prevend;
164+
entry->end=InvalidXLogRecPtr;
131165

132-
ereport(DEBUG3,
133-
(errmsg_internal("history of timeline %u is %s",
134-
targetTLI,nodeToString(result))));
166+
result=lcons(entry,result);
135167

136168
returnresult;
137169
}
@@ -214,7 +246,7 @@ findNewestTimeLine(TimeLineID startTLI)
214246
*
215247
*newTLI: ID of the new timeline
216248
*parentTLI: ID of its immediate parent
217-
*endTLI et al: ID ofthelast used WAL file, for annotation purposes
249+
*switchpoint: XLOG position wherethesystem switched to the new timeline
218250
*reason: human-readable explanation of why the timeline was switched
219251
*
220252
* Currently this is only used at the end recovery, and so there are no locking
@@ -223,12 +255,11 @@ findNewestTimeLine(TimeLineID startTLI)
223255
*/
224256
void
225257
writeTimeLineHistory(TimeLineIDnewTLI,TimeLineIDparentTLI,
226-
TimeLineIDendTLI,XLogSegNoendLogSegNo,char*reason)
258+
XLogRecPtrswitchpoint,char*reason)
227259
{
228260
charpath[MAXPGPATH];
229261
chartmppath[MAXPGPATH];
230262
charhistfname[MAXFNAMELEN];
231-
charxlogfname[MAXFNAMELEN];
232263
charbuffer[BLCKSZ];
233264
intsrcfd;
234265
intfd;
@@ -313,13 +344,11 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
313344
* If we did have a parent file, insert an extra newline just in case the
314345
* parent file failed to end with one.
315346
*/
316-
XLogFileName(xlogfname,endTLI,endLogSegNo);
317-
318347
snprintf(buffer,sizeof(buffer),
319-
"%s%u\t%s\t%s\n",
348+
"%s%u\t%X/%X\t%s\n",
320349
(srcfd<0) ?"" :"\n",
321350
parentTLI,
322-
xlogfname,
351+
(uint32) (switchpoint >>32), (uint32) (switchpoint),
323352
reason);
324353

325354
nbytes=strlen(buffer);
@@ -380,3 +409,70 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
380409
TLHistoryFileName(histfname,newTLI);
381410
XLogArchiveNotify(histfname);
382411
}
412+
413+
/*
414+
* Returns true if 'expectedTLEs' contains a timeline with id 'tli'
415+
*/
416+
bool
417+
tliInHistory(TimeLineIDtli,List*expectedTLEs)
418+
{
419+
ListCell*cell;
420+
421+
foreach(cell,expectedTLEs)
422+
{
423+
if (((TimeLineHistoryEntry*)lfirst(cell))->tli==tli)
424+
return true;
425+
}
426+
427+
return false;
428+
}
429+
430+
/*
431+
* Returns the ID of the timeline in use at a particular point in time, in
432+
* the given timeline history.
433+
*/
434+
TimeLineID
435+
tliOfPointInHistory(XLogRecPtrptr,List*history)
436+
{
437+
ListCell*cell;
438+
439+
foreach(cell,history)
440+
{
441+
TimeLineHistoryEntry*tle= (TimeLineHistoryEntry*)lfirst(cell);
442+
if ((XLogRecPtrIsInvalid(tle->begin)||XLByteLE(tle->begin,ptr))&&
443+
(XLogRecPtrIsInvalid(tle->end)||XLByteLT(ptr,tle->end)))
444+
{
445+
/* found it */
446+
returntle->tli;
447+
}
448+
}
449+
450+
/* shouldn't happen. */
451+
elog(ERROR,"timeline history was not contiguous");
452+
return0;/* keep compiler quiet */
453+
}
454+
455+
/*
456+
* Returns the point in history where we branched off the given timeline.
457+
* Returns InvalidXLogRecPtr if the timeline is current (= we have not
458+
* branched off from it), and throws an error if the timeline is not part of
459+
* this server's history.
460+
*/
461+
XLogRecPtr
462+
tliSwitchPoint(TimeLineIDtli,List*history)
463+
{
464+
ListCell*cell;
465+
466+
foreach (cell,history)
467+
{
468+
TimeLineHistoryEntry*tle= (TimeLineHistoryEntry*)lfirst(cell);
469+
470+
if (tle->tli==tli)
471+
returntle->end;
472+
}
473+
474+
ereport(ERROR,
475+
(errmsg("requested timeline %u is not in this server's history",
476+
tli)));
477+
returnInvalidXLogRecPtr;/* keep compiler quiet */
478+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp