Improve some check logic in pg_receivewal
authorMichael Paquier <michael@paquier.xyz>
Sat, 18 Sep 2021 01:42:13 +0000 (10:42 +0900)
committerMichael Paquier <michael@paquier.xyz>
Sat, 18 Sep 2021 01:42:13 +0000 (10:42 +0900)
The following things are improved:
- Fetch the system identifier from the source server before any
WAL streaming loop.  This triggers extra checks to make sure that
pg_receivewal is still connected to a server with the same system ID
with a correct timeline.
- Switch umask() (for file creation mode mask) and RetrieveWalSegSize()
(to fetch the size of WAL segments) a bit later before the initial
stream attempt.  If the connection was done with a database,
pg_receivewal would fail but those commands were still executed, which
was a waste.  The slot creation and drop are now done before retrieving
the segment size.

Author: Bharath Rupireddy
Reviewed-by: Ronan Dunklau, Michael Paquier
Discussion: https://postgr.es/m/CALj2ACX00YYeyBfoi55Cy=NrP-FcfMgiYYx1qRUEib3yjCVoaA@mail.gmail.com

src/bin/pg_basebackup/pg_receivewal.c

index 9d1843728d742678e7f5174906fea5971c23d540..d5140a79fea9cab59d4afa5ad35e8609e0c6b27b 100644 (file)
@@ -372,6 +372,7 @@ StreamLog(void)
        XLogRecPtr      serverpos;
        TimeLineID      servertli;
        StreamCtl       stream;
+       char       *sysidentifier;
 
        MemSet(&stream, 0, sizeof(stream));
 
@@ -399,7 +400,7 @@ StreamLog(void)
         * at the same time, necessary if not valid data can be found in the
         * existing output directory.
         */
-       if (!RunIdentifySystem(conn, NULL, &servertli, &serverpos, NULL))
+       if (!RunIdentifySystem(conn, &sysidentifier, &servertli, &serverpos, NULL))
                exit(1);
 
        /*
@@ -435,6 +436,7 @@ StreamLog(void)
                                                                                                stream.do_sync);
        stream.partial_suffix = ".partial";
        stream.replication_slot = replication_slot;
+       stream.sysidentifier = sysidentifier;
 
        ReceiveXlogStream(conn, &stream);
 
@@ -449,6 +451,7 @@ StreamLog(void)
 
        FreeWalDirectoryMethod();
        pg_free(stream.walmethod);
+       pg_free(stream.sysidentifier);
 }
 
 /*
@@ -687,20 +690,6 @@ main(int argc, char **argv)
        if (!RunIdentifySystem(conn, NULL, NULL, NULL, &db_name))
                exit(1);
 
-       /*
-        * Set umask so that directories/files are created with the same
-        * permissions as directories/files in the source data directory.
-        *
-        * pg_mode_mask is set to owner-only by default and then updated in
-        * GetConnection() where we get the mode from the server-side with
-        * RetrieveDataDirCreatePerm() and then call SetDataDirectoryCreatePerm().
-        */
-       umask(pg_mode_mask);
-
-       /* determine remote server's xlog segment size */
-       if (!RetrieveWalSegSize(conn))
-               exit(1);
-
        /*
         * Check that there is a database associated with connection, none should
         * be defined in this context.
@@ -712,6 +701,16 @@ main(int argc, char **argv)
                exit(1);
        }
 
+       /*
+        * Set umask so that directories/files are created with the same
+        * permissions as directories/files in the source data directory.
+        *
+        * pg_mode_mask is set to owner-only by default and then updated in
+        * GetConnection() where we get the mode from the server-side with
+        * RetrieveDataDirCreatePerm() and then call SetDataDirectoryCreatePerm().
+        */
+       umask(pg_mode_mask);
+
        /*
         * Drop a replication slot.
         */
@@ -737,6 +736,10 @@ main(int argc, char **argv)
                exit(0);
        }
 
+       /* determine remote server's xlog segment size */
+       if (!RetrieveWalSegSize(conn))
+               exit(1);
+
        /*
         * Don't close the connection here so that subsequent StreamLog() can
         * reuse it.