Attached patch adds some more "metadata" to walsender results: * Adds the current xlog insert location as a third column in IDENTIFY_SYSTEM * Adds a resultset at the start of a base backup that contains the start xlog location (as returned by do_pg_start_backup) * Adds a resultset at the end of a base backup that contains the end xlog location (as returned by do_pg_stop_backup)
These are all information that's interesting for the "log receiver" version of pg_basebackup (the changes to BASE_BACKUP) and the pg_streamrecv program (the IDENTIFY_SYSTEM) once integrated. I still haven't had the time to clean up those programs enough to submit as a patch yet (it has progressed past that early post from a month ago or so, but isn't done yet), but I wanted to make sure that the backend parts gets reviewed and added as soon as possible. And they're also quite trivial. That way if I don't find time to clean up the streaming mode receiver in time for 9.1, it can be maintained outside of the main tree until 9.2 - but the small backend changes would still be required. -- Magnus Hagander Me: http://www.hagander.net/ Work: http://www.redpill-linpro.com/
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index 73c05ed..5e9b5d4 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -1315,7 +1315,7 @@ The commands accepted in walsender mode are: <listitem> <para> Requests the server to identify itself. Server replies with a result - set of a single row, containing two fields: + set of a single row, containing three fields: </para> <para> @@ -1344,6 +1344,19 @@ The commands accepted in walsender mode are: </para> </listitem> </varlistentry> + + <varlistentry> + <term> + xlogpos + </term> + <listitem> + <para> + Current xlog write location. Useful to get a known location in the + transaction log where streaming can start. + </para> + </listitem> + </varlistentry> + </variablelist> </para> </listitem> @@ -1520,15 +1533,16 @@ The commands accepted in walsender mode are: </variablelist> </para> <para> - When the backup is started, the server will first send a header in - ordinary result set format, followed by one or more CopyResponse - results, one for PGDATA and one for each additional tablespace other - than <literal>pg_default</> and <literal>pg_global</>. The data in - the CopyResponse results will be a tar format (using ustar00 - extensions) dump of the tablespace contents. + When the backup is started, the server will first send two + ordinary result sets, followed by one or more CopyResponse + results. + </para> + <para> + The first ordinary result set contains the starting position of the + backup, given in XLogRecPtr format as a single column in a single row. </para> <para> - The header is an ordinary resultset with one row for each tablespace. + The second ordinary result set has one row for each tablespace. The fields in this row are: <variablelist> <varlistentry> @@ -1561,6 +1575,15 @@ The commands accepted in walsender mode are: </variablelist> </para> <para> + After the two regular result set, one or more CopyResponse results + will be sent, one for PGDATA and one for each additional tablespace other + than <literal>pg_default</> and <literal>pg_global</>. The data in + the CopyResponse results will be a tar format (using ustar00 + extensions) dump of the tablespace contents. After the tar data is + complete, a final ordinary result set will be sent. + </para> + + <para> The tar archive for the data directory and each tablespace will contain all files in the directories, regardless of whether they are <productname>PostgreSQL</> files or other files added to the same @@ -1583,6 +1606,11 @@ The commands accepted in walsender mode are: Owner, group and file mode are set if the underlying filesystem on the server supports it. </para> + <para> + Once all tablespaces have been sent, a final regular result set will + be sent. This result set contains the end position of the + backup, given in XLogRecPtr format as a single column in a single row. + </para> </listitem> </varlistentry> </variablelist> diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index 29284a6..840d577 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -52,6 +52,7 @@ static void SendBackupHeader(List *tablespaces); static void base_backup_cleanup(int code, Datum arg); static void perform_base_backup(basebackup_options *opt, DIR *tblspcdir); static void parse_basebackup_options(List *options, basebackup_options *opt); +static void SendXlogRecPtrResult(XLogRecPtr ptr); /* * Size of each block sent into the tar stream for larger files. @@ -92,6 +93,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir) char *labelfile; startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &labelfile); + SendXlogRecPtrResult(startptr); PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0); { @@ -239,6 +241,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir) /* Send CopyDone message for the last tar file */ pq_putemptymessage('c'); } + SendXlogRecPtrResult(endptr); } /* @@ -432,6 +435,42 @@ SendBackupHeader(List *tablespaces) } /* + * Send a single resultset containing just a single + * XlogRecPtr record (in text format) + */ +static void +SendXlogRecPtrResult(XLogRecPtr ptr) +{ + StringInfoData buf; + char str[MAXFNAMELEN]; + + snprintf(str, sizeof(str), "%X/%X", ptr.xlogid, ptr.xrecoff); + + pq_beginmessage(&buf, 'T'); /* RowDescription */ + pq_sendint(&buf, 1, 2); /* 1 field */ + + /* Field header */ + pq_sendstring(&buf, "recptr"); + pq_sendint(&buf, 0, 4); /* table oid */ + pq_sendint(&buf, 0, 2); /* attnum */ + pq_sendint(&buf, TEXTOID, 4); /* type oid */ + pq_sendint(&buf, -1, 2); + pq_sendint(&buf, 0, 4); + pq_sendint(&buf, 0, 2); + pq_endmessage(&buf); + + /* Data row */ + pq_beginmessage(&buf, 'D'); + pq_sendint(&buf, 1, 2); /* number of columns */ + pq_sendint(&buf, strlen(str), 4); /* length */ + pq_sendbytes(&buf, str, strlen(str)); + pq_endmessage(&buf); + + /* Send a CommandComplete message */ + pq_puttextmessage('C', "SELECT"); +} + +/* * Inject a file with given name and content in the output tar stream. */ static void diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index f70458e..78963c1 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -258,19 +258,26 @@ IdentifySystem(void) StringInfoData buf; char sysid[32]; char tli[11]; + char xpos[MAXFNAMELEN]; + XLogRecPtr logptr; /* - * Reply with a result set with one row, two columns. First col is system - * ID, and second is timeline ID + * Reply with a result set with one row, three columns. First col is system + * ID, second is timeline ID, and third is current xlog location. */ snprintf(sysid, sizeof(sysid), UINT64_FORMAT, GetSystemIdentifier()); snprintf(tli, sizeof(tli), "%u", ThisTimeLineID); + logptr = GetInsertRecPtr(); + + snprintf(xpos, sizeof(xpos), "%X/%X", + logptr.xlogid, logptr.xrecoff); + /* Send a RowDescription message */ pq_beginmessage(&buf, 'T'); - pq_sendint(&buf, 2, 2); /* 2 fields */ + pq_sendint(&buf, 3, 2); /* 3 fields */ /* first field */ pq_sendstring(&buf, "systemid"); /* col name */ @@ -289,15 +296,27 @@ IdentifySystem(void) pq_sendint(&buf, 4, 2); /* typlen */ pq_sendint(&buf, 0, 4); /* typmod */ pq_sendint(&buf, 0, 2); /* format code */ + + /* third field */ + pq_sendstring(&buf, "xlogpos"); + pq_sendint(&buf, 0, 4); + pq_sendint(&buf, 0, 2); + pq_sendint(&buf, TEXTOID, 4); + pq_sendint(&buf, -1, 2); + pq_sendint(&buf, 0, 4); + pq_sendint(&buf, 0, 2); pq_endmessage(&buf); /* Send a DataRow message */ pq_beginmessage(&buf, 'D'); - pq_sendint(&buf, 2, 2); /* # of columns */ + pq_sendint(&buf, 3, 2); /* # of columns */ pq_sendint(&buf, strlen(sysid), 4); /* col1 len */ pq_sendbytes(&buf, (char *) &sysid, strlen(sysid)); pq_sendint(&buf, strlen(tli), 4); /* col2 len */ pq_sendbytes(&buf, (char *) tli, strlen(tli)); + pq_sendint(&buf, strlen(xpos), 4); /* col3 len */ + pq_sendbytes(&buf, (char *) xpos, strlen(xpos)); + pq_endmessage(&buf); /* Send CommandComplete and ReadyForQuery messages */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers