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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy