s4-ldb: fixed request handling for schemaUpdateNow op
[ira/wip.git] / source4 / dsdb / samdb / ldb_modules / partition.c
index 4626eefa7c3a82033fe054e118fffa846765fd27..587d9206c568f8598320b573fbb02e3306f8eb2b 100644 (file)
@@ -66,7 +66,7 @@ static struct partition_context *partition_init_ctx(struct ldb_module *module, s
  *    helper functions to call the next module in chain
  *    */
 
-static int partition_request(struct ldb_module *module, struct ldb_request *request)
+int partition_request(struct ldb_module *module, struct ldb_request *request)
 {
        int ret;
        switch (request->operation) {
@@ -158,8 +158,9 @@ static int partition_req_callback(struct ldb_request *req,
        struct partition_context *ac;
        struct ldb_module *module;
        struct ldb_request *nreq;
-       int ret, i;
+       int ret;
        struct partition_private_data *data;
+       struct ldb_control *partition_ctrl;
 
        ac = talloc_get_type(req->context, struct partition_context);
        data = talloc_get_type(ac->module->private_data, struct partition_private_data);
@@ -169,6 +170,21 @@ static int partition_req_callback(struct ldb_request *req,
                                        LDB_ERR_OPERATIONS_ERROR);
        }
 
+       partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
+       if (partition_ctrl && (ac->num_requests == 1 || ares->type == LDB_REPLY_ENTRY)) {
+               /* If we didn't fan this request out to mulitple partitions,
+                * or this is an individual search result, we can
+                * deterministily tell the caller what partition this was
+                * written to (repl_meta_data likes to know) */
+                       ret = ldb_reply_add_control(ares,
+                                                   DSDB_CONTROL_CURRENT_PARTITION_OID,
+                                                   false, partition_ctrl->data);
+                       if (ret != LDB_SUCCESS) {
+                               return ldb_module_done(ac->req, NULL, NULL,
+                                                      ret);
+                       }
+       }
+
        if (ares->error != LDB_SUCCESS && !ac->got_success) {
                return ldb_module_done(ac->req, ares->controls,
                                        ares->response, ares->error);
@@ -187,21 +203,6 @@ static int partition_req_callback(struct ldb_request *req,
                        return ldb_module_done(ac->req, NULL, NULL,
                                                LDB_ERR_OPERATIONS_ERROR);
                }
-               for (i=0; data && data->partitions && data->partitions[i]; i++) {
-                       if (ldb_dn_compare(ares->message->dn, data->partitions[i]->ctrl->dn) == 0) {
-                               struct ldb_control *part_control;
-                               /* this is a partition root message - make
-                                  sure it isn't one of our fake root
-                                  entries from a parent partition */
-                               part_control = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
-                               if (part_control && part_control->data != data->partitions[i]->ctrl) {
-                                       DEBUG(6,(__location__ ": Discarding partition mount object %s\n",
-                                                ldb_dn_get_linearized(ares->message->dn)));
-                                       talloc_free(ares);
-                                       return LDB_SUCCESS;
-                               }
-                       }
-               }
                
                return ldb_module_send_entry(ac->req, ares->message, ares->controls);
 
@@ -413,11 +414,6 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re
                return ldb_next_request(module, req);
        }
 
-       ret = partition_reload_if_required(module, data);
-       if (ret != LDB_SUCCESS) {
-               return ret;
-       }
-       
        if (req->operation != LDB_SEARCH) {
                /* Is this a special DN, we need to replicate to every backend? */
                for (i=0; data->replicate && data->replicate[i]; i++) {
@@ -626,7 +622,6 @@ static int partition_delete(struct ldb_module *module, struct ldb_request *req)
 /* rename */
 static int partition_rename(struct ldb_module *module, struct ldb_request *req)
 {
-       int ret;
        /* Find backend */
        struct dsdb_partition *backend, *backend2;
        
@@ -638,11 +633,6 @@ static int partition_rename(struct ldb_module *module, struct ldb_request *req)
                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);
        backend2 = find_partition(data, req->op.rename.newdn, req);
 
@@ -678,6 +668,11 @@ static int partition_start_trans(struct ldb_module *module)
                return ret;
        }
 
+       ret = partition_reload_if_required(module, data);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
        for (i=0; data && data->partitions && data->partitions[i]; i++) {
                struct ldb_module *next = data->partitions[i]->module;
                PARTITION_FIND_OP(next, start_transaction);
@@ -695,6 +690,9 @@ static int partition_start_trans(struct ldb_module *module)
                        return ret;
                }
        }
+
+       data->in_transaction++;
+
        return LDB_SUCCESS;
 }
 
@@ -742,6 +740,12 @@ static int partition_end_trans(struct ldb_module *module)
                }
        }
 
+       if (data->in_transaction == 0) {
+               DEBUG(0,("partition end transaction mismatch\n"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       data->in_transaction--;
+
        return ldb_next_end_trans(module);
 }
 
@@ -761,6 +765,12 @@ static int partition_del_trans(struct ldb_module *module)
                }
        }       
 
+       if (data->in_transaction == 0) {
+               DEBUG(0,("partition del transaction mismatch\n"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       data->in_transaction--;
+
        ret = ldb_next_del_trans(module);
        if (ret != LDB_SUCCESS) {
                final_ret = ret;
@@ -1104,7 +1114,7 @@ static int partition_extended_schema_update_now(struct ldb_module *module, struc
                return ret;
        }
 
-       return ldb_request_done(req, ret);
+       return ldb_module_done(req, NULL, NULL, ret);
 }