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
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);
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) {
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;
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);
if (ret != LDB_SUCCESS) {
return schema;
}
-
+
if (is_global_schema) {
dsdb_make_schema_global(ldb, new_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,
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);
{
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] &&
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:
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;
}