Skip to content

Commit 76129e7

Browse files
committed
Include more status information in walsender results
Add the current xlog insert location to the response of IDENTIFY_SYSTEM, and adds result sets containing start and stop location of backups to BASE_BACKUP responses.
1 parent f001cb3 commit 76129e7

File tree

4 files changed

+167
-13
lines changed

4 files changed

+167
-13
lines changed

doc/src/sgml/protocol.sgml

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,7 @@ The commands accepted in walsender mode are:
13151315
<listitem>
13161316
<para>
13171317
Requests the server to identify itself. Server replies with a result
1318-
set of a single row, containing two fields:
1318+
set of a single row, containing three fields:
13191319
</para>
13201320

13211321
<para>
@@ -1344,6 +1344,19 @@ The commands accepted in walsender mode are:
13441344
</para>
13451345
</listitem>
13461346
</varlistentry>
1347+
1348+
<varlistentry>
1349+
<term>
1350+
xlogpos
1351+
</term>
1352+
<listitem>
1353+
<para>
1354+
Current xlog write location. Useful to get a known location in the
1355+
transaction log where streaming can start.
1356+
</para>
1357+
</listitem>
1358+
</varlistentry>
1359+
13471360
</variablelist>
13481361
</para>
13491362
</listitem>
@@ -1520,15 +1533,16 @@ The commands accepted in walsender mode are:
15201533
</variablelist>
15211534
</para>
15221535
<para>
1523-
When the backup is started, the server will first send a header in
1524-
ordinary result set format, followed by one or more CopyResponse
1525-
results, one for PGDATA and one for each additional tablespace other
1526-
than <literal>pg_default</> and <literal>pg_global</>. The data in
1527-
the CopyResponse results will be a tar format (using ustar00
1528-
extensions) dump of the tablespace contents.
1536+
When the backup is started, the server will first send two
1537+
ordinary result sets, followed by one or more CopyResponse
1538+
results.
1539+
</para>
1540+
<para>
1541+
The first ordinary result set contains the starting position of the
1542+
backup, given in XLogRecPtr format as a single column in a single row.
15291543
</para>
15301544
<para>
1531-
The header is an ordinary resultset with one row for each tablespace.
1545+
The second ordinary result set has one row for each tablespace.
15321546
The fields in this row are:
15331547
<variablelist>
15341548
<varlistentry>
@@ -1560,6 +1574,15 @@ The commands accepted in walsender mode are:
15601574
</varlistentry>
15611575
</variablelist>
15621576
</para>
1577+
<para>
1578+
After the second regular result set, one or more CopyResponse results
1579+
will be sent, one for PGDATA and one for each additional tablespace other
1580+
than <literal>pg_default</> and <literal>pg_global</>. The data in
1581+
the CopyResponse results will be a tar format (using ustar00
1582+
extensions) dump of the tablespace contents. After the tar data is
1583+
complete, a final ordinary result set will be sent.
1584+
</para>
1585+
15631586
<para>
15641587
The tar archive for the data directory and each tablespace will contain
15651588
all files in the directories, regardless of whether they are
@@ -1583,6 +1606,11 @@ The commands accepted in walsender mode are:
15831606
Owner, group and file mode are set if the underlying filesystem on
15841607
the server supports it.
15851608
</para>
1609+
<para>
1610+
Once all tablespaces have been sent, a final regular result set will
1611+
be sent. This result set contains the end position of the
1612+
backup, given in XLogRecPtr format as a single column in a single row.
1613+
</para>
15861614
</listitem>
15871615
</varlistentry>
15881616
</variablelist>

src/backend/replication/basebackup.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static void SendBackupHeader(List *tablespaces);
5252
static void base_backup_cleanup(int code, Datum arg);
5353
static void perform_base_backup(basebackup_options *opt, DIR *tblspcdir);
5454
static void parse_basebackup_options(List *options, basebackup_options *opt);
55+
static void SendXlogRecPtrResult(XLogRecPtr ptr);
5556

5657
/*
5758
* Size of each block sent into the tar stream for larger files.
@@ -92,6 +93,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
9293
char *labelfile;
9394

9495
startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &labelfile);
96+
SendXlogRecPtrResult(startptr);
9597

9698
PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
9799
{
@@ -239,6 +241,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
239241
/* Send CopyDone message for the last tar file */
240242
pq_putemptymessage('c');
241243
}
244+
SendXlogRecPtrResult(endptr);
242245
}
243246

244247
/*
@@ -431,6 +434,42 @@ SendBackupHeader(List *tablespaces)
431434
pq_puttextmessage('C', "SELECT");
432435
}
433436

437+
/*
438+
* Send a single resultset containing just a single
439+
* XlogRecPtr record (in text format)
440+
*/
441+
static void
442+
SendXlogRecPtrResult(XLogRecPtr ptr)
443+
{
444+
StringInfoData buf;
445+
char str[MAXFNAMELEN];
446+
447+
snprintf(str, sizeof(str), "%X/%X", ptr.xlogid, ptr.xrecoff);
448+
449+
pq_beginmessage(&buf, 'T'); /* RowDescription */
450+
pq_sendint(&buf, 1, 2); /* 1 field */
451+
452+
/* Field header */
453+
pq_sendstring(&buf, "recptr");
454+
pq_sendint(&buf, 0, 4); /* table oid */
455+
pq_sendint(&buf, 0, 2); /* attnum */
456+
pq_sendint(&buf, TEXTOID, 4); /* type oid */
457+
pq_sendint(&buf, -1, 2);
458+
pq_sendint(&buf, 0, 4);
459+
pq_sendint(&buf, 0, 2);
460+
pq_endmessage(&buf);
461+
462+
/* Data row */
463+
pq_beginmessage(&buf, 'D');
464+
pq_sendint(&buf, 1, 2); /* number of columns */
465+
pq_sendint(&buf, strlen(str), 4); /* length */
466+
pq_sendbytes(&buf, str, strlen(str));
467+
pq_endmessage(&buf);
468+
469+
/* Send a CommandComplete message */
470+
pq_puttextmessage('C', "SELECT");
471+
}
472+
434473
/*
435474
* Inject a file with given name and content in the output tar stream.
436475
*/

src/backend/replication/walsender.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,19 +258,26 @@ IdentifySystem(void)
258258
StringInfoData buf;
259259
char sysid[32];
260260
char tli[11];
261+
char xpos[MAXFNAMELEN];
262+
XLogRecPtr logptr;
261263

262264
/*
263-
* Reply with a result set with one row, two columns. First col is system
264-
* ID, and second is timeline ID
265+
* Reply with a result set with one row, three columns. First col is system
266+
* ID, second is timeline ID, and third is current xlog location.
265267
*/
266268

267269
snprintf(sysid, sizeof(sysid), UINT64_FORMAT,
268270
GetSystemIdentifier());
269271
snprintf(tli, sizeof(tli), "%u", ThisTimeLineID);
270272

273+
logptr = GetInsertRecPtr();
274+
275+
snprintf(xpos, sizeof(xpos), "%X/%X",
276+
logptr.xlogid, logptr.xrecoff);
277+
271278
/* Send a RowDescription message */
272279
pq_beginmessage(&buf, 'T');
273-
pq_sendint(&buf, 2, 2); /* 2 fields */
280+
pq_sendint(&buf, 3, 2); /* 3 fields */
274281

275282
/* first field */
276283
pq_sendstring(&buf, "systemid"); /* col name */
@@ -289,15 +296,27 @@ IdentifySystem(void)
289296
pq_sendint(&buf, 4, 2); /* typlen */
290297
pq_sendint(&buf, 0, 4); /* typmod */
291298
pq_sendint(&buf, 0, 2); /* format code */
299+
300+
/* third field */
301+
pq_sendstring(&buf, "xlogpos");
302+
pq_sendint(&buf, 0, 4);
303+
pq_sendint(&buf, 0, 2);
304+
pq_sendint(&buf, TEXTOID, 4);
305+
pq_sendint(&buf, -1, 2);
306+
pq_sendint(&buf, 0, 4);
307+
pq_sendint(&buf, 0, 2);
292308
pq_endmessage(&buf);
293309

294310
/* Send a DataRow message */
295311
pq_beginmessage(&buf, 'D');
296-
pq_sendint(&buf, 2, 2); /* # of columns */
312+
pq_sendint(&buf, 3, 2); /* # of columns */
297313
pq_sendint(&buf, strlen(sysid), 4); /* col1 len */
298314
pq_sendbytes(&buf, (char *) &sysid, strlen(sysid));
299315
pq_sendint(&buf, strlen(tli), 4); /* col2 len */
300316
pq_sendbytes(&buf, (char *) tli, strlen(tli));
317+
pq_sendint(&buf, strlen(xpos), 4); /* col3 len */
318+
pq_sendbytes(&buf, (char *) xpos, strlen(xpos));
319+
301320
pq_endmessage(&buf);
302321

303322
/* Send CommandComplete and ReadyForQuery messages */

src/bin/pg_basebackup/pg_basebackup.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,15 +742,40 @@ static void
742742
BaseBackup()
743743
{
744744
PGresult *res;
745+
uint32 timeline;
745746
char current_path[MAXPGPATH];
746747
char escaped_label[MAXPGPATH];
747748
int i;
749+
char xlogstart[64];
750+
char xlogend[64];
748751

749752
/*
750753
* Connect in replication mode to the server
751754
*/
752755
conn = GetConnection();
753756

757+
/*
758+
* Run IDENFITY_SYSTEM so we can get the timeline
759+
*/
760+
res = PQexec(conn, "IDENTIFY_SYSTEM");
761+
if (PQresultStatus(res) != PGRES_TUPLES_OK)
762+
{
763+
fprintf(stderr, _("%s: could not identify system: %s\n"),
764+
progname, PQerrorMessage(conn));
765+
disconnect_and_exit(1);
766+
}
767+
if (PQntuples(res) != 1)
768+
{
769+
fprintf(stderr, _("%s: could not identify system, got %i rows\n"),
770+
progname, PQntuples(res));
771+
disconnect_and_exit(1);
772+
}
773+
timeline = atoi(PQgetvalue(res, 0, 1));
774+
PQclear(res);
775+
776+
/*
777+
* Start the actual backup
778+
*/
754779
PQescapeStringConn(conn, escaped_label, label, sizeof(escaped_label), &i);
755780
snprintf(current_path, sizeof(current_path), "BASE_BACKUP LABEL '%s' %s %s %s",
756781
escaped_label,
@@ -766,7 +791,7 @@ BaseBackup()
766791
}
767792

768793
/*
769-
* Get the header
794+
* Get the starting xlog position
770795
*/
771796
res = PQgetResult(conn);
772797
if (PQresultStatus(res) != PGRES_TUPLES_OK)
@@ -775,6 +800,28 @@ BaseBackup()
775800
progname, PQerrorMessage(conn));
776801
disconnect_and_exit(1);
777802
}
803+
if (PQntuples(res) != 1)
804+
{
805+
fprintf(stderr, _("%s: no start point returned from server.\n"),
806+
progname);
807+
disconnect_and_exit(1);
808+
}
809+
strcpy(xlogstart, PQgetvalue(res, 0, 0));
810+
if (verbose && includewal)
811+
fprintf(stderr, "xlog start point: %s\n", xlogstart);
812+
PQclear(res);
813+
MemSet(xlogend, 0, sizeof(xlogend));
814+
815+
/*
816+
* Get the header
817+
*/
818+
res = PQgetResult(conn);
819+
if (PQresultStatus(res) != PGRES_TUPLES_OK)
820+
{
821+
fprintf(stderr, _("%s: could not get backup header: %s\n"),
822+
progname, PQerrorMessage(conn));
823+
disconnect_and_exit(1);
824+
}
778825
if (PQntuples(res) < 1)
779826
{
780827
fprintf(stderr, _("%s: no data returned from server.\n"), progname);
@@ -828,6 +875,27 @@ BaseBackup()
828875
}
829876
PQclear(res);
830877

878+
/*
879+
* Get the stop position
880+
*/
881+
res = PQgetResult(conn);
882+
if (PQresultStatus(res) != PGRES_TUPLES_OK)
883+
{
884+
fprintf(stderr, _("%s: could not get end xlog position from server.\n"),
885+
progname);
886+
disconnect_and_exit(1);
887+
}
888+
if (PQntuples(res) != 1)
889+
{
890+
fprintf(stderr, _("%s: no end point returned from server.\n"),
891+
progname);
892+
disconnect_and_exit(1);
893+
}
894+
strcpy(xlogend, PQgetvalue(res, 0, 0));
895+
if (verbose && includewal)
896+
fprintf(stderr, "xlog end point: %s\n", xlogend);
897+
PQclear(res);
898+
831899
res = PQgetResult(conn);
832900
if (PQresultStatus(res) != PGRES_COMMAND_OK)
833901
{

0 commit comments

Comments
 (0)