* a schema cache being refreshed from database.
*/
if (working_schema) {
- struct ldb_message *msg;
- struct ldb_request *req;
-
- /* Force a reload */
- working_schema->last_refresh = 0;
+ /* Reload the schema */
new_schema = dsdb_get_schema(ldb, tmp_ctx);
- /* TODO:
+ /* TODO:
* If dsdb_get_schema() fails, we just fall back
* to what we had. However, the database is probably
* unable to operate for other users from this
* point... */
- if (new_schema && used_global_schema) {
- dsdb_make_schema_global(ldb, new_schema);
- } else if (used_global_schema) {
- DEBUG(0,("Failed to re-load schema after commit of transaction\n"));
- dsdb_set_global_schema(ldb);
- TALLOC_FREE(tmp_ctx);
- return WERR_INTERNAL_ERROR;
- } else {
- DEBUG(0,("Failed to re-load schema after commit of transaction\n"));
+ if (new_schema == NULL || new_schema == working_schema) {
+ DEBUG(0,("Failed to re-load schema after commit of transaction (working: %p/%llu, new: %p/%llu)\n",
+ new_schema, (unsigned long long)new_schema->metadata_usn,
+ working_schema, (unsigned long long)working_schema->metadata_usn));
dsdb_reference_schema(ldb, cur_schema, false);
+ if (used_global_schema) {
+ dsdb_set_global_schema(ldb);
+ }
TALLOC_FREE(tmp_ctx);
return WERR_INTERNAL_ERROR;
- }
- msg = ldb_msg_new(tmp_ctx);
- if (msg == NULL) {
- TALLOC_FREE(tmp_ctx);
- return WERR_NOMEM;
- }
- msg->dn = ldb_dn_new(msg, ldb, "");
- if (msg->dn == NULL) {
- TALLOC_FREE(tmp_ctx);
- return WERR_NOMEM;
- }
-
- ret = ldb_msg_add_string(msg, "schemaUpdateNow", "1");
- if (ret != LDB_SUCCESS) {
- TALLOC_FREE(tmp_ctx);
- return WERR_INTERNAL_ERROR;
- }
-
- ret = ldb_build_mod_req(&req, ldb, objects,
- msg,
- NULL,
- NULL,
- ldb_op_default_callback,
- NULL);
-
- if (ret != LDB_SUCCESS) {
- TALLOC_FREE(tmp_ctx);
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
-
- ret = ldb_transaction_start(ldb);
- if (ret != LDB_SUCCESS) {
- TALLOC_FREE(tmp_ctx);
- DEBUG(0, ("Autotransaction start failed\n"));
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
-
- ret = ldb_request(ldb, req);
- if (ret == LDB_SUCCESS) {
- ret = ldb_wait(req->handle, LDB_WAIT_ALL);
- }
-
- if (ret == LDB_SUCCESS) {
- ret = ldb_transaction_commit(ldb);
- } else {
- DEBUG(0, ("Schema update now failed: %s\n",
- ldb_errstring(ldb)));
- ldb_transaction_cancel(ldb);
- }
-
- if (ret != LDB_SUCCESS) {
- DEBUG(0, ("Commit failed: %s\n", ldb_errstring(ldb)));
- TALLOC_FREE(tmp_ctx);
- return WERR_DS_INTERNAL_FAILURE;
+ } else if (used_global_schema) {
+ dsdb_make_schema_global(ldb, new_schema);
}
}
#include "system/filesys.h"
struct schema_load_private_data {
+ struct ldb_module *module;
bool in_transaction;
struct tdb_wrap *metadata;
uint64_t schema_seq_num_cache;
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);
return LDB_SUCCESS;
}
-static int schema_metadata_get_uint64(struct ldb_module *module,
+static int schema_metadata_get_uint64(struct schema_load_private_data *data,
const char *key, uint64_t *value,
uint64_t default_value)
{
- struct schema_load_private_data *data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
struct tdb_context *tdb;
TDB_DATA tdb_key, tdb_data;
char *value_str;
TALLOC_CTX *tmp_ctx;
int tdb_seqnum;
- if (!data || !data->metadata) {
+ if (!data) {
*value = default_value;
return LDB_SUCCESS;
}
+ if (!data->metadata) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
tdb_seqnum = tdb_get_seqnum(data->metadata->tdb);
if (tdb_seqnum == data->tdb_seqnum) {
*value = data->schema_seq_num_cache;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
- return ldb_module_oom(module);
+ return ldb_module_oom(data->module);
}
tdb = data->metadata->tdb;
return LDB_SUCCESS;
} else {
talloc_free(tmp_ctx);
- return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
+ return ldb_module_error(data->module, LDB_ERR_OPERATIONS_ERROR,
tdb_errorstr(tdb));
}
}
if (value_str == NULL) {
SAFE_FREE(tdb_data.dptr);
talloc_free(tmp_ctx);
- return ldb_module_oom(module);
+ return ldb_module_oom(data->module);
}
/*
struct dsdb_schema *schema, bool is_global_schema)
{
TALLOC_CTX *mem_ctx;
- uint64_t current_usn, schema_seq_num = 0;
+ uint64_t 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);
if (!private_data) {
* continue to hit the database to get the highest USN.
*/
- ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &schema_seq_num, 0);
+ ret = schema_metadata_get_uint64(private_data, 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;
+ if (schema->metadata_usn == schema_seq_num) {
+ TALLOC_FREE(mem_ctx);
+ return schema;
+ } else {
+ DEBUG(3, ("Schema refresh needed %lld != %lld\n",
+ (unsigned long long)schema->metadata_usn,
+ (unsigned long long)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;
+ TALLOC_FREE(mem_ctx);
+ return schema;
}
- schema->last_refresh = ts;
-
- }
-
- ret = dsdb_module_load_partition_usn(module, schema_dn, ¤t_usn, NULL, NULL);
- if (ret != LDB_SUCCESS || (schema && (current_usn == schema->loaded_usn))) {
- TALLOC_FREE(mem_ctx);
- return schema;
+ } else {
+ DEBUG(3, ("Initial schema load needed, as we have no existing schema, seq_num: %lld\n",
+ (unsigned long long)schema_seq_num));
}
- ret = dsdb_schema_from_db(module, mem_ctx, current_usn, schema_seq_num, &new_schema);
+ ret = dsdb_schema_from_db(module, mem_ctx, schema_seq_num, &new_schema);
if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
"dsdb_schema_from_db() failed: %d:%s: %s",
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)
{
goto failed;
}
- (*schema)->loaded_usn = current_usn;
(*schema)->metadata_usn = schema_seq_num;
- (*schema)->last_refresh = time(NULL);
talloc_steal(mem_ctx, *schema);
struct ldb_context *ldb = ldb_module_get_ctx(module);
struct dsdb_schema *schema;
void *readOnlySchema;
- int ret;
+ int ret, metadata_ret;
private_data = talloc_zero(module, struct schema_load_private_data);
if (private_data == NULL) {
return ldb_oom(ldb);
}
-
+ private_data->module = module;
+
ldb_module_set_private(module, private_data);
ret = ldb_next_init(module);
schema = dsdb_get_schema(ldb, NULL);
+ metadata_ret = schema_metadata_open(module);
+
/* We might already have a schema */
if (schema != NULL) {
- /* Hook up the refresh function */
- if (dsdb_uses_global_schema(ldb)) {
+ /* If we have the metadata.tdb, then hook up the refresh function */
+ if (metadata_ret == LDB_SUCCESS && dsdb_uses_global_schema(ldb)) {
ret = dsdb_set_schema_refresh_function(ldb, dsdb_schema_refresh, module);
if (ret != LDB_SUCCESS) {
* 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);
+ ret = dsdb_schema_from_db(module, private_data, 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",
return ret;
}
- } else {
+ } else if (metadata_ret == LDB_SUCCESS) {
ret = dsdb_set_schema_refresh_function(ldb, dsdb_schema_refresh, module);
if (ret != LDB_SUCCESS) {
ret, ldb_strerror(ret), ldb_errstring(ldb));
return ret;
}
+ } else {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: failed to open metadata.tdb");
+ return metadata_ret;
}
schema = dsdb_get_schema(ldb, NULL);
static int schema_search(struct ldb_module *module, struct ldb_request *req)
{
- struct dsdb_schema *schema;
struct ldb_context *ldb = ldb_module_get_ctx(module);
- uint64_t value;
- int ret;
- struct schema_load_private_data *private_data =
- talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
- schema = dsdb_get_schema(ldb, NULL);
- if (schema && private_data && !private_data->in_transaction) {
- ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &value, 0);
- if (ret == LDB_SUCCESS && schema->metadata_usn < value) {
- /* The usn of the schema was changed in the metadata,
- * this indicate that another process has modified the schema and
- * that a reload is needed.
- */
- schema->last_refresh = 0;
- schema = dsdb_get_schema(ldb, NULL);
- }
- }
+ /* Try the schema refresh now */
+ dsdb_get_schema(ldb, NULL);
return ldb_next_request(module, req);
}
{
struct schema_load_private_data *private_data =
talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
- struct dsdb_schema *schema;
struct ldb_context *ldb = ldb_module_get_ctx(module);
- uint64_t value;
- int ret;
+ struct dsdb_schema *schema;
+ /* Try the schema refresh now */
schema = dsdb_get_schema(ldb, NULL);
- if (!private_data->metadata) {
- schema_metadata_open(module);
- }
- ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &value, 0);
- if (ret == LDB_SUCCESS && schema->metadata_usn < value) {
- /* The usn of the schema was changed in the metadata,
- * this indicate that another process has modified the schema and
- * that a reload is needed.
- */
- schema->last_refresh = 0;
- schema = dsdb_get_schema(ldb, NULL);
+ if (schema == NULL) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: dsdb_get_schema failed");
+ return LDB_ERR_OPERATIONS_ERROR;
}
private_data->in_transaction = true;
{
time_t *lastts;
struct ldb_context *ldb = ldb_module_get_ctx(module);
- struct dsdb_schema *schema;
if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
return ldb_next_request(module, req);
if (!lastts) {
lastts = talloc(ldb, time_t);
}
- schema = dsdb_get_schema(ldb, NULL);
/* Force a refresh */
- schema->last_refresh = 0;
+ dsdb_get_schema(ldb, NULL);
*lastts = 0;
ldb_set_opaque(ldb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME, lastts);