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.