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

Commit 31d9658

Browse files
committed
Fix base backup streaming xlog from standby
When backing up from a standby server, the backup process will not automatically switch xlog segment. So we must accept a partially transferred xlog file in this case, but rename it into position anyway. In passing, merge the two callbacks for segment end and stop stream into a single callback, since their implementations were close to identical, and rename this callback to reflect that it stops streaming rather than continues it. Patch by Magnus Hagander, review by Fujii Masao
1 parent d226e23 commit 31d9658

File tree

4 files changed

+34
-45
lines changed

4 files changed

+34
-45
lines changed

src/bin/pg_basebackup/pg_basebackup.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static void ReceiveTarFile(PGconn *conn, PGresult *res, int rownum);
7878
static void ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum);
7979
static void BaseBackup(void);
8080

81-
static bool segment_callback(XLogRecPtr segendpos, uint32 timeline);
81+
static bool reached_end_position(XLogRecPtr segendpos, uint32 timeline, bool segment_finished);
8282

8383
#ifdef HAVE_LIBZ
8484
static const char *
@@ -129,16 +129,15 @@ usage(void)
129129

130130

131131
/*
132-
* Called in the background process whenever a complete segment of WAL
133-
* has been received.
132+
* Called in the background process every time data is received.
134133
* On Unix, we check to see if there is any data on our pipe
135134
* (which would mean we have a stop position), and if it is, check if
136135
* it is time to stop.
137136
* On Windows, we are in a single process, so we can just check if it's
138137
* time to stop.
139138
*/
140139
static bool
141-
segment_callback(XLogRecPtr segendpos, uint32 timeline)
140+
reached_end_position(XLogRecPtr segendpos, uint32 timeline, bool segment_finished)
142141
{
143142
if (!has_xlogendptr)
144143
{
@@ -231,7 +230,7 @@ LogStreamerMain(logstreamer_param * param)
231230
{
232231
if (!ReceiveXlogStream(param->bgconn, param->startptr, param->timeline,
233232
param->sysidentifier, param->xlogdir,
234-
segment_callback, NULL, standby_message_timeout))
233+
reached_end_position, standby_message_timeout, true))
235234

236235
/*
237236
* Any errors will already have been reported in the function process,

src/bin/pg_basebackup/pg_receivexlog.c

+5-14
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ volatile bool time_to_abort = false;
4343
static void usage(void);
4444
static XLogRecPtr FindStreamingStart(XLogRecPtr currentpos, uint32 currenttimeline);
4545
static void StreamLog();
46-
static bool segment_callback(XLogRecPtr segendpos, uint32 timeline);
46+
static bool stop_streaming(XLogRecPtr segendpos, uint32 timeline, bool segment_finished);
4747

4848
static void
4949
usage(void)
@@ -69,21 +69,12 @@ usage(void)
6969
}
7070

7171
static bool
72-
segment_callback(XLogRecPtr segendpos, uint32 timeline)
72+
stop_streaming(XLogRecPtr segendpos, uint32 timeline, bool segment_finished)
7373
{
74-
if (verbose)
74+
if (verbose && segment_finished)
7575
fprintf(stderr, _("%s: finished segment at %X/%X (timeline %u)\n"),
7676
progname, segendpos.xlogid, segendpos.xrecoff, timeline);
7777

78-
/*
79-
* Never abort from this - we handle all aborting in continue_streaming()
80-
*/
81-
return false;
82-
}
83-
84-
static bool
85-
continue_streaming(void)
86-
{
8778
if (time_to_abort)
8879
{
8980
fprintf(stderr, _("%s: received interrupt signal, exiting.\n"),
@@ -268,8 +259,8 @@ StreamLog(void)
268259
progname, startpos.xlogid, startpos.xrecoff, timeline);
269260

270261
ReceiveXlogStream(conn, startpos, timeline, NULL, basedir,
271-
segment_callback, continue_streaming,
272-
standby_message_timeout);
262+
stop_streaming,
263+
standby_message_timeout, false);
273264

274265
PQfinish(conn);
275266
}

src/bin/pg_basebackup/receivelog.c

+19-14
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,14 @@ open_walfile(XLogRecPtr startpoint, uint32 timeline, char *basedir, char *namebu
113113
return f;
114114
}
115115

116+
/*
117+
* Close the current WAL file, and rename it to the correct filename if it's complete.
118+
*
119+
* If segment_complete is true, rename the current WAL file even if we've not
120+
* completed writing the whole segment.
121+
*/
116122
static bool
117-
close_walfile(int walfile, char *basedir, char *walname)
123+
close_walfile(int walfile, char *basedir, char *walname, bool segment_complete)
118124
{
119125
off_t currpos = lseek(walfile, 0, SEEK_CUR);
120126

@@ -141,9 +147,9 @@ close_walfile(int walfile, char *basedir, char *walname)
141147

142148
/*
143149
* Rename the .partial file only if we've completed writing the
144-
* whole segment.
150+
* whole segment or segment_complete is true.
145151
*/
146-
if (currpos == XLOG_SEG_SIZE)
152+
if (currpos == XLOG_SEG_SIZE || segment_complete)
147153
{
148154
char oldfn[MAXPGPATH];
149155
char newfn[MAXPGPATH];
@@ -199,11 +205,10 @@ localGetCurrentTimestamp(void)
199205
* All received segments will be written to the directory
200206
* specified by basedir.
201207
*
202-
* The segment_finish callback will be called after each segment
203-
* has been finished, and the stream_continue callback will be
204-
* called every time data is received. If either of these callbacks
205-
* return true, the streaming will stop and the function
206-
* return. As long as they return false, streaming will continue
208+
* The stream_stop callback will be called every time data
209+
* is received, and whenever a segment is completed. If it returns
210+
* true, the streaming will stop and the function
211+
* return. As long as it returns false, streaming will continue
207212
* indefinitely.
208213
*
209214
* standby_message_timeout controls how often we send a message
@@ -214,7 +219,7 @@ localGetCurrentTimestamp(void)
214219
* Note: The log position *must* be at a log segment start!
215220
*/
216221
bool
217-
ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysidentifier, char *basedir, segment_finish_callback segment_finish, stream_continue_callback stream_continue, int standby_message_timeout)
222+
ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysidentifier, char *basedir, stream_stop_callback stream_stop, int standby_message_timeout, bool rename_partial)
218223
{
219224
char query[128];
220225
char current_walfile_name[MAXPGPATH];
@@ -288,11 +293,11 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
288293
/*
289294
* Check if we should continue streaming, or abort at this point.
290295
*/
291-
if (stream_continue && stream_continue())
296+
if (stream_stop && stream_stop(blockpos, timeline, false))
292297
{
293298
if (walfile != -1)
294299
/* Potential error message is written by close_walfile */
295-
return close_walfile(walfile, basedir, current_walfile_name);
300+
return close_walfile(walfile, basedir, current_walfile_name, rename_partial);
296301
return true;
297302
}
298303

@@ -486,20 +491,20 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
486491
/* Did we reach the end of a WAL segment? */
487492
if (blockpos.xrecoff % XLOG_SEG_SIZE == 0)
488493
{
489-
if (!close_walfile(walfile, basedir, current_walfile_name))
494+
if (!close_walfile(walfile, basedir, current_walfile_name, false))
490495
/* Error message written in close_walfile() */
491496
return false;
492497

493498
walfile = -1;
494499
xlogoff = 0;
495500

496-
if (segment_finish != NULL)
501+
if (stream_stop != NULL)
497502
{
498503
/*
499504
* Callback when the segment finished, and return if it
500505
* told us to.
501506
*/
502-
if (segment_finish(blockpos, timeline))
507+
if (stream_stop(blockpos, timeline, true))
503508
return true;
504509
}
505510
}

src/bin/pg_basebackup/receivelog.h

+6-12
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
#include "access/xlogdefs.h"
22

33
/*
4-
* Called whenever a segment is finished, return true to stop
5-
* the streaming at this point.
4+
* Called before trying to read more data or when a segment is
5+
* finished. Return true to stop streaming.
66
*/
7-
typedef bool (*segment_finish_callback)(XLogRecPtr segendpos, uint32 timeline);
8-
9-
/*
10-
* Called before trying to read more data. Return true to stop
11-
* the streaming at this point.
12-
*/
13-
typedef bool (*stream_continue_callback)(void);
7+
typedef bool (*stream_stop_callback)(XLogRecPtr segendpos, uint32 timeline, bool segment_finished);
148

159
extern bool ReceiveXlogStream(PGconn *conn,
1610
XLogRecPtr startpos,
1711
uint32 timeline,
1812
char *sysidentifier,
1913
char *basedir,
20-
segment_finish_callback segment_finish,
21-
stream_continue_callback stream_continue,
22-
int standby_message_timeout);
14+
stream_stop_callback stream_stop,
15+
int standby_message_timeout,
16+
bool rename_partial);

0 commit comments

Comments
 (0)