Blame SOURCES/0044-Ticket-48957-set-proper-update-status-to-replication.patch

7c7f29
From e48616639e254b698edaa778d41597094243ced5 Mon Sep 17 00:00:00 2001
7c7f29
From: Mark Reynolds <mreynolds@redhat.com>
7c7f29
Date: Fri, 26 Aug 2016 15:04:02 -0400
7c7f29
Subject: [PATCH 44/45] Ticket 48957 - set proper update status to replication 
7c7f29
 agreement in case of failure
7c7f29
7c7f29
Bug Description:  If a replication agreement fails to send updates it always returns
7c7f29
                  a generic error message even though there are many ways it could be
7c7f29
                  failing.
7c7f29
7c7f29
Fix Description:  Set a proper error message when we fail to update a replica.  Also made
7c7f29
                  all the messages consistent in format, and added new response strings
7c7f29
                  for known errors.
7c7f29
7c7f29
                  Also fixed some minor compiler warnings.
7c7f29
7c7f29
https://fedorahosted.org/389/ticket/48957
7c7f29
7c7f29
Reviewed by: nhosoi(Thanks!)
7c7f29
7c7f29
(cherry picked from commit cdf4fb4ea6f26b4198d2d6b146ca51dcd51a31ef)
7c7f29
---
7c7f29
 ldap/servers/plugins/replication/repl5.h           | 15 +++--
7c7f29
 ldap/servers/plugins/replication/repl5_agmt.c      | 26 ++++----
7c7f29
 .../plugins/replication/repl5_inc_protocol.c       | 70 ++++++++++++++--------
7c7f29
 .../plugins/replication/repl5_protocol_util.c      | 65 ++++++++++++++++++--
7c7f29
 .../plugins/replication/repl5_replica_config.c     |  4 +-
7c7f29
 ldap/servers/plugins/replication/repl5_total.c     |  5 +-
7c7f29
 6 files changed, 132 insertions(+), 53 deletions(-)
7c7f29
7c7f29
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
7c7f29
index 6f6c81a..13a38fd 100644
7c7f29
--- a/ldap/servers/plugins/replication/repl5.h
7c7f29
+++ b/ldap/servers/plugins/replication/repl5.h
7c7f29
@@ -91,11 +91,16 @@
7c7f29
 #define NSDS50_REPL_BELOW_PURGEPOINT 0x07 /* Supplier provided a CSN below the consumer's purge point */
7c7f29
 #define NSDS50_REPL_INTERNAL_ERROR 0x08 /* Something bad happened on consumer */
7c7f29
 #define NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED 0x09 /* Replica released successfully */
7c7f29
-#define NSDS50_REPL_LEGACY_CONSUMER 0x0A    /* replica is a legacy consumer */
7c7f29
-#define NSDS50_REPL_REPLICAID_ERROR 0x0B	/* replicaID doesn't seem to be unique */
7c7f29
-#define NSDS50_REPL_DISABLED 0x0C	/* replica suffix is disabled */
7c7f29
-#define NSDS50_REPL_UPTODATE 0x0D	/* replica is uptodate */
7c7f29
-#define NSDS50_REPL_BACKOFF 0x0E        /* replica wants master to go into backoff mode */
7c7f29
+#define NSDS50_REPL_LEGACY_CONSUMER 0x0A /* replica is a legacy consumer */
7c7f29
+#define NSDS50_REPL_REPLICAID_ERROR 0x0B /* replicaID doesn't seem to be unique */
7c7f29
+#define NSDS50_REPL_DISABLED 0x0C /* replica suffix is disabled */
7c7f29
+#define NSDS50_REPL_UPTODATE 0x0D /* replica is uptodate */
7c7f29
+#define NSDS50_REPL_BACKOFF 0x0E /* replica wants master to go into backoff mode */
7c7f29
+#define NSDS50_REPL_CL_ERROR 0x0F /* Problem reading changelog */
7c7f29
+#define NSDS50_REPL_CONN_ERROR 0x10 /* Problem with replication connection*/
7c7f29
+#define NSDS50_REPL_CONN_TIMEOUT 0x11 /* Connection timeout */
7c7f29
+#define NSDS50_REPL_TRANSIENT_ERROR 0x12 /* Transient error */
7c7f29
+#define NSDS50_REPL_RUV_ERROR 0x13 /* Problem with the RUV */
7c7f29
 #define NSDS50_REPL_REPLICA_NO_RESPONSE 0xff /* No response received */
7c7f29
 
7c7f29
 /* Protocol status */
7c7f29
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
7c7f29
index 76d26a1..52cc8b6 100644
7c7f29
--- a/ldap/servers/plugins/replication/repl5_agmt.c
7c7f29
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
7c7f29
@@ -2460,9 +2460,9 @@ agmt_set_last_update_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *
7c7f29
 					replmsg = NULL;
7c7f29
 				}
7c7f29
 			}
7c7f29
-			PR_snprintf(ra->last_update_status, STATUS_LEN, "%d %s%sLDAP error: %s%s%s",
7c7f29
+			PR_snprintf(ra->last_update_status, STATUS_LEN, "Error (%d) %s%s - LDAP error: %s%s%s%s",
7c7f29
 				ldaprc, message?message:"",message?"":" - ",
7c7f29
-				slapi_err2string(ldaprc), replmsg ? " - " : "", replmsg ? replmsg : "");
7c7f29
+				slapi_err2string(ldaprc), replmsg ? " (" : "", replmsg ? replmsg : "", replmsg ? ")" : "");
7c7f29
 		}
7c7f29
 		/* ldaprc == LDAP_SUCCESS */
7c7f29
 		else if (replrc != 0)
7c7f29
@@ -2470,16 +2470,15 @@ agmt_set_last_update_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *
7c7f29
 			if (replrc == NSDS50_REPL_REPLICA_BUSY)
7c7f29
 			{
7c7f29
 				PR_snprintf(ra->last_update_status, STATUS_LEN,
7c7f29
-					"%d Can't acquire busy replica", replrc ); 
7c7f29
+					"Error (%d) Can't acquire busy replica", replrc );
7c7f29
 			}
7c7f29
 			else if (replrc == NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED)
7c7f29
 			{
7c7f29
-				PR_snprintf(ra->last_update_status, STATUS_LEN, "%d %s",
7c7f29
-					ldaprc, "Replication session successful");
7c7f29
+				PR_snprintf(ra->last_update_status, STATUS_LEN, "Error (0) Replication session successful");
7c7f29
 			}
7c7f29
 			else if (replrc == NSDS50_REPL_DISABLED)
7c7f29
 			{
7c7f29
-				PR_snprintf(ra->last_update_status, STATUS_LEN, "%d Incremental update aborted: "
7c7f29
+				PR_snprintf(ra->last_update_status, STATUS_LEN, "Error (%d) Incremental update aborted: "
7c7f29
 					"Replication agreement for %s\n can not be updated while the replica is disabled.\n"
7c7f29
 					"(If the suffix is disabled you must enable it then restart the server for replication to take place).",
7c7f29
 					replrc, ra->long_name ? ra->long_name : "a replica");
7c7f29
@@ -2493,20 +2492,18 @@ agmt_set_last_update_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *
7c7f29
 			else
7c7f29
 			{
7c7f29
 				PR_snprintf(ra->last_update_status, STATUS_LEN,
7c7f29
-					"%d Replication error acquiring replica: %s%s%s",
7c7f29
-					replrc, protocol_response2string(replrc),
7c7f29
-					message?" - ":"",message?message:"");
7c7f29
+					"Error (%d) Replication error acquiring replica: %s%s(%s)",
7c7f29
+					replrc, message?message:"", message?" ":"", protocol_response2string(replrc));
7c7f29
 			}
7c7f29
 		}
7c7f29
 		else if (message != NULL) /* replrc == NSDS50_REPL_REPLICA_READY == 0 */
7c7f29
 		{
7c7f29
-			PR_snprintf(ra->last_update_status, STATUS_LEN, 
7c7f29
-						"%d Replica acquired successfully: %s",
7c7f29
-						ldaprc, message);
7c7f29
+			PR_snprintf(ra->last_update_status, STATUS_LEN,
7c7f29
+				"Error (0) Replica acquired successfully: %s", message);
7c7f29
 		}
7c7f29
 		else
7c7f29
 		{ /* agmt_set_last_update_status(0,0,NULL) to reset agmt */
7c7f29
-			PR_snprintf(ra->last_update_status, STATUS_LEN, "%d", ldaprc);
7c7f29
+			ra->last_update_status[0] = '\0';
7c7f29
 		}
7c7f29
 	}
7c7f29
 }
7c7f29
@@ -2737,7 +2734,8 @@ get_agmt_status(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
7c7f29
 		slapi_entry_add_string(e, "nsds5replicaChangesSentSinceStartup", changecount_string);
7c7f29
 		if (ra->last_update_status[0] == '\0')
7c7f29
 		{
7c7f29
-			slapi_entry_add_string(e, "nsds5replicaLastUpdateStatus", "0 No replication sessions started since server startup");
7c7f29
+			slapi_entry_add_string(e, "nsds5replicaLastUpdateStatus",
7c7f29
+			                       "Error (0) No replication sessions started since server startup");
7c7f29
 		}
7c7f29
 		else
7c7f29
 		{
7c7f29
diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c
7c7f29
index 27bac5d..d1de6c5 100644
7c7f29
--- a/ldap/servers/plugins/replication/repl5_inc_protocol.c
7c7f29
+++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c
7c7f29
@@ -671,7 +671,6 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
   int wait_change_timer_set = 0;
7c7f29
   int current_state = STATE_START;
7c7f29
   int next_state = STATE_START;
7c7f29
-  int optype, ldaprc;
7c7f29
   int done;
7c7f29
   int e1;
7c7f29
 
7c7f29
@@ -838,14 +837,6 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
           } else if (rc == ACQUIRE_FATAL_ERROR){
7c7f29
               next_state = STATE_STOP_FATAL_ERROR;
7c7f29
           }
7c7f29
-
7c7f29
-          if (rc != ACQUIRE_SUCCESS){
7c7f29
-              int optype, ldaprc;
7c7f29
-              conn_get_error(prp->conn, &optype, &ldaprc);
7c7f29
-              agmt_set_last_update_status(prp->agmt, ldaprc,
7c7f29
-                  prp->last_acquire_response_code, "Unable to acquire replica");
7c7f29
-          }
7c7f29
-
7c7f29
           object_release(prp->replica_object);
7c7f29
           break;
7c7f29
 
7c7f29
@@ -934,10 +925,6 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
               } else if (rc == ACQUIRE_FATAL_ERROR){
7c7f29
                   next_state = STATE_STOP_FATAL_ERROR;
7c7f29
               }
7c7f29
-              if (rc != ACQUIRE_SUCCESS){
7c7f29
-                  conn_get_error(prp->conn, &optype, &ldaprc);
7c7f29
-                  agmt_set_last_update_status(prp->agmt, ldaprc, prp->last_acquire_response_code, "Unable to acquire replica");
7c7f29
-              }
7c7f29
               /*
7c7f29
                * We either need to step the backoff timer, or
7c7f29
                * destroy it if we don't need it anymore
7c7f29
@@ -1037,7 +1024,8 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
                   slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
                       "%s: Replica has no update vector. It has never been initialized.\n",
7c7f29
                       agmt_get_long_name(prp->agmt));
7c7f29
-                  agmt_set_last_update_status(prp->agmt, 0, rc, "Replica is not initialized");
7c7f29
+                  agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_RUV_ERROR,
7c7f29
+                      "Replica is not initialized");
7c7f29
                   next_state = STATE_BACKOFF_START;
7c7f29
                   break;
7c7f29
               case EXAMINE_RUV_GENERATION_MISMATCH:
7c7f29
@@ -1045,8 +1033,9 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
                       "%s: The remote replica has a different database generation ID than "
7c7f29
                       "the local database.  You may have to reinitialize the remote replica, "
7c7f29
                       "or the local replica.\n", agmt_get_long_name(prp->agmt));
7c7f29
-                  agmt_set_last_update_status(prp->agmt, 0, rc, "Replica has different database "
7c7f29
-                      "generation ID, remote replica may need to be initialized");
7c7f29
+                  agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_RUV_ERROR,
7c7f29
+                      "Replica has different database generation ID, remote "
7c7f29
+                      "replica may need to be initialized");
7c7f29
                   next_state = STATE_BACKOFF_START;
7c7f29
                   break;
7c7f29
               case EXAMINE_RUV_REPLICA_TOO_OLD:
7c7f29
@@ -1054,7 +1043,8 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
                       "%s: Replica update vector is too out of date to bring "
7c7f29
                       "into sync using the incremental protocol. The replica "
7c7f29
                       "must be reinitialized.\n", agmt_get_long_name(prp->agmt));
7c7f29
-                  agmt_set_last_update_status(prp->agmt, 0, rc, "Replica needs to be reinitialized");
7c7f29
+                  agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_RUV_ERROR,
7c7f29
+                      "Replica needs to be reinitialized");
7c7f29
                   next_state = STATE_BACKOFF_START;
7c7f29
                   break;
7c7f29
               case EXAMINE_RUV_OK:
7c7f29
@@ -1069,11 +1059,15 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
                       slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
                           "%s: Incremental protocol: fatal error - too much time skew between replicas!\n",
7c7f29
                           agmt_get_long_name(prp->agmt));
7c7f29
+                      agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_EXCESSIVE_CLOCK_SKEW,
7c7f29
+                          "fatal error - too much time skew between replicas");
7c7f29
                       next_state = STATE_STOP_FATAL_ERROR;
7c7f29
                   } else if (rc != 0) /* internal error */ {
7c7f29
                       slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
                           "%s: Incremental protocol: fatal internal error updating the CSN generator!\n",
7c7f29
                           agmt_get_long_name(prp->agmt));
7c7f29
+                      agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_INTERNAL_ERROR,
7c7f29
+                          "fatal internal error updating the CSN generator");
7c7f29
                       next_state = STATE_STOP_FATAL_ERROR;
7c7f29
                   } else {
7c7f29
                       /*
7c7f29
@@ -1097,7 +1091,8 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
                           next_state = STATE_BACKOFF_START;
7c7f29
                       } else if (rc == UPDATE_TRANSIENT_ERROR){
7c7f29
                           dev_debug("repl5_inc_run(STATE_SENDING_UPDATES) -> send_updates = UPDATE_TRANSIENT_ERROR -> STATE_BACKOFF_START");
7c7f29
-                          agmt_set_last_update_status(prp->agmt, 0, rc, "Incremental update transient error.  Backing off, will retry update later.");
7c7f29
+                          agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_TRANSIENT_ERROR,
7c7f29
+                              "Incremental update transient error.  Backing off, will retry update later.");
7c7f29
                           next_state = STATE_BACKOFF_START;
7c7f29
                       } else if (rc == UPDATE_FATAL_ERROR){
7c7f29
                           dev_debug("repl5_inc_run(STATE_SENDING_UPDATES) -> send_updates = UPDATE_FATAL_ERROR -> STATE_STOP_FATAL_ERROR");
7c7f29
@@ -1114,11 +1109,13 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
                           conn_disconnect (prp->conn);
7c7f29
                       } else if (rc == UPDATE_CONNECTION_LOST){
7c7f29
                           dev_debug("repl5_inc_run(STATE_SENDING_UPDATES) -> send_updates = UPDATE_CONNECTION_LOST -> STATE_BACKOFF_START");
7c7f29
-                          agmt_set_last_update_status(prp->agmt, 0, rc, "Incremental update connection error.  Backing off, will retry update later.");
7c7f29
+                          agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CONN_ERROR,
7c7f29
+                              "Incremental update connection error.  Backing off, will retry update later.");
7c7f29
                           next_state = STATE_BACKOFF_START;
7c7f29
                       } else if (rc == UPDATE_TIMEOUT){
7c7f29
                           dev_debug("repl5_inc_run(STATE_SENDING_UPDATES) -> send_updates = UPDATE_TIMEOUT -> STATE_BACKOFF_START");
7c7f29
-                          agmt_set_last_update_status(prp->agmt, 0, rc, "Incremental update timeout error.  Backing off, will retry update later.");
7c7f29
+                          agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CONN_TIMEOUT,
7c7f29
+                              "Incremental update timeout error.  Backing off, will retry update later.");
7c7f29
                           next_state = STATE_BACKOFF_START;
7c7f29
                       }
7c7f29
                       /* Set the updates times based off the result of send_updates() */
7c7f29
@@ -1173,8 +1170,6 @@ repl5_inc_run(Private_Repl_Protocol *prp)
7c7f29
           /*
7c7f29
            * We encountered some sort of a fatal error. Suspend.
7c7f29
            */
7c7f29
-          /* XXXggood update state in replica */
7c7f29
-          agmt_set_last_update_status(prp->agmt, -1, 0, "Incremental update has failed and requires administrator action");
7c7f29
           dev_debug("repl5_inc_run(STATE_STOP_FATAL_ERROR)");
7c7f29
           slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
               "%s: Incremental update failed and requires administrator action\n",
7c7f29
@@ -1630,30 +1625,40 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
7c7f29
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 				"%s: Invalid parameter passed to cl5CreateReplayIterator\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+				"Invalid parameter passed to cl5CreateReplayIterator");
7c7f29
 			return_value = UPDATE_FATAL_ERROR;
7c7f29
 			break;
7c7f29
 		case CL5_BAD_FORMAT:     /* db data has unexpected format */
7c7f29
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 				"%s: Unexpected format encountered in changelog database\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+				"Unexpected format encountered in changelog database");
7c7f29
 			return_value = UPDATE_FATAL_ERROR;
7c7f29
 			break;
7c7f29
 		case CL5_BAD_STATE: /* changelog is in an incorrect state for attempted operation */
7c7f29
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 				"%s: Changelog database was in an incorrect state\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+				"Changelog database was in an incorrect state");
7c7f29
 			return_value = UPDATE_FATAL_ERROR;
7c7f29
 			break;
7c7f29
 		case CL5_BAD_DBVERSION:  /* changelog has invalid dbversion */
7c7f29
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 				"%s: Incorrect dbversion found in changelog database\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+				"Incorrect dbversion found in changelog database");
7c7f29
 			return_value = UPDATE_FATAL_ERROR;
7c7f29
 			break;
7c7f29
 		case CL5_DB_ERROR:       /* database error */
7c7f29
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 				"%s: A changelog database error was encountered\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+				"Changelog database error was encountered");
7c7f29
 			return_value = UPDATE_FATAL_ERROR;
7c7f29
 			break;
7c7f29
 		case CL5_NOTFOUND:       /* we have no changes to send */
7c7f29
@@ -1666,6 +1671,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
7c7f29
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 				"%s: Memory allocation error occurred\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+				"changelog memory allocation error occurred");
7c7f29
 			return_value = UPDATE_FATAL_ERROR;
7c7f29
 			break;
7c7f29
 		case CL5_SYSTEM_ERROR:   /* NSPR error occurred: use PR_GetError for further info */
7c7f29
@@ -1694,15 +1701,20 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
7c7f29
 			break;
7c7f29
 		case CL5_PURGED_DATA:    /* requested data has been purged */
7c7f29
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
-				"%s: Data required to update replica has been purged. "
7c7f29
+				"%s: Data required to update replica has been purged from the changelog. "
7c7f29
 				"The replica must be reinitialized.\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+				"Data required to update replica has been purged from the changelog. "
7c7f29
+				"The replica must be reinitialized.");
7c7f29
 			return_value = UPDATE_FATAL_ERROR;
7c7f29
 			break;
7c7f29
 		case CL5_MISSING_DATA:   /* data should be in the changelog, but is missing */
7c7f29
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 				"%s: Missing data encountered\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+				"Changelog data is missing");
7c7f29
 			return_value = UPDATE_FATAL_ERROR;
7c7f29
 			break;
7c7f29
 		case CL5_UNKNOWN_ERROR:   /* unclassified error */
7c7f29
@@ -1738,8 +1750,9 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
7c7f29
 			rc = repl5_inc_create_async_result_thread(rd);
7c7f29
 			if (rc) {
7c7f29
 				slapi_log_error (SLAPI_LOG_FATAL, repl_plugin_name, "%s: repl5_inc_run: "
7c7f29
-							 "repl5_tot_create_async_result_thread failed; error - %d\n", 
7c7f29
+							 "repl5_inc_create_async_result_thread failed; error - %d\n",
7c7f29
 							 agmt_get_long_name(prp->agmt), rc);
7c7f29
+				agmt_set_last_update_status(prp->agmt, 0, rc, "Failed to create result thread");
7c7f29
 				return_value = UPDATE_FATAL_ERROR;
7c7f29
 			}
7c7f29
 		}
7c7f29
@@ -1898,6 +1911,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
7c7f29
 				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 					"%s: Invalid parameter passed to cl5GetNextOperationToReplay\n",
7c7f29
 					agmt_get_long_name(prp->agmt));
7c7f29
+				agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+					"Invalid parameter passed to cl5GetNextOperationToReplay");
7c7f29
 				return_value = UPDATE_FATAL_ERROR;
7c7f29
 				finished = 1;
7c7f29
 				break;
7c7f29
@@ -1912,6 +1927,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
7c7f29
 				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 					"%s: A database error occurred (cl5GetNextOperationToReplay)\n",
7c7f29
 					agmt_get_long_name(prp->agmt));
7c7f29
+				agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+					"Database error occurred while getting the next operation to replay");
7c7f29
 				return_value = UPDATE_FATAL_ERROR;
7c7f29
 				finished = 1;
7c7f29
 				break;
7c7f29
@@ -1922,8 +1939,10 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
7c7f29
 				break;
7c7f29
 			case CL5_MEMORY_ERROR:
7c7f29
 				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
-					"%s: A memory allocation error occurred (cl5GetNextOperationToRepla)\n",
7c7f29
+					"%s: A memory allocation error occurred (cl5GetNextOperationToReplay)\n",
7c7f29
 					agmt_get_long_name(prp->agmt));
7c7f29
+				agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_CL_ERROR,
7c7f29
+					"Memory allocation error occurred (cl5GetNextOperationToReplay)");
7c7f29
 				return_value = UPDATE_FATAL_ERROR;
7c7f29
 				break;
7c7f29
 			case CL5_IGNORE_OP:
7c7f29
@@ -1985,6 +2004,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
7c7f29
 			if (!replarea_sdn) {
7c7f29
 				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
7c7f29
 				                "send_updates: Unknown replication area due to agreement not found.");
7c7f29
+				agmt_set_last_update_status(prp->agmt, 0, -1, "Agreement is corrupted: missing suffix");
7c7f29
 				return_value = UPDATE_FATAL_ERROR;
7c7f29
 			} else {
7c7f29
 				replica_subentry_update(replarea_sdn, rid);
7c7f29
diff --git a/ldap/servers/plugins/replication/repl5_protocol_util.c b/ldap/servers/plugins/replication/repl5_protocol_util.c
7c7f29
index ce27a8a..ce6281a 100644
7c7f29
--- a/ldap/servers/plugins/replication/repl5_protocol_util.c
7c7f29
+++ b/ldap/servers/plugins/replication/repl5_protocol_util.c
7c7f29
@@ -140,10 +140,18 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 	crc = conn_connect(conn);
7c7f29
 	if (CONN_OPERATION_FAILED == crc)
7c7f29
 	{
7c7f29
+		int operation, error;
7c7f29
+		conn_get_error(conn, &operation, &error);
7c7f29
+		agmt_set_last_update_status(prp->agmt, error, NSDS50_REPL_CONN_ERROR,
7c7f29
+			"Problem connecting to replica");
7c7f29
 		return_value = ACQUIRE_TRANSIENT_ERROR;
7c7f29
 	}
7c7f29
 	else if (CONN_SSL_NOT_ENABLED == crc)
7c7f29
 	{
7c7f29
+		int operation, error;
7c7f29
+		conn_get_error(conn, &operation, &error);
7c7f29
+		agmt_set_last_update_status(prp->agmt, error, NSDS50_REPL_CONN_ERROR,
7c7f29
+			"Problem connecting to replica (SSL not enabled)");
7c7f29
 		return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 	}
7c7f29
 	else
7c7f29
@@ -295,6 +303,9 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 								"an internal error occurred on the remote replica. "
7c7f29
 								"Replication is aborting.\n",
7c7f29
 								agmt_get_long_name(prp->agmt));
7c7f29
+							agmt_set_last_update_status(prp->agmt, 0, extop_result,
7c7f29
+								"Failed to acquire replica: "
7c7f29
+								"Internal error occurred on the remote replica");
7c7f29
 							return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 							break;
7c7f29
 					case NSDS50_REPL_PERMISSION_DENIED:
7c7f29
@@ -307,6 +318,11 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 								"supply replication updates to the replica. "
7c7f29
 								"Will retry later.\n",
7c7f29
 								agmt_get_long_name(prp->agmt), repl_binddn);
7c7f29
+							agmt_set_last_update_status(prp->agmt, 0, extop_result,
7c7f29
+								"Unable to acquire replica: permission denied. "
7c7f29
+								"The bind dn does not have permission to "
7c7f29
+								"supply replication updates to the replica. "
7c7f29
+								"Will retry later.");
7c7f29
 							slapi_ch_free((void **)&repl_binddn);
7c7f29
 							return_value = ACQUIRE_TRANSIENT_ERROR;
7c7f29
 							break;
7c7f29
@@ -321,6 +337,10 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 								"Replication is aborting.\n",
7c7f29
 								agmt_get_long_name(prp->agmt),
7c7f29
 								slapi_sdn_get_dn(repl_root));
7c7f29
+							agmt_set_last_update_status(prp->agmt, 0, extop_result,
7c7f29
+								"Unable to acquire replica: there is no "
7c7f29
+								"replicated area on the consumer server. "
7c7f29
+								"Replication is aborting.");
7c7f29
 							slapi_sdn_free(&repl_root);
7c7f29
 							return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 							break;
7c7f29
@@ -342,6 +362,11 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 							"startReplicationRequest extended operation sent by the "
7c7f29
 							"supplier. Replication is aborting.\n",
7c7f29
 							agmt_get_long_name(prp->agmt));
7c7f29
+						agmt_set_last_update_status(prp->agmt, 0, extop_result,
7c7f29
+							"Unable to acquire replica: "
7c7f29
+							"the consumer was unable to decode the "
7c7f29
+							"startReplicationRequest extended operation sent "
7c7f29
+							"by the supplier. Replication is aborting.");
7c7f29
 						return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 						break;
7c7f29
 					case NSDS50_REPL_REPLICA_BUSY:
7c7f29
@@ -365,6 +390,10 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 								"by another supplier. Will try later\n",
7c7f29
 								agmt_get_long_name(prp->agmt));
7c7f29
 						}
7c7f29
+						agmt_set_last_update_status(prp->agmt, 0, extop_result,
7c7f29
+							"Unable to acquire replica: "
7c7f29
+							"the replica is currently being updated by another "
7c7f29
+							"supplier.");
7c7f29
 						return_value = ACQUIRE_REPLICA_BUSY;
7c7f29
 						break;
7c7f29
 					case NSDS50_REPL_LEGACY_CONSUMER:
7c7f29
@@ -373,6 +402,9 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 							"%s: Unable to acquire replica: the replica "
7c7f29
 							"is supplied by a legacy supplier. "
7c7f29
 							"Replication is aborting.\n", agmt_get_long_name(prp->agmt));
7c7f29
+						agmt_set_last_update_status(prp->agmt, 0, extop_result,
7c7f29
+							"Unable to acquire replica: the replica is supplied "
7c7f29
+							"by a legacy supplier.  Replication is aborting.");
7c7f29
 						return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 						break;
7c7f29
 					case NSDS50_REPL_REPLICAID_ERROR:
7c7f29
@@ -382,6 +414,9 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 							"has the same Replica ID as this one. "
7c7f29
 							"Replication is aborting.\n",
7c7f29
 							agmt_get_long_name(prp->agmt));
7c7f29
+						agmt_set_last_update_status(prp->agmt, 0, 0,
7c7f29
+							"Unable to aquire replica: the replica has the same "
7c7f29
+							"Replica ID as this one. Replication is aborting.");
7c7f29
 						return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 						break;
7c7f29
 					case NSDS50_REPL_BACKOFF:
7c7f29
@@ -392,6 +427,9 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
                                                         "the replica instructed us to go into "
7c7f29
                                                         "backoff mode. Will retry later.\n",
7c7f29
                                                         agmt_get_long_name(prp->agmt));
7c7f29
+						agmt_set_last_update_status(prp->agmt, 0, extop_result,
7c7f29
+							"Unable to acquire replica: the replica instructed "
7c7f29
+							"us to go into backoff mode. Will retry later.");
7c7f29
 						return_value = ACQUIRE_TRANSIENT_ERROR;
7c7f29
 						break;
7c7f29
 					case NSDS50_REPL_REPLICA_READY:
7c7f29
@@ -450,6 +488,8 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 						return_value = ACQUIRE_SUCCESS;
7c7f29
 						break;
7c7f29
 					default:
7c7f29
+						agmt_set_last_update_status(prp->agmt, 0, extop_result,
7c7f29
+							"Unable to acquire replica");
7c7f29
 						return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 					}
7c7f29
 				}
7c7f29
@@ -461,6 +501,10 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 						"startReplication extended operation. "
7c7f29
 						"Replication is aborting.\n", 
7c7f29
 						agmt_get_long_name(prp->agmt));
7c7f29
+					agmt_set_last_update_status(prp->agmt, 0, NSDS50_REPL_DECODING_ERROR,
7c7f29
+						"Unable to parse the response to the "
7c7f29
+						"startReplication extended operation. "
7c7f29
+						"Replication is aborting.");
7c7f29
 					prp->last_acquire_response_code = NSDS50_REPL_INTERNAL_ERROR;
7c7f29
 					return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 				}
7c7f29
@@ -477,6 +521,9 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 					"extended operation to consumer (%s). Will retry later.\n",
7c7f29
 					agmt_get_long_name(prp->agmt),
7c7f29
 					error ? ldap_err2string(error) : "unknown error");
7c7f29
+				agmt_set_last_update_status(prp->agmt, error, NSDS50_REPL_CONN_ERROR,
7c7f29
+					"Unable to receive the response for a startReplication "
7c7f29
+					"extended operation to consumer. Will retry later.");
7c7f29
 			}
7c7f29
 		}
7c7f29
 		else
7c7f29
@@ -486,6 +533,9 @@ acquire_replica(Private_Repl_Protocol *prp, char *prot_oid, RUV **ruv)
7c7f29
 				"%s: Unable to obtain current CSN. "
7c7f29
 				"Replication is aborting.\n",
7c7f29
 				agmt_get_long_name(prp->agmt));
7c7f29
+			agmt_set_last_update_status(prp->agmt, 0, 0,
7c7f29
+				"Unable to obtain current CSN. "
7c7f29
+				"Replication is aborting.");
7c7f29
 			return_value = ACQUIRE_FATAL_ERROR;
7c7f29
 		}
7c7f29
 	}
7c7f29
@@ -535,8 +585,8 @@ release_replica(Private_Repl_Protocol *prp)
7c7f29
 	PR_ASSERT(NULL != prp);
7c7f29
 	PR_ASSERT(NULL != prp->conn);
7c7f29
 
7c7f29
-    if (!prp->replica_acquired)
7c7f29
-        return;
7c7f29
+	if (!prp->replica_acquired)
7c7f29
+		return;
7c7f29
     
7c7f29
 	replarea_sdn = agmt_get_replarea(prp->agmt);
7c7f29
 	payload = NSDS50EndReplicationRequest_new((char *)slapi_sdn_get_dn(replarea_sdn)); /* XXXggood had to cast away const */
7c7f29
@@ -650,9 +700,14 @@ protocol_response2string (int response)
7c7f29
         case NSDS50_REPL_BELOW_PURGEPOINT:          return "csn below purge point";
7c7f29
         case NSDS50_REPL_INTERNAL_ERROR:            return "internal error";
7c7f29
         case NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED: return "replica released";
7c7f29
-        case NSDS50_REPL_LEGACY_CONSUMER:           return "replica is a legacy consumer";						
7c7f29
-		case NSDS50_REPL_REPLICAID_ERROR:			return "duplicate replica ID detected";
7c7f29
-		case NSDS50_REPL_UPTODATE:					return "no change to send";
7c7f29
+        case NSDS50_REPL_LEGACY_CONSUMER:           return "replica is a legacy consumer";
7c7f29
+        case NSDS50_REPL_REPLICAID_ERROR:           return "duplicate replica ID detected";
7c7f29
+        case NSDS50_REPL_UPTODATE:                  return "no change to send";
7c7f29
+        case NSDS50_REPL_CL_ERROR:                  return "changelog error";
7c7f29
+        case NSDS50_REPL_CONN_ERROR:                return "connection error";
7c7f29
+        case NSDS50_REPL_CONN_TIMEOUT:              return "connection timeout";
7c7f29
+        case NSDS50_REPL_TRANSIENT_ERROR:           return "transient error";
7c7f29
+        case NSDS50_REPL_RUV_ERROR:                 return "RUV error";
7c7f29
         default:                                    return "unknown error";
7c7f29
     }
7c7f29
 }
7c7f29
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
7c7f29
index 011e4ca..59e5298 100644
7c7f29
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
7c7f29
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
7c7f29
@@ -639,8 +639,8 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
7c7f29
 	}
7c7f29
 
7c7f29
 done:
7c7f29
-    if (mtnode_ext->replica)
7c7f29
-        object_release (mtnode_ext->replica);
7c7f29
+	if (mtnode_ext->replica)
7c7f29
+		object_release (mtnode_ext->replica);
7c7f29
 
7c7f29
 	/* slapi_ch_free accepts NULL pointer */
7c7f29
 	slapi_ch_free_string(&replica_root);
7c7f29
diff --git a/ldap/servers/plugins/replication/repl5_total.c b/ldap/servers/plugins/replication/repl5_total.c
7c7f29
index 0512dfa..dcb7af5 100644
7c7f29
--- a/ldap/servers/plugins/replication/repl5_total.c
7c7f29
+++ b/ldap/servers/plugins/replication/repl5_total.c
7c7f29
@@ -533,8 +533,9 @@ my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
7c7f29
 		goto loser;
7c7f29
 	}
7c7f29
 	
7c7f29
-    if (attrval)
7c7f29
-        ber_bvfree(attrval); 
7c7f29
+	if (attrval)
7c7f29
+		ber_bvfree(attrval);
7c7f29
+
7c7f29
 	return 0;
7c7f29
 
7c7f29
 loser:
7c7f29
-- 
7c7f29
2.4.11
7c7f29