summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb')
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c119
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.h2
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition_init.c38
3 files changed, 120 insertions, 39 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index f6031fb944..4626eefa7c 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -412,6 +412,11 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re
if (!data || !data->partitions) {
return ldb_next_request(module, req);
}
+
+ ret = partition_reload_if_required(module, data);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
if (req->operation != LDB_SEARCH) {
/* Is this a special DN, we need to replicate to every backend? */
@@ -463,6 +468,7 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re
/* search */
static int partition_search(struct ldb_module *module, struct ldb_request *req)
{
+ int ret;
struct ldb_control **saved_controls;
/* Find backend */
struct partition_private_data *data = talloc_get_type(module->private_data,
@@ -479,6 +485,11 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req)
struct ldb_search_options_control *search_options = NULL;
struct dsdb_partition *p;
+ ret = partition_reload_if_required(module, data);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
p = find_partition(data, NULL, req);
if (p != NULL) {
/* the caller specified what partition they want the
@@ -511,7 +522,7 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req)
*/
if (search_options && (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) {
- int ret, i;
+ int i;
struct partition_context *ac;
if ((search_options->search_options & ~LDB_SEARCH_OPTION_PHANTOM_ROOT) == 0) {
/* We have processed this flag, so we are done with this control now */
@@ -615,6 +626,7 @@ static int partition_delete(struct ldb_module *module, struct ldb_request *req)
/* rename */
static int partition_rename(struct ldb_module *module, struct ldb_request *req)
{
+ int ret;
/* Find backend */
struct dsdb_partition *backend, *backend2;
@@ -626,6 +638,11 @@ static int partition_rename(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_OPERATIONS_ERROR;
}
+ ret = partition_reload_if_required(module, data);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
backend = find_partition(data, req->op.rename.olddn, req);
backend2 = find_partition(data, req->op.rename.newdn, req);
@@ -751,6 +768,61 @@ static int partition_del_trans(struct ldb_module *module)
return final_ret;
}
+int partition_primary_sequence_number(struct ldb_module *module, TALLOC_CTX *mem_ctx,
+ enum ldb_sequence_type type, uint64_t *seq_number)
+{
+ int ret;
+ struct ldb_result *res;
+ struct ldb_seqnum_request *tseq;
+ struct ldb_request *treq;
+ struct ldb_seqnum_result *seqr;
+ res = talloc_zero(mem_ctx, struct ldb_result);
+ if (res == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ tseq = talloc_zero(res, struct ldb_seqnum_request);
+ if (tseq == NULL) {
+ talloc_free(res);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ tseq->type = type;
+
+ 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 ret;
+ }
+
+ ret = ldb_next_request(module, treq);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+ ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+
+ seqr = talloc_get_type(res->extended->data,
+ struct ldb_seqnum_result);
+ if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ ldb_set_errstring(ldb_module_get_ctx(module), "Primary backend in partitions module returned a timestamp based seq number (must return a normal number)");
+ talloc_free(res);
+ return ret;
+ } else {
+ *seq_number = seqr->seq_num;
+ }
+ talloc_free(res);
+ return LDB_SUCCESS;
+}
/* FIXME: This function is still semi-async */
static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req)
@@ -783,49 +855,12 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque
switch (seq->type) {
case LDB_SEQ_NEXT:
case LDB_SEQ_HIGHEST_SEQ:
- res = talloc_zero(req, struct ldb_result);
- if (res == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- tseq = talloc_zero(res, struct ldb_seqnum_request);
- if (tseq == NULL) {
- talloc_free(res);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- tseq->type = seq->type;
- ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res,
- LDB_EXTENDED_SEQUENCE_NUMBER,
- tseq,
- NULL,
- res,
- ldb_extended_default_callback,
- NULL);
+ ret = partition_primary_sequence_number(module, req, seq->type, &seq_number);
if (ret != LDB_SUCCESS) {
- talloc_free(res);
return ret;
}
- ret = ldb_next_request(module, treq);
- if (ret != LDB_SUCCESS) {
- talloc_free(res);
- return ret;
- }
- ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
- if (ret != LDB_SUCCESS) {
- talloc_free(res);
- return ret;
- }
-
- seqr = talloc_get_type(res->extended->data,
- struct ldb_seqnum_result);
- if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
- timestamp_sequence = seqr->seq_num;
- } else {
- seq_number += seqr->seq_num;
- }
- talloc_free(res);
-
/* Skip the lot if 'data' isn't here yet (initialisation) */
for (i=0; data && data->partitions && data->partitions[i]; i++) {
@@ -1078,12 +1113,18 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req
{
struct partition_private_data *data;
struct partition_context *ac;
+ int ret;
data = talloc_get_type(module->private_data, struct partition_private_data);
if (!data) {
return ldb_next_request(module, req);
}
+ ret = partition_reload_if_required(module, data);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
return partition_sequence_number(module, req);
}
diff --git a/source4/dsdb/samdb/ldb_modules/partition.h b/source4/dsdb/samdb/ldb_modules/partition.h
index 2fbcada0a1..9bab2dbcbc 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.h
+++ b/source4/dsdb/samdb/ldb_modules/partition.h
@@ -42,6 +42,8 @@ struct partition_private_data {
struct partition_module **modules;
const char *ldapBackend;
+
+ uint64_t metadata_seq;
};
#define PARTITION_FIND_OP_NOERROR(module, op) do { \
diff --git a/source4/dsdb/samdb/ldb_modules/partition_init.c b/source4/dsdb/samdb/ldb_modules/partition_init.c
index cfec1aa585..2da938d20e 100644
--- a/source4/dsdb/samdb/ldb_modules/partition_init.c
+++ b/source4/dsdb/samdb/ldb_modules/partition_init.c
@@ -159,6 +159,38 @@ static int partition_reload_metadata(struct ldb_module *module, struct partition
return LDB_SUCCESS;
}
+int partition_reload_if_required(struct ldb_module *module,
+ struct partition_private_data *data)
+
+{
+ uint64_t seq;
+ int ret;
+ TALLOC_CTX *mem_ctx = talloc_new(data);
+ if (!data) {
+ /* Not initilised yet */
+ return LDB_SUCCESS;
+ }
+ if (!mem_ctx) {
+ ldb_oom(ldb_module_get_ctx(module));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ret = partition_primary_sequence_number(module, mem_ctx, LDB_SEQ_HIGHEST_SEQ, &seq);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+ if (seq != data->metadata_seq) {
+ ret = partition_reload_metadata(module, data, mem_ctx, NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+ data->metadata_seq = seq;
+ }
+ talloc_free(mem_ctx);
+ return LDB_SUCCESS;
+}
+
static const char **find_modules_for_dn(struct partition_private_data *data, struct ldb_dn *dn)
{
int i;
@@ -577,6 +609,12 @@ int partition_init(struct ldb_module *module)
return LDB_ERR_OPERATIONS_ERROR;
}
+ ret = partition_primary_sequence_number(module, mem_ctx, LDB_SEQ_HIGHEST_SEQ, &data->metadata_seq);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
ret = partition_reload_metadata(module, data, mem_ctx, &msg);
if (ret != LDB_SUCCESS) {
return ret;