summaryrefslogtreecommitdiffstats
path: root/ldap/servers/plugins/replication/windows_protocol_util.c
diff options
context:
space:
mode:
authorDavid Boreham <dboreham@redhat.com>2005-04-28 22:50:15 +0000
committerDavid Boreham <dboreham@redhat.com>2005-04-28 22:50:15 +0000
commit7cf67d15b3c96b1fad71e20036552de08527e276 (patch)
treeee77212f8d285b76aa63a6e8c2bce004e8287d17 /ldap/servers/plugins/replication/windows_protocol_util.c
parent984a784f2c0d1c9115baee85b967f010285830a1 (diff)
downloadds-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/plugins/replication/windows_protocol_util.c')
-rw-r--r--ldap/servers/plugins/replication/windows_protocol_util.c128
1 files changed, 124 insertions, 4 deletions
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)
{