struct ldb_context *from_ldb;
struct dsdb_schema *schema;
int ret;
- char write_indices_and_attributes = true;
+ char write_indices_and_attributes = SCHEMA_WRITE;
if (!PyArg_ParseTuple(args, "OO|b",
&py_ldb, &py_from_ldb, &write_indices_and_attributes))
return NULL;
cur_schema = dsdb_get_schema(ldb, tmp_ctx);
used_global_schema = dsdb_uses_global_schema(ldb);
- ret = dsdb_reference_schema(ldb, working_schema, false);
+ ret = dsdb_reference_schema(ldb, working_schema, SCHEMA_MEMORY_ONLY);
if (ret != LDB_SUCCESS) {
DEBUG(0,(__location__ "Failed to reference working schema - %s\n",
ldb_strerror(ret)));
if (used_global_schema) {
dsdb_set_global_schema(ldb);
} else if (cur_schema) {
- dsdb_reference_schema(ldb, cur_schema, false);
+ dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
}
if (W_ERROR_EQUAL(objects->error, WERR_DS_DRA_RECYCLED_TARGET)) {
if (used_global_schema) {
dsdb_set_global_schema(ldb);
} else if (cur_schema ) {
- dsdb_reference_schema(ldb, cur_schema, false);
+ dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
}
DEBUG(0,("Failed to save updated prefixMap: %s\n",
win_errstr(werr)));
if (used_global_schema) {
dsdb_set_global_schema(ldb);
} else if (cur_schema ) {
- dsdb_reference_schema(ldb, cur_schema, false);
+ dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
}
DEBUG(0,(__location__ " Failed to prepare commit of transaction: %s\n",
ldb_errstring(ldb)));
if (used_global_schema) {
dsdb_set_global_schema(ldb);
} else if (cur_schema ) {
- dsdb_reference_schema(ldb, cur_schema, false);
+ dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
}
DEBUG(0,(__location__ " Failed to load partition uSN\n"));
ldb_transaction_cancel(ldb);
if (used_global_schema) {
dsdb_set_global_schema(ldb);
} else if (cur_schema ) {
- dsdb_reference_schema(ldb, cur_schema, false);
+ dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
}
DEBUG(0,(__location__ " Failed to commit transaction\n"));
TALLOC_FREE(tmp_ctx);
new_schema != NULL ?
new_schema->metadata_usn : 0,
working_schema, working_schema->metadata_usn);
- dsdb_reference_schema(ldb, cur_schema, false);
+ dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
if (used_global_schema) {
dsdb_set_global_schema(ldb);
}
return schema;
}
- ret = dsdb_set_schema(ldb, new_schema, false);
+ ret = dsdb_set_schema(ldb, new_schema, SCHEMA_MEMORY_ONLY);
if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
"dsdb_set_schema() failed: %d:%s: %s",
}
static int schema_load(struct ldb_context *ldb,
- struct ldb_module *module)
+ struct ldb_module *module,
+ bool *need_write)
{
struct dsdb_schema *schema;
void *readOnlySchema;
}
/* "dsdb_set_schema()" steals schema into the ldb_context */
- ret = dsdb_set_schema(ldb, new_schema, false);
+ ret = dsdb_set_schema(ldb, new_schema, SCHEMA_MEMORY_ONLY);
if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
"schema_load_init: dsdb_set_schema() failed: %d:%s: %s",
/* Now check the @INDEXLIST is correct, or fix it up */
ret = dsdb_schema_set_indices_and_attributes(ldb, schema,
- true);
+ SCHEMA_COMPARE);
+ if (ret == LDB_ERR_BUSY) {
+ *need_write = true;
+ ret = LDB_SUCCESS;
+ } else {
+ *need_write = false;
+ }
+
if (ret != LDB_SUCCESS) {
ldb_asprintf_errstring(ldb, "Failed to update "
"@INDEXLIST and @ATTRIBUTES "
struct ldb_context *ldb = ldb_module_get_ctx(module);
struct schema_load_private_data *private_data;
int ret;
+ bool need_write = false;
private_data = talloc_zero(module, struct schema_load_private_data);
if (private_data == NULL) {
return ret;
}
- ret = schema_load(ldb, module);
- if (ret != LDB_SUCCESS) {
- return ret;
+ ret = schema_load(ldb, module, &need_write);
+
+ if (ret == LDB_SUCCESS && need_write) {
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct dsdb_schema *schema = NULL;
+
+ ret = ldb_transaction_start(ldb);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: transaction start failed");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ schema = dsdb_get_schema(ldb, frame);
+ if (schema == NULL) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: dsdb_get_schema failed");
+ ldb_transaction_cancel(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ret = dsdb_schema_set_indices_and_attributes(ldb, schema,
+ SCHEMA_WRITE);
+
+ TALLOC_FREE(frame);
+
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to write new "
+ "@INDEXLIST and @ATTRIBUTES "
+ "records for updated schema: %s",
+ ldb_errstring(ldb));
+ ldb_transaction_cancel(ldb);
+ return ret;
+ }
+
+ ret = ldb_transaction_commit(ldb);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+ "schema_load_init: transaction commit failed");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
}
+
return ret;
}
ret = dsdb_schema_set_indices_and_attributes(ldb,
schema,
- true);
+ SCHEMA_WRITE);
if (ret != LDB_SUCCESS) {
ldb_asprintf_errstring(ldb, "Failed to write new "
} tmp;
};
+enum schema_set_enum {
+ SCHEMA_MEMORY_ONLY = 0,
+ SCHEMA_WRITE = 1,
+ SCHEMA_COMPARE = 2,
+};
+
/**
* data stored in schemaInfo attribute
*/
*/
int dsdb_schema_set_indices_and_attributes(struct ldb_context *ldb,
struct dsdb_schema *schema,
- bool write_indices_and_attributes)
+ enum schema_set_enum mode)
{
int ret = LDB_SUCCESS;
struct ldb_result *res;
ldb_schema_set_override_GUID_index(ldb, "objectGUID", "GUID");
}
- if (!write_indices_and_attributes) {
+ if (mode == SCHEMA_MEMORY_ONLY) {
return ret;
}
ret = ldb_search(ldb, mem_ctx, &res, msg->dn, LDB_SCOPE_BASE, NULL,
NULL);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ if (mode == SCHEMA_COMPARE) {
+ /* We are probably not in a transaction */
+ goto wrong_mode;
+ }
ret = ldb_add(ldb, msg);
} else if (ret != LDB_SUCCESS) {
} else if (res->count != 1) {
+ if (mode == SCHEMA_COMPARE) {
+ /* We are probably not in a transaction */
+ goto wrong_mode;
+ }
ret = ldb_add(ldb, msg);
} else {
ret = LDB_SUCCESS;
* are under the read lock and we wish to do a
* delete of any removed/renamed attributes
*/
+ if (mode == SCHEMA_COMPARE) {
+ /* We are probably not in a transaction */
+ goto wrong_mode;
+ }
ret = dsdb_modify(ldb, mod_msg, 0);
}
talloc_free(mod_msg);
ret = ldb_search(ldb, mem_ctx, &res_idx, msg_idx->dn, LDB_SCOPE_BASE,
NULL, NULL);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ if (mode == SCHEMA_COMPARE) {
+ /* We are probably not in a transaction */
+ goto wrong_mode;
+ }
ret = ldb_add(ldb, msg_idx);
} else if (ret != LDB_SUCCESS) {
} else if (res_idx->count != 1) {
+ if (mode == SCHEMA_COMPARE) {
+ /* We are probably not in a transaction */
+ goto wrong_mode;
+ }
ret = ldb_add(ldb, msg_idx);
} else {
ret = LDB_SUCCESS;
* are under the read lock and we wish to do a
* delete of any removed/renamed attributes
*/
+ if (mode == SCHEMA_COMPARE) {
+ /* We are probably not in a transaction */
+ goto wrong_mode;
+ }
ret = dsdb_modify(ldb, mod_msg, 0);
}
talloc_free(mod_msg);
op_error:
talloc_free(mem_ctx);
return ldb_operr(ldb);
+
+wrong_mode:
+ talloc_free(mem_ctx);
+ return LDB_ERR_BUSY;
}
*/
int dsdb_set_schema(struct ldb_context *ldb,
struct dsdb_schema *schema,
- bool write_indices_and_attributes)
+ enum schema_set_enum write_indices_and_attributes)
{
struct dsdb_schema *old_schema;
int ret;
* disk.
*/
int dsdb_reference_schema(struct ldb_context *ldb, struct dsdb_schema *schema,
- bool write_indices_and_attributes)
+ enum schema_set_enum write_indices_and_attributes)
{
int ret;
struct dsdb_schema *old_schema;
talloc_unlink(ldb, old_schema);
/* Set the new attributes based on the new schema */
- ret = dsdb_schema_set_indices_and_attributes(ldb, global_schema, false /* Don't write indices and attributes, it's expensive */);
+ /* Don't write indices and attributes, it's expensive */
+ ret = dsdb_schema_set_indices_and_attributes(ldb, global_schema, SCHEMA_MEMORY_ONLY);
if (ret == LDB_SUCCESS) {
/* Keep a reference to this schema, just in case the original copy is replaced */
if (talloc_reference(ldb, global_schema) == NULL) {
}
}
- ret = dsdb_set_schema(ldb, schema, true);
+ ret = dsdb_set_schema(ldb, schema, SCHEMA_WRITE);
if (ret != LDB_SUCCESS) {
status = WERR_FOOBAR;
DEBUG(0,("ERROR: dsdb_set_schema() failed with %s / %s\n",
ldb_ldif_read_free(ldb, ldif);
torture_assert_werr_ok(tctx, werr, "dsdb_set_attribute_from_ldb() failed!");
- ldb_res = dsdb_set_schema(ldb, schema, true);
+ ldb_res = dsdb_set_schema(ldb, schema, SCHEMA_WRITE);
torture_assert_int_equal(tctx, ldb_res, LDB_SUCCESS, "dsdb_set_schema() failed");
return true;
provision_schema = dsdb_get_schema(s->ldb, s);
} else {
provision_schema = dsdb_get_schema(schema_ldb, s);
- ret = dsdb_reference_schema(s->ldb, provision_schema, false);
+ ret = dsdb_reference_schema(s->ldb, provision_schema, SCHEMA_MEMORY_ONLY);
if (ret != LDB_SUCCESS) {
DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
return WERR_INTERNAL_ERROR;
* attach the schema we just brought over DRS to the ldb,
* so we can use it in dsdb_convert_object_ex below
*/
- ret = dsdb_set_schema(s->ldb, s->self_made_schema, true);
+ ret = dsdb_set_schema(s->ldb, s->self_made_schema, SCHEMA_WRITE);
if (ret != LDB_SUCCESS) {
DEBUG(0,("Failed to attach working schema from DRS.\n"));
return WERR_INTERNAL_ERROR;
talloc_free(res);
- ret = dsdb_set_schema(ldb, ldap_schema, true);
+ ret = dsdb_set_schema(ldb, ldap_schema, SCHEMA_WRITE);
if (ret != LDB_SUCCESS) {
torture_fail(tctx,
talloc_asprintf(tctx, "dsdb_set_schema() failed: %s", ldb_strerror(ret)));