From: Craig Ringer Date: Thu, 15 May 2014 12:40:23 +0000 (+0800) Subject: bdr: Add db oid param to fetch_sysid_via_node_id, add bdr_ prefix X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=d36c34e19a94a75d7a287b87fb868cd6e9131ac1;p=users%2Fandresfreund%2Fpostgres.git bdr: Add db oid param to fetch_sysid_via_node_id, add bdr_ prefix Rename fetch_sysid_via_node_id to bdr_fetch_sysid_via_node_id and add a new output parameter to return the database oid for the database that's local to that RepNodeId. This allows bdr_fetch_sysid_via_node_id to return the full identifying key for a node now that we support intra-node replication. --- diff --git a/contrib/bdr/bdr.h b/contrib/bdr/bdr.h index 89bdad69bf..cb24853ba8 100644 --- a/contrib/bdr/bdr.h +++ b/contrib/bdr/bdr.h @@ -237,8 +237,8 @@ extern Oid BdrVotesRelid; /* apply support */ extern void bdr_process_remote_action(StringInfo s); -extern void fetch_sysid_via_node_id(RepNodeId node_id, uint64 *sysid, - TimeLineID *tli); +extern void bdr_fetch_sysid_via_node_id(RepNodeId node_id, uint64 *sysid, + TimeLineID *tli, Oid *remote_dboid); /* Index maintenance, heap access, etc */ extern struct EState * bdr_create_rel_estate(Relation rel); diff --git a/contrib/bdr/bdr_apply.c b/contrib/bdr/bdr_apply.c index b6997af851..86a9b1b619 100644 --- a/contrib/bdr/bdr_apply.c +++ b/contrib/bdr/bdr_apply.c @@ -73,6 +73,7 @@ Oid QueuedDropsRelid = InvalidOid; /* Global apply worker state */ uint64 origin_sysid; TimeLineID origin_timeline; +Oid origin_dboid; bool started_transaction = false; /* During apply, holds xid of remote transaction */ TransactionId replication_origin_xid = InvalidTransactionId; @@ -835,10 +836,6 @@ check_apply_update(RepNodeId local_node_id, TimestampTz local_ts, HeapTuple *new_tuple, bool *perform_update, bool *log_update, BdrConflictResolution *resolution) { - uint64 local_sysid, - remote_sysid; - TimeLineID local_tli, - remote_tli; int cmp, microsecs; long secs; @@ -930,18 +927,29 @@ check_apply_update(RepNodeId local_node_id, TimestampTz local_ts, } else if (cmp == 0) { + uint64 local_sysid, + remote_sysid; + TimeLineID local_tli, + remote_tli; + Oid local_dboid, + remote_dboid; /* * Timestamps are equal. Use sysid + timeline id to decide which * tuple to retain. */ - fetch_sysid_via_node_id(local_node_id, - &local_sysid, &local_tli); - fetch_sysid_via_node_id(replication_origin_id, - &remote_sysid, &remote_tli); + bdr_fetch_sysid_via_node_id(local_node_id, + &local_sysid, &local_tli, + &local_dboid); + bdr_fetch_sysid_via_node_id(replication_origin_id, + &remote_sysid, &remote_tli, + &remote_dboid); /* - * Apply the user tuple or, if none supplied, fall back to "last - * update wins" + * As the timestamps were equal, we have to break the tie in a + * consistent manner that'll match across all nodes. + * + * Use the ordering of the node's unique identifier, the tuple of + * (sysid, timelineid, dboid). */ if (local_sysid < remote_sysid) *perform_update = true; @@ -951,6 +959,10 @@ check_apply_update(RepNodeId local_node_id, TimestampTz local_ts, *perform_update = true; else if (local_tli > remote_tli) *perform_update = false; + else if (local_dboid < remote_dboid) + *perform_update = true; + else if (local_dboid > remote_dboid) + *perform_update = false; else /* shouldn't happen */ elog(ERROR, "unsuccessful node comparison"); @@ -987,15 +999,20 @@ do_log_update(RepNodeId local_node_id, bool apply_update, TimestampTz ts, remote_sysid; TimeLineID local_tli, remote_tli; + Oid local_dboid, + remote_dboid; - fetch_sysid_via_node_id(local_node_id, - &local_sysid, &local_tli); - fetch_sysid_via_node_id(replication_origin_id, - &remote_sysid, &remote_tli); + bdr_fetch_sysid_via_node_id(local_node_id, + &local_sysid, &local_tli, + &local_dboid); + bdr_fetch_sysid_via_node_id(replication_origin_id, + &remote_sysid, &remote_tli, + &remote_dboid); Assert(remote_sysid == origin_sysid); Assert(remote_tli == origin_timeline); + Assert(remote_dboid == origin_dboid); memcpy(remote_ts, timestamptz_to_str(replication_origin_timestamp), MAXDATELEN); @@ -1013,9 +1030,9 @@ do_log_update(RepNodeId local_node_id, bool apply_update, TimestampTz ts, ereport(LOG, (errcode(ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION), - errmsg("CONFLICT: %s remote update originating at node " UINT64_FORMAT ":%u at ts %s; row was previously updated at %s node " UINT64_FORMAT ":%u at ts %s. PKEY:%s, resolved by user tuple:%s", + errmsg("CONFLICT: %s remote update originating at node " UINT64_FORMAT ":%u:%u at ts %s; row was previously updated at %s node " UINT64_FORMAT ":%u at ts %s. PKEY:%s, resolved by user tuple:%s", apply_update ? "applying" : "skipping", - remote_sysid, remote_tli, remote_ts, + remote_sysid, remote_tli, remote_dboid, remote_ts, local_node_id == InvalidRepNodeId ? "local" : "remote", local_sysid, local_tli, local_ts, s_key.data, s_user_tuple.data))); @@ -1024,9 +1041,9 @@ do_log_update(RepNodeId local_node_id, bool apply_update, TimestampTz ts, { ereport(LOG, (errcode(ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION), - errmsg("CONFLICT: %s remote update originating at node " UINT64_FORMAT ":%u at ts %s; row was previously updated at %s node " UINT64_FORMAT ":%u at ts %s. PKEY:%s", + errmsg("CONFLICT: %s remote update originating at node " UINT64_FORMAT ":%u:%u at ts %s; row was previously updated at %s node " UINT64_FORMAT ":%u at ts %s. PKEY:%s", apply_update ? "applying" : "skipping", - remote_sysid, remote_tli, remote_ts, + remote_sysid, remote_tli, remote_dboid, remote_ts, local_node_id == InvalidRepNodeId ? "local" : "remote", local_sysid, local_tli, local_ts, s_key.data))); } diff --git a/contrib/bdr/bdr_catalogs.c b/contrib/bdr/bdr_catalogs.c index 6331dbc20a..232de10ae0 100644 --- a/contrib/bdr/bdr_catalogs.c +++ b/contrib/bdr/bdr_catalogs.c @@ -17,6 +17,7 @@ #include "postgres.h" #include "bdr.h" +#include "miscadmin.h" #include "access/xact.h" @@ -164,15 +165,18 @@ bdr_nodes_set_local_status(Name dbname, char status) /* * Given a node's local RepNodeId, get its globally unique identifier - * (sysid, timeline id) + * (sysid, timeline id, database oid) */ void -fetch_sysid_via_node_id(RepNodeId node_id, uint64 *sysid, TimeLineID *tli) +bdr_fetch_sysid_via_node_id(RepNodeId node_id, uint64 *sysid, TimeLineID *tli, + Oid *dboid) { if (node_id == InvalidRepNodeId) { + /* It's the local node */ *sysid = GetSystemIdentifier(); *tli = ThisTimeLineID; + *dboid = MyDatabaseId; } else { @@ -201,5 +205,6 @@ fetch_sysid_via_node_id(RepNodeId node_id, uint64 *sysid, TimeLineID *tli) *sysid = remote_sysid; *tli = remote_tli; + *dboid = remote_dboid; } } diff --git a/contrib/bdr/bdr_conflict_logging.c b/contrib/bdr/bdr_conflict_logging.c index 9556fa5db2..9e288ee293 100644 --- a/contrib/bdr/bdr_conflict_logging.c +++ b/contrib/bdr/bdr_conflict_logging.c @@ -444,6 +444,7 @@ bdr_conflict_log(BdrConflictType conflict_type, MemoryContext log_context, old_context; BdrApplyConflict conflict; TimeLineID tli; + Oid dboid; if (IsAbortedTransactionBlockState()) elog(ERROR, "bdr: attempt to log conflict in aborted transaction"); @@ -480,8 +481,8 @@ bdr_conflict_log(BdrConflictType conflict_type, } /* TODO: May make sense to cache the remote sysid in a global too... */ - fetch_sysid_via_node_id(replication_origin_id, - &conflict.remote_sysid, &tli); + bdr_fetch_sysid_via_node_id(replication_origin_id, + &conflict.remote_sysid, &tli, &dboid); conflict.remote_commit_time = replication_origin_timestamp; conflict.remote_txid = remote_txid; conflict.remote_commit_lsn = replication_origin_lsn; @@ -508,8 +509,9 @@ bdr_conflict_log(BdrConflictType conflict_type, if (local_tuple_origin_id != InvalidRepNodeId) { - fetch_sysid_via_node_id(local_tuple_origin_id, - &conflict.local_tuple_origin_sysid, &tli); + bdr_fetch_sysid_via_node_id(local_tuple_origin_id, + &conflict.local_tuple_origin_sysid, &tli, + &dboid); } else {