From 2590b7795d38728f53f795c2b60b32ace9ca5c4b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 6 Jan 2010 17:18:42 +1100 Subject: s4-repl: implement MSG_DREPL_ALLOCATE_RID When the repl server gets MSG_DREPL_ALLOCATE_RID it contacts the RID Manager to ask for another RID pool. We use a callback on completion of the operation to make sure that we don't have two RID allocation requests in flight at once Pair-Programmed-With: Andrew Bartlett --- source4/dsdb/repl/drepl_ridalloc.c | 66 +++++++++++++++++++++++++++----------- source4/dsdb/repl/drepl_service.c | 1 + 2 files changed, 48 insertions(+), 19 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/repl/drepl_ridalloc.c b/source4/dsdb/repl/drepl_ridalloc.c index 34f75862da..43fc5a2c51 100644 --- a/source4/dsdb/repl/drepl_ridalloc.c +++ b/source4/dsdb/repl/drepl_ridalloc.c @@ -96,13 +96,32 @@ static WERROR drepl_create_rid_manager_source_dsa(struct dreplsrv_service *servi return WERR_OK; } +/* + called when a rid allocation request has completed + */ +static void drepl_new_rid_pool_callback(struct dreplsrv_service *service, WERROR werr) +{ + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,(__location__ ": RID Manager failed RID allocation - %s\n", + win_errstr(werr))); + } else { + DEBUG(3,(__location__ ": RID Manager completed RID allocation OK\n")); + } + + /* don't keep the connection open to the RID Manager */ + talloc_free(service->ridalloc.rid_manager_source_dsa); + service->ridalloc.rid_manager_source_dsa = NULL; + + service->ridalloc.in_progress = false; +} /* schedule a getncchanges request to the RID Manager to ask for a new set of RIDs using DRSUAPI_EXOP_FSMO_RID_ALLOC */ static WERROR drepl_request_new_rid_pool(struct dreplsrv_service *service, - struct ldb_dn *rid_manager_dn, struct ldb_dn *fsmo_role_dn) + struct ldb_dn *rid_manager_dn, struct ldb_dn *fsmo_role_dn, + uint64_t alloc_pool) { WERROR werr; @@ -113,8 +132,11 @@ static WERROR drepl_request_new_rid_pool(struct dreplsrv_service *service, W_ERROR_NOT_OK_RETURN(werr); } + service->ridalloc.in_progress = true; + werr = dreplsrv_schedule_partition_pull_source(service, service->ridalloc.rid_manager_source_dsa, - DRSUAPI_EXOP_FSMO_RID_ALLOC); + DRSUAPI_EXOP_FSMO_RID_ALLOC, alloc_pool, + drepl_new_rid_pool_callback); return werr; } @@ -122,11 +144,11 @@ static WERROR drepl_request_new_rid_pool(struct dreplsrv_service *service, /* see if we are on the last pool we have */ -static int drepl_ridalloc_pool_exhausted(struct ldb_context *ldb, bool *exhausted) +static int drepl_ridalloc_pool_exhausted(struct ldb_context *ldb, bool *exhausted, uint64_t *alloc_pool) { struct ldb_dn *server_dn, *machine_dn, *rid_set_dn; TALLOC_CTX *tmp_ctx = talloc_new(ldb); - uint64_t alloc_pool, prev_alloc_pool; + uint64_t prev_alloc_pool; const char *attrs[] = { "rIDPreviousAllocationPool", "rIDAllocationPool", NULL }; int ret; struct ldb_result *res; @@ -166,10 +188,10 @@ static int drepl_ridalloc_pool_exhausted(struct ldb_context *ldb, bool *exhauste return ret; } - alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0); + *alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0); prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0); - if (alloc_pool != prev_alloc_pool) { + if (*alloc_pool != prev_alloc_pool) { *exhausted = false; } else { *exhausted = true; @@ -193,6 +215,12 @@ WERROR dreplsrv_ridalloc_check_rid_pool(struct dreplsrv_service *service) bool exhausted; WERROR werr; int ret; + uint64_t alloc_pool; + + if (service->ridalloc.in_progress) { + talloc_free(tmp_ctx); + return WERR_OK; + } /* steps: @@ -230,25 +258,25 @@ WERROR dreplsrv_ridalloc_check_rid_pool(struct dreplsrv_service *service) return WERR_OK; } - ret = drepl_ridalloc_pool_exhausted(ldb, &exhausted); + ret = drepl_ridalloc_pool_exhausted(ldb, &exhausted, &alloc_pool); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return WERR_DS_DRA_INTERNAL_ERROR; } - if (!exhausted) { - /* if we're not exhausted we don't need the exop call */ - talloc_free(tmp_ctx); - - /* we don't need to keep an open connection to the RID - Manager */ - talloc_free(service->ridalloc.rid_manager_source_dsa); - service->ridalloc.rid_manager_source_dsa = NULL; + DEBUG(2,(__location__ ": Requesting more RIDs from RID Manager\n")); - return WERR_OK; - } - - werr = drepl_request_new_rid_pool(service, rid_manager_dn, fsmo_role_dn); + werr = drepl_request_new_rid_pool(service, rid_manager_dn, fsmo_role_dn, alloc_pool); talloc_free(tmp_ctx); return werr; } + +/* called by the samldb ldb module to tell us to ask for a new RID + pool */ +void dreplsrv_allocate_rid(struct messaging_context *msg, void *private_data, + uint32_t msg_type, + struct server_id server_id, DATA_BLOB *data) +{ + struct dreplsrv_service *service = talloc_get_type(private_data, struct dreplsrv_service); + dreplsrv_ridalloc_check_rid_pool(service); +} diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c index a05ccc8d70..44164ff68f 100644 --- a/source4/dsdb/repl/drepl_service.c +++ b/source4/dsdb/repl/drepl_service.c @@ -206,6 +206,7 @@ static void dreplsrv_task_init(struct task_server *task) irpc_add_name(task->msg_ctx, "dreplsrv"); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICASYNC, drepl_replica_sync, service); + messaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid); } /* -- cgit