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

Commitb882246

Browse files
committed
Fix two timeline handling bugs in pg_receivexlog.
When a timeline history file is fetched from server, it is initially createdwith a temporary file name, and renamed to place. However, the temporaryfile name was constructed using an uninitialized buffer. Usually that meantthat the file was created in current directory instead of the target, whichusually goes unnoticed, but if the target is on a different filesystem thanthe current dir, the rename() would fail. Fix that.The second issue is that pg_receivexlog would not take .partial files intoaccount when determining when scanning the target directory for existingWAL files. If the timeline has switched in the server several times in thelast WAL segment, and pg_receivexlog is restarted, it would choose a tooold starting point. That's not a problem as long as the old WAL segmentexists in the server and can be streamed over, but will cause a failure ifit's not.Backpatch to 9.3, where this timeline handling code was written.Analysed by Andrew Gierth, bug #8453, based on a bug report on IRC.
1 parent496439d commitb882246

File tree

2 files changed

+52
-29
lines changed

2 files changed

+52
-29
lines changed

‎src/bin/pg_basebackup/pg_receivexlog.c

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ FindStreamingStart(uint32 *tli)
121121
structdirent*dirent;
122122
XLogSegNohigh_segno=0;
123123
uint32high_tli=0;
124+
boolhigh_ispartial= false;
124125

125126
dir=opendir(basedir);
126127
if (dir==NULL)
@@ -132,20 +133,32 @@ FindStreamingStart(uint32 *tli)
132133

133134
while ((dirent=readdir(dir))!=NULL)
134135
{
135-
charfullpath[MAXPGPATH];
136-
structstatstatbuf;
137136
uint32tli;
138137
unsignedintlog,
139138
seg;
140139
XLogSegNosegno;
140+
boolispartial;
141141

142142
/*
143143
* Check if the filename looks like an xlog file, or a .partial file.
144144
* Xlog files are always 24 characters, and .partial files are 32
145145
* characters.
146146
*/
147-
if (strlen(dirent->d_name)!=24||
148-
strspn(dirent->d_name,"0123456789ABCDEF")!=24)
147+
if (strlen(dirent->d_name)==24)
148+
{
149+
if (strspn(dirent->d_name,"0123456789ABCDEF")!=24)
150+
continue;
151+
ispartial= false;
152+
}
153+
elseif (strlen(dirent->d_name)==32)
154+
{
155+
if (strspn(dirent->d_name,"0123456789ABCDEF")!=24)
156+
continue;
157+
if (strcmp(&dirent->d_name[24],".partial")!=0)
158+
continue;
159+
ispartial= true;
160+
}
161+
else
149162
continue;
150163

151164
/*
@@ -160,31 +173,40 @@ FindStreamingStart(uint32 *tli)
160173
}
161174
segno= ((uint64)log) <<32 |seg;
162175

163-
/* Check if this is a completed segment or not */
164-
snprintf(fullpath,sizeof(fullpath),"%s/%s",basedir,dirent->d_name);
165-
if (stat(fullpath,&statbuf)!=0)
176+
/*
177+
* Check that the segment has the right size, if it's supposed to be
178+
* completed.
179+
*/
180+
if (!ispartial)
166181
{
167-
fprintf(stderr,_("%s: could not stat file \"%s\": %s\n"),
168-
progname,fullpath,strerror(errno));
169-
disconnect_and_exit(1);
170-
}
182+
structstatstatbuf;
183+
charfullpath[MAXPGPATH];
171184

172-
if (statbuf.st_size==XLOG_SEG_SIZE)
173-
{
174-
/* Completed segment */
175-
if (segno>high_segno|| (segno==high_segno&&tli>high_tli))
185+
snprintf(fullpath,sizeof(fullpath),"%s/%s",basedir,dirent->d_name);
186+
if (stat(fullpath,&statbuf)!=0)
187+
{
188+
fprintf(stderr,_("%s: could not stat file \"%s\": %s\n"),
189+
progname,fullpath,strerror(errno));
190+
disconnect_and_exit(1);
191+
}
192+
193+
if (statbuf.st_size!=XLOG_SEG_SIZE)
176194
{
177-
high_segno=segno;
178-
high_tli=tli;
195+
fprintf(stderr,
196+
_("%s: segment file \"%s\" has incorrect size %d, skipping\n"),
197+
progname,dirent->d_name, (int)statbuf.st_size);
179198
continue;
180199
}
181200
}
182-
else
201+
202+
/* Looks like a valid segment. Remember that we saw it. */
203+
if ((segno>high_segno)||
204+
(segno==high_segno&&tli>high_tli)||
205+
(segno==high_segno&&tli==high_tli&&high_ispartial&& !ispartial))
183206
{
184-
fprintf(stderr,
185-
_("%s: segment file \"%s\" has incorrect size %d, skipping\n"),
186-
progname,dirent->d_name, (int)statbuf.st_size);
187-
continue;
207+
high_segno=segno;
208+
high_tli=tli;
209+
high_ispartial=ispartial;
188210
}
189211
}
190212

@@ -195,10 +217,12 @@ FindStreamingStart(uint32 *tli)
195217
XLogRecPtrhigh_ptr;
196218

197219
/*
198-
* Move the starting pointer to the start of the next segment, since
199-
* the highest one we've seen was completed.
220+
* Move the starting pointer to the start of the next segment, if
221+
* the highest one we saw was completed. Otherwise start streaming
222+
* from the beginning of the .partial segment.
200223
*/
201-
high_segno++;
224+
if (!high_ispartial)
225+
high_segno++;
202226

203227
XLogSegNoOffsetToRecPtr(high_segno,0,high_ptr);
204228

‎src/bin/pg_basebackup/receivelog.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,7 @@ close_walfile(char *basedir, char *partial_suffix)
166166
walfile=-1;
167167

168168
/*
169-
* Rename the .partial file only if we've completed writing the whole
170-
* segment or segment_complete is true.
169+
* If we finished writing a .partial file, rename it into place.
171170
*/
172171
if (currpos==XLOG_SEG_SIZE&&partial_suffix)
173172
{
@@ -306,6 +305,8 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
306305
return false;
307306
}
308307

308+
snprintf(path,sizeof(path),"%s/%s",basedir,histfname);
309+
309310
/*
310311
* Write into a temp file name.
311312
*/
@@ -356,8 +357,6 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
356357
/*
357358
* Now move the completed history file into place with its final name.
358359
*/
359-
360-
snprintf(path,sizeof(path),"%s/%s",basedir,histfname);
361360
if (rename(tmppath,path)<0)
362361
{
363362
fprintf(stderr,_("%s: could not rename file \"%s\" to \"%s\": %s\n"),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp