diff options
-rw-r--r-- | source4/dsdb/repl/drepl_out_helpers.c | 2 | ||||
-rw-r--r-- | source4/dsdb/repl/replicated_objects.c | 55 | ||||
-rw-r--r-- | source4/libnet/libnet_vampire.c | 4 |
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); |