s4:drepl_ridalloc: only ask the rid master for a new rid pool if we need to.
authorStefan Metzmacher <metze@samba.org>
Thu, 8 Jul 2010 13:38:16 +0000 (15:38 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 9 Jul 2010 07:27:15 +0000 (09:27 +0200)
if we are at least half-exhausted then ask for a new pool.

This fixes a bug where we're sending unintialized alloc_pool
variable as exop->fsmo_info to the rid master and get back
DRSUAPI_EXOP_ERR_PARAM_ERROR.

metze

source4/dsdb/repl/drepl_ridalloc.c

index 7b225d5f20711b34527902fe2acfda11cdc7d725..918307b36305a3f599f479c80a0d431cdbc57532 100644 (file)
@@ -145,15 +145,28 @@ 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, uint64_t *alloc_pool)
+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 prev_alloc_pool;
-       const char *attrs[] = { "rIDPreviousAllocationPool", "rIDAllocationPool", NULL };
+       uint64_t alloc_pool;
+       uint64_t prev_pool;
+       uint32_t prev_pool_lo, prev_pool_hi;
+       uint32_t next_rid;
+       static const char * const attrs[] = {
+               "rIDAllocationPool",
+               "rIDPreviousAllocationPool",
+               "rIDNextRid",
+               NULL
+       };
        int ret;
        struct ldb_result *res;
 
+       *exhausted = false;
+       *_alloc_pool = UINT64_MAX;
+
        server_dn = ldb_dn_get_parent(tmp_ctx, samdb_ntds_settings_dn(ldb));
        if (!server_dn) {
                talloc_free(tmp_ctx);
@@ -171,6 +184,7 @@ static int drepl_ridalloc_pool_exhausted(struct ldb_context *ldb, bool *exhauste
        ret = samdb_reference_dn(ldb, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
        if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
                *exhausted = true;
+               *_alloc_pool = 0;
                talloc_free(tmp_ctx);
                return LDB_SUCCESS;
        }
@@ -189,15 +203,24 @@ 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);
-       prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
+       alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
+       prev_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
+       prev_pool_lo = prev_pool & 0xFFFFFFFF;
+       prev_pool_hi = prev_pool >> 32;
+       next_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "rIDNextRid", 0);
 
-       if (*alloc_pool != prev_alloc_pool) {
-               *exhausted = false;
-       } else {
-               *exhausted = true;
+       if (alloc_pool != prev_pool) {
+               talloc_free(tmp_ctx);
+               return LDB_SUCCESS;
+       }
+
+       if (next_rid < (prev_pool_hi + prev_pool_lo)/2) {
+               talloc_free(tmp_ctx);
+               return LDB_SUCCESS;
        }
 
+       *exhausted = true;
+       *_alloc_pool = alloc_pool;
        talloc_free(tmp_ctx);
        return LDB_SUCCESS;
 }
@@ -265,6 +288,12 @@ WERROR dreplsrv_ridalloc_check_rid_pool(struct dreplsrv_service *service)
                return WERR_DS_DRA_INTERNAL_ERROR;
        }
 
+       if (!exhausted) {
+               /* don't need a new pool */
+               talloc_free(tmp_ctx);
+               return WERR_OK;
+       }
+
        DEBUG(2,(__location__ ": Requesting more RIDs from RID Manager\n"));
 
        werr = drepl_request_new_rid_pool(service, rid_manager_dn, fsmo_role_dn, alloc_pool);