Add bdr.bdr_apply_is_paused() information function
authorCraig Ringer <craig@2ndquadrant.com>
Tue, 26 May 2015 09:51:55 +0000 (17:51 +0800)
committerCraig Ringer <craig@2ndquadrant.com>
Fri, 29 May 2015 13:04:46 +0000 (21:04 +0800)
This makes it possible to see whether replay is paused on
a node.

Also adds some tests for pause/resume.

Closes #59

Makefile.in
bdr.c
doc/manual-functions.sgml
expected/pause.out [new file with mode: 0644]
extsql/bdr--0.10.0.1--0.10.0.2.sql
extsql/bdr--0.9.0.4--0.9.0.5.sql
sql/pause.sql [new file with mode: 0644]

index 52153c7c16a35df3c08b86a58e941c89cf69b23c..0917a4129ece1300186345517132fd3a297b6ca7 100644 (file)
@@ -257,6 +257,7 @@ REGRESSCHECKS= \
    supervisordb \
    upgrade \
    identifier \
+   pause \
    $(DDLREGRESSCHECKS) \
    dml/basic dml/contrib dml/delete_pk dml/extended dml/missing_pk dml/toasted \
    $(REGRESSTEARDOWN)
diff --git a/bdr.c b/bdr.c
index e72f94644de879579080f7e067906974c03c5420..6f3b3bce5aadbf8fe365712cbbb8d5528aa319cf 100644 (file)
--- a/bdr.c
+++ b/bdr.c
@@ -95,6 +95,7 @@ void      _PG_init(void);
 
 PGDLLEXPORT Datum bdr_apply_pause(PG_FUNCTION_ARGS);
 PGDLLEXPORT Datum bdr_apply_resume(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum bdr_apply_is_paused(PG_FUNCTION_ARGS);
 PGDLLEXPORT Datum bdr_version(PG_FUNCTION_ARGS);
 PGDLLEXPORT Datum bdr_version_num(PG_FUNCTION_ARGS);
 PGDLLEXPORT Datum bdr_min_remote_version_num(PG_FUNCTION_ARGS);
@@ -105,6 +106,7 @@ PGDLLEXPORT Datum bdr_format_slot_name_sql(PG_FUNCTION_ARGS);
 
 PG_FUNCTION_INFO_V1(bdr_apply_pause);
 PG_FUNCTION_INFO_V1(bdr_apply_resume);
+PG_FUNCTION_INFO_V1(bdr_apply_is_paused);
 PG_FUNCTION_INFO_V1(bdr_version);
 PG_FUNCTION_INFO_V1(bdr_version_num);
 PG_FUNCTION_INFO_V1(bdr_min_remote_version_num);
@@ -918,6 +920,12 @@ bdr_apply_resume(PG_FUNCTION_ARGS)
    PG_RETURN_VOID();
 }
 
+Datum
+bdr_apply_is_paused(PG_FUNCTION_ARGS)
+{
+   PG_RETURN_BOOL(BdrWorkerCtl->pause_apply);
+}
+
 Datum
 bdr_version(PG_FUNCTION_ARGS)
 {
index c7459f4f8f3a964153579f0b222a48574868ec61..b4f94bcb404b3cee56e6133db649150ce870077f 100644 (file)
        </entry>
       </row>
 
+      <row>
+       <entry>&bdr;/&udr;</entry>
+       <entry>
+        <indexterm>
+         <primary>bdr.bdr_apply_is_paused</primary>
+        </indexterm>
+        <literal><function>bdr.bdr_apply_is_paused()</function></literal>
+       </entry>
+       <entry>boolean</entry>
+       <entry>
+        Report whether replay is paused (e.g. with
+        <function>bdr.bdr_apply_pause()</function>). A false return
+        does not mean replay is actually progressing, only that
+        it's not intentionally paused.
+       </entry>
+      </row>
+
       <row id="function-bdr-replicate-ddl-command" xreflabel="bdr.bdr_replicate_ddl_command">
        <entry>&bdr;/&udr;</entry>
        <entry>
diff --git a/expected/pause.out b/expected/pause.out
new file mode 100644 (file)
index 0000000..85e1ba5
--- /dev/null
@@ -0,0 +1,103 @@
+\ccc regression
+invalid command \ccc
+SELECT bdr.bdr_apply_is_paused();
+ bdr_apply_is_paused 
+---------------------
+ f
+(1 row)
+
+SELECT bdr.bdr_replicate_ddl_command('CREATE TABLE public.pause_test(x text primary key);');
+ bdr_replicate_ddl_command 
+---------------------------
+(1 row)
+
+INSERT INTO pause_test(x) VALUES ('before pause');
+SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0);
+ pg_xlog_wait_remote_apply 
+---------------------------
+(1 row)
+
+\cc postgres
+invalid command \cc
+SELECT bdr.bdr_apply_is_paused();
+ bdr_apply_is_paused 
+---------------------
+ f
+(1 row)
+
+SELECT bdr.bdr_apply_pause();
+ bdr_apply_pause 
+-----------------
+(1 row)
+
+SELECT bdr.bdr_apply_is_paused();
+ bdr_apply_is_paused 
+---------------------
+ t
+(1 row)
+
+-- It's necessary to wait for a latch timeout on apply workers
+-- until bdr_apply_pause gets taught to set their latches.
+SELECT pg_sleep(6);
+ pg_sleep 
+----------
+(1 row)
+
+\ccc regression
+invalid command \ccc
+INSERT INTO pause_test(x) VALUES ('after pause before resume');
+\cc postgres
+invalid command \cc
+-- Give more time for a row to replicate if it's going to
+-- (it shouldn't)
+SELECT pg_sleep(1);
+ pg_sleep 
+----------
+(1 row)
+
+-- Pause state is preserved across sessions
+SELECT bdr.bdr_apply_is_paused();
+ bdr_apply_is_paused 
+---------------------
+ t
+(1 row)
+
+-- Must not see row from after pause
+SELECT x FROM pause_test;
+             x             
+---------------------------
+ before pause
+ after pause before resume
+(2 rows)
+
+SELECT bdr.bdr_apply_resume();
+ bdr_apply_resume 
+------------------
+(1 row)
+
+\ccc regression
+invalid command \ccc
+INSERT INTO pause_test(x) VALUES ('after resume');
+SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0);
+ pg_xlog_wait_remote_apply 
+---------------------------
+(1 row)
+
+\cc postgres
+invalid command \cc
+-- Must see all three rows
+SELECT x FROM pause_test;
+             x             
+---------------------------
+ before pause
+ after pause before resume
+ after resume
+(3 rows)
+
index 9d32af72ec0c79d60cb1e992953431bbafb5f667..cd6390d2131fe57f6658ff2d979d5abb23184ae8 100644 (file)
@@ -9,6 +9,8 @@ SET bdr.skip_ddl_replication = true;
 ALTER FUNCTION bdr.table_set_replication_sets(p_relation regclass, p_sets text[])
 SET bdr.permit_unsafe_ddl_commands = true;
 
+CREATE OR REPLACE FUNCTION bdr.bdr_apply_is_paused()
+RETURNS boolean LANGUAGE c AS 'MODULE_PATHNAME';
 
 RESET bdr.permit_unsafe_ddl_commands;
 RESET bdr.skip_ddl_replication;
index 9d32af72ec0c79d60cb1e992953431bbafb5f667..cd6390d2131fe57f6658ff2d979d5abb23184ae8 100644 (file)
@@ -9,6 +9,8 @@ SET bdr.skip_ddl_replication = true;
 ALTER FUNCTION bdr.table_set_replication_sets(p_relation regclass, p_sets text[])
 SET bdr.permit_unsafe_ddl_commands = true;
 
+CREATE OR REPLACE FUNCTION bdr.bdr_apply_is_paused()
+RETURNS boolean LANGUAGE c AS 'MODULE_PATHNAME';
 
 RESET bdr.permit_unsafe_ddl_commands;
 RESET bdr.skip_ddl_replication;
diff --git a/sql/pause.sql b/sql/pause.sql
new file mode 100644 (file)
index 0000000..792a30d
--- /dev/null
@@ -0,0 +1,44 @@
+\ccc regression
+
+SELECT bdr.bdr_apply_is_paused();
+
+SELECT bdr.bdr_replicate_ddl_command('CREATE TABLE public.pause_test(x text primary key);');
+INSERT INTO pause_test(x) VALUES ('before pause');
+SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0);
+
+\cc postgres
+
+SELECT bdr.bdr_apply_is_paused();
+SELECT bdr.bdr_apply_pause();
+SELECT bdr.bdr_apply_is_paused();
+-- It's necessary to wait for a latch timeout on apply workers
+-- until bdr_apply_pause gets taught to set their latches.
+SELECT pg_sleep(6);
+
+\ccc regression
+
+INSERT INTO pause_test(x) VALUES ('after pause before resume');
+
+\cc postgres
+
+-- Give more time for a row to replicate if it's going to
+-- (it shouldn't)
+SELECT pg_sleep(1);
+
+-- Pause state is preserved across sessions
+SELECT bdr.bdr_apply_is_paused();
+
+-- Must not see row from after pause
+SELECT x FROM pause_test;
+
+SELECT bdr.bdr_apply_resume();
+
+\ccc regression
+
+INSERT INTO pause_test(x) VALUES ('after resume');
+SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0);
+
+\cc postgres
+
+-- Must see all three rows
+SELECT x FROM pause_test;