[389-commits] 2 commits - ldap/servers

Noriko Hosoi nhosoi at fedoraproject.org
Fri Mar 5 23:06:50 UTC 2010


 ldap/servers/plugins/replication/repl5.h          |    6 ++++
 ldap/servers/plugins/replication/repl5_protocol.c |   28 ++++++++++++++++++++++
 ldap/servers/plugins/replication/repl_extop.c     |   24 ++++++++++++++++++
 3 files changed, 58 insertions(+)

New commits:
commit f2a04fdc45cc8a408267019990504354282c4303
Merge: f4b90ed... 0b95451...
Author: Noriko Hosoi <nhosoi at redhat.com>
Date:   Fri Mar 5 15:06:43 2010 -0800

    Merge branch '547503'



commit 0b95451c7e50cb6b2d0cb310dddca18336e1b2ac
Author: Noriko Hosoi <nhosoi at redhat.com>
Date:   Fri Mar 5 10:07:38 2010 -0800

    570667 - MMR: simultaneous total updates on the masters cause
             deadlock and data loss
    
    https://bugzilla.redhat.com/show_bug.cgi?id=570667
    
    Description: In the MMR topology, if a master receives a total
    update request to initialize the other master and being initialized
    by the other master at the same time, the 2 replication threads hang
    and the replicated backend instance could be wiped out.
    
    To prevent the server running the total update supplier and the
    consumer at the same time, REPLICA_TOTAL_EXCL_SEND and _RECV bits
    have been introduced.  If the server is sending the total update
    to other replicas, the server rejects the total update request
    on the backend.  But the server can send multiple total updates
    to other replicas at the same time.  If the total update from
    other master is in progress on the server, the server rejects
    another total update from yet another master as well as a request
    to initialize other replicas.

diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 97ce556..c6859dd 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -521,6 +521,12 @@ void replica_write_ruv (Replica *r);
 #define REPLICA_INCREMENTAL_IN_PROGRESS 2 /* Set only between start and stop inc */
 #define REPLICA_TOTAL_IN_PROGRESS 4 /* Set only between start and stop total */
 #define REPLICA_AGREEMENTS_DISABLED 8 /* Replica is offline */
+#define REPLICA_TOTAL_EXCL_SEND 16 /* The server is either sending or receiving
+                                      the total update.  Introducing it if SEND
+                                      is active, RECV should back off. And
+                                      vice versa.  But SEND can coexist. */
+#define REPLICA_TOTAL_EXCL_RECV 32 /* ditto */
+
 PRBool replica_is_state_flag_set(Replica *r, PRInt32 flag);
 void replica_set_state_flag (Replica *r, PRUint32 flag, PRBool clear); 
 void replica_set_tombstone_reap_stop(Replica *r, PRBool val);
diff --git a/ldap/servers/plugins/replication/repl5_protocol.c b/ldap/servers/plugins/replication/repl5_protocol.c
index 927c450..efb3271 100644
--- a/ldap/servers/plugins/replication/repl5_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_protocol.c
@@ -317,6 +317,28 @@ prot_thread_main(void *arg)
 		dev_debug("prot_thread_main(STATE_PERFORMING_INCREMENTAL_UPDATE): end");
 		break;
 	      case STATE_PERFORMING_TOTAL_UPDATE:
+		{
+		Slapi_DN *dn = agmt_get_replarea(agmt);
+		Replica *replica = NULL;
+		Object *replica_obj = replica_get_replica_from_dn(dn);
+		if (replica_obj)
+		{
+		    replica = (Replica*) object_get_data (replica_obj);
+		    /* If total update against this replica is in progress,
+		     * we should not initiate the total update to other replicas. */
+		    if (replica_is_state_flag_set(replica, REPLICA_TOTAL_EXCL_RECV))
+		    {
+		        object_release(replica_obj);
+                slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+                    "%s: total update on the replica is in progress.  Cannot initiate the total update.\n", agmt_get_long_name(rp->agmt));
+		        break;
+		    }
+		    else
+		    {
+		        replica_set_state_flag (replica, REPLICA_TOTAL_EXCL_SEND, 0);
+		    }
+		}
+
 		PR_Lock(rp->lock);
     
 		/* stop incremental protocol if running */
@@ -332,7 +354,13 @@ prot_thread_main(void *arg)
 		   replica initialization is completed. */
 		agmt_replica_init_done (agmt);
     
+		if (replica_obj)
+		{
+		    replica_set_state_flag (replica, REPLICA_TOTAL_EXCL_SEND, 1);
+		    object_release(replica_obj);
+		}
 		break;
+		}
 	      case STATE_FINISHED:
 		dev_debug("prot_thread_main(STATE_FINISHED): exiting prot_thread_main");
 		done = 1;
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index b65c6c8..c47ea93 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -678,6 +678,25 @@ multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb)
 		goto send_response;
 	}
 
+	if (REPL_PROTOCOL_50_TOTALUPDATE == connext->repl_protocol_version)
+	{
+		/* If total update has been initiated against other replicas or
+		 * this replica is already being initialized, we should return
+		 * an error immediately. */
+		if (replica_is_state_flag_set(replica,
+							REPLICA_TOTAL_EXCL_SEND|REPLICA_TOTAL_EXCL_RECV))
+		{
+			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+				"%s: total update on is initiated on the replica.  Cannot execute the total update from other master.\n", repl_root);
+			response = NSDS50_REPL_REPLICA_BUSY;
+			goto send_response;
+		}
+		else
+		{
+			replica_set_state_flag (replica, REPLICA_TOTAL_EXCL_RECV, 0);
+		}
+	}
+
     /* check that this replica is not a 4.0 consumer */
     if (replica_is_legacy_consumer (replica))
     {
@@ -861,6 +880,11 @@ multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb)
 	slapi_pblock_get(pb, SLAPI_CONNECTION, &connext->connection);
 
 send_response:
+	if (connext && replica &&
+		(REPL_PROTOCOL_50_TOTALUPDATE == connext->repl_protocol_version))
+	{
+		replica_set_state_flag (replica, REPLICA_TOTAL_EXCL_RECV, 1);
+	}
     if (response != NSDS50_REPL_REPLICA_READY)
     {
 		int resp_log_level = SLAPI_LOG_FATAL;




More information about the 389-commits mailing list