summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/ldb_modules/schema_load.c
diff options
context:
space:
mode:
authorMatthieu Patou <mat@matws.net>2012-05-09 22:08:55 -0700
committerMatthieu Patou <mat@matws.net>2012-06-22 23:16:04 -0700
commit1521bb95a7bb3df5cb3a128085a088cb09555f8b (patch)
treea2a28b508601ccf25078b215c519950a72319287 /source4/dsdb/samdb/ldb_modules/schema_load.c
parentf8fd615c5950bab9a38cd31872ae447ffdc974f3 (diff)
downloadsamba-1521bb95a7bb3df5cb3a128085a088cb09555f8b.tar.gz
samba-1521bb95a7bb3df5cb3a128085a088cb09555f8b.tar.bz2
samba-1521bb95a7bb3df5cb3a128085a088cb09555f8b.zip
dsdb-schema: do not reload more often than schema_reload_interval
Samba 4 use to try to reload the schema every time dsdb_get_schema was called (which could be 20+ time per ldb request). Now we only reload at most every xx seconds (xx being the value of dsdb:"schema_reload_interval" or 120). The timestamp of the last reloaded schema is kept in the dsdb_schema object. There is also a timestamp in the ldb_context, that is used by the LDAP server to know if it has to reload the schema after handling the request. This is used to allow that the schema will be immediately reload after a schemaUpdateNow request has been issued, the reload can't occur in the handling of the LDAP request itself because we have a transaction autostarted.
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules/schema_load.c')
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_load.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c
index 4c166d51ce..f922aabba9 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_load.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_load.c
@@ -49,6 +49,10 @@ static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct
struct dsdb_control_current_partition *ctrl;
struct ldb_context *ldb = ldb_module_get_ctx(module);
struct dsdb_schema *new_schema;
+ int interval;
+ time_t ts, lastts;
+ struct loadparm_context *lp_ctx =
+ (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
struct schema_load_private_data *private_data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
if (!private_data) {
@@ -61,6 +65,14 @@ static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct
return schema;
}
+ lastts = schema->last_refresh;
+ ts = time(NULL);
+ interval = lpcfg_parm_int(lp_ctx, NULL, "dsdb", "schema_reload_interval", 120);
+ if (lastts > (ts - interval)) {
+ DEBUG(11, ("Less than %d seconds since last reload, returning cached version ts = %d\n", interval, (int)lastts));
+ return schema;
+ }
+
res = talloc_zero(schema, struct ldb_result);
if (res == NULL) {
return NULL;
@@ -84,7 +96,16 @@ static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct
talloc_free(res);
return NULL;
}
-
+
+ /*
+ * We update right now the last refresh timestamp so that if
+ * the schema partition hasn't change we don't keep on retrying.
+ * Otherwise if the timestamp was update only when the schema has
+ * actually changed (and therefor completely reloaded) we would
+ * continue to hit the database to get the highest USN.
+ */
+ schema->last_refresh = ts;
+
ctrl = talloc(treq, struct dsdb_control_current_partition);
if (!ctrl) {
talloc_free(res);
@@ -130,7 +151,7 @@ static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct
if (ret != LDB_SUCCESS) {
return schema;
}
-
+
if (is_global_schema) {
dsdb_make_schema_global(ldb, new_schema);
}
@@ -226,6 +247,7 @@ static int dsdb_schema_from_db(struct ldb_module *module, struct ldb_dn *schema_
ret = dsdb_set_schema(ldb, (*schema));
(*schema)->refresh_in_progress = false;
+ (*schema)->last_refresh = time(NULL);
if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
@@ -324,9 +346,22 @@ static int schema_load_del_transaction(struct ldb_module *module)
static int schema_load_extended(struct ldb_module *module, struct ldb_request *req)
{
+ time_t *lastts;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct dsdb_schema *schema;
+
if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
return ldb_next_request(module, req);
}
+ lastts = (time_t *)ldb_get_opaque(ldb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME);
+ if (!lastts) {
+ lastts = talloc(ldb, time_t);
+ }
+ schema = dsdb_get_schema(ldb, NULL);
+ /* Force a refresh */
+ schema->last_refresh = 0;
+ *lastts = 0;
+ ldb_set_opaque(ldb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME, lastts);
/* This is a no-op. We reload as soon as we can */
return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);