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

Commit d298b50

Browse files
committed
Make pg_basebackup work with pre-9.3 servers, and add server version check.
A new 'starttli' field was added to the response of BASE_BACKUP command. Make pg_basebackup tolerate the case that it's missing, so that it still works with older servers. Add an explicit check for the server version, so that you get a nicer error message if you try to use it with a pre-9.1 server. The streaming protocol message format changed in 9.3, so -X stream still won't work with pre-9.3 servers. I added a version check to ReceiveXLogStream() earlier, but write that slightly differently, so that in 9.4, it will still work with a 9.3 server. (In 9.4, the error message needs to be adjusted to "9.3 or above", though). Also, if the version check fails, don't retry.
1 parent ea988ee commit d298b50

File tree

5 files changed

+93
-14
lines changed

5 files changed

+93
-14
lines changed

doc/src/sgml/ref/pg_basebackup.sgml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,12 @@ PostgreSQL documentation
520520
for all additional tablespaces must be identical whenever a backup is
521521
restored. The main data directory, however, is relocatable to any location.
522522
</para>
523+
524+
<para>
525+
<application>pg_basebackup</application> works with servers of the same
526+
or an older major version, down to 9.1. However, WAL streaming mode (-X
527+
stream) only works with server version 9.3.
528+
</para>
523529
</refsect1>
524530

525531
<refsect1>

src/bin/pg_basebackup/pg_basebackup.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,12 +1223,16 @@ BaseBackup(void)
12231223
{
12241224
PGresult *res;
12251225
char *sysidentifier;
1226+
uint32 latesttli;
12261227
uint32 starttli;
12271228
char current_path[MAXPGPATH];
12281229
char escaped_label[MAXPGPATH];
12291230
int i;
12301231
char xlogstart[64];
12311232
char xlogend[64];
1233+
int minServerMajor,
1234+
maxServerMajor;
1235+
int serverMajor;
12321236

12331237
/*
12341238
* Connect in replication mode to the server
@@ -1238,6 +1242,31 @@ BaseBackup(void)
12381242
/* Error message already written in GetConnection() */
12391243
exit(1);
12401244

1245+
/*
1246+
* Check server version. BASE_BACKUP command was introduced in 9.1, so
1247+
* we can't work with servers older than 9.1.
1248+
*/
1249+
minServerMajor = 901;
1250+
maxServerMajor = PG_VERSION_NUM / 100;
1251+
serverMajor = PQserverVersion(conn) / 100;
1252+
if (serverMajor < minServerMajor || serverMajor > maxServerMajor)
1253+
{
1254+
const char *serverver = PQparameterStatus(conn, "server_version");
1255+
fprintf(stderr, _("%s: incompatible server version %s\n"),
1256+
progname, serverver ? serverver : "'unknown'");
1257+
disconnect_and_exit(1);
1258+
}
1259+
1260+
/*
1261+
* If WAL streaming was requested, also check that the server is new
1262+
* enough for that.
1263+
*/
1264+
if (streamwal && !CheckServerVersionForStreaming(conn))
1265+
{
1266+
/* Error message already written in CheckServerVersionForStreaming() */
1267+
disconnect_and_exit(1);
1268+
}
1269+
12411270
/*
12421271
* Build contents of recovery.conf if requested
12431272
*/
@@ -1262,6 +1291,7 @@ BaseBackup(void)
12621291
disconnect_and_exit(1);
12631292
}
12641293
sysidentifier = pg_strdup(PQgetvalue(res, 0, 0));
1294+
latesttli = atoi(PQgetvalue(res, 0, 1));
12651295
PQclear(res);
12661296

12671297
/*
@@ -1293,7 +1323,7 @@ BaseBackup(void)
12931323
progname, PQerrorMessage(conn));
12941324
disconnect_and_exit(1);
12951325
}
1296-
if (PQntuples(res) != 1 || PQnfields(res) < 2)
1326+
if (PQntuples(res) != 1)
12971327
{
12981328
fprintf(stderr,
12991329
_("%s: server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields\n"),
@@ -1302,8 +1332,14 @@ BaseBackup(void)
13021332
}
13031333

13041334
strcpy(xlogstart, PQgetvalue(res, 0, 0));
1305-
starttli = atoi(PQgetvalue(res, 0, 1));
1306-
1335+
/*
1336+
* 9.3 and later sends the TLI of the starting point. With older servers,
1337+
* assume it's the same as the latest timeline reported by IDENTIFY_SYSTEM.
1338+
*/
1339+
if (PQnfields(res) >= 2)
1340+
starttli = atoi(PQgetvalue(res, 0, 1));
1341+
else
1342+
starttli = latesttli;
13071343
PQclear(res);
13081344
MemSet(xlogend, 0, sizeof(xlogend));
13091345

src/bin/pg_basebackup/pg_receivexlog.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,16 @@ StreamLog(void)
229229
/* Error message already written in GetConnection() */
230230
return;
231231

232+
if (!CheckServerVersionForStreaming(conn))
233+
{
234+
/*
235+
* Error message already written in CheckServerVersionForStreaming().
236+
* There's no hope of recovering from a version mismatch, so don't
237+
* retry.
238+
*/
239+
disconnect_and_exit(1);
240+
}
241+
232242
/*
233243
* Run IDENTIFY_SYSTEM so we can get the timeline and current xlog
234244
* position.

src/bin/pg_basebackup/receivelog.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,40 @@ sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool replyRequested)
436436
return true;
437437
}
438438

439+
/*
440+
* Check that the server version we're connected to is supported by
441+
* ReceiveXlogStream().
442+
*
443+
* If it's not, an error message is printed to stderr, and false is returned.
444+
*/
445+
bool
446+
CheckServerVersionForStreaming(PGconn *conn)
447+
{
448+
int minServerMajor,
449+
maxServerMajor;
450+
int serverMajor;
451+
452+
/*
453+
* The message format used in streaming replication changed in 9.3, so we
454+
* cannot stream from older servers. And we don't support servers newer
455+
* than the client; it might work, but we don't know, so err on the safe
456+
* side.
457+
*/
458+
minServerMajor = 903;
459+
maxServerMajor = PG_VERSION_NUM / 100;
460+
serverMajor = PQserverVersion(conn) / 100;
461+
if (serverMajor < minServerMajor || serverMajor > maxServerMajor)
462+
{
463+
const char *serverver = PQparameterStatus(conn, "server_version");
464+
fprintf(stderr, _("%s: incompatible server version %s; streaming is only supported with server version %s\n"),
465+
progname,
466+
serverver ? serverver : "'unknown'",
467+
"9.3");
468+
return false;
469+
}
470+
return true;
471+
}
472+
439473
/*
440474
* Receive a log stream starting at the specified position.
441475
*
@@ -476,19 +510,11 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
476510
XLogRecPtr stoppos;
477511

478512
/*
479-
* The message format used in streaming replication changed in 9.3, so we
480-
* cannot stream from older servers. Don't know if we would work with
481-
* newer versions, but let's not take the risk.
513+
* The caller should've checked the server version already, but doesn't do
514+
* any harm to check it here too.
482515
*/
483-
if (PQserverVersion(conn) / 100 != PG_VERSION_NUM / 100)
484-
{
485-
const char *serverver = PQparameterStatus(conn, "server_version");
486-
fprintf(stderr, _("%s: incompatible server version %s; streaming is only supported with server version %s\n"),
487-
progname,
488-
serverver ? serverver : "'unknown'",
489-
PG_MAJORVERSION);
516+
if (!CheckServerVersionForStreaming(conn))
490517
return false;
491-
}
492518

493519
if (sysidentifier != NULL)
494520
{

src/bin/pg_basebackup/receivelog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
typedef bool (*stream_stop_callback) (XLogRecPtr segendpos, uint32 timeline, bool segment_finished);
88

9+
extern bool CheckServerVersionForStreaming(PGconn *conn);
910
extern bool ReceiveXlogStream(PGconn *conn,
1011
XLogRecPtr startpos,
1112
uint32 timeline,

0 commit comments

Comments
 (0)