diff options
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema_load.c | 93 | ||||
-rw-r--r-- | source4/dsdb/schema/schema.h | 2 |
2 files changed, 81 insertions, 14 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c index 5dd8fb78c9..d13b339f60 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_load.c +++ b/source4/dsdb/samdb/ldb_modules/schema_load.c @@ -42,6 +42,14 @@ struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct dsdb_s { uint64_t current_usn; int ret; + struct ldb_result *res; + struct ldb_request *treq; + struct ldb_seqnum_request *tseq; + struct ldb_seqnum_result *tseqr; + struct dsdb_control_current_partition *ctrl; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct dsdb_schema *new_schema; + struct schema_load_private_data *private_data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data); if (!private_data) { /* We can't refresh until the init function has run */ @@ -53,22 +61,79 @@ struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct dsdb_s return schema; } + res = talloc_zero(schema, struct ldb_result); + if (res == NULL) { + return NULL; + } + tseq = talloc_zero(res, struct ldb_seqnum_request); + if (tseq == NULL) { + talloc_free(res); + return NULL; + } + tseq->type = LDB_SEQ_HIGHEST_SEQ; + + ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res, + LDB_EXTENDED_SEQUENCE_NUMBER, + tseq, + NULL, + res, + ldb_extended_default_callback, + NULL); + if (ret != LDB_SUCCESS) { + talloc_free(res); + return NULL; + } + + ctrl = talloc(treq, struct dsdb_control_current_partition); + if (!ctrl) { + talloc_free(res); + return NULL; + } + ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION; + ctrl->dn = schema->base_dn; + + ret = ldb_request_add_control(treq, + DSDB_CONTROL_CURRENT_PARTITION_OID, + false, ctrl); + if (ret != LDB_SUCCESS) { + talloc_free(res); + return NULL; + } + + ret = ldb_next_request(module, treq); + if (ret != LDB_SUCCESS) { + talloc_free(res); + return NULL; + } + ret = ldb_wait(treq->handle, LDB_WAIT_ALL); + if (ret != LDB_SUCCESS) { + talloc_free(res); + return NULL; + } + tseqr = talloc_get_type(res->extended->data, + struct ldb_seqnum_result); + if (tseqr->seq_num == schema->reload_seq_number) { + talloc_free(res); + return schema; + } + + schema->reload_seq_number = tseqr->seq_num; + talloc_free(res); + ret = dsdb_module_load_partition_usn(module, schema->base_dn, ¤t_usn, NULL); - if (ret == LDB_SUCCESS && current_usn != schema->loaded_usn) { - struct ldb_context *ldb = ldb_module_get_ctx(module); - struct dsdb_schema *new_schema; - - ret = dsdb_schema_from_db(module, schema->base_dn, current_usn, &new_schema); - if (ret != LDB_SUCCESS) { - return schema; - } - - if (is_global_schema) { - dsdb_make_schema_global(ldb, new_schema); - } - return new_schema; + if (ret != LDB_SUCCESS || current_usn == schema->loaded_usn) { + return schema; + } + + ret = dsdb_schema_from_db(module, schema->base_dn, current_usn, &new_schema); + if (ret != LDB_SUCCESS) { + return schema; + } + + if (is_global_schema) { + dsdb_make_schema_global(ldb, new_schema); } - return schema; + return new_schema; } diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index b5334c7313..7283744f7d 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -213,6 +213,8 @@ struct dsdb_schema { struct ldb_module *loaded_from_module; struct dsdb_schema *(*refresh_fn)(struct ldb_module *module, struct dsdb_schema *schema, bool is_global_schema); bool refresh_in_progress; + /* an 'opaque' sequence number that the reload function may also wish to use */ + uint64_t reload_seq_number; }; enum dsdb_attr_list_query { |