s4:dsdb Add a shortcut sequence number for schema reloads
authorAndrew Bartlett <abartlet@samba.org>
Mon, 22 Mar 2010 07:44:51 +0000 (18:44 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 22 Mar 2010 09:24:41 +0000 (20:24 +1100)
This uses the ldb sequence number, in a hope to detect an unchanged
schema quicker.

Andrew Bartlett

source4/dsdb/samdb/ldb_modules/schema_load.c
source4/dsdb/schema/schema.h

index 5dd8fb78c9fc950308a268e007d1418b8c864aa1..d13b339f6047ccf0484bd870e3259a62f51c148b 100644 (file)
@@ -42,6 +42,14 @@ struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct dsdb_s
 {
        uint64_t current_usn;
        int ret;
+       struct ldb_result *res;
+       struct ldb_request *treq;
+       struct ldb_seqnum_request *tseq;
+       struct ldb_seqnum_result *tseqr;
+       struct dsdb_control_current_partition *ctrl;
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
+       struct dsdb_schema *new_schema;
+       
        struct schema_load_private_data *private_data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
        if (!private_data) {
                /* We can't refresh until the init function has run */
@@ -53,22 +61,79 @@ struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct dsdb_s
                return schema;
        }
 
+       res = talloc_zero(schema, struct ldb_result);
+       if (res == NULL) {
+               return NULL;
+       }
+       tseq = talloc_zero(res, struct ldb_seqnum_request);
+       if (tseq == NULL) {
+               talloc_free(res);
+               return NULL;
+       }
+       tseq->type = LDB_SEQ_HIGHEST_SEQ;
+       
+       ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res,
+                                    LDB_EXTENDED_SEQUENCE_NUMBER,
+                                    tseq,
+                                    NULL,
+                                    res,
+                                    ldb_extended_default_callback,
+                                    NULL);
+       if (ret != LDB_SUCCESS) {
+               talloc_free(res);
+               return NULL;
+       }
+       
+       ctrl = talloc(treq, struct dsdb_control_current_partition);
+       if (!ctrl) {
+               talloc_free(res);
+               return NULL;
+       }
+       ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
+       ctrl->dn = schema->base_dn;
+       
+       ret = ldb_request_add_control(treq,
+                                     DSDB_CONTROL_CURRENT_PARTITION_OID,
+                                     false, ctrl);
+       if (ret != LDB_SUCCESS) {
+               talloc_free(res);
+               return NULL;
+       }
+       
+       ret = ldb_next_request(module, treq);
+       if (ret != LDB_SUCCESS) {
+               talloc_free(res);
+               return NULL;
+       }
+       ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+       if (ret != LDB_SUCCESS) {
+               talloc_free(res);
+               return NULL;
+       }
+       tseqr = talloc_get_type(res->extended->data,
+                               struct ldb_seqnum_result);
+       if (tseqr->seq_num == schema->reload_seq_number) {
+               talloc_free(res);
+               return schema;
+       }
+
+       schema->reload_seq_number = tseqr->seq_num;
+       talloc_free(res);
+               
        ret = dsdb_module_load_partition_usn(module, schema->base_dn, &current_usn, NULL);
-       if (ret == LDB_SUCCESS && current_usn != schema->loaded_usn) {
-               struct ldb_context *ldb = ldb_module_get_ctx(module);
-               struct dsdb_schema *new_schema;
-
-               ret = dsdb_schema_from_db(module, schema->base_dn, current_usn, &new_schema);
-               if (ret != LDB_SUCCESS) {
-                       return schema;
-               }
-
-               if (is_global_schema) {
-                       dsdb_make_schema_global(ldb, new_schema);
-               }
-               return new_schema;
+       if (ret != LDB_SUCCESS || current_usn == schema->loaded_usn) {
+               return schema;
+       }
+
+       ret = dsdb_schema_from_db(module, schema->base_dn, current_usn, &new_schema);
+       if (ret != LDB_SUCCESS) {
+               return schema;
+       }
+       
+       if (is_global_schema) {
+               dsdb_make_schema_global(ldb, new_schema);
        }
-       return schema;
+       return new_schema;
 }
 
 
index b5334c731352da441c7c3a5b328acc798642858c..7283744f7d088e9db24b12ca831aa91dfb03034e 100644 (file)
@@ -213,6 +213,8 @@ struct dsdb_schema {
        struct ldb_module *loaded_from_module;
        struct dsdb_schema *(*refresh_fn)(struct ldb_module *module, struct dsdb_schema *schema, bool is_global_schema);
        bool refresh_in_progress;
+       /* an 'opaque' sequence number that the reload function may also wish to use */
+       uint64_t reload_seq_number;
 };
 
 enum dsdb_attr_list_query {