summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/ldb_modules/schema_load.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules/schema_load.c')
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_load.c207
1 files changed, 125 insertions, 82 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c
index faaf3f2071c..17c20338b81 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_load.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_load.c
@@ -39,7 +39,10 @@ struct schema_load_private_data {
struct tdb_wrap *metadata;
};
-static int dsdb_schema_from_db(struct ldb_module *module, struct ldb_dn *schema_dn, uint64_t current_usn,
+static int dsdb_schema_from_db(struct ldb_module *module,
+ TALLOC_CTX *mem_ctx,
+ uint64_t current_usn,
+ uint64_t schema_seq_num,
struct dsdb_schema **schema);
/*
@@ -68,13 +71,13 @@ static int schema_metadata_open(struct ldb_module *module)
}
sam_name = (const char *)ldb_get_opaque(ldb, "ldb_url");
- if (strncmp("tdb://", sam_name, 6) == 0) {
- sam_name += 6;
- }
if (!sam_name) {
talloc_free(tmp_ctx);
return ldb_operr(ldb);
}
+ if (strncmp("tdb://", sam_name, 6) == 0) {
+ sam_name += 6;
+ }
filename = talloc_asprintf(tmp_ctx, "%s.d/metadata.tdb", sam_name);
if (!filename) {
talloc_free(tmp_ctx);
@@ -113,8 +116,8 @@ static int schema_metadata_get_uint64(struct ldb_module *module,
TALLOC_CTX *tmp_ctx;
if (!data || !data->metadata) {
- return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
- "schema: metadata tdb not initialized");
+ *value = default_value;
+ return LDB_SUCCESS;
}
tmp_ctx = talloc_new(NULL);
@@ -155,12 +158,15 @@ static int schema_metadata_get_uint64(struct ldb_module *module,
return LDB_SUCCESS;
}
-static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct dsdb_schema *schema, bool is_global_schema)
+static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct tevent_context *ev,
+ struct dsdb_schema *schema, bool is_global_schema)
{
- uint64_t current_usn, value;
+ TALLOC_CTX *mem_ctx;
+ uint64_t current_usn, schema_seq_num = 0;
int ret;
struct ldb_context *ldb = ldb_module_get_ctx(module);
struct dsdb_schema *new_schema;
+ struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
time_t ts, lastts;
struct schema_load_private_data *private_data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
@@ -174,11 +180,11 @@ static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct
return schema;
}
- lastts = schema->last_refresh;
- ts = time(NULL);
- if (lastts > (ts - schema->refresh_interval)) {
- DEBUG(11, ("Less than %d seconds since last reload, returning cached version ts = %d\n", (int)schema->refresh_interval, (int)lastts));
- return schema;
+ SMB_ASSERT(ev == ldb_get_event_context(ldb));
+
+ mem_ctx = talloc_new(module);
+ if (mem_ctx == NULL) {
+ return NULL;
}
/*
@@ -189,29 +195,59 @@ static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct
* continue to hit the database to get the highest USN.
*/
- ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &value, 0);
- if (ret == LDB_SUCCESS) {
- schema->metadata_usn = value;
- } else {
- /* From an old provision it can happen that the tdb didn't exists yet */
- DEBUG(0, ("Error while searching for the schema usn in the metadata\n"));
- schema->metadata_usn = 0;
+ ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &schema_seq_num, 0);
+
+ if (schema != NULL) {
+ lastts = schema->last_refresh;
+ ts = time(NULL);
+ if (lastts > (ts - schema->refresh_interval)) {
+ DEBUG(11, ("Less than %d seconds since last reload, "
+ "returning cached version ts = %d\n",
+ (int)schema->refresh_interval,
+ (int)lastts));
+ TALLOC_FREE(mem_ctx);
+ return schema;
+ }
+
+ if (ret == LDB_SUCCESS) {
+ schema->metadata_usn = schema_seq_num;
+ } else {
+ /* From an old provision it can happen that the tdb didn't exists yet */
+ DEBUG(0, ("Error while searching for the schema usn in the metadata ignoring: %d:%s:%s\n",
+ ret, ldb_strerror(ret), ldb_errstring(ldb)));
+ schema->metadata_usn = 0;
+ }
+ schema->last_refresh = ts;
+
}
- schema->last_refresh = ts;
- ret = dsdb_module_load_partition_usn(module, schema->base_dn, &current_usn, NULL, NULL);
- if (ret != LDB_SUCCESS || current_usn == schema->loaded_usn) {
+ ret = dsdb_module_load_partition_usn(module, schema_dn, &current_usn, NULL, NULL);
+ if (ret != LDB_SUCCESS || (schema && (current_usn == schema->loaded_usn))) {
+ TALLOC_FREE(mem_ctx);
return schema;
}
- ret = dsdb_schema_from_db(module, schema->base_dn, current_usn, &new_schema);
+ ret = dsdb_schema_from_db(module, mem_ctx, current_usn, schema_seq_num, &new_schema);
if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "dsdb_schema_from_db() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
+ TALLOC_FREE(mem_ctx);
return schema;
}
+ ret = dsdb_set_schema(ldb, new_schema);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "dsdb_set_schema() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
+ TALLOC_FREE(mem_ctx);
+ return schema;
+ }
if (is_global_schema) {
dsdb_make_schema_global(ldb, new_schema);
}
+ TALLOC_FREE(mem_ctx);
return new_schema;
}
@@ -220,13 +256,17 @@ static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct
Given an LDB module (pointing at the schema DB), and the DN, set the populated schema
*/
-static int dsdb_schema_from_db(struct ldb_module *module, struct ldb_dn *schema_dn, uint64_t current_usn,
+static int dsdb_schema_from_db(struct ldb_module *module,
+ TALLOC_CTX *mem_ctx,
+ uint64_t current_usn,
+ uint64_t schema_seq_num,
struct dsdb_schema **schema)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
TALLOC_CTX *tmp_ctx;
char *error_string;
int ret;
+ struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
struct ldb_result *schema_res;
struct ldb_result *res;
static const char *schema_attrs[] = {
@@ -289,37 +329,11 @@ static int dsdb_schema_from_db(struct ldb_module *module, struct ldb_dn *schema_
goto failed;
}
- (*schema)->refresh_in_progress = true;
-
- /* If we have the readOnlySchema opaque, then don't check for
- * runtime schema updates, as they are not permitted (we would
- * have to update the backend server schema too */
- if (!ldb_get_opaque(ldb, "readOnlySchema")) {
- (*schema)->refresh_fn = dsdb_schema_refresh;
- (*schema)->loaded_from_module = module;
- (*schema)->loaded_usn = current_usn;
- }
-
- /* "dsdb_set_schema()" steals schema into the ldb_context */
- ret = dsdb_set_schema(ldb, (*schema));
-
- (*schema)->refresh_in_progress = false;
+ (*schema)->loaded_usn = current_usn;
+ (*schema)->metadata_usn = schema_seq_num;
(*schema)->last_refresh = time(NULL);
- if (ret != LDB_SUCCESS) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "schema_load_init: dsdb_set_schema() failed: %d:%s: %s",
- ret, ldb_strerror(ret), ldb_errstring(ldb));
- goto failed;
- }
-
- /* Ensure this module won't go away before the callback. This
- * causes every schema to have the LDB that originally loaded
- * the first schema as a talloc child. */
- if (talloc_reference(*schema, ldb) == NULL) {
- ldb_oom(ldb);
- ret = LDB_ERR_OPERATIONS_ERROR;
- }
+ talloc_steal(mem_ctx, *schema);
failed:
if (flags & LDB_FLG_ENABLE_TRACING) {
@@ -334,11 +348,10 @@ failed:
static int schema_load_init(struct ldb_module *module)
{
struct schema_load_private_data *private_data;
- struct dsdb_schema *schema;
struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct dsdb_schema *schema;
+ void *readOnlySchema;
int ret;
- uint64_t current_usn;
- struct ldb_dn *schema_dn;
private_data = talloc_zero(module, struct schema_load_private_data);
if (private_data == NULL) {
@@ -352,39 +365,69 @@ static int schema_load_init(struct ldb_module *module)
return ret;
}
- if (dsdb_get_schema(ldb, NULL)) {
- return LDB_SUCCESS;
- }
+ schema = dsdb_get_schema(ldb, NULL);
+
+ /* We might already have a schema */
+ if (schema != NULL) {
+ /* Hook up the refresh function */
+ if (dsdb_uses_global_schema(ldb)) {
+ ret = dsdb_set_schema_refresh_function(ldb, dsdb_schema_refresh, module);
+
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: dsdb_set_schema_refresh_fns() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
+ return ret;
+ }
+ }
- schema_dn = ldb_get_schema_basedn(ldb);
- if (!schema_dn) {
- ldb_reset_err_string(ldb);
- ldb_debug(ldb, LDB_DEBUG_WARNING,
- "schema_load_init: no schema dn present: (skip schema loading)\n");
return LDB_SUCCESS;
}
- ret = dsdb_module_load_partition_usn(module, schema_dn, &current_usn, NULL, NULL);
- if (ret != LDB_SUCCESS) {
- /* Ignore the error and just reload the DB more often */
- current_usn = 0;
- }
+ readOnlySchema = ldb_get_opaque(ldb, "readOnlySchema");
- ret = dsdb_schema_from_db(module, schema_dn, current_usn, &schema);
- /* We don't care too much on the result of this action
- * the most probable reason for this to fail is that the tdb didn't
- * exists yet and this will be corrected by the partition module.
- */
- if (ret == LDB_SUCCESS && schema_metadata_open(module) == LDB_SUCCESS) {
- uint64_t value;
+ /* If we have the readOnlySchema opaque, then don't check for
+ * runtime schema updates, as they are not permitted (we would
+ * have to update the backend server schema too */
+ if (readOnlySchema != NULL) {
+ struct dsdb_schema *new_schema;
+ ret = dsdb_schema_from_db(module, private_data, 0, 0, &new_schema);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: dsdb_schema_from_db() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
+ return ret;
+ }
- ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &value, 0);
- if (ret == LDB_SUCCESS) {
- schema->metadata_usn = value;
- } else {
- schema->metadata_usn = 0;
+ /* "dsdb_set_schema()" steals schema into the ldb_context */
+ ret = dsdb_set_schema(ldb, new_schema);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: dsdb_set_schema() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
+ return ret;
+ }
+
+ } else {
+ ret = dsdb_set_schema_refresh_function(ldb, dsdb_schema_refresh, module);
+
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: dsdb_set_schema_refresh_fns() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
+ return ret;
}
}
+
+ schema = dsdb_get_schema(ldb, NULL);
+
+ /* We do this, invoking the refresh handler, so we know that it works */
+ if (schema == NULL) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: dsdb_get_schema failed");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
return ret;
}