1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-01 04:58:35 +03:00

dsdb: Rework subtree_rename module to use recursive LDB_SCOPE_ONELEVEL searches

This should be more efficient, particularly in the leaf node case when renaming and
deleting entries on large databases.

Andrew Bartlett

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
Andrew Bartlett 2013-06-23 21:38:40 +10:00 committed by Stefan Metzmacher
parent 03b44d26fd
commit 31fb7f9c1b
2 changed files with 103 additions and 108 deletions

View File

@ -34,19 +34,11 @@
#include <ldb_module.h>
#include "libds/common/flags.h"
#include "dsdb/samdb/samdb.h"
struct subren_msg_store {
struct subren_msg_store *next;
struct ldb_dn *olddn;
struct ldb_dn *newdn;
};
#include "dsdb/samdb/ldb_modules/util.h"
struct subtree_rename_context {
struct ldb_module *module;
struct ldb_request *req;
struct subren_msg_store *list;
struct subren_msg_store *current;
};
static struct subtree_rename_context *subren_ctx_init(struct ldb_module *module,
@ -66,14 +58,11 @@ static struct subtree_rename_context *subren_ctx_init(struct ldb_module *module,
return ac;
}
static int subtree_rename_next_request(struct subtree_rename_context *ac);
static int subtree_rename_callback(struct ldb_request *req,
struct ldb_reply *ares)
{
struct ldb_context *ldb;
struct subtree_rename_context *ac;
int ret;
ac = talloc_get_type(req->context, struct subtree_rename_context);
ldb = ldb_module_get_ctx(ac->module);
@ -98,47 +87,8 @@ static int subtree_rename_callback(struct ldb_request *req,
LDB_ERR_OPERATIONS_ERROR);
}
if (ac->current == NULL) {
/* this was the last one */
return ldb_module_done(ac->req, ares->controls,
ares->response, LDB_SUCCESS);
}
ret = subtree_rename_next_request(ac);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
}
talloc_free(ares);
return LDB_SUCCESS;
}
static int subtree_rename_next_request(struct subtree_rename_context *ac)
{
struct ldb_context *ldb;
struct ldb_request *req;
int ret;
ldb = ldb_module_get_ctx(ac->module);
if (ac->current == NULL) {
return ldb_operr(ldb);
}
ret = ldb_build_rename_req(&req, ldb, ac->current,
ac->current->olddn,
ac->current->newdn,
ac->req->controls,
ac, subtree_rename_callback,
ac->req);
LDB_REQ_SET_LOCATION(req);
if (ret != LDB_SUCCESS) {
return ret;
}
ac->current = ac->current->next;
return ldb_next_request(ac->module, req);
return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
}
static int check_constraints(struct ldb_message *msg,
@ -297,16 +247,86 @@ static int check_constraints(struct ldb_message *msg,
return LDB_SUCCESS;
}
static int subtree_rename_search_callback(struct ldb_request *req,
static int subtree_rename_search_onelevel_callback(struct ldb_request *req,
struct ldb_reply *ares)
{
struct subren_msg_store *store;
struct subtree_rename_context *ac;
int ret;
ac = talloc_get_type(req->context, struct subtree_rename_context);
if (!ares || !ac->current) {
if (!ares) {
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
}
if (ares->error != LDB_SUCCESS) {
return ldb_module_done(ac->req, ares->controls,
ares->response, ares->error);
}
switch (ares->type) {
case LDB_REPLY_ENTRY:
{
struct ldb_dn *old_dn = ares->message->dn;
struct ldb_dn *new_dn = ldb_dn_copy(ares, old_dn);
if (!new_dn) {
return ldb_module_oom(ac->module);
}
if ( ! ldb_dn_remove_base_components(new_dn,
ldb_dn_get_comp_num(ac->req->op.rename.olddn))) {
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
}
if ( ! ldb_dn_add_base(new_dn, ac->req->op.rename.newdn)) {
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
}
ret = dsdb_module_rename(ac->module, old_dn, new_dn, DSDB_FLAG_OWN_MODULE, req);
if (ret != LDB_SUCCESS) {
return ret;
}
talloc_free(ares);
return LDB_SUCCESS;
}
case LDB_REPLY_REFERRAL:
/* ignore */
break;
case LDB_REPLY_DONE:
ret = ldb_build_rename_req(&req, ldb_module_get_ctx(ac->module), ac,
ac->req->op.rename.olddn,
ac->req->op.rename.newdn,
ac->req->controls,
ac, subtree_rename_callback,
ac->req);
LDB_REQ_SET_LOCATION(req);
if (ret != LDB_SUCCESS) {
return ret;
}
talloc_free(ares);
return ldb_next_request(ac->module, req);
}
return LDB_SUCCESS;
}
static int subtree_rename_search_base_callback(struct ldb_request *req,
struct ldb_reply *ares)
{
struct ldb_request *search_req;
struct subtree_rename_context *ac;
static const char * const no_attrs[] = {NULL};
int ret;
ac = talloc_get_type(req->context, struct subtree_rename_context);
if (!ares) {
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
}
@ -317,7 +337,6 @@ static int subtree_rename_search_callback(struct ldb_request *req,
switch (ares->type) {
case LDB_REPLY_ENTRY:
if (ldb_dn_compare(ares->message->dn, ac->list->olddn) == 0) {
/*
* This is the root entry of the originating move
* respectively rename request. It has been already
@ -325,39 +344,12 @@ static int subtree_rename_search_callback(struct ldb_request *req,
* Only this one is subject to constraint checking.
*/
ret = check_constraints(ares->message, ac,
ac->list->olddn,
ac->list->newdn);
ac->req->op.rename.olddn,
ac->req->op.rename.newdn);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL,
ret);
}
talloc_free(ares);
return LDB_SUCCESS;
}
store = talloc_zero(ac, struct subren_msg_store);
if (store == NULL) {
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
}
ac->current->next = store;
ac->current = store;
/* the first list element contains the base for the rename */
store->olddn = talloc_steal(store, ares->message->dn);
store->newdn = ldb_dn_copy(store, store->olddn);
if ( ! ldb_dn_remove_base_components(store->newdn,
ldb_dn_get_comp_num(ac->list->olddn))) {
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
}
if ( ! ldb_dn_add_base(store->newdn, ac->list->newdn)) {
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
}
break;
case LDB_REPLY_REFERRAL:
@ -366,16 +358,28 @@ static int subtree_rename_search_callback(struct ldb_request *req,
case LDB_REPLY_DONE:
/* rewind ac->current */
ac->current = ac->list;
/* All dns set up, start with the first one */
ret = subtree_rename_next_request(ac);
ret = ldb_build_search_req(&search_req, ldb_module_get_ctx(ac->module), ac,
ac->req->op.rename.olddn,
LDB_SCOPE_ONELEVEL,
"(objectClass=*)",
no_attrs,
NULL,
ac,
subtree_rename_search_onelevel_callback,
req);
LDB_REQ_SET_LOCATION(search_req);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
return ret;
}
break;
ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
true, NULL);
if (ret != LDB_SUCCESS) {
return ret;
}
talloc_free(ares);
return ldb_next_request(ac->module, search_req);
}
talloc_free(ares);
@ -412,23 +416,14 @@ static int subtree_rename(struct ldb_module *module, struct ldb_request *req)
return ldb_oom(ldb);
}
/* add this entry as the first to do */
ac->current = talloc_zero(ac, struct subren_msg_store);
if (ac->current == NULL) {
return ldb_oom(ldb);
}
ac->current->olddn = req->op.rename.olddn;
ac->current->newdn = req->op.rename.newdn;
ac->list = ac->current;
ret = ldb_build_search_req(&search_req, ldb, ac,
req->op.rename.olddn,
LDB_SCOPE_SUBTREE,
LDB_SCOPE_BASE,
"(objectClass=*)",
attrs,
NULL,
ac,
subtree_rename_search_callback,
subtree_rename_search_base_callback,
req);
LDB_REQ_SET_LOCATION(search_req);
if (ret != LDB_SUCCESS) {

View File

@ -235,7 +235,7 @@ bld.SAMBA_MODULE('ldb_subtree_rename',
init_function='ldb_subtree_rename_module_init',
module_init_name='ldb_init_module',
internal_module=False,
deps='talloc samba-util ldb samdb-common'
deps='talloc samba-util ldb samdb-common DSDB_MODULE_HELPERS'
)