From c72f6ba1e991f6e1a4fef5fac04ee474ec846692 Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Mar 08 2012 21:32:14 +0000 Subject: Ticket 317 - RHDS fractional replication with excluded password policy attributes leads to wrong error messages. https://fedorahosted.org/389/ticket/317 Resolves: Ticket 317 Bug Description: RHDS fractional replication with excluded password policy attributes leads to wrong error messages. Reviewed by: nhosoi (Thanks!) Branch: master Fix Description: Fractional replication can remove _all_ mods in an add or modify operation. The code should just skip add and modify operations that contain no data. Platforms tested: RHEL6 x86_64 Flag Day: no Doc impact: no cherry picked and ported from 72401ea2588d3aec7622155fdf5dd9e5af7f8f95 on Directory_Server_8_2_Branch --- diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c index c9ad6fc..a615a29 100644 --- a/ldap/servers/plugins/replication/repl5_inc_protocol.c +++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c @@ -163,6 +163,9 @@ typedef struct result_data */ #define PROTOCOL_IS_SHUTDOWN(prp) (event_occurred(prp, EVENT_PROTOCOL_SHUTDOWN) || prp->terminate) +/* mods should be LDAPMod **mods */ +#define MODS_ARE_EMPTY(mods) ((mods == NULL) || (mods[0] == NULL)) + /* Forward declarations */ static PRUint32 event_occurred(Private_Repl_Protocol *prp, PRUint32 event); static void reset_events (Private_Repl_Protocol *prp); @@ -1385,6 +1388,12 @@ replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op, int *m LDAPMod **modrdn_mods = NULL; char csn_str[CSN_STRSIZE]; /* For logging only */ + if (message_id) { + /* if we get out of this function without setting message_id, it means + we didn't send an op, so no result needs to be processed */ + *message_id = 0; + } + /* Construct the replication info control that accompanies the operation */ if (SLAPI_OPERATION_ADD == op->operation_type) { @@ -1445,8 +1454,21 @@ replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op, int *m { repl5_strip_fractional_mods(prp->agmt,entryattrs); } - return_value = conn_send_add(prp->conn, REPL_GET_DN(&op->target_address), - entryattrs, update_control, message_id); + if (MODS_ARE_EMPTY(entryattrs)) { + if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: replay_update: %s operation (dn=\"%s\" csn=%s) " + "not sent - empty\n", + agmt_get_long_name(prp->agmt), + op2string(op->operation_type), + REPL_GET_DN(&op->target_address), + csn_as_string(op->csn, PR_FALSE, csn_str)); + } + return_value = CONN_OPERATION_SUCCESS; + } else { + return_value = conn_send_add(prp->conn, REPL_GET_DN(&op->target_address), + entryattrs, update_control, message_id); + } ldap_mods_free(entryattrs, 1); } break; @@ -1457,8 +1479,21 @@ replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op, int *m { repl5_strip_fractional_mods(prp->agmt,op->p.p_modify.modify_mods); } - return_value = conn_send_modify(prp->conn, REPL_GET_DN(&op->target_address), - op->p.p_modify.modify_mods, update_control, message_id); + if (MODS_ARE_EMPTY(op->p.p_modify.modify_mods)) { + if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: replay_update: %ss operation (dn=\"%s\" csn=%s) " + "not sent - empty\n", + agmt_get_long_name(prp->agmt), + op2string(op->operation_type), + REPL_GET_DN(&op->target_address), + csn_as_string(op->csn, PR_FALSE, csn_str)); + } + return_value = CONN_OPERATION_SUCCESS; + } else { + return_value = conn_send_modify(prp->conn, REPL_GET_DN(&op->target_address), + op->p.p_modify.modify_mods, update_control, message_id); + } break; case SLAPI_OPERATION_DELETE: return_value = conn_send_delete(prp->conn, REPL_GET_DN(&op->target_address), @@ -1869,7 +1904,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu replica_id = csn_get_replicaid(entry.op->csn); uniqueid = entry.op->target_address.uniqueid; - if (prp->repl50consumer) + if (prp->repl50consumer && message_id) { int operation, error = 0; @@ -1881,7 +1916,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu csn_as_string(entry.op->csn, PR_FALSE, csn_str); return_value = repl5_inc_update_from_op_result(prp, replay_crc, error, csn_str, uniqueid, replica_id, &finished, num_changes_sent); } - else { + else if (message_id) { /* Queue the details for pickup later in the response thread */ repl5_inc_operation *sop = NULL; sop = repl5_inc_operation_new(); @@ -1891,6 +1926,12 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu sop->replica_id = replica_id; PL_strncpyz(sop->uniqueid, uniqueid, sizeof(sop->uniqueid)); repl5_int_push_operation(rd,sop); + } else { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: Skipping update operation with no message_id (uniqueid %s, CSN %s):\n", + agmt_get_long_name(prp->agmt), + entry.op->target_address.uniqueid, csn_str); + agmt_inc_last_update_changecount (prp->agmt, csn_get_replicaid(entry.op->csn), 1 /*skipped*/); } } break;