diff options
author | David Boreham <dboreham@redhat.com> | 2005-04-28 22:50:15 +0000 |
---|---|---|
committer | David Boreham <dboreham@redhat.com> | 2005-04-28 22:50:15 +0000 |
commit | 7cf67d15b3c96b1fad71e20036552de08527e276 (patch) | |
tree | ee77212f8d285b76aa63a6e8c2bce004e8287d17 /ldap/servers | |
parent | 984a784f2c0d1c9115baee85b967f010285830a1 (diff) | |
download | ds-7cf67d15b3c96b1fad71e20036552de08527e276.tar.gz ds-7cf67d15b3c96b1fad71e20036552de08527e276.tar.xz ds-7cf67d15b3c96b1fad71e20036552de08527e276.zip |
Fix the fact that if an operation fails in a total update, we immediately halt
Diffstat (limited to 'ldap/servers')
3 files changed, 127 insertions, 101 deletions
diff --git a/ldap/servers/plugins/replication/windows_inc_protocol.c b/ldap/servers/plugins/replication/windows_inc_protocol.c index cb9e9c0e..b5325b92 100644 --- a/ldap/servers/plugins/replication/windows_inc_protocol.c +++ b/ldap/servers/plugins/replication/windows_inc_protocol.c @@ -142,7 +142,6 @@ static void protocol_sleep(Private_Repl_Protocol *prp, PRIntervalTime duration); static int send_updates(Private_Repl_Protocol *prp, RUV *ruv, PRUint32 *num_changes_sent); static void windows_inc_backoff_expired(time_t timer_fire_time, void *arg); static int windows_examine_update_vector(Private_Repl_Protocol *prp, RUV *ruv); -static PRBool ignore_error_and_keep_going(int error); static const char* state2name (int state); static const char* event2name (int event); static const char* acquire2name (int code); @@ -1271,7 +1270,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu if (CONN_OPERATION_FAILED == replay_crc) { /* Map ldap error code to return value */ - if (!ignore_error_and_keep_going(error)) + if (!windows_ignore_error_and_keep_going(error)) { return_value = UPDATE_TRANSIENT_ERROR; finished = 1; @@ -1643,101 +1642,6 @@ windows_examine_update_vector(Private_Repl_Protocol *prp, RUV *remote_ruv) } -/* - * When we get an error from an LDAP operation, we call this - * function to decide if we should just keep replaying - * updates, or if we should stop, back off, and try again - * later. - * Returns PR_TRUE if we shoould keep going, PR_FALSE if - * we should back off and try again later. - * - * In general, we keep going if the return code is consistent - * with some sort of bug in URP that causes the consumer to - * emit an error code that it shouldn't have, e.g. LDAP_ALREADY_EXISTS. - * - * We stop if there's some indication that the server just completely - * failed to process the operation, e.g. LDAP_OPERATIONS_ERROR. - */ -static PRBool -ignore_error_and_keep_going(int error) -{ - int return_value; - - LDAPDebug( LDAP_DEBUG_TRACE, "=> ignore_error_and_keep_going\n", 0, 0, 0 ); - - switch (error) - { - /* Cases where we keep going */ - case LDAP_SUCCESS: - case LDAP_NO_SUCH_ATTRIBUTE: - case LDAP_UNDEFINED_TYPE: - case LDAP_CONSTRAINT_VIOLATION: - case LDAP_TYPE_OR_VALUE_EXISTS: - case LDAP_INVALID_SYNTAX: - case LDAP_NO_SUCH_OBJECT: - case LDAP_INVALID_DN_SYNTAX: - case LDAP_IS_LEAF: - case LDAP_INSUFFICIENT_ACCESS: - case LDAP_NAMING_VIOLATION: - case LDAP_OBJECT_CLASS_VIOLATION: - case LDAP_NOT_ALLOWED_ON_NONLEAF: - case LDAP_NOT_ALLOWED_ON_RDN: - case LDAP_ALREADY_EXISTS: - case LDAP_NO_OBJECT_CLASS_MODS: - return_value = PR_TRUE; - break; - - /* Cases where we stop and retry */ - case LDAP_OPERATIONS_ERROR: - case LDAP_PROTOCOL_ERROR: - case LDAP_TIMELIMIT_EXCEEDED: - case LDAP_SIZELIMIT_EXCEEDED: - case LDAP_STRONG_AUTH_NOT_SUPPORTED: - case LDAP_STRONG_AUTH_REQUIRED: - case LDAP_PARTIAL_RESULTS: - case LDAP_REFERRAL: - case LDAP_ADMINLIMIT_EXCEEDED: - case LDAP_UNAVAILABLE_CRITICAL_EXTENSION: - case LDAP_CONFIDENTIALITY_REQUIRED: - case LDAP_SASL_BIND_IN_PROGRESS: - case LDAP_INAPPROPRIATE_MATCHING: - case LDAP_ALIAS_PROBLEM: - case LDAP_ALIAS_DEREF_PROBLEM: - case LDAP_INAPPROPRIATE_AUTH: - case LDAP_INVALID_CREDENTIALS: - case LDAP_BUSY: - case LDAP_UNAVAILABLE: - case LDAP_UNWILLING_TO_PERFORM: - case LDAP_LOOP_DETECT: - case LDAP_SORT_CONTROL_MISSING: - case LDAP_INDEX_RANGE_ERROR: - case LDAP_RESULTS_TOO_LARGE: - case LDAP_AFFECTS_MULTIPLE_DSAS: - case LDAP_OTHER: - case LDAP_SERVER_DOWN: - case LDAP_LOCAL_ERROR: - case LDAP_ENCODING_ERROR: - case LDAP_DECODING_ERROR: - case LDAP_TIMEOUT: - case LDAP_AUTH_UNKNOWN: - case LDAP_FILTER_ERROR: - case LDAP_USER_CANCELLED: - case LDAP_PARAM_ERROR: - case LDAP_NO_MEMORY: - case LDAP_CONNECT_ERROR: - case LDAP_NOT_SUPPORTED: - case LDAP_CONTROL_NOT_FOUND: - case LDAP_NO_RESULTS_RETURNED: - case LDAP_MORE_RESULTS_TO_RETURN: - case LDAP_CLIENT_LOOP: - case LDAP_REFERRAL_LIMIT_EXCEEDED: - return_value = PR_FALSE; - break; - } - LDAPDebug( LDAP_DEBUG_TRACE, "<= ignore_error_and_keep_going\n", 0, 0, 0 ); - return return_value; -} - /* this function converts an aquisition code to a string - for debug output */ static const char* acquire2name (int code) diff --git a/ldap/servers/plugins/replication/windows_prot_private.h b/ldap/servers/plugins/replication/windows_prot_private.h index 772aa792..c01e8cb0 100644 --- a/ldap/servers/plugins/replication/windows_prot_private.h +++ b/ldap/servers/plugins/replication/windows_prot_private.h @@ -101,4 +101,6 @@ void windows_dirsync_inc_run(Private_Repl_Protocol *prp); ConnResult windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op); int windows_process_total_entry(Private_Repl_Protocol *prp,Slapi_Entry *e); +PRBool windows_ignore_error_and_keep_going(int error); + #endif /* _REPL5_PROT_PRIVATE_H_ */ diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c index 8c06d1aa..b942fcb4 100644 --- a/ldap/servers/plugins/replication/windows_protocol_util.c +++ b/ldap/servers/plugins/replication/windows_protocol_util.c @@ -197,7 +197,7 @@ static windows_attribute_map user_attribute_map[] = { "streetAddress", "street", towindowsonly, always, normal}, { "userParameters", "ntUserParms", bidirectional, always, normal}, { "userWorkstations", "ntUserWorkstations", bidirectional, always, normal}, - { "sAMAccountName", "ntUserDomainId", bidirectional, createonly, normal}, + { "sAMAccountName", "ntUserDomainId", bidirectional, always, normal}, /* cn is a naming attribute in AD, so we don't want to change it after entry creation */ { "cn", "cn", towindowsonly, createonly, normal}, /* However, it isn't a naming attribute in DS (we use uid) so it's safe to accept changes inbound */ @@ -231,6 +231,101 @@ static windows_attribute_map group_attribute_map[] = * 6. NT4 has less and different schema from AD. For example users in NT4 have no firstname/lastname, only an optional 'description'. */ +/* + * When we get an error from an LDAP operation, we call this + * function to decide if we should just keep replaying + * updates, or if we should stop, back off, and try again + * later. + * Returns PR_TRUE if we shoould keep going, PR_FALSE if + * we should back off and try again later. + * + * In general, we keep going if the return code is consistent + * with some sort of bug in URP that causes the consumer to + * emit an error code that it shouldn't have, e.g. LDAP_ALREADY_EXISTS. + * + * We stop if there's some indication that the server just completely + * failed to process the operation, e.g. LDAP_OPERATIONS_ERROR. + */ +PRBool +windows_ignore_error_and_keep_going(int error) +{ + int return_value; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_ignore_error_and_keep_going\n", 0, 0, 0 ); + + switch (error) + { + /* Cases where we keep going */ + case LDAP_SUCCESS: + case LDAP_NO_SUCH_ATTRIBUTE: + case LDAP_UNDEFINED_TYPE: + case LDAP_CONSTRAINT_VIOLATION: + case LDAP_TYPE_OR_VALUE_EXISTS: + case LDAP_INVALID_SYNTAX: + case LDAP_NO_SUCH_OBJECT: + case LDAP_INVALID_DN_SYNTAX: + case LDAP_IS_LEAF: + case LDAP_INSUFFICIENT_ACCESS: + case LDAP_NAMING_VIOLATION: + case LDAP_OBJECT_CLASS_VIOLATION: + case LDAP_NOT_ALLOWED_ON_NONLEAF: + case LDAP_NOT_ALLOWED_ON_RDN: + case LDAP_ALREADY_EXISTS: + case LDAP_NO_OBJECT_CLASS_MODS: + return_value = PR_TRUE; + break; + + /* Cases where we stop and retry */ + case LDAP_OPERATIONS_ERROR: + case LDAP_PROTOCOL_ERROR: + case LDAP_TIMELIMIT_EXCEEDED: + case LDAP_SIZELIMIT_EXCEEDED: + case LDAP_STRONG_AUTH_NOT_SUPPORTED: + case LDAP_STRONG_AUTH_REQUIRED: + case LDAP_PARTIAL_RESULTS: + case LDAP_REFERRAL: + case LDAP_ADMINLIMIT_EXCEEDED: + case LDAP_UNAVAILABLE_CRITICAL_EXTENSION: + case LDAP_CONFIDENTIALITY_REQUIRED: + case LDAP_SASL_BIND_IN_PROGRESS: + case LDAP_INAPPROPRIATE_MATCHING: + case LDAP_ALIAS_PROBLEM: + case LDAP_ALIAS_DEREF_PROBLEM: + case LDAP_INAPPROPRIATE_AUTH: + case LDAP_INVALID_CREDENTIALS: + case LDAP_BUSY: + case LDAP_UNAVAILABLE: + case LDAP_UNWILLING_TO_PERFORM: + case LDAP_LOOP_DETECT: + case LDAP_SORT_CONTROL_MISSING: + case LDAP_INDEX_RANGE_ERROR: + case LDAP_RESULTS_TOO_LARGE: + case LDAP_AFFECTS_MULTIPLE_DSAS: + case LDAP_OTHER: + case LDAP_SERVER_DOWN: + case LDAP_LOCAL_ERROR: + case LDAP_ENCODING_ERROR: + case LDAP_DECODING_ERROR: + case LDAP_TIMEOUT: + case LDAP_AUTH_UNKNOWN: + case LDAP_FILTER_ERROR: + case LDAP_USER_CANCELLED: + case LDAP_PARAM_ERROR: + case LDAP_NO_MEMORY: + case LDAP_CONNECT_ERROR: + case LDAP_NOT_SUPPORTED: + case LDAP_CONTROL_NOT_FOUND: + case LDAP_NO_RESULTS_RETURNED: + case LDAP_MORE_RESULTS_TO_RETURN: + case LDAP_CLIENT_LOOP: + case LDAP_REFERRAL_LIMIT_EXCEEDED: + return_value = PR_FALSE; + break; + } + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_ignore_error_and_keep_going\n", 0, 0, 0 ); + return return_value; +} + static const char* op2string(int op) { @@ -318,7 +413,13 @@ map_dn_values(Private_Repl_Protocol *prp,Slapi_ValueSet *original_values, Slapi_ } } slapi_sdn_free(&remote_dn); + } else + { + slapi_log_error(SLAPI_LOG_REPL, NULL, "map_dn_values: no remote dn found for %s\n", original_dn_string); } + } else + { + slapi_log_error(SLAPI_LOG_REPL, NULL, "map_dn_values: this entry is not ours %s\n", original_dn_string); } } else { slapi_log_error(SLAPI_LOG_REPL, NULL, "map_dn_values: no local entry found for %s\n", original_dn_string); @@ -354,6 +455,9 @@ map_dn_values(Private_Repl_Protocol *prp,Slapi_ValueSet *original_values, Slapi_ { slapi_log_error(SLAPI_LOG_REPL, NULL, "map_dn_values: no local dn found for %s\n", original_dn_string); } + } else + { + slapi_log_error(SLAPI_LOG_REPL, NULL, "map_dn_values: this entry is not ours %s\n", original_dn_string); } } else { @@ -2316,7 +2420,7 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr int rc = 0; int is_nt4 = windows_private_get_isnt4(prp->agmt); /* Iterate over the attributes on the remote entry, updating the local entry where appropriate */ - LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_update_local_entry\n", 0, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_generate_update_mods\n", 0, 0, 0 ); *do_modify = 0; if (to_windows) @@ -2379,12 +2483,14 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr /* If it is then we need to replace the local values with the remote values if they are different */ if (!values_equal) { + slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, + "windows_generate_update_mods: %s, %s : values are different\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type); slapi_mods_add_mod_values(smods,LDAP_MOD_REPLACE,local_type,valueset_get_valuearray(vs)); *do_modify = 1; } else { slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "windows_update_local_entry: %s, %s : values are equal\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type); + "windows_generate_update_mods: %s, %s : values are equal\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type); } } else { /* A dn-valued attribute : need to take special steps */ @@ -2418,6 +2524,8 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr { if (!is_present_local) { + slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, + "windows_generate_update_mods: %s, %s : values not present on peer entry\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type); /* If it is currently absent, then we add the value from the remote entry */ if (is_guid) { @@ -2464,7 +2572,7 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr { slapi_mods_dump(smods,"windows sync"); } - LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_update_local_entry: %d\n", retval, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_generate_update_mods: %d\n", retval, 0, 0 ); return retval; } @@ -2583,6 +2691,18 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r if (0 == retval && remote_entry) { retval = windows_update_remote_entry(prp,remote_entry,e); + /* Detect the case where the error is benign */ + if (retval) + { + int operation = 0; + int error = 0; + + conn_get_error(prp->conn, &operation, &error); + if (windows_ignore_error_and_keep_going(error)) + { + retval = CONN_OPERATION_SUCCESS; + } + } } if (remote_entry) { |