summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/repl/drepl_out_helpers.c2
-rw-r--r--source4/dsdb/repl/replicated_objects.c55
-rw-r--r--source4/libnet/libnet_vampire.c4
3 files changed, 59 insertions, 2 deletions
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index f02fae9510..8c5c9da6c3 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -629,6 +629,7 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
}
status = dsdb_replicated_objects_commit(service->samdb,
+ NULL,
objects,
&state->op->source_dsa->notify_uSN);
talloc_free(objects);
@@ -639,6 +640,7 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
tevent_req_nterror(req, nt_status);
return;
}
+
if (state->op->extended_op == DRSUAPI_EXOP_NONE) {
/* if it applied fine, we need to update the highwatermark */
*state->op->source_dsa->repsFrom1 = rf1;
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index 1ea1640e29..f3b6356649 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -433,11 +433,20 @@ WERROR dsdb_replicated_objects_convert(struct ldb_context *ldb,
return WERR_OK;
}
+/**
+ * Commits a list of replicated objects.
+ *
+ * @param working_schema dsdb_schema to be used for resolving
+ * Classes/Attributes during Schema replication. If not NULL,
+ * it will be set on ldb and used while committing replicated objects
+ */
WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
+ struct dsdb_schema *working_schema,
struct dsdb_extended_replicated_objects *objects,
uint64_t *notify_uSN)
{
struct ldb_result *ext_res;
+ struct dsdb_schema *cur_schema = NULL;
int ret;
uint64_t seq_num1, seq_num2;
@@ -459,8 +468,33 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
return WERR_FOOBAR;
}
+ /*
+ * Set working_schema for ldb in case we are replicating from Schema NC.
+ * Schema won't be reloaded during Replicated Objects commit, as it is
+ * done in a transaction. So we need some way to search for newly
+ * added Classes and Attributes
+ */
+ if (working_schema) {
+ /* store current schema so we can fall back in case of failure */
+ cur_schema = dsdb_get_schema(ldb, objects);
+
+ ret = dsdb_reference_schema(ldb, working_schema, false);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ "Failed to reference working schema - %s\n",
+ ldb_strerror(ret)));
+ /* TODO: Map LDB Error to NTSTATUS? */
+ ldb_transaction_cancel(ldb);
+ return WERR_INTERNAL_ERROR;
+ }
+ }
+
ret = ldb_extended(ldb, DSDB_EXTENDED_REPLICATED_OBJECTS_OID, objects, &ext_res);
if (ret != LDB_SUCCESS) {
+ /* restore previous schema */
+ if (cur_schema ) {
+ dsdb_reference_schema(ldb, cur_schema, false);
+ }
+
DEBUG(0,("Failed to apply records: %s: %s\n",
ldb_errstring(ldb), ldb_strerror(ret)));
ldb_transaction_cancel(ldb);
@@ -470,6 +504,10 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
ret = ldb_transaction_prepare_commit(ldb);
if (ret != LDB_SUCCESS) {
+ /* restore previous schema */
+ if (cur_schema ) {
+ dsdb_reference_schema(ldb, cur_schema, false);
+ }
DEBUG(0,(__location__ " Failed to prepare commit of transaction: %s\n",
ldb_errstring(ldb)));
return WERR_FOOBAR;
@@ -477,6 +515,10 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
ret = dsdb_load_partition_usn(ldb, objects->partition_dn, &seq_num2, NULL);
if (ret != LDB_SUCCESS) {
+ /* restore previous schema */
+ if (cur_schema ) {
+ dsdb_reference_schema(ldb, cur_schema, false);
+ }
DEBUG(0,(__location__ " Failed to load partition uSN\n"));
ldb_transaction_cancel(ldb);
return WERR_FOOBAR;
@@ -491,10 +533,23 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
ret = ldb_transaction_commit(ldb);
if (ret != LDB_SUCCESS) {
+ /* restore previous schema */
+ if (cur_schema ) {
+ dsdb_reference_schema(ldb, cur_schema, false);
+ }
DEBUG(0,(__location__ " Failed to commit transaction\n"));
return WERR_FOOBAR;
}
+ /*
+ * Reset the Schema used by ldb. This will lead to
+ * a schema cache being refreshed from database.
+ */
+ if (working_schema) {
+ cur_schema = dsdb_get_schema(ldb, NULL);
+ /* TODO: What we do in case dsdb_get_schema() fail?
+ * We can't fallback at this point anymore */
+ }
DEBUG(2,("Replicated %u objects (%u linked attributes) for %s\n",
objects->num_objects, objects->linked_attributes_count,
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
index 1d7d7268ae..40cf01ed52 100644
--- a/source4/libnet/libnet_vampire.c
+++ b/source4/libnet/libnet_vampire.c
@@ -446,7 +446,7 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
}
}
- status = dsdb_replicated_objects_commit(s->ldb, schema_objs, &seq_num);
+ status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
if (!W_ERROR_IS_OK(status)) {
DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
return werror_to_ntstatus(status);
@@ -720,7 +720,7 @@ NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
}
}
- status = dsdb_replicated_objects_commit(s->ldb, objs, &seq_num);
+ status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
if (!W_ERROR_IS_OK(status)) {
DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
return werror_to_ntstatus(status);