summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c3
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_load.c39
-rw-r--r--source4/dsdb/samdb/samdb.h1
-rw-r--r--source4/dsdb/schema/schema.h1
-rw-r--r--source4/ldap_server/ldap_backend.c25
5 files changed, 65 insertions, 4 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 41c97bf32a..7b98dd62c1 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -4,6 +4,7 @@
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
Copyright (C) Simo Sorce 2004-2008
Copyright (C) Matthias Dieter Wallnöfer 2009-2011
+ Copyright (C) Matthieu Patou 2012
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -428,6 +429,8 @@ static int samldb_add_handle_msDS_IntId(struct samldb_ctx *ac)
struct ldb_context *ldb;
struct ldb_result *ldb_res;
struct ldb_dn *schema_dn;
+ struct samldb_msds_intid_persistant *msds_intid_struct;
+ struct dsdb_schema *schema;
ldb = ldb_module_get_ctx(ac->module);
schema_dn = ldb_get_schema_basedn(ldb);
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);
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index 50f7bf7d13..2a4bd355eb 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -199,6 +199,7 @@ struct dsdb_extended_dn_store_format {
bool store_extended_dn_in_ldb;
};
+#define DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME "DSDB_OPAQUE_LAST_SCHEMA_UPDATE"
#define DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME "DSDB_OPAQUE_PARTITION_MODULE_MSG"
/* this takes a struct dsdb_fsmo_extended_op */
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h
index b1ae76882a..d3dd035e01 100644
--- a/source4/dsdb/schema/schema.h
+++ b/source4/dsdb/schema/schema.h
@@ -245,6 +245,7 @@ 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;
+ time_t last_refresh;
/* an 'opaque' sequence number that the reload function may also wish to use */
uint64_t reload_seq_number;
diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index afeb3500d0..000d7e28f8 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -1162,6 +1162,9 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
{
unsigned int i;
struct ldap_message *msg = call->request;
+ struct ldb_context *samdb = call->conn->ldb;
+ NTSTATUS status;
+ time_t *lastts;
/* Check for undecoded critical extensions */
for (i=0; msg->controls && msg->controls[i]; i++) {
if (!msg->controls_decoded[i] &&
@@ -1180,9 +1183,11 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
case LDAP_TAG_SearchRequest:
return ldapsrv_SearchRequest(call);
case LDAP_TAG_ModifyRequest:
- return ldapsrv_ModifyRequest(call);
+ status = ldapsrv_ModifyRequest(call);
+ break;
case LDAP_TAG_AddRequest:
- return ldapsrv_AddRequest(call);
+ status = ldapsrv_AddRequest(call);
+ break;
case LDAP_TAG_DelRequest:
return ldapsrv_DelRequest(call);
case LDAP_TAG_ModifyDNRequest:
@@ -1196,4 +1201,20 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
default:
return ldapsrv_unwilling(call, LDAP_PROTOCOL_ERROR);
}
+
+ if (NT_STATUS_IS_OK(status)) {
+ lastts = (time_t *)ldb_get_opaque(samdb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME);
+ if (lastts && !*lastts) {
+ DEBUG(10, ("Schema update now was requested, fullfilling the request ts = %d\n", lastts));
+ /*
+ * Just requesting the schema will do the trick
+ * as the delay for reload is experied, we will have a reload
+ * from the schema as expected as we are not yet in a transaction!
+ */
+ dsdb_get_schema(samdb, NULL);
+ *lastts = time(NULL);
+ ldb_set_opaque(samdb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME, lastts);
+ }
+ }
+ return status;
}