bdr: Introduce support for forwarding changes from foreign nodes
authorCraig Ringer <[email protected]>
Mon, 7 Apr 2014 08:07:14 +0000 (16:07 +0800)
committerAndres Freund <[email protected]>
Thu, 3 Jul 2014 15:55:23 +0000 (17:55 +0200)
Adds the "forward_changesets" option to the bdr_output plugin.

This can be used to cascade changes from one node to another,
potentially allowing cascading logical replication.

It's required to support proper addition of a new node via logical
dump.

contrib/bdr/bdr_output.c

index 8c05927c9a6a485e29e9eaeb3d55bab6373ed061..3725a5a5982c6cab6156cb180a719e2851937ca6 100644 (file)
@@ -52,6 +52,7 @@ typedef struct
    bool allow_binary_protocol;
    bool allow_sendrecv_protocol;
    bool int_datetime_mismatch;
+   bool forward_changesets;
 
    uint32 client_pg_version;
    uint32 client_pg_catversion;
@@ -198,6 +199,8 @@ pg_decode_startup(LogicalDecodingContext * ctx, OutputPluginOptions *opt, bool i
            bdr_parse_bool(elem, &data->client_int_datetime);
        else if (strcmp(elem->defname, "db_encoding") == 0)
            data->client_db_encoding = pstrdup(strVal(elem->arg));
+       else if (strcmp(elem->defname, "forward_changesets") == 0)
+           bdr_parse_bool(elem, &data->forward_changesets);
        else
        {
            ereport(ERROR,
@@ -291,6 +294,17 @@ pg_decode_startup(LogicalDecodingContext * ctx, OutputPluginOptions *opt, bool i
    }
 }
 
+/*
+ * Only changesets generated on the local node should be replicated
+ * to the client unless we're in changeset forwarding mode.
+ */
+static inline bool
+should_forward_changeset(LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
+{
+   return (txn->origin_id == InvalidRepNodeId)
+          || ((BdrOutputData*)ctx->output_plugin_private)->forward_changesets;
+}
+
 /* BEGIN callback */
 void
 pg_decode_begin_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
@@ -300,7 +314,7 @@ pg_decode_begin_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
 #endif
    AssertVariableIsOfType(&pg_decode_begin_txn, LogicalDecodeBeginCB);
 
-   if (txn->origin_id != InvalidRepNodeId)
+   if (!should_forward_changeset(ctx, txn))
        return;
 
    OutputPluginPrepareWrite(ctx, true);
@@ -320,7 +334,7 @@ pg_decode_commit_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
    BdrOutputData *data = ctx->output_plugin_private;
 #endif
 
-   if (txn->origin_id != InvalidRepNodeId)
+   if (!should_forward_changeset(ctx, txn))
        return;
 
    OutputPluginPrepareWrite(ctx, true);
@@ -343,8 +357,7 @@ pg_decode_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
    /* Avoid leaking memory by using and resetting our own context */
    old = MemoryContextSwitchTo(data->context);
 
-   /* only log changes originating locally */
-   if (txn->origin_id != InvalidRepNodeId)
+   if (!should_forward_changeset(ctx, txn))
        return;
 
    OutputPluginPrepareWrite(ctx, true);