s4-dsdb: ensure that new partitions inherit any transaction
[ira/wip.git] / source4 / dsdb / samdb / ldb_modules / partition_init.c
index f4163dab3d4e7a390403d4b31dc6f5c34c725c69..5967bc81593884a2da3029aed8ea34e9b9960d02 100644 (file)
@@ -89,32 +89,34 @@ static int partition_load_modules(struct ldb_context *ldb,
        }
        
        for (i=0; i < modules_attributes->num_values; i++) {
-               char *base;
                char *p;
-
+               DATA_BLOB dn_blob;
                data->modules[i] = talloc(data->modules, struct partition_module);
                if (!data->modules[i]) {
                        ldb_oom(ldb);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
 
-               base = talloc_strdup(data->partitions, (char *)modules_attributes->values[i].data);
-               p = strchr(base, ':');
+               dn_blob = modules_attributes->values[i];
+
+               p = strchr((const char *)dn_blob.data, ':');
                if (!p) {
                        ldb_asprintf_errstring(ldb, 
                                               "partition_load_modules: "
-                                              "invalid form for partition module record (missing ':'): %s", base);
+                                              "invalid form for partition module record (missing ':'): %s", (const char *)dn_blob.data);
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }
-               p[0] = '\0';
+               /* Now trim off the filename */
+               dn_blob.length = ((uint8_t *)p - dn_blob.data);
+
                p++;
                data->modules[i]->modules = ldb_modules_list_from_string(ldb, data->modules[i],
                                                                         p);
                
-               if (strcmp(base, "*") == 0) {
+               if (dn_blob.length == 1 && dn_blob.data[0] == '*') {
                        data->modules[i]->dn = NULL;
                } else {
-                       data->modules[i]->dn = ldb_dn_new(data->modules[i], ldb, base);
+                       data->modules[i]->dn = ldb_dn_from_ldb_val(data->modules[i], ldb, &dn_blob);
                        if (!data->modules[i]->dn || !ldb_dn_validate(data->modules[i]->dn)) {
                                return LDB_ERR_OPERATIONS_ERROR;
                        }
@@ -280,6 +282,16 @@ static int new_partition_from_dn(struct ldb_context *ldb, struct partition_priva
 
        talloc_steal((*partition), (*partition)->module);
 
+       /* if we were in a transaction then we need to start a
+          transaction on this new partition, otherwise we'll get a
+          transaction mismatch when we end the transaction */
+       if (data->in_transaction) {
+               struct ldb_module *next = (*partition)->module;
+               PARTITION_FIND_OP(next, start_transaction);
+
+               ret = next->ops->start_transaction(next);
+       }
+
        return ret;
 }
 
@@ -351,22 +363,25 @@ static int add_partition_to_data(struct ldb_context *ldb, struct partition_priva
 
 int partition_reload_if_required(struct ldb_module *module, 
                                 struct partition_private_data *data)
-       
 {
        uint64_t seq;
        int ret, i;
        struct ldb_context *ldb = ldb_module_get_ctx(module);
        struct ldb_message *msg;
        struct ldb_message_element *partition_attributes;
-       TALLOC_CTX *mem_ctx = talloc_new(data);
+       TALLOC_CTX *mem_ctx;
+
        if (!data) {
                /* Not initilised yet */
                return LDB_SUCCESS;
        }
+
+       mem_ctx = talloc_new(data);
        if (!mem_ctx) {
                ldb_oom(ldb);
                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);
@@ -394,6 +409,7 @@ int partition_reload_if_required(struct ldb_module *module,
                DATA_BLOB dn_blob;
                struct ldb_dn *dn;
                struct dsdb_partition *partition;
+               struct ldb_module tmp_module;
                struct ldb_result *dn_res;
                const char *no_attrs[] = { NULL };
 
@@ -454,8 +470,12 @@ int partition_reload_if_required(struct ldb_module *module,
                        return ret;
                }
 
+               /* Hack to be able to re-use dsdb_module_search_dn, which calls ldb_next_request(), which needs ->next filled out */
+               tmp_module = *partition->module;
+               tmp_module.next = partition->module;
+               
                /* Get the 'correct' case of the partition DNs from the database */
-               ret = dsdb_module_search_dn(partition->module, data, &dn_res, 
+               ret = dsdb_module_search_dn(&tmp_module, data, &dn_res, 
                                            dn, no_attrs);
                if (ret == LDB_SUCCESS) {
                        talloc_free(partition->ctrl->dn);
@@ -463,11 +483,9 @@ int partition_reload_if_required(struct ldb_module *module,
                        talloc_free(dn_res);
                } else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
                        ldb_asprintf_errstring(ldb,
-                                              "Failed to search for %s from " DSDB_PARTITION_DN 
-                                              " replicateEntries for new partition at %s on %s: %s", 
-                                              ldb_dn_get_linearized(data->replicate[i]), 
-                                              partition->backend_url,
-                                              ldb_dn_get_linearized(partition->ctrl->dn), 
+                                              "Failed to search for partition base %s in new partition at %s: %s", 
+                                              ldb_dn_get_linearized(dn), 
+                                              partition->backend_url, 
                                               ldb_errstring(ldb));
                        talloc_free(mem_ctx);
                        return ret;
@@ -690,17 +708,6 @@ int partition_create(struct ldb_module *module, struct ldb_request *req)
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
-               
-               /* Start a transaction on the DB (as it won't be in one being brand new) */
-               {
-                       struct ldb_module *next = partition->module;
-                       PARTITION_FIND_OP(next, start_transaction);
-                       
-                       ret = next->ops->start_transaction(next);
-                       if (ret != LDB_SUCCESS) {
-                               return ret;
-                       }
-               }
        }
        
        ret = new_partition_set_replicated_metadata(ldb, module, last_req, data, partition);
@@ -742,6 +749,9 @@ int partition_init(struct ldb_module *module)
                return ret;
        }
 
+       module->private_data = talloc_steal(module, data);
+       talloc_free(mem_ctx);
+
        ret = ldb_mod_register_control(module, LDB_CONTROL_DOMAIN_SCOPE_OID);
        if (ret != LDB_SUCCESS) {
                ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
@@ -756,8 +766,5 @@ int partition_init(struct ldb_module *module)
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       module->private_data = talloc_steal(module, data);
-
-       talloc_free(mem_ctx);
        return ldb_next_init(module);
 }