mirror of
https://github.com/samba-team/samba.git
synced 2025-08-04 08:22:08 +03:00
s4:dsdb Reload partition metadata if the main db updates
This uses the fact that the primary DB does not change often. Before each operation, we see if the sequence number has changed. Andrew Bartlett
This commit is contained in:
@ -412,6 +412,11 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re
|
|||||||
if (!data || !data->partitions) {
|
if (!data || !data->partitions) {
|
||||||
return ldb_next_request(module, req);
|
return ldb_next_request(module, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = partition_reload_if_required(module, data);
|
||||||
|
if (ret != LDB_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (req->operation != LDB_SEARCH) {
|
if (req->operation != LDB_SEARCH) {
|
||||||
/* Is this a special DN, we need to replicate to every backend? */
|
/* 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 */
|
/* search */
|
||||||
static int partition_search(struct ldb_module *module, struct ldb_request *req)
|
static int partition_search(struct ldb_module *module, struct ldb_request *req)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct ldb_control **saved_controls;
|
struct ldb_control **saved_controls;
|
||||||
/* Find backend */
|
/* Find backend */
|
||||||
struct partition_private_data *data = talloc_get_type(module->private_data,
|
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 ldb_search_options_control *search_options = NULL;
|
||||||
struct dsdb_partition *p;
|
struct dsdb_partition *p;
|
||||||
|
|
||||||
|
ret = partition_reload_if_required(module, data);
|
||||||
|
if (ret != LDB_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
p = find_partition(data, NULL, req);
|
p = find_partition(data, NULL, req);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
/* the caller specified what partition they want the
|
/* 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)) {
|
if (search_options && (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) {
|
||||||
int ret, i;
|
int i;
|
||||||
struct partition_context *ac;
|
struct partition_context *ac;
|
||||||
if ((search_options->search_options & ~LDB_SEARCH_OPTION_PHANTOM_ROOT) == 0) {
|
if ((search_options->search_options & ~LDB_SEARCH_OPTION_PHANTOM_ROOT) == 0) {
|
||||||
/* We have processed this flag, so we are done with this control now */
|
/* 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 */
|
/* rename */
|
||||||
static int partition_rename(struct ldb_module *module, struct ldb_request *req)
|
static int partition_rename(struct ldb_module *module, struct ldb_request *req)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
/* Find backend */
|
/* Find backend */
|
||||||
struct dsdb_partition *backend, *backend2;
|
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;
|
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);
|
backend = find_partition(data, req->op.rename.olddn, req);
|
||||||
backend2 = find_partition(data, req->op.rename.newdn, 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;
|
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 */
|
/* FIXME: This function is still semi-async */
|
||||||
static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req)
|
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) {
|
switch (seq->type) {
|
||||||
case LDB_SEQ_NEXT:
|
case LDB_SEQ_NEXT:
|
||||||
case LDB_SEQ_HIGHEST_SEQ:
|
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,
|
ret = partition_primary_sequence_number(module, req, seq->type, &seq_number);
|
||||||
LDB_EXTENDED_SEQUENCE_NUMBER,
|
|
||||||
tseq,
|
|
||||||
NULL,
|
|
||||||
res,
|
|
||||||
ldb_extended_default_callback,
|
|
||||||
NULL);
|
|
||||||
if (ret != LDB_SUCCESS) {
|
if (ret != LDB_SUCCESS) {
|
||||||
talloc_free(res);
|
|
||||||
return ret;
|
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) */
|
/* Skip the lot if 'data' isn't here yet (initialisation) */
|
||||||
for (i=0; data && data->partitions && data->partitions[i]; i++) {
|
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_private_data *data;
|
||||||
struct partition_context *ac;
|
struct partition_context *ac;
|
||||||
|
int ret;
|
||||||
|
|
||||||
data = talloc_get_type(module->private_data, struct partition_private_data);
|
data = talloc_get_type(module->private_data, struct partition_private_data);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return ldb_next_request(module, req);
|
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) {
|
if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
|
||||||
return partition_sequence_number(module, req);
|
return partition_sequence_number(module, req);
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@ struct partition_private_data {
|
|||||||
|
|
||||||
struct partition_module **modules;
|
struct partition_module **modules;
|
||||||
const char *ldapBackend;
|
const char *ldapBackend;
|
||||||
|
|
||||||
|
uint64_t metadata_seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PARTITION_FIND_OP_NOERROR(module, op) do { \
|
#define PARTITION_FIND_OP_NOERROR(module, op) do { \
|
||||||
|
@ -159,6 +159,38 @@ static int partition_reload_metadata(struct ldb_module *module, struct partition
|
|||||||
return LDB_SUCCESS;
|
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)
|
static const char **find_modules_for_dn(struct partition_private_data *data, struct ldb_dn *dn)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -577,6 +609,12 @@ int partition_init(struct ldb_module *module)
|
|||||||
return LDB_ERR_OPERATIONS_ERROR;
|
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);
|
ret = partition_reload_metadata(module, data, mem_ctx, &msg);
|
||||||
if (ret != LDB_SUCCESS) {
|
if (ret != LDB_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
|
Reference in New Issue
Block a user