bdr: Add bdr_apply_pause/_resume functions
authorAbhijit Menon-Sen <[email protected]>
Fri, 25 Apr 2014 11:03:54 +0000 (16:33 +0530)
committerAndres Freund <[email protected]>
Thu, 3 Jul 2014 15:55:27 +0000 (17:55 +0200)
These are analogous to pg_xlog_replay_pause()/_resume().

contrib/bdr/bdr--0.5.sql
contrib/bdr/bdr.c

index 2a441dc1ec0c5011862e5e3ce2587a266a2b5ed5..d76b53e686ba58a656d70ce7bf78c766453c0ac7 100644 (file)
@@ -255,6 +255,18 @@ CREATE EVENT TRIGGER queue_drops
 ON sql_drop
 EXECUTE PROCEDURE bdr.queue_dropped_objects();
 
+CREATE OR REPLACE FUNCTION bdr_apply_pause()
+RETURNS VOID
+LANGUAGE C
+AS 'MODULE_PATHNAME'
+;
+
+CREATE OR REPLACE FUNCTION bdr_apply_resume()
+RETURNS VOID
+LANGUAGE C
+AS 'MODULE_PATHNAME'
+;
+
 ---
 --- this should always be last to avoid replicating our internal schema
 ---
index 6fbe8d2ea73e8b0e33305d46b861d2fd07e2d8b0..192d35ee00b83f56c08d7070df6603edac39baec 100644 (file)
@@ -80,6 +80,8 @@ typedef struct BdrWorkerControl
    LWLockId     lock;
    /* Required only for bgworker restart issues: */
    bool         launch_workers;
+   /* Set/unset by bdr_apply_pause()/_replay(). */
+   bool         pause_apply;
    /* Array members, of size bdr_max_workers */
    BdrWorker    slots[FLEXIBLE_ARRAY_MEMBER];
 } BdrWorkerControl;
@@ -127,6 +129,12 @@ static void bdr_worker_shmem_release(BdrWorker* worker,
                                     BackgroundWorkerHandle *handle)
    __attribute__((unused)); /* TODO: remove this attribute when function is used */
 
+Datum bdr_apply_pause(PG_FUNCTION_ARGS);
+Datum bdr_apply_resume(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(bdr_apply_pause);
+PG_FUNCTION_INFO_V1(bdr_apply_resume);
+
 /*
  * Converts an int64 to network byte order.
  */
@@ -723,6 +731,24 @@ bdr_apply_main(Datum main_arg)
        if (last_received != InvalidXLogRecPtr)
            bdr_send_feedback(streamConn, last_received,
                         GetCurrentTimestamp(), false, false);
+
+       /*
+        * If the user has paused replication with bdr_apply_pause(), we
+        * wait on our procLatch until pg_bdr_apply_resume() unsets the
+        * flag in shmem. We don't pause until the end of the current
+        * transaction, to avoid sleeping with locks held.
+        *
+        * XXX With the 1s timeout below, we don't risk delaying the
+        * resumption too much. But it would be better to use a global
+        * latch that can be set by pg_bdr_apply_resume(), and not have
+        * to wake up so often.
+        */
+
+       while (BdrWorkerCtl->pause_apply && !IsTransactionState())
+       {
+           ResetLatch(&MyProc->procLatch);
+           rc = WaitLatch(&MyProc->procLatch, WL_TIMEOUT, 1000L);
+       }
    }
 
    proc_exit(0);
@@ -1554,3 +1580,17 @@ bdr_maintain_schema(void)
    PopActiveSnapshot();
    CommitTransactionCommand();
 }
+
+Datum
+bdr_apply_pause(PG_FUNCTION_ARGS)
+{
+   BdrWorkerCtl->pause_apply = true;
+   PG_RETURN_VOID();
+}
+
+Datum
+bdr_apply_resume(PG_FUNCTION_ARGS)
+{
+   BdrWorkerCtl->pause_apply = false;
+   PG_RETURN_VOID();
+}