r15795: Try to use the async code by default
authorSimo Sorce <idra@samba.org>
Mon, 22 May 2006 03:55:01 +0000 (03:55 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:08:21 +0000 (14:08 -0500)
It passess all my tests, but I still need to work on a lot of stuff.
Shouldn't impact anybody else work, so I want to commit now and see what happens

Will work to remove the old code from modules and backends soon, and make some
more restyling in ldb internals.

So, if there is something you don't like in this desgin please speak now.

Simo.
(This used to be commit 8b2a563e716a789ea77cbfbf2f372724de5361ce)

source4/dsdb/samdb/ldb_modules/password_hash.c
source4/dsdb/samdb/ldb_modules/samldb.c
source4/lib/ldb/common/ldb.c
source4/setup/provision_init.ldif

index 0d4f0c6a0f72a725e661335c51bd37e752b4e262..c1eb244e19eb7c8cafb934b32cb4a798b728e5f4 100644 (file)
@@ -975,16 +975,25 @@ static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_messa
        return LDB_SUCCESS;
 }
 
-static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg)
+static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg, int is_mod)
 {
        NTTIME now_nt;
 
        /* set it as now */
        unix_to_nt_time(&now_nt, time(NULL));
 
-       /* replace or add */
-       if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE) != 0) {
-               return LDB_ERR_OPERATIONS_ERROR;
+       if (!is_mod) {
+               /* be sure there isn't a 0 value set (eg. coming from the template) */
+               ldb_msg_remove_attr(msg, "pwdLastSet");
+               /* add */
+               if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_ADD) != 0) {
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
+       } else {
+               /* replace */
+               if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE) != 0) {
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
        }
 
        if (samdb_msg_add_uint64(module->ldb, msg, msg, "pwdLastSet", now_nt) != 0) {
@@ -1326,7 +1335,7 @@ static int password_hash_add_async_do_add(struct ldb_async_handle *h) {
 
        /* don't touch it if a value is set. It could be an incoming samsync */
        if (ldb_msg_find_uint64(msg, "pwdLastSet", 0) == 0) {
-               if (set_pwdLastSet(ac->module, msg) != LDB_SUCCESS) {
+               if (set_pwdLastSet(ac->module, msg, 0) != LDB_SUCCESS) {
                        return LDB_ERR_OPERATIONS_ERROR;
                }
        }
@@ -1630,7 +1639,7 @@ static int password_hash_mod_async_do_mod(struct ldb_async_handle *h) {
        }
 
        /* set change time */
-       if (set_pwdLastSet(ac->module, msg) != LDB_SUCCESS) {
+       if (set_pwdLastSet(ac->module, msg, 1) != LDB_SUCCESS) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
index e662b2a6636d35ea0244c188e64d38f4e01f3498..9bf322f3844ed6123f4fc153dcb650ca32b230e1 100644 (file)
@@ -94,14 +94,35 @@ static BOOL samldb_msg_add_sid(struct ldb_module *module, struct ldb_message *ms
        return (ldb_msg_add_value(msg, name, &v) == 0);
 }
 
-static BOOL samldb_find_or_add_attribute(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *value, const char *set_value)
+static BOOL samldb_find_or_add_value(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *value, const char *set_value)
 {
+       if (msg == NULL || name == NULL || value == NULL || set_value == NULL) {
+               return False;
+       }
+
        if (samldb_find_attribute(msg, name, value) == NULL) {
                return samldb_msg_add_string(module, msg, name, set_value);
        }
        return True;
 }
 
+static BOOL samldb_find_or_add_attribute(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *set_value)
+{
+       int j;
+       struct ldb_message_element *el;
+
+       if (msg == NULL || name == NULL || set_value == NULL) {
+               return False;
+       }
+
+               el = ldb_msg_find_element(msg, name);
+       if (el) {
+               return True;
+       }
+               
+       return samldb_msg_add_string(module, msg, name, set_value);
+}
+
 /*
   allocate a new id, attempting to do it atomically
   return 0 on failure, the id on success
@@ -492,16 +513,15 @@ static int samldb_copy_template(struct ldb_module *module, struct ldb_message *m
                                    strcasecmp((char *)el->values[j].data, "secretTemplate") == 0) {
                                        continue;
                                }
-                               if ( ! samldb_find_or_add_attribute(module, msg, el->name, 
-                                                                   (char *)el->values[j].data,
-                                                                   (char *)el->values[j].data)) {
+                               if ( ! samldb_find_or_add_value(module, msg, el->name, 
+                                                               (char *)el->values[j].data,
+                                                               (char *)el->values[j].data)) {
                                        ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Attribute adding failed...\n");
                                        talloc_free(res);
                                        return -1;
                                }
                        } else {
                                if ( ! samldb_find_or_add_attribute(module, msg, el->name, 
-                                                                   NULL,
                                                                    (char *)el->values[j].data)) {
                                        ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Attribute adding failed...\n");
                                        talloc_free(res);
@@ -558,7 +578,7 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
                        talloc_free(mem_ctx);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
-               if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, name)) {
+               if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", name)) {
                        talloc_free(mem_ctx);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
@@ -620,7 +640,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
        }
 
        /* if the only attribute was: "objectclass: computer", then make sure we also add "user" objectclass */
-       if ( ! samldb_find_or_add_attribute(module, msg2, "objectclass", "user", "user")) {
+       if ( ! samldb_find_or_add_value(module, msg2, "objectclass", "user", "user")) {
                talloc_free(mem_ctx);
                return LDB_ERR_OPERATIONS_ERROR;
        }
@@ -633,7 +653,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
                        talloc_free(mem_ctx);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
-               if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, name)) {
+               if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", name)) {
                        talloc_free(mem_ctx);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
index 68e3c116fc7b347fb69842d588e3340ec63e490c..3d5f816fe8771e43ddb5ba8c32e64fe01ed0e648 100644 (file)
@@ -2,6 +2,7 @@
    ldb database library
 
    Copyright (C) Andrew Tridgell  2004
+   Copyright (C) Simo Sorce  2005-2006
 
      ** NOTE! The following LGPL license applies to the ldb
      ** library. This does NOT imply that all of Samba is released
@@ -251,6 +252,7 @@ int ldb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type typ
        return handle->module->ops->async_wait(handle, type);
 }
 
+
 /*
   check for an error return from an op 
   if an op fails, but has not setup an error string, then setup one now
@@ -272,6 +274,7 @@ static int ldb_op_finish(struct ldb_context *ldb, int status)
 /*
   start an ldb request
   autostarts a transacion if none active and the operation is not a search
+  does not work for ASYNC operations
   NOTE: the request must be a talloc context.
   returns LDB_ERR_* on errors.
 */
@@ -285,7 +288,7 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
                req->op.search.res = NULL;
        }
 
-       /* start a transaction if needed */
+       /* start a transaction if not async and not search */
        if ((!ldb->transaction_active) &&
            (req->operation == LDB_REQ_ADD ||
             req->operation == LDB_REQ_MODIFY ||
@@ -317,6 +320,71 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
   Use talloc_free to free the ldb_message returned in 'res', if successful
 
 */
+static int ldb_search_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares)
+{
+       struct ldb_result *res;
+       int n;
+       
+       if (!context) {
+               ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context in callback"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }       
+
+       res = *((struct ldb_result **)context);
+
+       if (!res || !ares) {
+               goto error;
+       }
+
+       if (ares->type == LDB_REPLY_ENTRY) {
+               res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
+               if (! res->msgs) {
+                       goto error;
+               }
+
+               res->msgs[res->count + 1] = NULL;
+
+               res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+               if (! res->msgs[res->count]) {
+                       goto error;
+               }
+
+               res->count++;
+       }
+
+       if (ares->type == LDB_REPLY_REFERRAL) {
+               if (res->refs) {
+                       for (n = 0; res->refs[n]; n++) /*noop*/ ;
+               } else {
+                       n = 0;
+               }
+
+               res->refs = talloc_realloc(res, res->refs, char *, n + 2);
+               if (! res->refs) {
+                       goto error;
+               }
+
+               res->refs[n] = talloc_steal(res->refs, ares->referral);
+               res->refs[n + 1] = NULL;
+       }
+
+       if (ares->controls) {
+               res->controls = talloc_steal(res, ares->controls);
+               if (! res->controls) {
+                       goto error;
+               }
+       }
+
+       talloc_free(ares);
+       return LDB_SUCCESS;
+
+error:
+       talloc_free(ares);
+       talloc_free(res);
+       *((struct ldb_result **)context) = NULL;
+       return LDB_ERR_OPERATIONS_ERROR;
+}
+
 int ldb_search(struct ldb_context *ldb, 
               const struct ldb_dn *base,
               enum ldb_scope scope,
@@ -327,7 +395,10 @@ int ldb_search(struct ldb_context *ldb,
        struct ldb_request *req;
        int ret;
 
-       (*res) = NULL;
+       *res = talloc_zero(ldb, struct ldb_result);
+       if (! *res) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
        req = talloc(ldb, struct ldb_request);
        if (req == NULL) {
@@ -335,7 +406,7 @@ int ldb_search(struct ldb_context *ldb,
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       req->operation = LDB_REQ_SEARCH;
+       req->operation = LDB_ASYNC_SEARCH;
        req->op.search.base = base;
        req->op.search.scope = scope;
 
@@ -348,16 +419,53 @@ int ldb_search(struct ldb_context *ldb,
 
        req->op.search.attrs = attrs;
        req->controls = NULL;
+       req->creds = NULL;
+       req->async.context = res;
+       req->async.callback = ldb_search_callback;
+       req->async.timeout = 600; /* 10 minutes */
 
        ret = ldb_request(ldb, req);
        
        if (ret == LDB_SUCCESS) {
-               (*res) = talloc_steal(ldb, req->op.search.res);
+               ret = ldb_async_wait(req->async.handle, LDB_WAIT_ALL);
        }
+       
+       if (ret != LDB_SUCCESS) {
+               talloc_free(*res);
+               *res = NULL;
+       }
+
        talloc_free(req);
        return ret;
 }
 
+static int ldb_autotransaction_request(struct ldb_context *ldb, struct ldb_request *req)
+{
+       int ret, close_transaction;
+
+       close_transaction = 0;
+       if (!ldb->transaction_active) {
+               ret = ldb_transaction_start(ldb);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+               close_transaction = 1;
+       }
+
+       ret = ldb_request(ldb, req);
+
+       if (ret == LDB_SUCCESS) {
+               ret = ldb_async_wait(req->async.handle, LDB_WAIT_ALL);
+       }
+
+       if (close_transaction) {
+               return ldb_op_finish(ldb, ret);
+       }
+
+       return ret;
+}
+
+
 /*
   add a record to the database. Will fail if a record with the given class and key
   already exists
@@ -377,11 +485,16 @@ int ldb_add(struct ldb_context *ldb,
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       req->operation = LDB_REQ_ADD;
+       req->operation = LDB_ASYNC_ADD;
        req->op.add.message = message;
        req->controls = NULL;
+       req->creds = NULL;
+       req->async.context = NULL;
+       req->async.callback = NULL;
+       req->async.timeout = 600; /* 10 minutes */
 
-       ret = ldb_request(ldb, req);
+       /* do request and autostart a transaction */
+       ret = ldb_autotransaction_request(ldb, req);
 
        talloc_free(req);
        return ret;
@@ -405,11 +518,16 @@ int ldb_modify(struct ldb_context *ldb,
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       req->operation = LDB_REQ_MODIFY;
+       req->operation = LDB_ASYNC_MODIFY;
        req->op.add.message = message;
        req->controls = NULL;
+       req->creds = NULL;
+       req->async.context = NULL;
+       req->async.callback = NULL;
+       req->async.timeout = 600; /* 10 minutes */
 
-       ret = ldb_request(ldb, req);
+       /* do request and autostart a transaction */
+       ret = ldb_autotransaction_request(ldb, req);
 
        talloc_free(req);
        return ret;
@@ -430,11 +548,16 @@ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       req->operation = LDB_REQ_DELETE;
+       req->operation = LDB_ASYNC_DELETE;
        req->op.del.dn = dn;
        req->controls = NULL;
+       req->creds = NULL;
+       req->async.context = NULL;
+       req->async.callback = NULL;
+       req->async.timeout = 600; /* 10 minutes */
 
-       ret = ldb_request(ldb, req);
+       /* do request and autostart a transaction */
+       ret = ldb_autotransaction_request(ldb, req);
 
        talloc_free(req);
        return ret;
@@ -454,12 +577,17 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       req->operation = LDB_REQ_RENAME;
+       req->operation = LDB_ASYNC_RENAME;
        req->op.rename.olddn = olddn;
        req->op.rename.newdn = newdn;
        req->controls = NULL;
+       req->creds = NULL;
+       req->async.context = NULL;
+       req->async.callback = NULL;
+       req->async.timeout = 600; /* 10 minutes */
 
-       ret = ldb_request(ldb, req);
+       /* do request and autostart a transaction */
+       ret = ldb_autotransaction_request(ldb, req);
 
        talloc_free(req);
        return ret;
index ee09f73340055125657ef8f2af1d9755637b8d08..6698b27e33b5d029748a9535f51cc665169d69c9 100644 (file)
@@ -82,8 +82,8 @@ vendorVersion: ${VERSION}
 #
 # Some Known ordering constraints:
 # - rootdse must be first, as it makes redirects from "" -> cn=rootdse
-# - password_hash must be before samldb, or else the template code in samldb breaks setting the pwdLastSet attribute
+# - samldb must be before password_hash, because password_hash checks that the objectclass is of type person (filled in by samldb)
 
 dn: @MODULES
-@LIST: rootdse,kludge_acl,paged_results,server_sort,extended_dn,asq,password_hash,samldb,operational,objectguid,rdn_name,objectclass
+@LIST: rootdse,kludge_acl,paged_results,server_sort,extended_dn,asq,samldb,password_hash,operational,objectguid,rdn_name,objectclass