New recovery.conf parameter, primary_slotname.
authorRobert Haas <[email protected]>
Tue, 28 Jan 2014 19:07:31 +0000 (14:07 -0500)
committerRobert Haas <[email protected]>
Tue, 28 Jan 2014 19:07:31 +0000 (14:07 -0500)
So you can, like, use slots.

src/backend/access/transam/xlog.c
src/backend/replication/README
src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
src/backend/replication/walreceiver.c
src/backend/replication/walreceiverfuncs.c
src/include/replication/walreceiver.h

index 7f787a5a1cd8322ffaf7514343d1aefc0b84c4af..63a00e378b2f65e5c9aff267664d245a0b0c8bb4 100644 (file)
@@ -226,6 +226,7 @@ static TimestampTz recoveryDelayUntilTime;
 /* options taken from recovery.conf for XLOG streaming */
 static bool StandbyModeRequested = false;
 static char *PrimaryConnInfo = NULL;
+static char *PrimarySlotName = NULL;
 static char *TriggerFile = NULL;
 
 /* are we currently in standby mode? */
@@ -5510,11 +5511,19 @@ readRecoveryCommandFile(void)
                }
                else if (strcmp(item->name, "primary_conninfo") == 0)
                {
-                       PrimaryConnInfo = pstrdup(item->value);
+                       PrimaryConnInfo = pstrdup(item->value); 
                        ereport(DEBUG2,
                                        (errmsg_internal("primary_conninfo = '%s'",
                                                                         PrimaryConnInfo)));
                }
+               else if (strcmp(item->name, "primary_slotname") == 0)
+               {
+                       ReplicationSlotValidateName(item->value, ERROR);
+                       PrimarySlotName = pstrdup(item->value);
+                       ereport(DEBUG2,
+                                       (errmsg_internal("primary_slotname = '%s'",
+                                                                        PrimarySlotName)));
+               }
                else if (strcmp(item->name, "trigger_file") == 0)
                {
                        TriggerFile = pstrdup(item->value);
@@ -11084,7 +11093,8 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
                                                                         tli, curFileTLI);
                                                }
                                                curFileTLI = tli;
-                                               RequestXLogStreaming(tli, ptr, PrimaryConnInfo);
+                                               RequestXLogStreaming(tli, ptr, PrimaryConnInfo,
+                                                                                        PrimarySlotName);
                                                receivedUpto = 0;
                                        }
 
index 60120ede29ced5559a507153eab234971db6a69c..2f5df49de67b3c93cc0dc81653e191bb31e735b4 100644 (file)
@@ -47,8 +47,9 @@ to fetch more WAL (if streaming replication is configured).
 
 Walreceiver is a postmaster subprocess, so the startup process can't fork it
 directly. Instead, it sends a signal to postmaster, asking postmaster to launch
-it. Before that, however, startup process fills in WalRcvData->conninfo,
-and initializes the starting point in WalRcvData->receiveStart.
+it. Before that, however, startup process fills in WalRcvData->conninfo
+and WalRcvData->slotname, and initializes the starting point in
+WalRcvData->receiveStart.
 
 As walreceiver receives WAL from the master server, and writes and flushes
 it to disk (in pg_xlog), it updates WalRcvData->receivedUpto and signals
index 2e057b8969fa8d4a1ae15fb123746f0953764c30..ecec8b345634960d591289ba90b220aad0f5e5da 100644 (file)
@@ -49,7 +49,8 @@ static char *recvBuf = NULL;
 static void libpqrcv_connect(char *conninfo);
 static void libpqrcv_identify_system(TimeLineID *primary_tli);
 static void libpqrcv_readtimelinehistoryfile(TimeLineID tli, char **filename, char **content, int *len);
-static bool libpqrcv_startstreaming(TimeLineID tli, XLogRecPtr startpoint);
+static bool libpqrcv_startstreaming(TimeLineID tli, XLogRecPtr startpoint,
+                                                                       char *slotname);
 static void libpqrcv_endstreaming(TimeLineID *next_tli);
 static int     libpqrcv_receive(int timeout, char **buffer);
 static void libpqrcv_send(const char *buffer, int nbytes);
@@ -171,15 +172,20 @@ libpqrcv_identify_system(TimeLineID *primary_tli)
  * throws an ERROR.
  */
 static bool
-libpqrcv_startstreaming(TimeLineID tli, XLogRecPtr startpoint)
+libpqrcv_startstreaming(TimeLineID tli, XLogRecPtr startpoint, char *slotname)
 {
        char            cmd[64];
        PGresult   *res;
 
        /* Start streaming from the point requested by startup process */
-       snprintf(cmd, sizeof(cmd), "START_REPLICATION %X/%X TIMELINE %u",
-                        (uint32) (startpoint >> 32), (uint32) startpoint,
-                        tli);
+       if (slotname != NULL)
+               snprintf(cmd, sizeof(cmd),
+                                "START_REPLICATION SLOT \"%s\" %X/%X TIMELINE %u", slotname,
+                                (uint32) (startpoint >> 32), (uint32) startpoint, tli);
+       else
+               snprintf(cmd, sizeof(cmd),
+                                "START_REPLICATION %X/%X TIMELINE %u",
+                                (uint32) (startpoint >> 32), (uint32) startpoint, tli);
        res = libpqrcv_PQexec(cmd);
 
        if (PQresultStatus(res) == PGRES_COMMAND_OK)
index 1fbd33ef61b004d3940a5e17f80007f051e28084..cc3d775307406e95a4d07f59866a2a74fffdd04d 100644 (file)
@@ -187,6 +187,7 @@ void
 WalReceiverMain(void)
 {
        char            conninfo[MAXCONNINFO];
+       char            slotname[NAMEDATALEN];
        XLogRecPtr      startpoint;
        TimeLineID      startpointTLI;
        TimeLineID      primaryTLI;
@@ -241,6 +242,7 @@ WalReceiverMain(void)
 
        /* Fetch information required to start streaming */
        strlcpy(conninfo, (char *) walrcv->conninfo, MAXCONNINFO);
+       strlcpy(slotname, (char *) walrcv->slotname, NAMEDATALEN);
        startpoint = walrcv->receiveStart;
        startpointTLI = walrcv->receiveStartTLI;
 
@@ -355,7 +357,8 @@ WalReceiverMain(void)
                 * on the new timeline.
                 */
                ThisTimeLineID = startpointTLI;
-               if (walrcv_startstreaming(startpointTLI, startpoint))
+               if (walrcv_startstreaming(startpointTLI, startpoint,
+                                                                 slotname[0] != '\0' ? slotname : NULL))
                {
                        bool            endofwal = false;
 
index cc96d7c2f8a967708238a3f9a5d6342a473316e1..acadec57f5a77c5fab39c179b5dad4f2c505af7b 100644 (file)
@@ -219,11 +219,13 @@ ShutdownWalRcv(void)
 /*
  * Request postmaster to start walreceiver.
  *
- * recptr indicates the position where streaming should begin, and conninfo
- * is a libpq connection string to use.
+ * recptr indicates the position where streaming should begin, conninfo
+ * is a libpq connection string to use, and slotname is, optionally, the name
+ * of a replication slot to acquire.
  */
 void
-RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo)
+RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
+                                        const char *slotname)
 {
        /* use volatile pointer to prevent code rearrangement */
        volatile WalRcvData *walrcv = WalRcv;
@@ -250,6 +252,11 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo)
        else
                walrcv->conninfo[0] = '\0';
 
+       if (slotname != NULL)
+               strlcpy((char *) walrcv->slotname, slotname, NAMEDATALEN);
+       else
+               walrcv->slotname[0] = '\0';
+
        if (walrcv->walRcvState == WALRCV_STOPPED)
        {
                launch = true;
index 3c656197cc0d6ceed12fc0c58a1caad2a89c8bc4..3d9401059b769fca852027776b4c0df6285bf08a 100644 (file)
@@ -103,6 +103,12 @@ typedef struct
         */
        char            conninfo[MAXCONNINFO];
 
+       /*
+        * replication slot name; is also used for walreceiver to connect with
+        * the primary
+        */
+       char            slotname[NAMEDATALEN];
+
        slock_t         mutex;                  /* locks shared variables shown above */
 
        /*
@@ -125,7 +131,7 @@ extern PGDLLIMPORT walrcv_identify_system_type walrcv_identify_system;
 typedef void (*walrcv_readtimelinehistoryfile_type) (TimeLineID tli, char **filename, char **content, int *size);
 extern PGDLLIMPORT walrcv_readtimelinehistoryfile_type walrcv_readtimelinehistoryfile;
 
-typedef bool (*walrcv_startstreaming_type) (TimeLineID tli, XLogRecPtr startpoint);
+typedef bool (*walrcv_startstreaming_type) (TimeLineID tli, XLogRecPtr startpoint, char *slotname);
 extern PGDLLIMPORT walrcv_startstreaming_type walrcv_startstreaming;
 
 typedef void (*walrcv_endstreaming_type) (TimeLineID *next_tli);
@@ -149,7 +155,8 @@ extern void WalRcvShmemInit(void);
 extern void ShutdownWalRcv(void);
 extern bool WalRcvStreaming(void);
 extern bool WalRcvRunning(void);
-extern void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo);
+extern void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr,
+                                        const char *conninfo, const char *slotname);
 extern XLogRecPtr GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI);
 extern int     GetReplicationApplyDelay(void);
 extern int     GetReplicationTransferLatency(void);