ldap/servers/plugins/schema_reload/schema_reload.c | 11 ++
ldap/servers/slapd/attrsyntax.c | 83 ++++++++++++++++++++-
ldap/servers/slapd/slapi-plugin.h | 9 ++
3 files changed, 98 insertions(+), 5 deletions(-)
New commits:
commit 03d1cbd785fbc4f193b4aa33b40ebfc9c8e39e69
Author: Noriko Hosoi <nhosoi(a)totoro.usersys.redhat.com>
Date: Mon Sep 24 17:24:18 2012 -0700
Trac Ticket #470 - 389 prevents from adding a posixaccount
with userpassword after schema reload
https://fedorahosted.org/389/ticket/470
Bug description: Schema reload task reloads schema files in the
schema directory. Not just them, DS has several internal schema
which are not stored in the schema file, which were lost after
the schema reload task is executed. One of them unhashed#
user#password was necessary for adding a posixaccount.
Fix description: When registering an internal schema, the schema
is stashed in a hash table. When schema reload is executed, the
internal schema are reloaded with the external schema.
(cherry picked from commit 628e2b353e2dd6ac6aaac39067667ed27cacfb59)
diff --git a/ldap/servers/plugins/schema_reload/schema_reload.c
b/ldap/servers/plugins/schema_reload/schema_reload.c
index 82d8e2e..efc0de2 100644
--- a/ldap/servers/plugins/schema_reload/schema_reload.c
+++ b/ldap/servers/plugins/schema_reload/schema_reload.c
@@ -170,6 +170,13 @@ schemareload_thread(void *arg)
slapi_task_log_notice(task, "Schema reload task finished.");
slapi_task_log_status(task, "Schema reload task finished.");
slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Schema
reload task finished.\n");
+
+ slapi_log_error(SLAPI_LOG_FATAL, "schemareload",
+ "Register internal schema.\n");
+ rv = slapi_reload_internal_attr_syntax();
+ slapi_log_error(SLAPI_LOG_FATAL, "schemareload",
+ "Register internal schema finished.\n");
+
} else {
slapi_task_log_notice(task, "Schema reload task failed.");
slapi_task_log_status(task, "Schema reload task failed.");
@@ -209,8 +216,8 @@ schemareload_destructor(Slapi_Task *task)
if (task) {
task_data *mydata = (task_data *)slapi_task_get_data(task);
if (mydata) {
- slapi_ch_free_string(&mydata->schemadir);
- slapi_ch_free_string(&mydata->bind_dn);
+ slapi_ch_free_string(&mydata->schemadir);
+ slapi_ch_free_string(&mydata->bind_dn);
/* Need to cast to avoid a compiler warning */
slapi_ch_free((void **)&mydata);
}
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index 62dfea1..ff137a8 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -56,6 +56,7 @@
static PLHashTable *oid2asi = NULL;
/* read/write lock to protect table */
static Slapi_RWLock *oid2asi_lock = NULL;
+static PLHashTable *internalasi = NULL;
/*
* This hashtable maps the name or alias of the attribute to the
@@ -911,13 +912,23 @@ attr_syntax_enumerate_internal(PLHashEntry *he, PRIntn i, void
*arg)
return rc;
}
-void
-attr_syntax_enumerate_attrs(AttrEnumFunc aef, void *arg, PRBool writelock )
+static void
+attr_syntax_enumerate_attrs_ext( PLHashTable *ht,
+ AttrEnumFunc aef, void *arg )
{
struct enum_arg_wrapper eaw;
eaw.aef = aef;
eaw.arg = arg;
+ if (!ht)
+ return;
+
+ PL_HashTableEnumerateEntries(ht, attr_syntax_enumerate_internal, &eaw);
+}
+
+void
+attr_syntax_enumerate_attrs(AttrEnumFunc aef, void *arg, PRBool writelock )
+{
if (!oid2asi)
return;
@@ -929,7 +940,7 @@ attr_syntax_enumerate_attrs(AttrEnumFunc aef, void *arg, PRBool
writelock )
AS_LOCK_READ(name2asi_lock);
}
- PL_HashTableEnumerateEntries(oid2asi, attr_syntax_enumerate_internal, &eaw);
+ attr_syntax_enumerate_attrs_ext(oid2asi, aef, arg);
if ( writelock ) {
AS_UNLOCK_WRITE(oid2asi_lock);
@@ -1076,6 +1087,36 @@ slapi_attr_syntax_exists(const char *attr_name)
}
/*
+ * Keep the internally added schema in the hash table,
+ * which are re-added if the schema is reloaded.
+ */
+static int
+attr_syntax_internal_asi_add_ht(struct asyntaxinfo *asip)
+{
+ if (!internalasi) {
+ internalasi = PL_NewHashTable(64, hashNocaseString,
+ hashNocaseCompare,
+ PL_CompareValues, 0, 0);
+ }
+ if (!internalasi) {
+ slapi_log_error(SLAPI_LOG_FATAL, "attr_syntax_internal_asi_add_ht",
+ "Failed to create HashTable.\n");
+ return 1;
+ }
+ if (!PL_HashTableLookup(internalasi, asip->asi_oid)) {
+ struct asyntaxinfo *asip_copy = attr_syntax_dup(asip);
+ if (!asip_copy) {
+ slapi_log_error(SLAPI_LOG_FATAL, "attr_syntax_internal_asi_add_ht",
+ "Failed to duplicate asyntaxinfo: %s.\n",
+ asip->asi_name);
+ return 1;
+ }
+ PL_HashTableAdd(internalasi, asip_copy->asi_oid, asip_copy);
+ }
+ return 0;
+}
+
+/*
* Add an attribute syntax using some default flags, etc.
* Returns an LDAP error code (LDAP_SUCCESS if all goes well)
*/
@@ -1106,7 +1147,43 @@ slapi_add_internal_attr_syntax( const char *name, const char *oid,
if ( rc == LDAP_SUCCESS ) {
rc = attr_syntax_add( asip );
+ if ( rc == LDAP_SUCCESS ) {
+ if (attr_syntax_internal_asi_add_ht(asip)) {
+ slapi_log_error(SLAPI_LOG_FATAL,
+ "slapi_add_internal_attr_syntax",
+ "Failed to stash internal asyntaxinfo: %s.\n",
+ asip->asi_name);
+ }
+ }
}
return rc;
}
+
+/* Adding internal asyncinfo via slapi_reload_internal_attr_syntax */
+static int
+attr_syntax_internal_asi_add(struct asyntaxinfo *asip, void *arg)
+{
+ struct asyntaxinfo *asip_copy;
+ if (!asip) {
+ return 1;
+ }
+ /* Copy is needed since when reloading the schema,
+ * existing syntax info is cleaned up. */
+ asip_copy = attr_syntax_dup(asip);
+ return attr_syntax_add(asip_copy);
+}
+
+/* Reload internal attribute syntax stashed in the internalasi hashtable. */
+int
+slapi_reload_internal_attr_syntax()
+{
+ int rc = LDAP_SUCCESS;
+ if (!internalasi) {
+ slapi_log_error(SLAPI_LOG_TRACE, "attr_reload_internal_attr_syntax",
+ "No internal attribute syntax to reload.\n");
+ return rc;
+ }
+ attr_syntax_enumerate_attrs_ext(internalasi, attr_syntax_internal_asi_add, NULL);
+ return rc;
+}
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index a9d7dfe..4316833 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -4871,6 +4871,15 @@ void slapi_filter_normalize(Slapi_Filter *f, PRBool norm_values);
*/
int slapi_attr_syntax_exists(const char *type);
+/**
+ * Reload internally registered attribute syntaxes.
+ *
+ * \param none
+ * \return \c 0 if the reload was successful.
+ * \return non-0 if the reload failed.
+ */
+int slapi_reload_internal_attr_syntax();
+
/*
* slapi_filter_apply() is used to apply a function to each simple filter
* component within a complex filter. A 'simple filter' is anything other