Branch '389-ds-base-1.3.2' - ldap/schema ldap/servers
by Mark Reynolds
ldap/schema/01core389.ldif | 2
ldap/servers/plugins/replication/cl5.h | 4 -
ldap/servers/plugins/replication/cl5_api.c | 5 +
ldap/servers/plugins/replication/cl5_api.h | 1
ldap/servers/plugins/replication/cl5_config.c | 94 ++++++++++++++++++++++----
5 files changed, 93 insertions(+), 13 deletions(-)
New commits:
commit 20cb0c07d266923b03a6b1decc84c6ca166dd09a
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Jan 12 14:58:56 2015 -0500
Ticket 47617 - replication changelog trimming setting validation
Bug Description: The changelog trimming interval setting is not validated.
Multiple and invalid values were allowed. The new interval
was also not taking effect until the old timeout completed.
Fix Description: Add the config attribute to the core schema to addreess
the multivalue issue. Added the setting validation checks,
and notify the trimming thread when the interval is changed.
Also applied these validatations to the changelog compact interval.
https://fedorahosted.org/389/ticket/47617
Reviewed by: nhosoi(Thanks!)
(cherry picked from commit f724b34b6c7ade56d3a66a58257b6b862c8fb221)
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index a91efd8..223493d 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -161,6 +161,8 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2168 NAME 'schemaUpdateAttributeReject'
attributeTypes: ( 2.16.840.1.113730.3.1.2307 NAME 'nsslapd-allow-hashed-passwords' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2310 NAME 'nsds5ReplicaFlowControlWindow' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2311 NAME 'nsds5ReplicaFlowControlPause' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2313 NAME 'nsslapd-changelogtrim-interval' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2314 NAME 'nsslapd-changelogcompactdb-interval' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
#
# objectclasses
#
diff --git a/ldap/servers/plugins/replication/cl5.h b/ldap/servers/plugins/replication/cl5.h
index 9666e9a..3c92193 100644
--- a/ldap/servers/plugins/replication/cl5.h
+++ b/ldap/servers/plugins/replication/cl5.h
@@ -56,8 +56,8 @@ typedef struct changelog5Config
/* the changelog DB configuration parameters are defined as CL5DBConfig in cl5_api.h */
CL5DBConfig dbconfig;
char *symmetricKey;
- int compactInterval;
- int trimInterval;
+ long compactInterval;
+ long trimInterval;
}changelog5Config;
/* initializes changelog*/
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 42e52ae..2d9a0bd 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -1232,6 +1232,11 @@ cl5ConfigTrimming (int maxEntries, const char *maxAge, int compactInterval, int
s_cl5Desc.dbTrim.trimInterval = trimInterval;
}
+ /* The config was updated, notify the changelog trimming thread */
+ PR_Lock(s_cl5Desc.clLock);
+ PR_NotifyCondVar(s_cl5Desc.clCvar);
+ PR_Unlock(s_cl5Desc.clLock);
+
PR_Unlock (s_cl5Desc.dbTrim.lock);
_cl5RemoveThread ();
diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h
index ba9eb32..eaf936f 100644
--- a/ldap/servers/plugins/replication/cl5_api.h
+++ b/ldap/servers/plugins/replication/cl5_api.h
@@ -47,6 +47,7 @@
#include "repl5.h"
#include "repl5_prot_private.h"
+#include <errno.h>
#define BDB_IMPL "bdb" /* changelog type */
#define BDB_REPLPLUGIN "libreplication-plugin" /* This backend plugin */
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index a3a0fb3..f4da738 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -398,20 +398,58 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
}
else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE ) == 0 )
{
- if (config_attr_value && config_attr_value[0] != '\0')
- {
- config.compactInterval = atoi (config_attr_value);
- }
- else
- {
- config.compactInterval = 0;
- }
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (config_attr_value && config_attr_value[0] != '\0')
+ {
+ value = strtol(config_attr_value, &endp, 10);
+
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ if (returntext)
+ {
+ PR_snprintf ( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid value \"%s\", %s must range from 0 to %lld",
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE, config_attr_value,
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE,
+ (long long int)LONG_MAX );
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+ config.compactInterval = value;
+ }
+ }
+ else
+ {
+ config.compactInterval = 0;
+ }
}
else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_TRIM_ATTRIBUTE ) == 0 )
{
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
if (config_attr_value && config_attr_value[0] != '\0')
{
- config.trimInterval = atoi (config_attr_value);
+ value = strtol(config_attr_value, &endp, 10);
+
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ if (returntext)
+ {
+ PR_snprintf ( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid value \"%s\", %s must range from 0 to %lld",
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE, config_attr_value,
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE,
+ (long long int)LONG_MAX );
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+ config.trimInterval = value;
+ }
}
else
{
@@ -761,7 +799,24 @@ static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *conf
arg = slapi_entry_attr_get_charptr(entry,CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE);
if (arg)
{
- config->compactInterval = atoi (arg);
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (arg)
+ {
+ value = strtol(arg, &endp, 10);
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "changelog5_extract_config: %s: invalid value \"%s\", using default value (%d)\n",
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE, arg,
+ CHANGELOGDB_COMPACT_INTERVAL );
+ config->compactInterval = CHANGELOGDB_COMPACT_INTERVAL;
+ } else {
+ config->compactInterval = value;
+ }
+ }
slapi_ch_free_string(&arg);
}
else
@@ -771,7 +826,24 @@ static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *conf
arg = slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_TRIM_ATTRIBUTE);
if (arg)
{
- config->trimInterval = atoi (arg);
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (arg)
+ {
+ value = strtol(arg, &endp, 10);
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "changelog5_extract_config: %s: invalid value \"%s\", using default value (%d)\n",
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE, arg,
+ CHANGELOGDB_TRIM_INTERVAL );
+ config->trimInterval = CHANGELOGDB_TRIM_INTERVAL;
+ } else {
+ config->trimInterval = value;
+ }
+ }
slapi_ch_free_string(&arg);
}
else
9 years, 3 months
Branch '389-ds-base-1.3.3' - ldap/schema ldap/servers
by Mark Reynolds
ldap/schema/01core389.ldif | 2
ldap/servers/plugins/replication/cl5.h | 4 -
ldap/servers/plugins/replication/cl5_api.c | 5 +
ldap/servers/plugins/replication/cl5_api.h | 1
ldap/servers/plugins/replication/cl5_config.c | 94 ++++++++++++++++++++++----
5 files changed, 93 insertions(+), 13 deletions(-)
New commits:
commit 87c7b15c5a1a4469e758f466ffae10b328a61284
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Jan 12 14:58:56 2015 -0500
Ticket 47617 - replication changelog trimming setting validation
Bug Description: The changelog trimming interval setting is not validated.
Multiple and invalid values were allowed. The new interval
was also not taking effect until the old timeout completed.
Fix Description: Add the config attribute to the core schema to addreess
the multivalue issue. Added the setting validation checks,
and notify the trimming thread when the interval is changed.
Also applied these validatations to the changelog compact interval.
https://fedorahosted.org/389/ticket/47617
Reviewed by: nhosoi(Thanks!)
(cherry picked from commit f724b34b6c7ade56d3a66a58257b6b862c8fb221)
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index c59d762..9b7ec1d 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -304,6 +304,8 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2308 NAME 'nstombstonecsn' DESC 'Netscap
attributeTypes: ( 2.16.840.1.113730.3.1.2309 NAME 'nsds5ReplicaPreciseTombstonePurging' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2310 NAME 'nsds5ReplicaFlowControlWindow' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2311 NAME 'nsds5ReplicaFlowControlPause' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2313 NAME 'nsslapd-changelogtrim-interval' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2314 NAME 'nsslapd-changelogcompactdb-interval' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
#
# objectclasses
#
diff --git a/ldap/servers/plugins/replication/cl5.h b/ldap/servers/plugins/replication/cl5.h
index 9666e9a..3c92193 100644
--- a/ldap/servers/plugins/replication/cl5.h
+++ b/ldap/servers/plugins/replication/cl5.h
@@ -56,8 +56,8 @@ typedef struct changelog5Config
/* the changelog DB configuration parameters are defined as CL5DBConfig in cl5_api.h */
CL5DBConfig dbconfig;
char *symmetricKey;
- int compactInterval;
- int trimInterval;
+ long compactInterval;
+ long trimInterval;
}changelog5Config;
/* initializes changelog*/
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 42e52ae..2d9a0bd 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -1232,6 +1232,11 @@ cl5ConfigTrimming (int maxEntries, const char *maxAge, int compactInterval, int
s_cl5Desc.dbTrim.trimInterval = trimInterval;
}
+ /* The config was updated, notify the changelog trimming thread */
+ PR_Lock(s_cl5Desc.clLock);
+ PR_NotifyCondVar(s_cl5Desc.clCvar);
+ PR_Unlock(s_cl5Desc.clLock);
+
PR_Unlock (s_cl5Desc.dbTrim.lock);
_cl5RemoveThread ();
diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h
index ba9eb32..eaf936f 100644
--- a/ldap/servers/plugins/replication/cl5_api.h
+++ b/ldap/servers/plugins/replication/cl5_api.h
@@ -47,6 +47,7 @@
#include "repl5.h"
#include "repl5_prot_private.h"
+#include <errno.h>
#define BDB_IMPL "bdb" /* changelog type */
#define BDB_REPLPLUGIN "libreplication-plugin" /* This backend plugin */
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index a3a0fb3..f4da738 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -398,20 +398,58 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
}
else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE ) == 0 )
{
- if (config_attr_value && config_attr_value[0] != '\0')
- {
- config.compactInterval = atoi (config_attr_value);
- }
- else
- {
- config.compactInterval = 0;
- }
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (config_attr_value && config_attr_value[0] != '\0')
+ {
+ value = strtol(config_attr_value, &endp, 10);
+
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ if (returntext)
+ {
+ PR_snprintf ( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid value \"%s\", %s must range from 0 to %lld",
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE, config_attr_value,
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE,
+ (long long int)LONG_MAX );
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+ config.compactInterval = value;
+ }
+ }
+ else
+ {
+ config.compactInterval = 0;
+ }
}
else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_TRIM_ATTRIBUTE ) == 0 )
{
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
if (config_attr_value && config_attr_value[0] != '\0')
{
- config.trimInterval = atoi (config_attr_value);
+ value = strtol(config_attr_value, &endp, 10);
+
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ if (returntext)
+ {
+ PR_snprintf ( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid value \"%s\", %s must range from 0 to %lld",
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE, config_attr_value,
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE,
+ (long long int)LONG_MAX );
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+ config.trimInterval = value;
+ }
}
else
{
@@ -761,7 +799,24 @@ static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *conf
arg = slapi_entry_attr_get_charptr(entry,CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE);
if (arg)
{
- config->compactInterval = atoi (arg);
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (arg)
+ {
+ value = strtol(arg, &endp, 10);
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "changelog5_extract_config: %s: invalid value \"%s\", using default value (%d)\n",
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE, arg,
+ CHANGELOGDB_COMPACT_INTERVAL );
+ config->compactInterval = CHANGELOGDB_COMPACT_INTERVAL;
+ } else {
+ config->compactInterval = value;
+ }
+ }
slapi_ch_free_string(&arg);
}
else
@@ -771,7 +826,24 @@ static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *conf
arg = slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_TRIM_ATTRIBUTE);
if (arg)
{
- config->trimInterval = atoi (arg);
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (arg)
+ {
+ value = strtol(arg, &endp, 10);
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "changelog5_extract_config: %s: invalid value \"%s\", using default value (%d)\n",
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE, arg,
+ CHANGELOGDB_TRIM_INTERVAL );
+ config->trimInterval = CHANGELOGDB_TRIM_INTERVAL;
+ } else {
+ config->trimInterval = value;
+ }
+ }
slapi_ch_free_string(&arg);
}
else
9 years, 3 months
ldap/schema ldap/servers
by Mark Reynolds
ldap/schema/01core389.ldif | 2
ldap/servers/plugins/replication/cl5.h | 4 -
ldap/servers/plugins/replication/cl5_api.c | 5 +
ldap/servers/plugins/replication/cl5_api.h | 1
ldap/servers/plugins/replication/cl5_config.c | 94 ++++++++++++++++++++++----
5 files changed, 93 insertions(+), 13 deletions(-)
New commits:
commit f724b34b6c7ade56d3a66a58257b6b862c8fb221
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Jan 12 14:58:56 2015 -0500
Ticket 47617 - replication changelog trimming setting validation
Bug Description: The changelog trimming interval setting is not validated.
Multiple and invalid values were allowed. The new interval
was also not taking effect until the old timeout completed.
Fix Description: Add the config attribute to the core schema to addreess
the multivalue issue. Added the setting validation checks,
and notify the trimming thread when the interval is changed.
Also applied these validatations to the changelog compact interval.
https://fedorahosted.org/389/ticket/47617
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index c59d762..9b7ec1d 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -304,6 +304,8 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2308 NAME 'nstombstonecsn' DESC 'Netscap
attributeTypes: ( 2.16.840.1.113730.3.1.2309 NAME 'nsds5ReplicaPreciseTombstonePurging' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2310 NAME 'nsds5ReplicaFlowControlWindow' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2311 NAME 'nsds5ReplicaFlowControlPause' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2313 NAME 'nsslapd-changelogtrim-interval' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2314 NAME 'nsslapd-changelogcompactdb-interval' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
#
# objectclasses
#
diff --git a/ldap/servers/plugins/replication/cl5.h b/ldap/servers/plugins/replication/cl5.h
index 9666e9a..3c92193 100644
--- a/ldap/servers/plugins/replication/cl5.h
+++ b/ldap/servers/plugins/replication/cl5.h
@@ -56,8 +56,8 @@ typedef struct changelog5Config
/* the changelog DB configuration parameters are defined as CL5DBConfig in cl5_api.h */
CL5DBConfig dbconfig;
char *symmetricKey;
- int compactInterval;
- int trimInterval;
+ long compactInterval;
+ long trimInterval;
}changelog5Config;
/* initializes changelog*/
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 42e52ae..2d9a0bd 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -1232,6 +1232,11 @@ cl5ConfigTrimming (int maxEntries, const char *maxAge, int compactInterval, int
s_cl5Desc.dbTrim.trimInterval = trimInterval;
}
+ /* The config was updated, notify the changelog trimming thread */
+ PR_Lock(s_cl5Desc.clLock);
+ PR_NotifyCondVar(s_cl5Desc.clCvar);
+ PR_Unlock(s_cl5Desc.clLock);
+
PR_Unlock (s_cl5Desc.dbTrim.lock);
_cl5RemoveThread ();
diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h
index ba9eb32..eaf936f 100644
--- a/ldap/servers/plugins/replication/cl5_api.h
+++ b/ldap/servers/plugins/replication/cl5_api.h
@@ -47,6 +47,7 @@
#include "repl5.h"
#include "repl5_prot_private.h"
+#include <errno.h>
#define BDB_IMPL "bdb" /* changelog type */
#define BDB_REPLPLUGIN "libreplication-plugin" /* This backend plugin */
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index a3a0fb3..f4da738 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -398,20 +398,58 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
}
else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE ) == 0 )
{
- if (config_attr_value && config_attr_value[0] != '\0')
- {
- config.compactInterval = atoi (config_attr_value);
- }
- else
- {
- config.compactInterval = 0;
- }
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (config_attr_value && config_attr_value[0] != '\0')
+ {
+ value = strtol(config_attr_value, &endp, 10);
+
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ if (returntext)
+ {
+ PR_snprintf ( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid value \"%s\", %s must range from 0 to %lld",
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE, config_attr_value,
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE,
+ (long long int)LONG_MAX );
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+ config.compactInterval = value;
+ }
+ }
+ else
+ {
+ config.compactInterval = 0;
+ }
}
else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_TRIM_ATTRIBUTE ) == 0 )
{
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
if (config_attr_value && config_attr_value[0] != '\0')
{
- config.trimInterval = atoi (config_attr_value);
+ value = strtol(config_attr_value, &endp, 10);
+
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ if (returntext)
+ {
+ PR_snprintf ( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid value \"%s\", %s must range from 0 to %lld",
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE, config_attr_value,
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE,
+ (long long int)LONG_MAX );
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+ config.trimInterval = value;
+ }
}
else
{
@@ -761,7 +799,24 @@ static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *conf
arg = slapi_entry_attr_get_charptr(entry,CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE);
if (arg)
{
- config->compactInterval = atoi (arg);
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (arg)
+ {
+ value = strtol(arg, &endp, 10);
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "changelog5_extract_config: %s: invalid value \"%s\", using default value (%d)\n",
+ CONFIG_CHANGELOG_COMPACTDB_ATTRIBUTE, arg,
+ CHANGELOGDB_COMPACT_INTERVAL );
+ config->compactInterval = CHANGELOGDB_COMPACT_INTERVAL;
+ } else {
+ config->compactInterval = value;
+ }
+ }
slapi_ch_free_string(&arg);
}
else
@@ -771,7 +826,24 @@ static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *conf
arg = slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_TRIM_ATTRIBUTE);
if (arg)
{
- config->trimInterval = atoi (arg);
+ char *endp = NULL;
+ long value;
+
+ errno = 0;
+
+ if (arg)
+ {
+ value = strtol(arg, &endp, 10);
+ if (*endp != '\0' || errno == ERANGE || value < 0 ) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "changelog5_extract_config: %s: invalid value \"%s\", using default value (%d)\n",
+ CONFIG_CHANGELOG_TRIM_ATTRIBUTE, arg,
+ CHANGELOGDB_TRIM_INTERVAL );
+ config->trimInterval = CHANGELOGDB_TRIM_INTERVAL;
+ } else {
+ config->trimInterval = value;
+ }
+ }
slapi_ch_free_string(&arg);
}
else
9 years, 3 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/pw.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
New commits:
commit 6b85c3a655896363826fe5aacee9e7493fcb9ca9
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Jan 9 14:22:50 2015 -0800
Ticket #47905 - Bad manipulation of passwordhistory
Description: The patch was provided by German Parente (gparente(a)redhat.com)
https://fedorahosted.org/389/ticket/47905#comment:6
If a value of password policy attribute (e.g., passwordhistory) is
accidentally deleted, it causes a null reference in pw_val2scheme.
This patch checks whether val is NULL or not. If the given val is
NULL, pw_val2scheme returns NULL.
https://fedorahosted.org/389/ticket/47905
Reviewed by nhosoi(a)redhat.com.
(cherry picked from commit 2c6e74adbea3c4799f30b0e3d679da9dd060ff58)
(cherry picked from commit baa26c96e873916d4c02651b04de7ca2a578863d)
(cherry picked from commit a9dee00b79016a51ebfed01c92267b751c5986de)
(cherry picked from commit bf274554956196b4fc3f80f60c1b61de28a1b9d2)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index c753133..4df24b7 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -145,7 +145,7 @@ slapi_pw_find_sv(
LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pw_find value: \"%s\"\n", slapi_value_get_string(v), 0, 0 ); /* JCM Innards */
- for ( i = 0; vals[i] != NULL; i++ )
+ for ( i = 0; vals && vals[i]; i++ )
{
pwsp = pw_val2scheme( (char*)slapi_value_get_string(vals[i]), &valpwd, 1 ); /* JCM Innards*/
if ( pwsp != NULL &&
@@ -287,9 +287,12 @@ struct pw_scheme *
pw_val2scheme( char *val, char **valpwdp, int first_is_default )
{
struct pw_scheme *pwsp;
- int namelen, prefixlen;
+ int namelen, prefixlen;
char *end, buf[ PWD_MAX_NAME_LEN + 1 ];
+ if (NULL == val) {
+ return( NULL );
+ }
if ( *val != PWD_HASH_PREFIX_START ||
( end = strchr( val, PWD_HASH_PREFIX_END )) == NULL ||
( namelen = end - val - 1 ) > PWD_MAX_NAME_LEN ) {
9 years, 3 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/pw.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
New commits:
commit bf274554956196b4fc3f80f60c1b61de28a1b9d2
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Jan 9 14:22:50 2015 -0800
Ticket #47905 - Bad manipulation of passwordhistory
Description: The patch was provided by German Parente (gparente(a)redhat.com)
https://fedorahosted.org/389/ticket/47905#comment:6
If a value of password policy attribute (e.g., passwordhistory) is
accidentally deleted, it causes a null reference in pw_val2scheme.
This patch checks whether val is NULL or not. If the given val is
NULL, pw_val2scheme returns NULL.
https://fedorahosted.org/389/ticket/47905
Reviewed by nhosoi(a)redhat.com.
(cherry picked from commit 2c6e74adbea3c4799f30b0e3d679da9dd060ff58)
(cherry picked from commit baa26c96e873916d4c02651b04de7ca2a578863d)
(cherry picked from commit a9dee00b79016a51ebfed01c92267b751c5986de)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 58b1f11..7d33d65 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -146,7 +146,7 @@ slapi_pw_find_sv(
LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pw_find value: \"%s\"\n", slapi_value_get_string(v), 0, 0 ); /* JCM Innards */
- for ( i = 0; vals[i] != NULL; i++ )
+ for ( i = 0; vals && vals[i]; i++ )
{
pwsp = pw_val2scheme( (char*)slapi_value_get_string(vals[i]), &valpwd, 1 ); /* JCM Innards*/
if ( pwsp != NULL &&
@@ -287,9 +287,12 @@ struct pw_scheme *
pw_val2scheme( char *val, char **valpwdp, int first_is_default )
{
struct pw_scheme *pwsp;
- int namelen, prefixlen;
+ int namelen, prefixlen;
char *end, buf[ PWD_MAX_NAME_LEN + 1 ];
+ if (NULL == val) {
+ return( NULL );
+ }
if ( *val != PWD_HASH_PREFIX_START ||
( end = strchr( val, PWD_HASH_PREFIX_END )) == NULL ||
( namelen = end - val - 1 ) > PWD_MAX_NAME_LEN ) {
9 years, 3 months
Branch '389-ds-base-1.3.2' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/pw.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
New commits:
commit a9dee00b79016a51ebfed01c92267b751c5986de
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Jan 9 14:22:50 2015 -0800
Ticket #47905 - Bad manipulation of passwordhistory
Description: The patch was provided by German Parente (gparente(a)redhat.com)
https://fedorahosted.org/389/ticket/47905#comment:6
If a value of password policy attribute (e.g., passwordhistory) is
accidentally deleted, it causes a null reference in pw_val2scheme.
This patch checks whether val is NULL or not. If the given val is
NULL, pw_val2scheme returns NULL.
https://fedorahosted.org/389/ticket/47905
Reviewed by nhosoi(a)redhat.com.
(cherry picked from commit 2c6e74adbea3c4799f30b0e3d679da9dd060ff58)
(cherry picked from commit baa26c96e873916d4c02651b04de7ca2a578863d)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 3cb40fc..082f69a 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -146,7 +146,7 @@ slapi_pw_find_sv(
LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pw_find value: \"%s\"\n", slapi_value_get_string(v), 0, 0 ); /* JCM Innards */
- for ( i = 0; vals[i] != NULL; i++ )
+ for ( i = 0; vals && vals[i]; i++ )
{
pwsp = pw_val2scheme( (char*)slapi_value_get_string(vals[i]), &valpwd, 1 ); /* JCM Innards*/
if ( pwsp != NULL &&
@@ -287,9 +287,12 @@ struct pw_scheme *
pw_val2scheme( char *val, char **valpwdp, int first_is_default )
{
struct pw_scheme *pwsp;
- int namelen, prefixlen;
+ int namelen, prefixlen;
char *end, buf[ PWD_MAX_NAME_LEN + 1 ];
+ if (NULL == val) {
+ return( NULL );
+ }
if ( *val != PWD_HASH_PREFIX_START ||
( end = strchr( val, PWD_HASH_PREFIX_END )) == NULL ||
( namelen = end - val - 1 ) > PWD_MAX_NAME_LEN ) {
9 years, 3 months
Branch '389-ds-base-1.3.3' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/pw.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
New commits:
commit baa26c96e873916d4c02651b04de7ca2a578863d
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Jan 9 14:22:50 2015 -0800
Ticket #47905 - Bad manipulation of passwordhistory
Description: The patch was provided by German Parente (gparente(a)redhat.com)
https://fedorahosted.org/389/ticket/47905#comment:6
If a value of password policy attribute (e.g., passwordhistory) is
accidentally deleted, it causes a null reference in pw_val2scheme.
This patch checks whether val is NULL or not. If the given val is
NULL, pw_val2scheme returns NULL.
https://fedorahosted.org/389/ticket/47905
Reviewed by nhosoi(a)redhat.com.
(cherry picked from commit 2c6e74adbea3c4799f30b0e3d679da9dd060ff58)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 3cb40fc..082f69a 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -146,7 +146,7 @@ slapi_pw_find_sv(
LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pw_find value: \"%s\"\n", slapi_value_get_string(v), 0, 0 ); /* JCM Innards */
- for ( i = 0; vals[i] != NULL; i++ )
+ for ( i = 0; vals && vals[i]; i++ )
{
pwsp = pw_val2scheme( (char*)slapi_value_get_string(vals[i]), &valpwd, 1 ); /* JCM Innards*/
if ( pwsp != NULL &&
@@ -287,9 +287,12 @@ struct pw_scheme *
pw_val2scheme( char *val, char **valpwdp, int first_is_default )
{
struct pw_scheme *pwsp;
- int namelen, prefixlen;
+ int namelen, prefixlen;
char *end, buf[ PWD_MAX_NAME_LEN + 1 ];
+ if (NULL == val) {
+ return( NULL );
+ }
if ( *val != PWD_HASH_PREFIX_START ||
( end = strchr( val, PWD_HASH_PREFIX_END )) == NULL ||
( namelen = end - val - 1 ) > PWD_MAX_NAME_LEN ) {
9 years, 3 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/pw.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
New commits:
commit 2c6e74adbea3c4799f30b0e3d679da9dd060ff58
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Jan 9 14:22:50 2015 -0800
Ticket #47905 - Bad manipulation of passwordhistory
Description: The patch was provided by German Parente (gparente(a)redhat.com)
https://fedorahosted.org/389/ticket/47905#comment:6
If a value of password policy attribute (e.g., passwordhistory) is
accidentally deleted, it causes a null reference in pw_val2scheme.
This patch checks whether val is NULL or not. If the given val is
NULL, pw_val2scheme returns NULL.
https://fedorahosted.org/389/ticket/47905
Reviewed by nhosoi(a)redhat.com.
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 3cb40fc..082f69a 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -146,7 +146,7 @@ slapi_pw_find_sv(
LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pw_find value: \"%s\"\n", slapi_value_get_string(v), 0, 0 ); /* JCM Innards */
- for ( i = 0; vals[i] != NULL; i++ )
+ for ( i = 0; vals && vals[i]; i++ )
{
pwsp = pw_val2scheme( (char*)slapi_value_get_string(vals[i]), &valpwd, 1 ); /* JCM Innards*/
if ( pwsp != NULL &&
@@ -287,9 +287,12 @@ struct pw_scheme *
pw_val2scheme( char *val, char **valpwdp, int first_is_default )
{
struct pw_scheme *pwsp;
- int namelen, prefixlen;
+ int namelen, prefixlen;
char *end, buf[ PWD_MAX_NAME_LEN + 1 ];
+ if (NULL == val) {
+ return( NULL );
+ }
if ( *val != PWD_HASH_PREFIX_START ||
( end = strchr( val, PWD_HASH_PREFIX_END )) == NULL ||
( namelen = end - val - 1 ) > PWD_MAX_NAME_LEN ) {
9 years, 3 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Mark Reynolds
ldap/servers/plugins/schema_reload/schema_reload.c | 7
ldap/servers/slapd/attr.c | 8
ldap/servers/slapd/attrsyntax.c | 230 +++++++++++++++------
ldap/servers/slapd/opshared.c | 2
ldap/servers/slapd/proto-slap.h | 12 -
ldap/servers/slapd/schema.c | 116 +++++-----
6 files changed, 243 insertions(+), 132 deletions(-)
New commits:
commit 457252f5c97aa8b72d94376e328e63c5d47a825b
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Jan 9 13:53:20 2015 -0500
Ticket 47973 - During schema reload sometimes the search
returns no results
Bug Description: During a schema reload operation the search of an existing
entry may randomly report no results. This is because during
the schema reload all existing attribute syntaxes are removed,
and there is a small window where ldap operations can be performed
before the new schema is loaded. During this window, attribute
values are normalized to NULL which causes operation to unexpectedly
fail.
Fix Description: Instead of wiping out the existing attribute syntax hastables
in the middle of the task, instead load the new schema into
temporary hash tables. Once the reload is complete, then take
the asi write lock, remove the old hash tables, and swap in the
new ones.
https://fedorahosted.org/389/ticket/47973
valgrind: PASSED
Reviewed by: nhosoi(Thanks!)
(cherry picked from commit 3fafcbe0a2ada038f02efdfdce77c1768f0e1819)
Conflicts:
ldap/servers/slapd/attrsyntax.c
ldap/servers/slapd/proto-slap.h
diff --git a/ldap/servers/plugins/schema_reload/schema_reload.c b/ldap/servers/plugins/schema_reload/schema_reload.c
index efc0de2..4e5c7f0 100644
--- a/ldap/servers/plugins/schema_reload/schema_reload.c
+++ b/ldap/servers/plugins/schema_reload/schema_reload.c
@@ -170,13 +170,6 @@ 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.");
diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c
index 983e286..a4d8a96 100644
--- a/ldap/servers/slapd/attr.c
+++ b/ldap/servers/slapd/attr.c
@@ -175,8 +175,8 @@ slapi_attr_types_equivalent(const char *t1, const char *t2)
return 0;
}
- asi1 = attr_syntax_get_by_name(t1);
- asi2 = attr_syntax_get_by_name(t2);
+ asi1 = attr_syntax_get_by_name(t1, 0);
+ asi2 = attr_syntax_get_by_name(t2, 0);
if (NULL != asi1) {
if (NULL != asi2) {
/* Both found - compare normalized names */
@@ -277,7 +277,7 @@ slapi_attr_init_locking_optional(Slapi_Attr *a, const char *type, PRBool use_loc
{
basetype = tmp; /* basetype was malloc'd */
}
- asi = attr_syntax_get_by_name_locking_optional(basetype, use_lock);
+ asi = attr_syntax_get_by_name_locking_optional(basetype, use_lock, 0);
}
if(NULL == asi)
{
@@ -288,7 +288,7 @@ slapi_attr_init_locking_optional(Slapi_Attr *a, const char *type, PRBool use_loc
* attribute type that has that syntax.
*/
asi = attr_syntax_get_by_name_locking_optional(
- ATTR_WITH_OCTETSTRING_SYNTAX, use_lock);
+ ATTR_WITH_OCTETSTRING_SYNTAX, use_lock, 0);
}
else
{
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index 75114e0..d92728a 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -73,14 +73,19 @@ static Slapi_RWLock *name2asi_lock = NULL;
#define AS_UNLOCK_READ(l) slapi_rwlock_unlock(l)
#define AS_UNLOCK_WRITE(l) slapi_rwlock_unlock(l)
+/*
+ * For the schema reload task, we need to use separate temporary hashtables & linked lists
+ */
+static PLHashTable *oid2asi_tmp = NULL;
+static PLHashTable *name2asi_tmp = NULL;
static struct asyntaxinfo *default_asi = NULL;
static void *attr_syntax_get_plugin_by_name_with_default( const char *type );
static void attr_syntax_delete_no_lock( struct asyntaxinfo *asip,
- PRBool remove_from_oid_table );
+ PRBool remove_from_oid_table, PRUint32 schema_flags );
static struct asyntaxinfo *attr_syntax_get_by_oid_locking_optional( const
- char *oid, PRBool use_lock);
+ char *oid, PRBool use_lock, PRUint32 schema_flags);
#ifdef ATTR_LDAP_DEBUG
static void attr_syntax_print();
@@ -198,8 +203,6 @@ attr_syntax_check_oids()
void
attr_syntax_free( struct asyntaxinfo *a )
{
- PR_ASSERT( a->asi_refcnt == 0 );
-
cool_charray_free( a->asi_aliases );
slapi_ch_free( (void**)&a->asi_name );
slapi_ch_free( (void **)&a->asi_desc );
@@ -228,9 +231,9 @@ attr_syntax_new()
* be returned by calling to attr_syntax_return().
*/
struct asyntaxinfo *
-attr_syntax_get_by_oid(const char *oid)
+attr_syntax_get_by_oid(const char *oid, PRUint32 schema_flags)
{
- return attr_syntax_get_by_oid_locking_optional( oid, PR_TRUE);
+ return attr_syntax_get_by_oid_locking_optional( oid, PR_TRUE, schema_flags);
}
@@ -243,15 +246,30 @@ attr_syntax_get_by_oid(const char *oid)
* same use_lock parameter.
*/
static struct asyntaxinfo *
-attr_syntax_get_by_oid_locking_optional( const char *oid, PRBool use_lock )
+attr_syntax_get_by_oid_locking_optional( const char *oid, PRBool use_lock, PRUint32 schema_flags )
{
struct asyntaxinfo *asi = 0;
- if (oid2asi)
+ PLHashTable *ht = oid2asi;
+ int using_tmp_ht = 0;
+
+ if (schema_flags & DSE_SCHEMA_LOCKED){
+ ht = oid2asi_tmp;
+ using_tmp_ht = 1;
+ use_lock = 0;
+ }
+ if (ht)
{
if ( use_lock ) {
AS_LOCK_READ(oid2asi_lock);
}
- asi = (struct asyntaxinfo *)PL_HashTableLookup_const(oid2asi, oid);
+ if (!using_tmp_ht){
+ /*
+ * The oid2asi pointer could have been rewritten by the schema_reload task
+ * while waiting on the lock, so grab it again.
+ */
+ ht = oid2asi;
+ }
+ asi = (struct asyntaxinfo *)PL_HashTableLookup_const(ht, oid);
if (asi)
{
PR_AtomicIncrement( &asi->asi_refcnt );
@@ -272,18 +290,22 @@ attr_syntax_get_by_oid_locking_optional( const char *oid, PRBool use_lock )
* to worry about resource contention.
*/
static void
-attr_syntax_add_by_oid(const char *oid, struct asyntaxinfo *a, int lock)
+attr_syntax_add_by_oid(const char *oid, struct asyntaxinfo *a, PRUint32 schema_flags, int lock)
{
if (0 != attr_syntax_init()) return;
- if (lock) {
- AS_LOCK_WRITE(oid2asi_lock);
- }
+ if(schema_flags & DSE_SCHEMA_LOCKED){
+ PL_HashTableAdd(oid2asi_tmp, oid, a);
+ } else {
+ if (lock) {
+ AS_LOCK_WRITE(oid2asi_lock);
+ }
- PL_HashTableAdd(oid2asi, oid, a);
+ PL_HashTableAdd(oid2asi, oid, a);
- if (lock) {
- AS_UNLOCK_WRITE(oid2asi_lock);
+ if (lock) {
+ AS_UNLOCK_WRITE(oid2asi_lock);
+ }
}
}
@@ -296,18 +318,19 @@ attr_syntax_add_by_oid(const char *oid, struct asyntaxinfo *a, int lock)
* be returned by calling to attr_syntax_return().
*/
struct asyntaxinfo *
-attr_syntax_get_by_name(const char *name)
+attr_syntax_get_by_name(const char *name, PRUint32 schema_flags)
{
- return attr_syntax_get_by_name_locking_optional(name, PR_TRUE);
+ return attr_syntax_get_by_name_locking_optional(name, PR_TRUE, schema_flags);
}
struct asyntaxinfo *
attr_syntax_get_by_name_with_default(const char *name)
{
struct asyntaxinfo *asi = NULL;
- asi = attr_syntax_get_by_name_locking_optional(name, PR_TRUE);
+
+ asi = attr_syntax_get_by_name_locking_optional(name, PR_TRUE, 0);
if (asi == NULL)
- asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX);
+ asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX, 0);
if ( asi == NULL )
asi = default_asi;
return asi;
@@ -322,15 +345,30 @@ attr_syntax_get_by_name_with_default(const char *name)
* same use_lock parameter.
*/
struct asyntaxinfo *
-attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock)
+attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock, PRUint32 schema_flags)
{
struct asyntaxinfo *asi = 0;
- if (name2asi)
+ PLHashTable *ht = name2asi;
+ int using_tmp_ht = 0;
+
+ if (schema_flags & DSE_SCHEMA_LOCKED){
+ ht = name2asi_tmp;
+ using_tmp_ht = 1;
+ use_lock = 0;
+ }
+ if (ht)
{
if ( use_lock ) {
AS_LOCK_READ(name2asi_lock);
}
- asi = (struct asyntaxinfo *)PL_HashTableLookup_const(name2asi, name);
+ if(!using_tmp_ht){
+ /*
+ * The name2asi pointer could have been rewritten by the schema_reload task
+ * while waiting on the lock, so grab it again.
+ */
+ ht = name2asi;
+ }
+ asi = (struct asyntaxinfo *)PL_HashTableLookup_const(ht, name);
if ( NULL != asi ) {
PR_AtomicIncrement( &asi->asi_refcnt );
}
@@ -339,7 +377,7 @@ attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock)
}
}
if (!asi) /* given name may be an OID */
- asi = attr_syntax_get_by_oid_locking_optional(name, use_lock);
+ asi = attr_syntax_get_by_oid_locking_optional(name, use_lock, schema_flags);
return asi;
}
@@ -402,26 +440,37 @@ attr_syntax_return_locking_optional(struct asyntaxinfo *asi, PRBool use_lock)
* to worry about resource contention.
*/
static void
-attr_syntax_add_by_name(struct asyntaxinfo *a, int lock)
+attr_syntax_add_by_name(struct asyntaxinfo *a, PRUint32 schema_flags, int lock)
{
if (0 != attr_syntax_init()) return;
- if (lock) {
- AS_LOCK_WRITE(name2asi_lock);
- }
+ if (schema_flags & DSE_SCHEMA_LOCKED ){
+ PL_HashTableAdd(name2asi_tmp, a->asi_name, a);
+ if ( a->asi_aliases != NULL ) {
+ int i;
+
+ for ( i = 0; a->asi_aliases[i] != NULL; ++i ) {
+ PL_HashTableAdd(name2asi_tmp, a->asi_aliases[i], a);
+ }
+ }
+ } else {
+ if (lock) {
+ AS_LOCK_WRITE(name2asi_lock);
+ }
- PL_HashTableAdd(name2asi, a->asi_name, a);
- if ( a->asi_aliases != NULL ) {
- int i;
+ PL_HashTableAdd(name2asi, a->asi_name, a);
+ if ( a->asi_aliases != NULL ) {
+ int i;
- for ( i = 0; a->asi_aliases[i] != NULL; ++i ) {
- PL_HashTableAdd(name2asi, a->asi_aliases[i], a);
+ for ( i = 0; a->asi_aliases[i] != NULL; ++i ) {
+ PL_HashTableAdd(name2asi, a->asi_aliases[i], a);
+ }
+ }
+ if (lock) {
+ AS_UNLOCK_WRITE(name2asi_lock);
}
}
- if (lock) {
- AS_UNLOCK_WRITE(name2asi_lock);
- }
}
@@ -430,7 +479,7 @@ attr_syntax_add_by_name(struct asyntaxinfo *a, int lock)
* and oids.
*/
void
-attr_syntax_delete( struct asyntaxinfo *asi )
+attr_syntax_delete( struct asyntaxinfo *asi, PRUint32 schema_flags )
{
PR_ASSERT( asi );
@@ -438,7 +487,7 @@ attr_syntax_delete( struct asyntaxinfo *asi )
AS_LOCK_WRITE(oid2asi_lock);
AS_LOCK_WRITE(name2asi_lock);
- attr_syntax_delete_no_lock( asi, PR_TRUE );
+ attr_syntax_delete_no_lock( asi, PR_TRUE, schema_flags );
AS_UNLOCK_WRITE(name2asi_lock);
AS_UNLOCK_WRITE(oid2asi_lock);
@@ -452,19 +501,34 @@ attr_syntax_delete( struct asyntaxinfo *asi )
*/
static void
attr_syntax_delete_no_lock( struct asyntaxinfo *asi,
- PRBool remove_from_oidtable )
+ PRBool remove_from_oidtable, PRUint32 schema_flags )
{
- int i;
+ PLHashTable *ht = NULL;
+ int using_tmp_ht = 0;
+ int i;
+ if (schema_flags & DSE_SCHEMA_LOCKED){
+ using_tmp_ht = 1;
+ }
if (oid2asi && remove_from_oidtable ) {
- PL_HashTableRemove(oid2asi, asi->asi_oid);
+ if (using_tmp_ht){
+ ht = oid2asi_tmp;
+ } else {
+ ht = oid2asi;
+ }
+ PL_HashTableRemove(ht, asi->asi_oid);
}
if(name2asi) {
- PL_HashTableRemove(name2asi, asi->asi_name);
+ if (using_tmp_ht){
+ ht = name2asi_tmp;
+ } else {
+ ht = name2asi;
+ }
+ PL_HashTableRemove(ht, asi->asi_name);
if ( asi->asi_aliases != NULL ) {
for ( i = 0; asi->asi_aliases[i] != NULL; ++i ) {
- PL_HashTableRemove(name2asi, asi->asi_aliases[i]);
+ PL_HashTableRemove(ht, asi->asi_aliases[i]);
}
}
if ( asi->asi_refcnt > 0 ) {
@@ -496,7 +560,7 @@ slapi_attr_syntax_normalize( const char *s )
struct asyntaxinfo *asi = NULL;
char *r = NULL;
- if((asi=attr_syntax_get_by_name(s)) != NULL ) {
+ if((asi=attr_syntax_get_by_name(s, 0)) != NULL ) {
r = slapi_ch_strdup(asi->asi_name);
attr_syntax_return( asi );
}
@@ -507,7 +571,6 @@ slapi_attr_syntax_normalize( const char *s )
return r;
}
-
/*
* attr_syntax_exists: return 1 if attr_name exists, 0 otherwise
*
@@ -517,7 +580,8 @@ attr_syntax_exists(const char *attr_name)
{
struct asyntaxinfo *asi;
- asi = attr_syntax_get_by_name(attr_name);
+
+ asi = attr_syntax_get_by_name(attr_name, 0);
attr_syntax_return( asi );
if ( asi != NULL )
@@ -686,13 +750,13 @@ attr_syntax_get_plugin_by_name_with_default( const char *type )
/*
* first we look for this attribute type explictly
*/
- if ( (asi = attr_syntax_get_by_name(type)) == NULL ) {
+ if ( (asi = attr_syntax_get_by_name(type, 0)) == NULL ) {
/*
* no syntax for this type... return Octet String
* syntax. we accomplish this by looking up a well known
* attribute type that has that syntax.
*/
- asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX);
+ asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX, 0);
if (asi == NULL)
asi = default_asi;
}
@@ -729,14 +793,13 @@ attr_syntax_dup( struct asyntaxinfo *a )
return( newas );
}
-
/*
* Add a new attribute type to the schema.
*
* Returns an LDAP error code (LDAP_SUCCESS if all goes well).
*/
int
-attr_syntax_add( struct asyntaxinfo *asip )
+attr_syntax_add( struct asyntaxinfo *asip, PRUint32 schema_flags )
{
int i, rc = LDAP_SUCCESS;
int nolock = asip->asi_flags & SLAPI_ATTR_FLAG_NOLOCKING;
@@ -748,7 +811,7 @@ attr_syntax_add( struct asyntaxinfo *asip )
/* make sure the oid is unique */
if ( NULL != ( oldas_from_oid = attr_syntax_get_by_oid_locking_optional(
- asip->asi_oid, !nolock))) {
+ asip->asi_oid, !nolock, schema_flags))) {
if ( 0 == (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE)) {
/* failure - OID is in use; no override flag */
rc = LDAP_TYPE_OR_VALUE_EXISTS;
@@ -760,7 +823,7 @@ attr_syntax_add( struct asyntaxinfo *asip )
* the primary name and OID point to the same schema definition.
*/
if ( NULL != ( oldas_from_name = attr_syntax_get_by_name_locking_optional(
- asip->asi_name, !nolock))) {
+ asip->asi_name, !nolock, schema_flags))) {
if ( 0 == (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE)
|| ( oldas_from_oid != oldas_from_name )) {
/* failure; no override flag OR OID and name don't match */
@@ -768,7 +831,7 @@ attr_syntax_add( struct asyntaxinfo *asip )
goto cleanup_and_return;
}
/* Flag for deletion. We are going to override this attr */
- attr_syntax_delete(oldas_from_name);
+ attr_syntax_delete(oldas_from_name, schema_flags);
} else if ( NULL != oldas_from_oid ) {
/* failure - OID is in use but name does not exist */
rc = LDAP_TYPE_OR_VALUE_EXISTS;
@@ -782,11 +845,11 @@ attr_syntax_add( struct asyntaxinfo *asip )
if ( NULL != ( tmpasi =
attr_syntax_get_by_name_locking_optional(
- asip->asi_aliases[i], !nolock))) {
+ asip->asi_aliases[i], !nolock, schema_flags))) {
if (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE) {
/* Flag for tmpasi for deletion. It will be free'd
* when attr_syntax_return is called. */
- attr_syntax_delete(tmpasi);
+ attr_syntax_delete(tmpasi, schema_flags);
} else {
/* failure - one of the aliases is already in use */
rc = LDAP_TYPE_OR_VALUE_EXISTS;
@@ -805,8 +868,8 @@ attr_syntax_add( struct asyntaxinfo *asip )
/* ditto for the override one */
asip->asi_flags &= ~SLAPI_ATTR_FLAG_OVERRIDE;
- attr_syntax_add_by_oid( asip->asi_oid, asip, !nolock);
- attr_syntax_add_by_name( asip, !nolock);
+ attr_syntax_add_by_oid( asip->asi_oid, asip, schema_flags, !nolock);
+ attr_syntax_add_by_name( asip, schema_flags, !nolock);
cleanup_and_return:
attr_syntax_return_locking_optional( oldas_from_oid, !nolock );
@@ -979,7 +1042,7 @@ slapi_attr_type2plugin( const char *type, void **pi )
int
slapi_attr_get_oid( const Slapi_Attr *a, char **oid )
{
- struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type);
+ struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type, 0);
if (asi) {
*oid = asi->asi_oid;
attr_syntax_return(asi);
@@ -995,7 +1058,7 @@ slapi_attr_get_oid( const Slapi_Attr *a, char **oid )
int
slapi_attr_get_oid_copy( const Slapi_Attr *a, char **oidp )
{
- struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type);
+ struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type, 0);
if (asi) {
*oidp = slapi_ch_strdup( asi->asi_oid );
attr_syntax_return(asi);
@@ -1191,7 +1254,7 @@ attr_syntax_delete_if_not_flagged(struct asyntaxinfo *asip, void *arg)
PR_ASSERT( fi != NULL );
if ( 0 == ( asip->asi_flags & fi->asef_flag )) {
- attr_syntax_delete_no_lock( asip, PR_FALSE );
+ attr_syntax_delete_no_lock( asip, PR_FALSE, 0 );
return ATTR_SYNTAX_ENUM_REMOVE;
} else {
return ATTR_SYNTAX_ENUM_NEXT;
@@ -1207,7 +1270,7 @@ attr_syntax_force_to_delete(struct asyntaxinfo *asip, void *arg)
fi = (struct attr_syntax_enum_flaginfo *)arg;
PR_ASSERT( fi != NULL );
- attr_syntax_delete_no_lock( asip, PR_FALSE );
+ attr_syntax_delete_no_lock( asip, PR_FALSE, 0 );
return ATTR_SYNTAX_ENUM_REMOVE;
}
@@ -1272,6 +1335,7 @@ attr_syntax_delete_all_for_schemareload(unsigned long flag)
#define ATTR_DEFAULT_SYNTAX_OID "1.1"
#define ATTR_DEFAULT_SYNTAX "defaultdirstringsyntax"
+
static int
attr_syntax_init(void)
{
@@ -1290,6 +1354,14 @@ attr_syntax_init(void)
}
}
+ if (!oid2asi_tmp)
+ {
+ /* temporary hash table for schema reload */
+ oid2asi_tmp = PL_NewHashTable(2047, hashNocaseString,
+ hashNocaseCompare,
+ PL_CompareValues, 0, 0);
+ }
+
if (!name2asi)
{
name2asi = PL_NewHashTable(2047, hashNocaseString,
@@ -1310,6 +1382,14 @@ attr_syntax_init(void)
DIRSTRING_SYNTAX_OID,
SLAPI_ATTR_FLAG_NOUSERMOD );
}
+ if (!name2asi_tmp)
+ {
+ /* temporary hash table for schema reload */
+ name2asi_tmp = PL_NewHashTable(2047, hashNocaseString,
+ hashNocaseCompare,
+ PL_CompareValues, 0, 0);
+ }
+
return 0;
}
@@ -1379,7 +1459,7 @@ slapi_add_internal_attr_syntax( const char *name, const char *oid,
&asip );
if ( rc == LDAP_SUCCESS ) {
- rc = attr_syntax_add( asip );
+ rc = attr_syntax_add( asip, 0 );
if ( rc == LDAP_SUCCESS ) {
if (attr_syntax_internal_asi_add_ht(asip)) {
slapi_log_error(SLAPI_LOG_FATAL,
@@ -1387,6 +1467,8 @@ slapi_add_internal_attr_syntax( const char *name, const char *oid,
"Failed to stash internal asyntaxinfo: %s.\n",
asip->asi_name);
}
+ } else {
+ attr_syntax_free(asip);
}
}
@@ -1406,7 +1488,7 @@ attr_syntax_internal_asi_add(struct asyntaxinfo *asip, void *arg)
/* Copy is needed since when reloading the schema,
* existing syntax info is cleaned up. */
asip_copy = attr_syntax_dup(asip);
- rc = attr_syntax_add(asip_copy);
+ rc = attr_syntax_add(asip_copy, 0);
if (LDAP_SUCCESS != rc) {
attr_syntax_free(asip_copy);
}
@@ -1426,3 +1508,25 @@ slapi_reload_internal_attr_syntax()
attr_syntax_enumerate_attrs_ext(internalasi, attr_syntax_internal_asi_add, NULL);
return rc;
}
+
+/*
+ * schema reload - now that we have loaded the schema into temporary
+ * hash tables, swap out the old for the new.
+ */
+void
+attr_syntax_swap_ht()
+{
+ /* Remove the old hash tables */
+ PL_HashTableDestroy(name2asi);
+ PL_HashTableDestroy(oid2asi);
+
+ /*
+ * Swap the hash table/linked list pointers, and set the
+ * temporary pointers to NULL
+ */
+ name2asi = name2asi_tmp;
+ name2asi_tmp = NULL;
+ oid2asi = oid2asi_tmp;
+ oid2asi_tmp = NULL;
+}
+
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 7a0b544..a7367a7 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -91,7 +91,7 @@ int op_shared_is_allowed_attr (const char *attr_name, int replicated_op)
struct asyntaxinfo *asi;
int no_user_mod = 0;
- asi = attr_syntax_get_by_name( attr_name );
+ asi = attr_syntax_get_by_name( attr_name, 0 );
if ( NULL != asi &&
0 != ( asi->asi_flags & SLAPI_ATTR_FLAG_NOUSERMOD ))
{
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 0891608..da9c925 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -117,7 +117,7 @@ void attr_syntax_write_lock(void);
void attr_syntax_unlock_read(void);
void attr_syntax_unlock_write(void);
int attr_syntax_exists (const char *attr_name);
-void attr_syntax_delete ( struct asyntaxinfo *asip );
+void attr_syntax_delete ( struct asyntaxinfo *asip, PRUint32 schema_flags );
#define SLAPI_SYNTAXLENGTH_NONE (-1) /* for syntaxlength parameter */
int attr_syntax_create( const char *attr_oid, char *const*attr_names,
int num_names, const char *attr_desc, const char *attr_superior,
@@ -126,15 +126,17 @@ int attr_syntax_create( const char *attr_oid, char *const*attr_names,
const char *attr_syntax, int syntaxlength, unsigned long flags,
struct asyntaxinfo **asip );
void attr_syntax_free( struct asyntaxinfo *a );
-int attr_syntax_add( struct asyntaxinfo *asip );
+int attr_syntax_add( struct asyntaxinfo *asip, PRUint32 schema_flags );
char *attr_syntax_normalize_no_lookup( const char *s );
void attr_syntax_enumerate_attrs(AttrEnumFunc aef, void *arg, PRBool writelock);
void attr_syntax_all_clear_flag( unsigned long flag );
void attr_syntax_delete_all_not_flagged( unsigned long flag );
-struct asyntaxinfo *attr_syntax_get_by_oid ( const char *oid );
-struct asyntaxinfo *attr_syntax_get_by_name ( const char *name );
-struct asyntaxinfo *attr_syntax_get_by_name_locking_optional ( const char *name, PRBool use_lock );
+struct asyntaxinfo *attr_syntax_get_by_oid ( const char *oid, PRUint32 schema_flags );
+struct asyntaxinfo *attr_syntax_get_by_name ( const char *name, PRUint32 schema_flags );
struct asyntaxinfo *attr_syntax_get_by_name_with_default ( const char *name );
+struct asyntaxinfo *attr_syntax_get_by_name_locking_optional ( const char *name, PRBool use_lock, PRUint32 schema_flags );
+struct asyntaxinfo *attr_syntax_get_global_at();
+void attr_syntax_swap_ht(void);
/*
* Call attr_syntax_return() when you are done using a value returned
* by attr_syntax_get_by_oid() or attr_syntax_get_by_name().
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 18ae152..798d905 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -154,6 +154,8 @@ static int schema_strcmp( const char *s1, const char *s2 );
static int schema_strcmp_array( char **sa1, char **sa2,
const char *ignorestr );
static PRBool schema_type_is_interesting( const char *type );
+static void reload_schemafile_lock(void);
+static void reload_schemafile_unlock(void);
static void schema_create_errormsg( char *errorbuf, size_t errorbufsize,
const char *prefix, const char *name, const char *fmt, ... )
#ifdef __GNUC__
@@ -2125,7 +2127,7 @@ schema_delete_attributes ( Slapi_Entry *entryBefore, LDAPMod *mod,
sscanf (attr_ldif, "%s name %s syntax %s",
psbAttrOid->buffer, psbAttrName->buffer, psbAttrSyntax->buffer);
- if ((a = attr_syntax_get_by_name ( psbAttrName->buffer)) != NULL ) {
+ if ((a = attr_syntax_get_by_name ( psbAttrName->buffer, 0 )) != NULL ) {
/* only modify attrs which were user defined */
if (a->asi_flags & SLAPI_ATTR_FLAG_STD_ATTR) {
schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
@@ -2177,7 +2179,7 @@ schema_delete_attributes ( Slapi_Entry *entryBefore, LDAPMod *mod,
}
/* Delete it. */
- attr_syntax_delete( a );
+ attr_syntax_delete( a, 0 );
attr_syntax_return( a );
}
else {
@@ -2300,7 +2302,7 @@ add_oc_internal(struct objclass *pnew_oc, char *errorbuf, size_t errorbufsize,
}
/* check to see if the oid is already in use by an attribute */
- if (!rc && (pasyntaxinfo = attr_syntax_get_by_oid(pnew_oc->oc_oid))) {
+ if (!rc && (pasyntaxinfo = attr_syntax_get_by_oid(pnew_oc->oc_oid, flags))) {
schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_oc,
pnew_oc->oc_name,
"The OID \"%s\" is also used by the attribute type \"%s\"",
@@ -2419,7 +2421,7 @@ schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
* handle the various cases.
*/
if ( NULL == ( oldasip =
- attr_syntax_get_by_oid( newasip->asi_oid ))) {
+ attr_syntax_get_by_oid( newasip->asi_oid, 0 ))) {
/* new attribute type */
LDAPDebug( LDAP_DEBUG_TRACE, "schema_replace_attributes:"
" new type %s (OID %s)\n",
@@ -2437,14 +2439,14 @@ schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
" replacing type %s (OID %s)\n",
newasip->asi_name, newasip->asi_oid, 0 );
/* flag for deletion */
- attr_syntax_delete( oldasip );
+ attr_syntax_delete( oldasip, 0 );
}
attr_syntax_return( oldasip );
}
if ( NULL != newasip ) { /* add new or replacement definition */
- rc = attr_syntax_add( newasip );
+ rc = attr_syntax_add( newasip, 0 );
if ( LDAP_SUCCESS != rc ) {
schema_create_errormsg( errorbuf, errorbufsize,
schema_errprefix_at, newasip->asi_name,
@@ -3355,7 +3357,7 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
if (!status && (NULL != pSuperior)) {
struct asyntaxinfo *asi_parent;
- asi_parent = attr_syntax_get_by_name(pSuperior);
+ asi_parent = attr_syntax_get_by_name(pSuperior, schema_flags);
/* if we find no match then server won't start or add the attribute type */
if (asi_parent == NULL) {
LDAPDebug (LDAP_DEBUG_PARSE,
@@ -3467,7 +3469,7 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
struct asyntaxinfo *tmpasi;
if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
- ( NULL != ( tmpasi = attr_syntax_get_by_oid(pOid)))) {
+ ( NULL != ( tmpasi = attr_syntax_get_by_oid(pOid, schema_flags)))) {
schema_create_errormsg( errorbuf, errorbufsize,
schema_errprefix_at, first_attr_name,
"Could not be added because the OID \"%s\" is already in use",
@@ -3490,7 +3492,7 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
if ( NULL != asipp ) {
*asipp = tmpasip; /* just return it */
} else { /* add the new attribute to the global store */
- status = attr_syntax_add( tmpasip );
+ status = attr_syntax_add( tmpasip, schema_flags );
if ( LDAP_SUCCESS != status ) {
if ( 0 != (flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
LDAP_TYPE_OR_VALUE_EXISTS == status ) {
@@ -4307,6 +4309,59 @@ get_tagged_oid( const char *tag, const char **inputp,
return( oid );
}
+/*
+ * Reload the schema files
+ *
+ * This is only called from the schema_reload task. The flag DSE_SCHEMA_LOCKED
+ * is also only set been called from this function. To not interrupt clients
+ * we will rebuild the schema in separate hash tables, and then swap the
+ * hash tables once the schema is completely reloaded. We use the DSE_SCHEMA_LOCKED
+ * flag to tell the attribute syntax functions to use the temporary hashtables.
+ */
+int
+slapi_reload_schema_files(char *schemadir)
+{
+ int rc = LDAP_SUCCESS;
+ struct dse *my_pschemadse = NULL;
+ /* get be to lock */
+ Slapi_Backend *be = slapi_be_select_by_instance_name( DSE_SCHEMA );
+
+ if (NULL == be)
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
+ "schema file reload failed\n" );
+ return LDAP_LOCAL_ERROR;
+ }
+ slapi_be_Wlock(be); /* be lock must be outer of schemafile lock */
+ reload_schemafile_lock();
+ oc_delete_all_nolock();
+ rc = init_schema_dse_ext(schemadir, be, &my_pschemadse,
+ DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_LOCKED);
+ if (rc) {
+ /*
+ * The schema has been reloaded into the temporary hash tables.
+ * Take the write lock, wipe out the existing hash tables, and
+ * swap in the new ones.
+ */
+ attr_syntax_write_lock();
+ attr_syntax_delete_all_for_schemareload(SLAPI_ATTR_FLAG_KEEP);
+ attr_syntax_swap_ht();
+ attr_syntax_unlock_write();
+ slapi_reload_internal_attr_syntax();
+
+ dse_destroy(pschemadse);
+ pschemadse = my_pschemadse;
+ reload_schemafile_unlock();
+ slapi_be_Unlock(be);
+ return LDAP_SUCCESS;
+ } else {
+ reload_schemafile_unlock();
+ slapi_be_Unlock(be);
+ slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
+ "schema file reload failed\n" );
+ return LDAP_LOCAL_ERROR;
+ }
+}
/*
* sprintf to `outp' the contents of `tag' followed by `oid' followed by a
@@ -4818,49 +4873,6 @@ slapi_validate_schema_files(char *schemadir)
}
/*
- * API to reload the schema files.
- * Rule: this function is called when slapi_validate_schema_files is passed.
- * Schema checking is skipped in this function.
- */
-int
-slapi_reload_schema_files(char *schemadir)
-{
- int rc = LDAP_SUCCESS;
- struct dse *my_pschemadse = NULL;
- /* get be to lock */
- Slapi_Backend *be = slapi_be_select_by_instance_name( DSE_SCHEMA );
-
- if (NULL == be)
- {
- slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
- "schema file reload failed\n" );
- return LDAP_LOCAL_ERROR;
- }
- slapi_be_Wlock(be); /* be lock must be outer of schemafile lock */
- reload_schemafile_lock();
- /* Exclude attr_syntax not to grab from the hash table while cleaning up */
- attr_syntax_write_lock();
- attr_syntax_delete_all_for_schemareload(SLAPI_ATTR_FLAG_KEEP);
- oc_delete_all_nolock();
- attr_syntax_unlock_write();
- rc = init_schema_dse_ext(schemadir, be, &my_pschemadse,
- DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_LOCKED);
- if (rc) {
- dse_destroy(pschemadse);
- pschemadse = my_pschemadse;
- reload_schemafile_unlock();
- slapi_be_Unlock(be);
- return LDAP_SUCCESS;
- } else {
- reload_schemafile_unlock();
- slapi_be_Unlock(be);
- slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
- "schema file reload failed\n" );
- return LDAP_LOCAL_ERROR;
- }
-}
-
-/*
* slapi_schema_list_objectclass_attributes:
* Return the list of attributes belonging to the objectclass
*
9 years, 3 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Mark Reynolds
ldap/servers/plugins/schema_reload/schema_reload.c | 7
ldap/servers/slapd/attr.c | 8
ldap/servers/slapd/attrsyntax.c | 249 ++++++++++++++-------
ldap/servers/slapd/opshared.c | 2
ldap/servers/slapd/proto-slap.h | 13 -
ldap/servers/slapd/schema.c | 116 +++++----
6 files changed, 254 insertions(+), 141 deletions(-)
New commits:
commit 3fafcbe0a2ada038f02efdfdce77c1768f0e1819
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Jan 9 13:53:20 2015 -0500
Ticket 47973 - During schema reload sometimes the search
returns no results
Bug Description: During a schema reload operation the search of an existing
entry may randomly report no results. This is because during
the schema reload all existing attribute syntaxes are removed,
and there is a small window where ldap operations can be performed
before the new schema is loaded. During this window, attribute
values are normalized to NULL which causes operation to unexpectedly
fail.
Fix Description: Instead of wiping out the existing attribute syntax hastables
in the middle of the task, instead load the new schema into
temporary hash tables. Once the reload is complete, then take
the asi write lock, remove the old hash tables, and swap in the
new ones.
https://fedorahosted.org/389/ticket/47973
valgrind: PASSED
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/plugins/schema_reload/schema_reload.c b/ldap/servers/plugins/schema_reload/schema_reload.c
index efc0de2..4e5c7f0 100644
--- a/ldap/servers/plugins/schema_reload/schema_reload.c
+++ b/ldap/servers/plugins/schema_reload/schema_reload.c
@@ -170,13 +170,6 @@ 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.");
diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c
index 9fa07be..28a4247 100644
--- a/ldap/servers/slapd/attr.c
+++ b/ldap/servers/slapd/attr.c
@@ -175,8 +175,8 @@ slapi_attr_types_equivalent(const char *t1, const char *t2)
return 0;
}
- asi1 = attr_syntax_get_by_name(t1);
- asi2 = attr_syntax_get_by_name(t2);
+ asi1 = attr_syntax_get_by_name(t1, 0);
+ asi2 = attr_syntax_get_by_name(t2, 0);
if (NULL != asi1) {
if (NULL != asi2) {
/* Both found - compare normalized names */
@@ -277,7 +277,7 @@ slapi_attr_init_locking_optional(Slapi_Attr *a, const char *type, PRBool use_loc
{
basetype = tmp; /* basetype was malloc'd */
}
- asi = attr_syntax_get_by_name_locking_optional(basetype, use_lock);
+ asi = attr_syntax_get_by_name_locking_optional(basetype, use_lock, 0);
}
if(NULL == asi)
{
@@ -288,7 +288,7 @@ slapi_attr_init_locking_optional(Slapi_Attr *a, const char *type, PRBool use_loc
* attribute type that has that syntax.
*/
asi = attr_syntax_get_by_name_locking_optional(
- ATTR_WITH_OCTETSTRING_SYNTAX, use_lock);
+ ATTR_WITH_OCTETSTRING_SYNTAX, use_lock, 0);
}
else
{
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index 18d0c52..673a903 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -67,8 +67,14 @@ static PLHashTable *internalasi = NULL;
static PLHashTable *name2asi = NULL;
/* read/write lock to protect table */
static Slapi_RWLock *name2asi_lock = NULL;
-static int asi_locking = 1;
+/*
+ * For the schema reload task, we need to use separate temporary hashtables & linked lists
+ */
+static PLHashTable *oid2asi_tmp = NULL;
+static PLHashTable *name2asi_tmp = NULL;
+
+static int asi_locking = 1;
#define AS_LOCK_READ(l) if (asi_locking) { slapi_rwlock_rdlock(l); }
#define AS_LOCK_WRITE(l) if (asi_locking) { slapi_rwlock_wrlock(l); }
#define AS_UNLOCK_READ(l) if (asi_locking) { slapi_rwlock_unlock(l); }
@@ -79,9 +85,9 @@ static struct asyntaxinfo *default_asi = NULL;
static void *attr_syntax_get_plugin_by_name_with_default( const char *type );
static void attr_syntax_delete_no_lock( struct asyntaxinfo *asip,
- PRBool remove_from_oid_table );
+ PRBool remove_from_oid_table, PRUint32 schema_flags );
static struct asyntaxinfo *attr_syntax_get_by_oid_locking_optional( const
- char *oid, PRBool use_lock);
+ char *oid, PRBool use_lock, PRUint32 schema_flags);
#ifdef ATTR_LDAP_DEBUG
static void attr_syntax_print();
@@ -199,8 +205,6 @@ attr_syntax_check_oids()
void
attr_syntax_free( struct asyntaxinfo *a )
{
- PR_ASSERT( a->asi_refcnt == 0 );
-
cool_charray_free( a->asi_aliases );
slapi_ch_free( (void**)&a->asi_name );
slapi_ch_free( (void **)&a->asi_desc );
@@ -229,9 +233,9 @@ attr_syntax_new()
* be returned by calling to attr_syntax_return().
*/
struct asyntaxinfo *
-attr_syntax_get_by_oid(const char *oid)
+attr_syntax_get_by_oid(const char *oid, PRUint32 schema_flags)
{
- return attr_syntax_get_by_oid_locking_optional( oid, PR_TRUE);
+ return attr_syntax_get_by_oid_locking_optional( oid, PR_TRUE, schema_flags);
}
@@ -244,15 +248,30 @@ attr_syntax_get_by_oid(const char *oid)
* same use_lock parameter.
*/
static struct asyntaxinfo *
-attr_syntax_get_by_oid_locking_optional( const char *oid, PRBool use_lock )
+attr_syntax_get_by_oid_locking_optional( const char *oid, PRBool use_lock, PRUint32 schema_flags )
{
struct asyntaxinfo *asi = 0;
- if (oid2asi)
+ PLHashTable *ht = oid2asi;
+ int using_tmp_ht = 0;
+
+ if (schema_flags & DSE_SCHEMA_LOCKED){
+ ht = oid2asi_tmp;
+ using_tmp_ht = 1;
+ use_lock = 0;
+ }
+ if (ht)
{
if ( use_lock ) {
AS_LOCK_READ(oid2asi_lock);
}
- asi = (struct asyntaxinfo *)PL_HashTableLookup_const(oid2asi, oid);
+ if (!using_tmp_ht){
+ /*
+ * The oid2asi pointer could have been rewritten by the schema_reload task
+ * while waiting on the lock, so grab it again.
+ */
+ ht = oid2asi;
+ }
+ asi = (struct asyntaxinfo *)PL_HashTableLookup_const(ht, oid);
if (asi)
{
PR_AtomicIncrement( &asi->asi_refcnt );
@@ -273,18 +292,22 @@ attr_syntax_get_by_oid_locking_optional( const char *oid, PRBool use_lock )
* to worry about resource contention.
*/
static void
-attr_syntax_add_by_oid(const char *oid, struct asyntaxinfo *a, int lock)
+attr_syntax_add_by_oid(const char *oid, struct asyntaxinfo *a, PRUint32 schema_flags, int lock)
{
if (0 != attr_syntax_init()) return;
- if (lock) {
- AS_LOCK_WRITE(oid2asi_lock);
- }
+ if(schema_flags & DSE_SCHEMA_LOCKED){
+ PL_HashTableAdd(oid2asi_tmp, oid, a);
+ } else {
+ if (lock) {
+ AS_LOCK_WRITE(oid2asi_lock);
+ }
- PL_HashTableAdd(oid2asi, oid, a);
+ PL_HashTableAdd(oid2asi, oid, a);
- if (lock) {
- AS_UNLOCK_WRITE(oid2asi_lock);
+ if (lock) {
+ AS_UNLOCK_WRITE(oid2asi_lock);
+ }
}
}
@@ -297,18 +320,18 @@ attr_syntax_add_by_oid(const char *oid, struct asyntaxinfo *a, int lock)
* be returned by calling to attr_syntax_return().
*/
struct asyntaxinfo *
-attr_syntax_get_by_name(const char *name)
+attr_syntax_get_by_name(const char *name, PRUint32 schema_flags)
{
- return attr_syntax_get_by_name_locking_optional(name, PR_TRUE);
+ return attr_syntax_get_by_name_locking_optional(name, PR_TRUE, schema_flags);
}
struct asyntaxinfo *
attr_syntax_get_by_name_with_default(const char *name)
{
struct asyntaxinfo *asi = NULL;
- asi = attr_syntax_get_by_name_locking_optional(name, PR_TRUE);
+ asi = attr_syntax_get_by_name_locking_optional(name, PR_TRUE, 0);
if (asi == NULL)
- asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX);
+ asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX, 0);
if ( asi == NULL )
asi = default_asi;
return asi;
@@ -323,15 +346,30 @@ struct asyntaxinfo *asi = NULL;
* same use_lock parameter.
*/
struct asyntaxinfo *
-attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock)
+attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock, PRUint32 schema_flags)
{
struct asyntaxinfo *asi = 0;
- if (name2asi)
+ PLHashTable *ht = name2asi;
+ int using_tmp_ht = 0;
+
+ if (schema_flags & DSE_SCHEMA_LOCKED){
+ ht = name2asi_tmp;
+ using_tmp_ht = 1;
+ use_lock = 0;
+ }
+ if (ht)
{
if ( use_lock ) {
AS_LOCK_READ(name2asi_lock);
}
- asi = (struct asyntaxinfo *)PL_HashTableLookup_const(name2asi, name);
+ if(!using_tmp_ht){
+ /*
+ * The name2asi pointer could have been rewritten by the schema_reload task
+ * while waiting on the lock, so grab it again.
+ */
+ ht = name2asi;
+ }
+ asi = (struct asyntaxinfo *)PL_HashTableLookup_const(ht, name);
if ( NULL != asi ) {
PR_AtomicIncrement( &asi->asi_refcnt );
}
@@ -340,7 +378,7 @@ attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock)
}
}
if (!asi) /* given name may be an OID */
- asi = attr_syntax_get_by_oid_locking_optional(name, use_lock);
+ asi = attr_syntax_get_by_oid_locking_optional(name, use_lock, schema_flags);
return asi;
}
@@ -403,26 +441,37 @@ attr_syntax_return_locking_optional(struct asyntaxinfo *asi, PRBool use_lock)
* to worry about resource contention.
*/
static void
-attr_syntax_add_by_name(struct asyntaxinfo *a, int lock)
+attr_syntax_add_by_name(struct asyntaxinfo *a, PRUint32 schema_flags, int lock)
{
if (0 != attr_syntax_init()) return;
- if (lock) {
- AS_LOCK_WRITE(name2asi_lock);
- }
+ if (schema_flags & DSE_SCHEMA_LOCKED ){
+ PL_HashTableAdd(name2asi_tmp, a->asi_name, a);
+ if ( a->asi_aliases != NULL ) {
+ int i;
+
+ for ( i = 0; a->asi_aliases[i] != NULL; ++i ) {
+ PL_HashTableAdd(name2asi_tmp, a->asi_aliases[i], a);
+ }
+ }
+ } else {
+ if (lock) {
+ AS_LOCK_WRITE(name2asi_lock);
+ }
- PL_HashTableAdd(name2asi, a->asi_name, a);
- if ( a->asi_aliases != NULL ) {
- int i;
+ PL_HashTableAdd(name2asi, a->asi_name, a);
+ if ( a->asi_aliases != NULL ) {
+ int i;
- for ( i = 0; a->asi_aliases[i] != NULL; ++i ) {
- PL_HashTableAdd(name2asi, a->asi_aliases[i], a);
+ for ( i = 0; a->asi_aliases[i] != NULL; ++i ) {
+ PL_HashTableAdd(name2asi, a->asi_aliases[i], a);
+ }
+ }
+ if (lock) {
+ AS_UNLOCK_WRITE(name2asi_lock);
}
}
- if (lock) {
- AS_UNLOCK_WRITE(name2asi_lock);
- }
}
@@ -431,7 +480,7 @@ attr_syntax_add_by_name(struct asyntaxinfo *a, int lock)
* and oids.
*/
void
-attr_syntax_delete( struct asyntaxinfo *asi )
+attr_syntax_delete( struct asyntaxinfo *asi, PRUint32 schema_flags )
{
PR_ASSERT( asi );
@@ -439,7 +488,7 @@ attr_syntax_delete( struct asyntaxinfo *asi )
AS_LOCK_WRITE(oid2asi_lock);
AS_LOCK_WRITE(name2asi_lock);
- attr_syntax_delete_no_lock( asi, PR_TRUE );
+ attr_syntax_delete_no_lock( asi, PR_TRUE, schema_flags );
AS_UNLOCK_WRITE(name2asi_lock);
AS_UNLOCK_WRITE(oid2asi_lock);
@@ -453,19 +502,34 @@ attr_syntax_delete( struct asyntaxinfo *asi )
*/
static void
attr_syntax_delete_no_lock( struct asyntaxinfo *asi,
- PRBool remove_from_oidtable )
+ PRBool remove_from_oidtable, PRUint32 schema_flags )
{
- int i;
+ PLHashTable *ht = NULL;
+ int using_tmp_ht = 0;
+ int i;
+ if (schema_flags & DSE_SCHEMA_LOCKED){
+ using_tmp_ht = 1;
+ }
if (oid2asi && remove_from_oidtable ) {
- PL_HashTableRemove(oid2asi, asi->asi_oid);
+ if (using_tmp_ht){
+ ht = oid2asi_tmp;
+ } else {
+ ht = oid2asi;
+ }
+ PL_HashTableRemove(ht, asi->asi_oid);
}
if(name2asi) {
- PL_HashTableRemove(name2asi, asi->asi_name);
+ if (using_tmp_ht){
+ ht = name2asi_tmp;
+ } else {
+ ht = name2asi;
+ }
+ PL_HashTableRemove(ht, asi->asi_name);
if ( asi->asi_aliases != NULL ) {
for ( i = 0; asi->asi_aliases[i] != NULL; ++i ) {
- PL_HashTableRemove(name2asi, asi->asi_aliases[i]);
+ PL_HashTableRemove(ht, asi->asi_aliases[i]);
}
}
if ( asi->asi_refcnt > 0 ) {
@@ -494,7 +558,7 @@ slapi_attr_syntax_normalize( const char *s )
struct asyntaxinfo *asi = NULL;
char *r = NULL;
- if((asi=attr_syntax_get_by_name(s)) != NULL ) {
+ if((asi=attr_syntax_get_by_name(s, 0)) != NULL ) {
r = slapi_ch_strdup(asi->asi_name);
attr_syntax_return( asi );
}
@@ -518,7 +582,7 @@ slapi_attr_syntax_normalize_ext( char *s, int flags )
struct asyntaxinfo *asi = NULL;
char *r = NULL;
- if((asi=attr_syntax_get_by_name(s)) != NULL ) {
+ if((asi=attr_syntax_get_by_name(s, flags)) != NULL ) {
r = slapi_ch_strdup(asi->asi_name);
attr_syntax_return( asi );
}
@@ -538,7 +602,8 @@ attr_syntax_exists(const char *attr_name)
{
struct asyntaxinfo *asi;
- asi = attr_syntax_get_by_name(attr_name);
+
+ asi = attr_syntax_get_by_name(attr_name, 0);
attr_syntax_return( asi );
if ( asi != NULL )
@@ -707,13 +772,13 @@ attr_syntax_get_plugin_by_name_with_default( const char *type )
/*
* first we look for this attribute type explictly
*/
- if ( (asi = attr_syntax_get_by_name(type)) == NULL ) {
+ if ( (asi = attr_syntax_get_by_name(type, 0)) == NULL ) {
/*
* no syntax for this type... return Octet String
* syntax. we accomplish this by looking up a well known
* attribute type that has that syntax.
*/
- asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX);
+ asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX, 0);
if (asi == NULL)
asi = default_asi;
}
@@ -750,14 +815,13 @@ attr_syntax_dup( struct asyntaxinfo *a )
return( newas );
}
-
/*
* Add a new attribute type to the schema.
*
* Returns an LDAP error code (LDAP_SUCCESS if all goes well).
*/
int
-attr_syntax_add( struct asyntaxinfo *asip )
+attr_syntax_add( struct asyntaxinfo *asip, PRUint32 schema_flags )
{
int i, rc = LDAP_SUCCESS;
int nolock = asip->asi_flags & SLAPI_ATTR_FLAG_NOLOCKING;
@@ -769,7 +833,7 @@ attr_syntax_add( struct asyntaxinfo *asip )
/* make sure the oid is unique */
if ( NULL != ( oldas_from_oid = attr_syntax_get_by_oid_locking_optional(
- asip->asi_oid, !nolock))) {
+ asip->asi_oid, !nolock, schema_flags))) {
if ( 0 == (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE)) {
/* failure - OID is in use; no override flag */
rc = LDAP_TYPE_OR_VALUE_EXISTS;
@@ -781,7 +845,7 @@ attr_syntax_add( struct asyntaxinfo *asip )
* the primary name and OID point to the same schema definition.
*/
if ( NULL != ( oldas_from_name = attr_syntax_get_by_name_locking_optional(
- asip->asi_name, !nolock))) {
+ asip->asi_name, !nolock, schema_flags))) {
if ( 0 == (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE)
|| ( oldas_from_oid != oldas_from_name )) {
/* failure; no override flag OR OID and name don't match */
@@ -789,7 +853,7 @@ attr_syntax_add( struct asyntaxinfo *asip )
goto cleanup_and_return;
}
/* Flag for deletion. We are going to override this attr */
- attr_syntax_delete(oldas_from_name);
+ attr_syntax_delete(oldas_from_name, schema_flags);
} else if ( NULL != oldas_from_oid ) {
/* failure - OID is in use but name does not exist */
rc = LDAP_TYPE_OR_VALUE_EXISTS;
@@ -803,11 +867,11 @@ attr_syntax_add( struct asyntaxinfo *asip )
if ( NULL != ( tmpasi =
attr_syntax_get_by_name_locking_optional(
- asip->asi_aliases[i], !nolock))) {
+ asip->asi_aliases[i], !nolock, schema_flags))) {
if (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE) {
/* Flag for tmpasi for deletion. It will be free'd
* when attr_syntax_return is called. */
- attr_syntax_delete(tmpasi);
+ attr_syntax_delete(tmpasi, schema_flags);
} else {
/* failure - one of the aliases is already in use */
rc = LDAP_TYPE_OR_VALUE_EXISTS;
@@ -826,8 +890,8 @@ attr_syntax_add( struct asyntaxinfo *asip )
/* ditto for the override one */
asip->asi_flags &= ~SLAPI_ATTR_FLAG_OVERRIDE;
- attr_syntax_add_by_oid( asip->asi_oid, asip, !nolock);
- attr_syntax_add_by_name( asip, !nolock);
+ attr_syntax_add_by_oid( asip->asi_oid, asip, schema_flags, !nolock);
+ attr_syntax_add_by_name( asip, schema_flags, !nolock);
cleanup_and_return:
attr_syntax_return_locking_optional( oldas_from_oid, !nolock );
@@ -1000,7 +1064,7 @@ slapi_attr_type2plugin( const char *type, void **pi )
int
slapi_attr_get_oid( const Slapi_Attr *a, char **oid )
{
- struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type);
+ struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type, 0);
if (asi) {
*oid = asi->asi_oid;
attr_syntax_return(asi);
@@ -1016,7 +1080,7 @@ slapi_attr_get_oid( const Slapi_Attr *a, char **oid )
int
slapi_attr_get_oid_copy( const Slapi_Attr *a, char **oidp )
{
- struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type);
+ struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type, 0);
if (asi) {
*oidp = slapi_ch_strdup( asi->asi_oid );
attr_syntax_return(asi);
@@ -1073,7 +1137,7 @@ slapi_attr_is_dn_syntax_type(char *type)
int dn_syntax = 0; /* not DN, by default */
struct asyntaxinfo * asi;
- asi = attr_syntax_get_by_name(type);
+ asi = attr_syntax_get_by_name(type, 0);
if (asi && asi->asi_plugin) { /* If not set, there is no way to get the info */
if ((syntaxoid = asi->asi_plugin->plg_syntax_oid)) {
@@ -1249,7 +1313,7 @@ attr_syntax_delete_if_not_flagged(struct asyntaxinfo *asip, void *arg)
PR_ASSERT( fi != NULL );
if ( 0 == ( asip->asi_flags & fi->asef_flag )) {
- attr_syntax_delete_no_lock( asip, PR_FALSE );
+ attr_syntax_delete_no_lock( asip, PR_FALSE, 0 );
return ATTR_SYNTAX_ENUM_REMOVE;
} else {
return ATTR_SYNTAX_ENUM_NEXT;
@@ -1265,7 +1329,7 @@ attr_syntax_force_to_delete(struct asyntaxinfo *asip, void *arg)
fi = (struct attr_syntax_enum_flaginfo *)arg;
PR_ASSERT( fi != NULL );
- attr_syntax_delete_no_lock( asip, PR_FALSE );
+ attr_syntax_delete_no_lock( asip, PR_FALSE, 0 );
return ATTR_SYNTAX_ENUM_REMOVE;
}
@@ -1330,6 +1394,7 @@ attr_syntax_delete_all_for_schemareload(unsigned long flag)
#define ATTR_DEFAULT_SYNTAX_OID "1.1"
#define ATTR_DEFAULT_SYNTAX "defaultdirstringsyntax"
+
static int
attr_syntax_init(void)
{
@@ -1339,8 +1404,8 @@ attr_syntax_init(void)
if (!oid2asi)
{
oid2asi = PL_NewHashTable(2047, hashNocaseString,
- hashNocaseCompare,
- PL_CompareValues, 0, 0);
+ hashNocaseCompare,
+ PL_CompareValues, 0, 0);
if ( asi_locking && NULL == ( oid2asi_lock = slapi_new_rwlock())) {
if(oid2asi) PL_HashTableDestroy(oid2asi);
oid2asi = NULL;
@@ -1351,11 +1416,19 @@ attr_syntax_init(void)
}
}
+ if (!oid2asi_tmp)
+ {
+ /* temporary hash table for schema reload */
+ oid2asi_tmp = PL_NewHashTable(2047, hashNocaseString,
+ hashNocaseCompare,
+ PL_CompareValues, 0, 0);
+ }
+
if (!name2asi)
{
name2asi = PL_NewHashTable(2047, hashNocaseString,
- hashNocaseCompare,
- PL_CompareValues, 0, 0);
+ hashNocaseCompare,
+ PL_CompareValues, 0, 0);
if ( asi_locking && NULL == ( name2asi_lock = slapi_new_rwlock())) {
if(name2asi) PL_HashTableDestroy(name2asi);
name2asi = NULL;
@@ -1367,10 +1440,18 @@ attr_syntax_init(void)
/* add a default syntax plugin as fallback, required during startup
*/
attr_syntax_create_default( ATTR_DEFAULT_SYNTAX,
- ATTR_DEFAULT_SYNTAX_OID,
- DIRSTRING_SYNTAX_OID,
- SLAPI_ATTR_FLAG_NOUSERMOD| SLAPI_ATTR_FLAG_NOEXPOSE);
+ ATTR_DEFAULT_SYNTAX_OID,
+ DIRSTRING_SYNTAX_OID,
+ SLAPI_ATTR_FLAG_NOUSERMOD| SLAPI_ATTR_FLAG_NOEXPOSE);
}
+ if (!name2asi_tmp)
+ {
+ /* temporary hash table for schema reload */
+ name2asi_tmp = PL_NewHashTable(2047, hashNocaseString,
+ hashNocaseCompare,
+ PL_CompareValues, 0, 0);
+ }
+
return 0;
}
@@ -1440,7 +1521,7 @@ slapi_add_internal_attr_syntax( const char *name, const char *oid,
&asip );
if ( rc == LDAP_SUCCESS ) {
- rc = attr_syntax_add( asip );
+ rc = attr_syntax_add( asip, 0 );
if ( rc == LDAP_SUCCESS ) {
if (attr_syntax_internal_asi_add_ht(asip)) {
slapi_log_error(SLAPI_LOG_FATAL,
@@ -1448,6 +1529,8 @@ slapi_add_internal_attr_syntax( const char *name, const char *oid,
"Failed to stash internal asyntaxinfo: %s.\n",
asip->asi_name);
}
+ } else {
+ attr_syntax_free(asip);
}
}
@@ -1467,7 +1550,7 @@ attr_syntax_internal_asi_add(struct asyntaxinfo *asip, void *arg)
/* Copy is needed since when reloading the schema,
* existing syntax info is cleaned up. */
asip_copy = attr_syntax_dup(asip);
- rc = attr_syntax_add(asip_copy);
+ rc = attr_syntax_add(asip_copy, 0);
if (LDAP_SUCCESS != rc) {
attr_syntax_free(asip_copy);
}
@@ -1487,3 +1570,25 @@ slapi_reload_internal_attr_syntax()
attr_syntax_enumerate_attrs_ext(internalasi, attr_syntax_internal_asi_add, NULL);
return rc;
}
+
+/*
+ * schema reload - now that we have loaded the schema into temporary
+ * hash tables, swap out the old for the new.
+ */
+void
+attr_syntax_swap_ht()
+{
+ /* Remove the old hash tables */
+ PL_HashTableDestroy(name2asi);
+ PL_HashTableDestroy(oid2asi);
+
+ /*
+ * Swap the hash table/linked list pointers, and set the
+ * temporary pointers to NULL
+ */
+ name2asi = name2asi_tmp;
+ name2asi_tmp = NULL;
+ oid2asi = oid2asi_tmp;
+ oid2asi_tmp = NULL;
+}
+
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index eb890b0..9e13d86 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -86,7 +86,7 @@ int op_shared_is_allowed_attr (const char *attr_name, int replicated_op)
* check to see if attribute is marked as one clients can't modify
*/
- asi = attr_syntax_get_by_name( attr_name );
+ asi = attr_syntax_get_by_name( attr_name, 0 );
if ( NULL != asi &&
0 != ( asi->asi_flags & SLAPI_ATTR_FLAG_NOUSERMOD )) {
/* this attribute is not allowed */
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index d854d0a..7fde382 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -118,7 +118,7 @@ void attr_syntax_write_lock(void);
void attr_syntax_unlock_read(void);
void attr_syntax_unlock_write(void);
int attr_syntax_exists (const char *attr_name);
-void attr_syntax_delete ( struct asyntaxinfo *asip );
+void attr_syntax_delete ( struct asyntaxinfo *asip, PRUint32 schema_flags );
#define SLAPI_SYNTAXLENGTH_NONE (-1) /* for syntaxlength parameter */
int attr_syntax_create( const char *attr_oid, char *const*attr_names,
int num_names, const char *attr_desc, const char *attr_superior,
@@ -127,16 +127,19 @@ int attr_syntax_create( const char *attr_oid, char *const*attr_names,
const char *attr_syntax, int syntaxlength, unsigned long flags,
struct asyntaxinfo **asip );
void attr_syntax_free( struct asyntaxinfo *a );
-int attr_syntax_add( struct asyntaxinfo *asip );
+int attr_syntax_add( struct asyntaxinfo *asip, PRUint32 schema_flags );
char *attr_syntax_normalize_no_lookup( const char *s );
char *attr_syntax_normalize_no_lookup_ext( char *s, int flags );
void attr_syntax_enumerate_attrs(AttrEnumFunc aef, void *arg, PRBool writelock);
void attr_syntax_all_clear_flag( unsigned long flag );
void attr_syntax_delete_all_not_flagged( unsigned long flag );
-struct asyntaxinfo *attr_syntax_get_by_oid ( const char *oid );
-struct asyntaxinfo *attr_syntax_get_by_name ( const char *name );
+struct asyntaxinfo *attr_syntax_get_by_oid ( const char *oid, PRUint32 schema_flags );
+struct asyntaxinfo *attr_syntax_get_by_name ( const char *name, PRUint32 schema_flags );
struct asyntaxinfo *attr_syntax_get_by_name_with_default ( const char *name );
-struct asyntaxinfo *attr_syntax_get_by_name_locking_optional ( const char *name, PRBool use_lock );
+struct asyntaxinfo *attr_syntax_get_by_name_locking_optional ( const char *name, PRBool use_lock, PRUint32 schema_flags );
+struct asyntaxinfo *attr_syntax_get_global_at();
+struct asyntaxinfo *attr_syntax_find(struct asyntaxinfo *at1, struct asyntaxinfo *at2);
+void attr_syntax_swap_ht(void);
/*
* Call attr_syntax_return() when you are done using a value returned
* by attr_syntax_get_by_oid() or attr_syntax_get_by_name().
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 98d5e17..5399d00 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -154,6 +154,8 @@ static int schema_strcmp( const char *s1, const char *s2 );
static int schema_strcmp_array( char **sa1, char **sa2,
const char *ignorestr );
static PRBool schema_type_is_interesting( const char *type );
+static void reload_schemafile_lock(void);
+static void reload_schemafile_unlock(void);
static void schema_create_errormsg( char *errorbuf, size_t errorbufsize,
const char *prefix, const char *name, const char *fmt, ... )
#ifdef __GNUC__
@@ -2138,7 +2140,7 @@ schema_delete_attributes ( Slapi_Entry *entryBefore, LDAPMod *mod,
sscanf (attr_ldif, "%s name %s syntax %s",
psbAttrOid->buffer, psbAttrName->buffer, psbAttrSyntax->buffer);
- if ((a = attr_syntax_get_by_name ( psbAttrName->buffer)) != NULL ) {
+ if ((a = attr_syntax_get_by_name ( psbAttrName->buffer, 0 )) != NULL ) {
/* only modify attrs which were user defined */
if (a->asi_flags & SLAPI_ATTR_FLAG_STD_ATTR) {
schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
@@ -2190,7 +2192,7 @@ schema_delete_attributes ( Slapi_Entry *entryBefore, LDAPMod *mod,
}
/* Delete it. */
- attr_syntax_delete( a );
+ attr_syntax_delete( a, 0 );
attr_syntax_return( a );
}
else {
@@ -2313,7 +2315,7 @@ add_oc_internal(struct objclass *pnew_oc, char *errorbuf, size_t errorbufsize,
}
/* check to see if the oid is already in use by an attribute */
- if (!rc && (pasyntaxinfo = attr_syntax_get_by_oid(pnew_oc->oc_oid))) {
+ if (!rc && (pasyntaxinfo = attr_syntax_get_by_oid(pnew_oc->oc_oid, flags))) {
schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_oc,
pnew_oc->oc_name,
"The OID \"%s\" is also used by the attribute type \"%s\"",
@@ -2432,7 +2434,7 @@ schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
* handle the various cases.
*/
if ( NULL == ( oldasip =
- attr_syntax_get_by_oid( newasip->asi_oid ))) {
+ attr_syntax_get_by_oid( newasip->asi_oid, 0 ))) {
/* new attribute type */
LDAPDebug( LDAP_DEBUG_TRACE, "schema_replace_attributes:"
" new type %s (OID %s)\n",
@@ -2450,14 +2452,14 @@ schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
" replacing type %s (OID %s)\n",
newasip->asi_name, newasip->asi_oid, 0 );
/* flag for deletion */
- attr_syntax_delete( oldasip );
+ attr_syntax_delete( oldasip, 0 );
}
attr_syntax_return( oldasip );
}
if ( NULL != newasip ) { /* add new or replacement definition */
- rc = attr_syntax_add( newasip );
+ rc = attr_syntax_add( newasip, 0 );
if ( LDAP_SUCCESS != rc ) {
schema_create_errormsg( errorbuf, errorbufsize,
schema_errprefix_at, newasip->asi_name,
@@ -3368,7 +3370,7 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
if (!status && (NULL != pSuperior)) {
struct asyntaxinfo *asi_parent;
- asi_parent = attr_syntax_get_by_name(pSuperior);
+ asi_parent = attr_syntax_get_by_name(pSuperior, schema_flags);
/* if we find no match then server won't start or add the attribute type */
if (asi_parent == NULL) {
LDAPDebug (LDAP_DEBUG_PARSE,
@@ -3480,7 +3482,7 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
struct asyntaxinfo *tmpasi;
if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
- ( NULL != ( tmpasi = attr_syntax_get_by_oid(pOid)))) {
+ ( NULL != ( tmpasi = attr_syntax_get_by_oid(pOid, schema_flags)))) {
schema_create_errormsg( errorbuf, errorbufsize,
schema_errprefix_at, first_attr_name,
"Could not be added because the OID \"%s\" is already in use",
@@ -3503,7 +3505,7 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
if ( NULL != asipp ) {
*asipp = tmpasip; /* just return it */
} else { /* add the new attribute to the global store */
- status = attr_syntax_add( tmpasip );
+ status = attr_syntax_add( tmpasip, schema_flags );
if ( LDAP_SUCCESS != status ) {
if ( 0 != (flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
LDAP_TYPE_OR_VALUE_EXISTS == status ) {
@@ -4320,6 +4322,59 @@ get_tagged_oid( const char *tag, const char **inputp,
return( oid );
}
+/*
+ * Reload the schema files
+ *
+ * This is only called from the schema_reload task. The flag DSE_SCHEMA_LOCKED
+ * is also only set been called from this function. To not interrupt clients
+ * we will rebuild the schema in separate hash tables, and then swap the
+ * hash tables once the schema is completely reloaded. We use the DSE_SCHEMA_LOCKED
+ * flag to tell the attribute syntax functions to use the temporary hashtables.
+ */
+int
+slapi_reload_schema_files(char *schemadir)
+{
+ int rc = LDAP_SUCCESS;
+ struct dse *my_pschemadse = NULL;
+ /* get be to lock */
+ Slapi_Backend *be = slapi_be_select_by_instance_name( DSE_SCHEMA );
+
+ if (NULL == be)
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
+ "schema file reload failed\n" );
+ return LDAP_LOCAL_ERROR;
+ }
+ slapi_be_Wlock(be); /* be lock must be outer of schemafile lock */
+ reload_schemafile_lock();
+ oc_delete_all_nolock();
+ rc = init_schema_dse_ext(schemadir, be, &my_pschemadse,
+ DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_LOCKED);
+ if (rc) {
+ /*
+ * The schema has been reloaded into the temporary hash tables.
+ * Take the write lock, wipe out the existing hash tables, and
+ * swap in the new ones.
+ */
+ attr_syntax_write_lock();
+ attr_syntax_delete_all_for_schemareload(SLAPI_ATTR_FLAG_KEEP);
+ attr_syntax_swap_ht();
+ attr_syntax_unlock_write();
+ slapi_reload_internal_attr_syntax();
+
+ dse_destroy(pschemadse);
+ pschemadse = my_pschemadse;
+ reload_schemafile_unlock();
+ slapi_be_Unlock(be);
+ return LDAP_SUCCESS;
+ } else {
+ reload_schemafile_unlock();
+ slapi_be_Unlock(be);
+ slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
+ "schema file reload failed\n" );
+ return LDAP_LOCAL_ERROR;
+ }
+}
/*
* sprintf to `outp' the contents of `tag' followed by `oid' followed by a
@@ -4833,49 +4888,6 @@ slapi_validate_schema_files(char *schemadir)
}
/*
- * API to reload the schema files.
- * Rule: this function is called when slapi_validate_schema_files is passed.
- * Schema checking is skipped in this function.
- */
-int
-slapi_reload_schema_files(char *schemadir)
-{
- int rc = LDAP_SUCCESS;
- struct dse *my_pschemadse = NULL;
- /* get be to lock */
- Slapi_Backend *be = slapi_be_select_by_instance_name( DSE_SCHEMA );
-
- if (NULL == be)
- {
- slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
- "schema file reload failed\n" );
- return LDAP_LOCAL_ERROR;
- }
- slapi_be_Wlock(be); /* be lock must be outer of schemafile lock */
- reload_schemafile_lock();
- /* Exclude attr_syntax not to grab from the hash table while cleaning up */
- attr_syntax_write_lock();
- attr_syntax_delete_all_for_schemareload(SLAPI_ATTR_FLAG_KEEP);
- oc_delete_all_nolock();
- attr_syntax_unlock_write();
- rc = init_schema_dse_ext(schemadir, be, &my_pschemadse,
- DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_LOCKED);
- if (rc) {
- dse_destroy(pschemadse);
- pschemadse = my_pschemadse;
- reload_schemafile_unlock();
- slapi_be_Unlock(be);
- return LDAP_SUCCESS;
- } else {
- reload_schemafile_unlock();
- slapi_be_Unlock(be);
- slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
- "schema file reload failed\n" );
- return LDAP_LOCAL_ERROR;
- }
-}
-
-/*
* slapi_schema_list_objectclass_attributes:
* Return the list of attributes belonging to the objectclass
*
9 years, 3 months