r16083: Make it possible to initialise a backend module, without it setting up
authorAndrew Bartlett <abartlet@samba.org>
Wed, 7 Jun 2006 21:03:38 +0000 (21:03 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:08:57 +0000 (14:08 -0500)
the whole ldb structure.

Because the sequence number was a fn pointer on the main ldb context,
turn it into a full request (currently sync).

Andrew Bartlett

source/dsdb/samdb/ldb_modules/rootdse.c
source/lib/ldb/common/ldb.c
source/lib/ldb/common/ldb_modules.c
source/lib/ldb/include/ldb.h
source/lib/ldb/include/ldb_private.h
source/lib/ldb/ldb_ildap/ldb_ildap.c
source/lib/ldb/ldb_ldap/ldb_ldap.c
source/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
source/lib/ldb/ldb_tdb/ldb_tdb.c

index e96da829eb908c8178443fe0f4e9100ec6ea14d7..49d93be7f2c254310fd11ae630d58a1e1c944c53 100644 (file)
@@ -102,10 +102,13 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
        }
 
        if (do_attribute(attrs, "highestCommittedUSN")) {
-               if (module->ldb->sequence_number != NULL && 
-                   ldb_msg_add_fmt(msg, "highestCommittedUSN", 
-                                   "%llu", module->ldb->sequence_number(module->ldb)) != 0) {
-                       goto failed;
+               uint64_t seq_num;
+               int ret = ldb_sequence_number(module->ldb, &seq_num);
+               if (ret == LDB_SUCCESS) {
+                       if (ldb_msg_add_fmt(msg, "highestCommittedUSN", 
+                                           "%llu", seq_num) != 0) {
+                               goto failed;
+                       }
                }
        }
        
index 1fdbeb55d2f55188188438c3d1d69fa58fff8b38..ff5d2a2e8b49120dab0fe8825c7643da6e7b2195 100644 (file)
@@ -91,16 +91,20 @@ static ldb_connect_fn ldb_find_backend(const char *url)
 }
 
 /* 
connect to a database. The URL can either be one of the following forms
  Return the ldb module form of a database. The URL can either be one of the following forms
    ldb://path
    ldapi://path
 
    flags is made up of LDB_FLG_*
 
    the options are passed uninterpreted to the backend, and are
-   backend specific
+   backend specific.
+
+  This allows modules to get at only the backend module, for example where a module 
+  may wish to direct certain requests at a particular backend.
 */
-int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[])
+int ldb_connect_backend(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[],
+                       struct ldb_module **backend_module)
 {
        int ret;
        char *backend;
@@ -128,12 +132,34 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co
                return LDB_ERR_OTHER;
        }
 
-       ret = fn(ldb, url, flags, options);
+       ret = fn(ldb, url, flags, options, backend_module);
 
        if (ret != LDB_SUCCESS) {
                ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'\n", url);
                return ret;
        }
+       return ret;
+}
+
+
+/* 
+ connect to a database. The URL can either be one of the following forms
+   ldb://path
+   ldapi://path
+
+   flags is made up of LDB_FLG_*
+
+   the options are passed uninterpreted to the backend, and are
+   backend specific
+*/
+int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[])
+{
+       int ret;
+
+       ret = ldb_connect_backend(ldb, url, flags, options, &ldb->modules);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
 
        if (ldb_load_modules(ldb, options) != LDB_SUCCESS) {
                ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'\n", url);
@@ -395,6 +421,10 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
                FIRST_OP(ldb, rename);
                ret = module->ops->rename(module, req);
                break;
+       case LDB_SEQUENCE_NUMBER:
+               FIRST_OP(ldb, sequence_number);
+               ret = module->ops->sequence_number(module, req);
+               break;
        default:
                FIRST_OP(ldb, request);
                ret = module->ops->request(module, req);
@@ -655,6 +685,38 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct
 }
 
 
+/*
+  rename a record in the database
+*/
+int ldb_sequence_number(struct ldb_context *ldb, uint64_t *seq_num)
+{
+       struct ldb_request *req;
+       int ret;
+
+       req = talloc(ldb, struct ldb_request);
+       if (req == NULL) {
+               ldb_set_errstring(ldb, talloc_strdup(ldb, "Out of memory!"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       req->operation = LDB_SEQUENCE_NUMBER;
+       req->controls = NULL;
+       req->async.context = NULL;
+       req->async.callback = NULL;
+       ldb_set_timeout(ldb, req, 0); /* use default timeout */
+
+       /* do request and autostart a transaction */
+       ret = ldb_request(ldb, req);
+       
+       if (ret == LDB_SUCCESS) {
+               *seq_num = req->op.seq_num.seq_num;
+       }
+
+       talloc_free(req);
+       return ret;
+}
+
+
 
 /*
   return extended error information 
index 6f36bdc5e94093e43066356631a21667367ac9f5..d09579510e9fc1db737f2cb98a1cb0829caa5dea 100644 (file)
@@ -366,6 +366,9 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
        case LDB_RENAME:
                FIND_OP(module, rename);
                return module->ops->rename(module, request);
+       case LDB_SEQUENCE_NUMBER:
+               FIND_OP(module, sequence_number);
+               return module->ops->sequence_number(module, request);
        default:
                FIND_OP(module, request);
                return module->ops->request(module, request);
index 644f74385f9308c33dfc8142c344ce6eaefda948..033a9c1f398e7df237b863cdc40fd595c0a6417b 100644 (file)
@@ -567,8 +567,8 @@ enum ldb_request_type {
        LDB_MODIFY,
        LDB_DELETE,
        LDB_RENAME,
-
-       LDB_REQ_REGISTER
+       LDB_REQ_REGISTER,
+       LDB_SEQUENCE_NUMBER
 };
 
 enum ldb_reply_type {
@@ -638,6 +638,10 @@ struct ldb_register_control {
        const char *oid;
 };
 
+struct ldb_sequence_number {
+       uint64_t seq_num;
+};
+
 struct ldb_request {
 
        enum ldb_request_type operation;
@@ -649,6 +653,7 @@ struct ldb_request {
                struct ldb_delete del;
                struct ldb_rename rename;
                struct ldb_register_control reg;
+               struct ldb_sequence_number seq_num;
        } op;
 
        struct ldb_control **controls;
@@ -810,6 +815,11 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct
 */
 int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn);
 
+/**
+  Obtain current database sequence number
+*/
+int ldb_sequence_number(struct ldb_context *ldb, uint64_t *seq_num);
+
 /**
   start a transaction
 */
index 14f04036978b24bc8bbfa6041d14daf653c3ca1f..6d017d5cc15e69d0fb2498eee3f950a7e1095c3e 100644 (file)
@@ -67,9 +67,11 @@ struct ldb_module_ops {
        int (*end_transaction)(struct ldb_module *);
        int (*del_transaction)(struct ldb_module *);
        int (*async_wait)(struct ldb_async_handle *, enum ldb_async_wait_type);
+       int (*sequence_number)(struct ldb_module *, struct ldb_request *);
 };
 
-typedef int (*ldb_connect_fn) (struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[]);
+typedef int (*ldb_connect_fn) (struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[],
+                              struct ldb_module **module);
 
 /*
   schema related information needed for matching rules
index 4fc34ccdcface3b24180204dc59133a96444ab77..340f89e48f71a14bdf002445489138414db4fd45 100644 (file)
@@ -792,7 +792,8 @@ static const struct ldb_module_ops ildb_ops = {
   connect to the database
 */
 static int ildb_connect(struct ldb_context *ldb, const char *url, 
-                unsigned int flags, const char *options[])
+                       unsigned int flags, const char *options[],
+                       struct ldb_module **module)
 {
        struct ildb_private *ildb = NULL;
        NTSTATUS status;
@@ -824,15 +825,17 @@ static int ildb_connect(struct ldb_context *ldb, const char *url,
                goto failed;
        }
 
-       ldb->modules = talloc(ldb, struct ldb_module);
-       if (!ldb->modules) {
+
+       *module = talloc(ldb, struct ldb_module);
+       if (!module) {
                ldb_oom(ldb);
-               goto failed;
+               talloc_free(ildb);
+               return -1;
        }
-       ldb->modules->ldb = ldb;
-       ldb->modules->prev = ldb->modules->next = NULL;
-       ldb->modules->private_data = ildb;
-       ldb->modules->ops = &ildb_ops;
+       (*module)->ldb = ldb;
+       (*module)->prev = ldb->modules->next = NULL;
+       (*module)->private_data = ildb;
+       (*module)->ops = &ildb_ops;
 
        /* caller can optionally setup credentials using the opaque token 'credentials' */
        creds = talloc_get_type(ldb_get_opaque(ldb, "credentials"), struct cli_credentials);
index 4132fa6c1574cb168d195c8368d8f49d6b3cb961..c74be37108336b4f570978ea1bc4ec8f35be8653 100644 (file)
@@ -771,9 +771,10 @@ static int lldb_destructor(struct lldb_private *lldb)
   connect to the database
 */
 static int lldb_connect(struct ldb_context *ldb,
-                const char *url, 
-                unsigned int flags, 
-                const char *options[])
+                       const char *url, 
+                       unsigned int flags, 
+                       const char *options[],
+                       struct ldb_module **module)
 {
        struct lldb_private *lldb = NULL;
        int version = 3;
@@ -803,15 +804,16 @@ static int lldb_connect(struct ldb_context *ldb,
                goto failed;
        }
 
-       ldb->modules = talloc(ldb, struct ldb_module);
-       if (!ldb->modules) {
+       *module = talloc(ldb, struct ldb_module);
+       if (!module) {
                ldb_oom(ldb);
-               goto failed;
+               talloc_free(lldb);
+               return -1;
        }
-       ldb->modules->ldb = ldb;
-       ldb->modules->prev = ldb->modules->next = NULL;
-       ldb->modules->private_data = lldb;
-       ldb->modules->ops = &lldb_ops;
+       (*module)->ldb = ldb;
+       (*module)->prev = ldb->modules->next = NULL;
+       (*module)->private_data = lldb;
+       (*module)->ops = &lldb_ops;
 
        return 0;
 
index 06b76e812d6b5a27eaef8721903718488c21a354..053ccd1b211f5cc0007beb8da0dafafab74cc229 100644 (file)
@@ -2073,9 +2073,10 @@ static const struct ldb_module_ops lsqlite3_ops = {
  * connect to the database
  */
 static int lsqlite3_connect(struct ldb_context *ldb,
-                    const char *url, 
-                    unsigned int flags, 
-                    const char *options[])
+                           const char *url, 
+                           unsigned int flags, 
+                           const char *options[],
+                           struct ldb_module **module)
 {
        int                         i;
         int                         ret;
@@ -2097,15 +2098,18 @@ static int lsqlite3_connect(struct ldb_context *ldb,
         
        talloc_set_destructor(lsqlite3, destructor);
         
-       ldb->modules = talloc(ldb, struct ldb_module);
-       if (!ldb->modules) {
+
+
+       *module = talloc(ldb, struct ldb_module);
+       if (!module) {
+               ldb_oom(ldb);
                goto failed;
        }
-       ldb->modules->ldb = ldb;
-       ldb->modules->prev = ldb->modules->next = NULL;
-       ldb->modules->private_data = lsqlite3;
-       ldb->modules->ops = &lsqlite3_ops;
-        
+       (*module)->ldb = ldb;
+       (*module)->prev = ldb->modules->next = NULL;
+       (*module)->private_data = lsqlite3;
+       (*module)->ops = &lsqlite3_ops;
+
        if (options) {
                /*
                  * take a copy of the options array, so we don't have to rely
index b8f4a024d287e1ada1979fe0077fd3b20e350e41..224c25891c8fcfd4308d85fa99b289d0d825d620 100644 (file)
@@ -923,26 +923,35 @@ static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
 /*
   return sequenceNumber from @BASEINFO
 */
-static uint64_t ltdb_sequence_number(struct ldb_context *ldb)
+static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
 {
-       TALLOC_CTX *tmp_ctx = talloc_new(ldb);
-       const char *attrs[] = { "sequenceNumber", NULL };
-       struct ldb_result *res = NULL;
+       TALLOC_CTX *tmp_ctx = talloc_new(req);
+       struct ldb_message *msg = NULL;
        struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, "@BASEINFO");
-       int ret;
-       uint64_t seq_num;
+       int tret;
+
+       if (tmp_ctx == NULL) {
+               talloc_free(tmp_ctx);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       msg = talloc(tmp_ctx, struct ldb_message);
+       if (msg == NULL) {
+               talloc_free(tmp_ctx);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
-       ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
-       talloc_steal(tmp_ctx, res);
-       if (ret != LDB_SUCCESS || res->count != 1) {
+       tret = ltdb_search_dn1(module, dn, msg);
+       if (tret != 1) {
                talloc_free(tmp_ctx);
+               req->op.seq_num.seq_num = 0;
                /* zero is as good as anything when we don't know */
-               return 0;
+               return LDB_SUCCESS;
        }
 
-       seq_num = ldb_msg_find_uint64(res->msgs[0], "sequenceNumber", 0);
+       req->op.seq_num.seq_num = ldb_msg_find_uint64(msg, "sequenceNumber", 0);
        talloc_free(tmp_ctx);
-       return seq_num; 
+       return LDB_SUCCESS;
 }
 
 static const struct ldb_module_ops ltdb_ops = {
@@ -956,7 +965,8 @@ static const struct ldb_module_ops ltdb_ops = {
        .start_transaction = ltdb_start_trans,
        .end_transaction   = ltdb_end_trans,
        .del_transaction   = ltdb_del_trans,
-       .async_wait        = ltdb_async_wait
+       .async_wait        = ltdb_async_wait,
+       .sequence_number   = ltdb_sequence_number
 };
 
 
@@ -964,7 +974,8 @@ static const struct ldb_module_ops ltdb_ops = {
   connect to the database
 */
 static int ltdb_connect(struct ldb_context *ldb, const char *url, 
-                unsigned int flags, const char *options[])
+                       unsigned int flags, const char *options[],
+                       struct ldb_module **module)
 {
        const char *path;
        int tdb_flags, open_flags;
@@ -1010,17 +1021,16 @@ static int ltdb_connect(struct ldb_context *ldb, const char *url,
 
        ltdb->sequence_number = 0;
 
-       ldb->modules = talloc(ldb, struct ldb_module);
-       if (!ldb->modules) {
+       *module = talloc(ldb, struct ldb_module);
+       if (!module) {
                ldb_oom(ldb);
                talloc_free(ltdb);
                return -1;
        }
-       ldb->modules->ldb = ldb;
-       ldb->modules->prev = ldb->modules->next = NULL;
-       ldb->modules->private_data = ltdb;
-       ldb->modules->ops = &ltdb_ops;
-       ldb->sequence_number = ltdb_sequence_number;
+       (*module)->ldb = ldb;
+       (*module)->prev = ldb->modules->next = NULL;
+       (*module)->private_data = ltdb;
+       (*module)->ops = &ltdb_ops;
 
        return 0;
 }