struct GUID *guid,
struct ldb_message_element *el,
const struct dsdb_attribute *sa,
- struct ldb_request *parent)
+ struct ldb_request *parent,
+ bool *caller_should_vanish)
{
unsigned int i;
TALLOC_CTX *tmp_ctx = talloc_new(module);
return LDB_ERR_OPERATIONS_ERROR;
}
-
msg->dn = dsdb_dn->dn;
target_attr = dsdb_attribute_by_linkID(schema, sa->linkID ^ 1);
DSDB_SEARCH_SHOW_RECYCLED,
parent);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ DBG_WARNING("Failed to find forward link object %s "
+ "to remove backlink %s on %s",
+ ldb_dn_get_linearized(msg->dn),
+ sa->lDAPDisplayName,
+ ldb_dn_get_linearized(dn));
+ *caller_should_vanish = true;
+ continue;
+ }
+
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
return ret;
link_el = ldb_msg_find_element(link_msg,
target_attr->lDAPDisplayName);
if (link_el == NULL) {
- talloc_free(tmp_ctx);
- return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ DBG_WARNING("Failed to find forward link on %s "
+ "as %s to remove backlink %s on %s",
+ ldb_dn_get_linearized(msg->dn),
+ target_attr->lDAPDisplayName,
+ sa->lDAPDisplayName,
+ ldb_dn_get_linearized(dn));
+ *caller_should_vanish = true;
+ continue;
}
/*
}
if (p == NULL) {
- ldb_asprintf_errstring(ldb_module_get_ctx(module),
- "Failed to find forward link on %s "
- "as %s to remove backlink %s on %s",
- ldb_dn_get_linearized(msg->dn),
- target_attr->lDAPDisplayName,
- sa->lDAPDisplayName,
- ldb_dn_get_linearized(dn));
- talloc_free(tmp_ctx);
- return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ DBG_WARNING("Failed to find forward link on %s "
+ "as %s to remove backlink %s on %s",
+ ldb_dn_get_linearized(msg->dn),
+ target_attr->lDAPDisplayName,
+ sa->lDAPDisplayName,
+ ldb_dn_get_linearized(dn));
+ *caller_should_vanish = true;
+ continue;
}
+ /*
+ * If we find a backlink to ourself, we will delete
+ * the forward link before we get to process that
+ * properly, so just let the caller process this via
+ * the forward link.
+ *
+ * We do this once we are sure we have the forward
+ * link (to ourself) in case something is very wrong
+ * and they are out of sync.
+ */
+ if (ldb_dn_compare(dsdb_dn->dn, dn) == 0) {
+ continue;
+ }
/* This needs to get the Binary DN, by first searching */
dn_str = dsdb_dn_get_linearized(tmp_ctx,
}
if (sa->linkID & 1) {
+ bool caller_should_vanish = false;
/*
* we have a backlink in this object
* that needs to be removed. We're not
ret = replmd_delete_remove_link(module, schema,
replmd_private,
old_dn, &guid,
- el, sa, req);
- if (ret == LDB_SUCCESS) {
- /*
- * now we continue, which means we
- * won't remove this backlink
- * directly
- */
- continue;
- }
-
- if (ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
+ el, sa, req,
+ &caller_should_vanish);
+ if (ret != LDB_SUCCESS) {
const char *old_dn_str
= ldb_dn_get_linearized(old_dn);
ldb_asprintf_errstring(ldb,
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (caller_should_vanish == false) {
+ /*
+ * now we continue, which means we
+ * won't remove this backlink
+ * directly
+ */
+ continue;
+ }
+
/*
* Otherwise vanish the link, we are
* out of sync and the controlling