Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
List overview
Download
389-commits
January 2015
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
389-commits@lists.fedoraproject.org
4 participants
91 discussions
Start a n
N
ew thread
Branch '389-ds-base-1.3.2' - ldap/schema ldap/servers
by Mark Reynolds
12 Jan '15
12 Jan '15
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
1
0
0
0
Branch '389-ds-base-1.3.3' - ldap/schema ldap/servers
by Mark Reynolds
12 Jan '15
12 Jan '15
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
1
0
0
0
ldap/schema ldap/servers
by Mark Reynolds
12 Jan '15
12 Jan '15
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
1
0
0
0
Branch '389-ds-base-1.2.11' - ldap/servers
by Noriko Hosoi
09 Jan '15
09 Jan '15
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 ) {
1
0
0
0
Branch '389-ds-base-1.3.1' - ldap/servers
by Noriko Hosoi
09 Jan '15
09 Jan '15
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 ) {
1
0
0
0
Branch '389-ds-base-1.3.2' - ldap/servers
by Noriko Hosoi
09 Jan '15
09 Jan '15
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 ) {
1
0
0
0
Branch '389-ds-base-1.3.3' - ldap/servers
by Noriko Hosoi
09 Jan '15
09 Jan '15
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 ) {
1
0
0
0
ldap/servers
by Noriko Hosoi
09 Jan '15
09 Jan '15
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 ) {
1
0
0
0
Branch '389-ds-base-1.2.11' - ldap/servers
by Mark Reynolds
09 Jan '15
09 Jan '15
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 *
1
0
0
0
Branch '389-ds-base-1.3.1' - ldap/servers
by Mark Reynolds
09 Jan '15
09 Jan '15
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 *
1
0
0
0
← Newer
1
2
3
4
5
6
7
8
9
10
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
Results per page:
10
25
50
100
200