ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5_tot_protocol.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
New commits:
commit e7f7e9127717c1d432b10493b626fed334cc595f
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Mar 7 14:07:01 2014 -0500
Ticket 47729 - Directory Server crashes if shutdown during a replication initialization
Bug Description: When a shutdown was detected we marked that the total update was done
prematurely(prp->stopped). This allowed the replication plugin to close
while the total update was still in progress. Other plugins continued to
be shutdown (e.g. ldbm database), while the total update was using shared
resources - which lead to a crash.
Fix Description: Only mark the total update protocol as stopped, after it is finished using
shared resources.
https://fedorahosted.org/389/ticket/47729
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/plugins/replication/repl5_tot_protocol.c b/ldap/servers/plugins/replication/repl5_tot_protocol.c
index 3895ace..2db5178 100644
--- a/ldap/servers/plugins/replication/repl5_tot_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_tot_protocol.c
@@ -343,7 +343,6 @@ repl5_tot_run(Private_Repl_Protocol *prp)
prp->stopped = 0;
if (prp->terminate)
{
- prp->stopped = 1;
goto done;
}
@@ -365,8 +364,7 @@ repl5_tot_run(Private_Repl_Protocol *prp)
}
else if (prp->terminate)
{
- conn_disconnect(prp->conn);
- prp->stopped = 1;
+ conn_disconnect(prp->conn);
goto done;
}
@@ -661,7 +659,6 @@ int send_entry (Slapi_Entry *e, void *cb_data)
if (prp->terminate)
{
conn_disconnect(prp->conn);
- prp->stopped = 1;
((callback_data*)cb_data)->rc = -1;
return -1;
}
@@ -674,7 +671,6 @@ int send_entry (Slapi_Entry *e, void *cb_data)
if (rc)
{
conn_disconnect(prp->conn);
- prp->stopped = 1;
((callback_data*)cb_data)->rc = -1;
return -1;
}
10 years, 2 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/ssl.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
New commits:
commit 6a24433cd264faa5e78b94bcd11b39d945f38069
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Mar 6 11:07:24 2014 -0500
Ticket 47637 - rsa_null_sha should not be enabled by default
Bug Description: rsa_null_sha is enabled by default, this can allow unencrypted
traffic over a TLS connection.
Fix Description: Disable rsa_null_sha, just like rsa_null_md5, by default.
https://fedorahosted.org/389/ticket/47637
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit 82b12c97afd34ecc8acfe54baaf0f32bd83a7edf)
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 61809aa..bbadf93 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -135,8 +135,8 @@ static cipherstruct _conf_ciphers[] = {
{"SSL3","fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, /* ditto */
{"SSL3","rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
{"SSL3","rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
- {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
- {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
+ {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, /* disabled by default */
+ {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, /* disabled by default */
{"TLS","tls_rsa_export1024_with_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
{"TLS","rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, /* ditto */
{"TLS","tls_rsa_export1024_with_des_cbc_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
@@ -265,7 +265,9 @@ _conf_setallciphers(int active, char ***suplist, char ***unsuplist)
* them to activate it by name. */
for(x = 0; _conf_ciphers[x].name; x++) {
PRBool enabled = active ? PR_TRUE : PR_FALSE;
- if(active && !strcmp(_conf_ciphers[x].name, "rsa_null_md5")) {
+ if(active && (!strcmp(_conf_ciphers[x].name, "rsa_null_md5") ||
+ !strcmp(_conf_ciphers[x].name, "rsa_null_sha")))
+ {
continue;
}
if (enabled) {
@@ -317,7 +319,12 @@ _conf_setciphers(char *ciphers)
slapi_ch_free((void **)&suplist); /* strings inside are static */
return NULL;
}
-/* Enable all the ciphers by default and the following while loop would disable the user disabled ones This is needed becuase we added a new set of ciphers in the table . Right now there is no support for this from the console */
+ /*
+ * Enable all the ciphers by default and the following while loop would
+ * disable the user disabled ones. This is needed because we added a new
+ * set of ciphers in the table. Right now there is no support for this
+ * from the console
+ */
_conf_setallciphers(1, &suplist, NULL);
t = ciphers;
10 years, 2 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/ssl.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
New commits:
commit 58e5152633c9062819cb48e4d3d56e016fe9d429
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Mar 6 11:07:24 2014 -0500
Ticket 47637 - rsa_null_sha should not be enabled by default
Bug Description: rsa_null_sha is enabled by default, this can allow unencrypted
traffic over a TLS connection.
Fix Description: Disable rsa_null_sha, just like rsa_null_md5, by default.
https://fedorahosted.org/389/ticket/47637
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit 82b12c97afd34ecc8acfe54baaf0f32bd83a7edf)
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 61809aa..bbadf93 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -135,8 +135,8 @@ static cipherstruct _conf_ciphers[] = {
{"SSL3","fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, /* ditto */
{"SSL3","rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
{"SSL3","rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
- {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
- {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
+ {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, /* disabled by default */
+ {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, /* disabled by default */
{"TLS","tls_rsa_export1024_with_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
{"TLS","rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, /* ditto */
{"TLS","tls_rsa_export1024_with_des_cbc_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
@@ -265,7 +265,9 @@ _conf_setallciphers(int active, char ***suplist, char ***unsuplist)
* them to activate it by name. */
for(x = 0; _conf_ciphers[x].name; x++) {
PRBool enabled = active ? PR_TRUE : PR_FALSE;
- if(active && !strcmp(_conf_ciphers[x].name, "rsa_null_md5")) {
+ if(active && (!strcmp(_conf_ciphers[x].name, "rsa_null_md5") ||
+ !strcmp(_conf_ciphers[x].name, "rsa_null_sha")))
+ {
continue;
}
if (enabled) {
@@ -317,7 +319,12 @@ _conf_setciphers(char *ciphers)
slapi_ch_free((void **)&suplist); /* strings inside are static */
return NULL;
}
-/* Enable all the ciphers by default and the following while loop would disable the user disabled ones This is needed becuase we added a new set of ciphers in the table . Right now there is no support for this from the console */
+ /*
+ * Enable all the ciphers by default and the following while loop would
+ * disable the user disabled ones. This is needed because we added a new
+ * set of ciphers in the table. Right now there is no support for this
+ * from the console
+ */
_conf_setallciphers(1, &suplist, NULL);
t = ciphers;
10 years, 2 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/ssl.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
New commits:
commit 86fbd5a9f14726dccf3d3d761cdb8fc7960e5a40
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Mar 6 11:07:24 2014 -0500
Ticket 47637 - rsa_null_sha should not be enabled by default
Bug Description: rsa_null_sha is enabled by default, this can allow unencrypted
traffic over a TLS connection.
Fix Description: Disable rsa_null_sha, just like rsa_null_md5, by default.
https://fedorahosted.org/389/ticket/47637
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit 82b12c97afd34ecc8acfe54baaf0f32bd83a7edf)
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 61809aa..bbadf93 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -135,8 +135,8 @@ static cipherstruct _conf_ciphers[] = {
{"SSL3","fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, /* ditto */
{"SSL3","rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
{"SSL3","rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
- {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
- {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
+ {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, /* disabled by default */
+ {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, /* disabled by default */
{"TLS","tls_rsa_export1024_with_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
{"TLS","rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, /* ditto */
{"TLS","tls_rsa_export1024_with_des_cbc_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
@@ -265,7 +265,9 @@ _conf_setallciphers(int active, char ***suplist, char ***unsuplist)
* them to activate it by name. */
for(x = 0; _conf_ciphers[x].name; x++) {
PRBool enabled = active ? PR_TRUE : PR_FALSE;
- if(active && !strcmp(_conf_ciphers[x].name, "rsa_null_md5")) {
+ if(active && (!strcmp(_conf_ciphers[x].name, "rsa_null_md5") ||
+ !strcmp(_conf_ciphers[x].name, "rsa_null_sha")))
+ {
continue;
}
if (enabled) {
@@ -317,7 +319,12 @@ _conf_setciphers(char *ciphers)
slapi_ch_free((void **)&suplist); /* strings inside are static */
return NULL;
}
-/* Enable all the ciphers by default and the following while loop would disable the user disabled ones This is needed becuase we added a new set of ciphers in the table . Right now there is no support for this from the console */
+ /*
+ * Enable all the ciphers by default and the following while loop would
+ * disable the user disabled ones. This is needed because we added a new
+ * set of ciphers in the table. Right now there is no support for this
+ * from the console
+ */
_conf_setallciphers(1, &suplist, NULL);
t = ciphers;
10 years, 2 months
Branch '389-ds-base-1.3.2' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/ssl.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
New commits:
commit 58252929d5bbfa35c148e3941fa00b3e2ab2c208
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Mar 6 11:07:24 2014 -0500
Ticket 47637 - rsa_null_sha should not be enabled by default
Bug Description: rsa_null_sha is enabled by default, this can allow unencrypted
traffic over a TLS connection.
Fix Description: Disable rsa_null_sha, just like rsa_null_md5, by default.
https://fedorahosted.org/389/ticket/47637
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit 82b12c97afd34ecc8acfe54baaf0f32bd83a7edf)
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 61809aa..bbadf93 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -135,8 +135,8 @@ static cipherstruct _conf_ciphers[] = {
{"SSL3","fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, /* ditto */
{"SSL3","rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
{"SSL3","rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
- {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
- {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
+ {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, /* disabled by default */
+ {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, /* disabled by default */
{"TLS","tls_rsa_export1024_with_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
{"TLS","rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, /* ditto */
{"TLS","tls_rsa_export1024_with_des_cbc_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
@@ -265,7 +265,9 @@ _conf_setallciphers(int active, char ***suplist, char ***unsuplist)
* them to activate it by name. */
for(x = 0; _conf_ciphers[x].name; x++) {
PRBool enabled = active ? PR_TRUE : PR_FALSE;
- if(active && !strcmp(_conf_ciphers[x].name, "rsa_null_md5")) {
+ if(active && (!strcmp(_conf_ciphers[x].name, "rsa_null_md5") ||
+ !strcmp(_conf_ciphers[x].name, "rsa_null_sha")))
+ {
continue;
}
if (enabled) {
@@ -317,7 +319,12 @@ _conf_setciphers(char *ciphers)
slapi_ch_free((void **)&suplist); /* strings inside are static */
return NULL;
}
-/* Enable all the ciphers by default and the following while loop would disable the user disabled ones This is needed becuase we added a new set of ciphers in the table . Right now there is no support for this from the console */
+ /*
+ * Enable all the ciphers by default and the following while loop would
+ * disable the user disabled ones. This is needed because we added a new
+ * set of ciphers in the table. Right now there is no support for this
+ * from the console
+ */
_conf_setallciphers(1, &suplist, NULL);
t = ciphers;
10 years, 2 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/ssl.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
New commits:
commit 82b12c97afd34ecc8acfe54baaf0f32bd83a7edf
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Mar 6 11:07:24 2014 -0500
Ticket 47637 - rsa_null_sha should not be enabled by default
Bug Description: rsa_null_sha is enabled by default, this can allow unencrypted
traffic over a TLS connection.
Fix Description: Disable rsa_null_sha, just like rsa_null_md5, by default.
https://fedorahosted.org/389/ticket/47637
Reviewed by: rmeggins(Thanks!)
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 48c3fe9..8dc39d2 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -147,8 +147,8 @@ static cipherstruct _conf_ciphers[] = {
{"SSL3","fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, /* ditto */
{"SSL3","rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
{"SSL3","rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
- {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
- {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
+ {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, /* disabled by default */
+ {"SSL3","rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, /* disabled by default */
{"TLS","tls_rsa_export1024_with_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
{"TLS","rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, /* ditto */
{"TLS","tls_rsa_export1024_with_des_cbc_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
@@ -282,7 +282,9 @@ _conf_setallciphers(int active, char ***suplist, char ***unsuplist)
* them to activate it by name. */
for(x = 0; _conf_ciphers[x].name; x++) {
PRBool enabled = active ? PR_TRUE : PR_FALSE;
- if(active && !strcmp(_conf_ciphers[x].name, "rsa_null_md5")) {
+ if(active && (!strcmp(_conf_ciphers[x].name, "rsa_null_md5") ||
+ !strcmp(_conf_ciphers[x].name, "rsa_null_sha")))
+ {
continue;
}
if (enabled) {
@@ -334,7 +336,12 @@ _conf_setciphers(char *ciphers)
slapi_ch_free((void **)&suplist); /* strings inside are static */
return NULL;
}
-/* Enable all the ciphers by default and the following while loop would disable the user disabled ones This is needed becuase we added a new set of ciphers in the table . Right now there is no support for this from the console */
+ /*
+ * Enable all the ciphers by default and the following while loop would
+ * disable the user disabled ones. This is needed because we added a new
+ * set of ciphers in the table. Right now there is no support for this
+ * from the console
+ */
_conf_setallciphers(1, &suplist, NULL);
t = ciphers;
10 years, 2 months
Branch '389-ds-base-1.2.11' - ldap/schema ldap/servers
by Mark Reynolds
ldap/schema/02common.ldif | 3
ldap/servers/slapd/entry.c | 50 +++++++++++----
ldap/servers/slapd/libglobs.c | 24 ++++++-
ldap/servers/slapd/modify.c | 25 ++++---
ldap/servers/slapd/pblock.c | 6 +
ldap/servers/slapd/proto-slap.h | 1
ldap/servers/slapd/pw.c | 123 ++++++++++++++++++++++++++++++++++++--
ldap/servers/slapd/pw.h | 1
ldap/servers/slapd/slap.h | 3
ldap/servers/slapd/slapi-plugin.h | 32 +++++++++
10 files changed, 236 insertions(+), 32 deletions(-)
New commits:
commit 096d8958a81ee57d3486d8260430cbfab81a0bbc
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Wed Mar 5 15:55:31 2014 -0500
Ticket 417, 458, 47522 - Password Administrator Backport
Description: Backported all the fixes needed to implement the feature.
https://fedorahosted.org/389/ticket/417
https://fedorahosted.org/389/ticket/458
https://fedorahosted.org/389/ticket/47522
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif
index ffec7ce..92feb49 100644
--- a/ldap/schema/02common.ldif
+++ b/ldap/schema/02common.ldif
@@ -95,6 +95,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2081 NAME ( 'passwordMaxRepeats' 'pwdMax
attributeTypes: ( 2.16.840.1.113730.3.1.2082 NAME ( 'passwordMinCategories' 'pwdMinCategories' ) DESC 'Netscape defined password policy 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.2083 NAME ( 'passwordMinTokenLength' 'pwdMinTokenLength' ) DESC 'Netscape defined password policy 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.2140 NAME ( 'passwordTrackUpdateTime' ) DESC 'Netscape defined password policy 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.2153 NAME ( 'passwordAdminDN' 'pwdAdminDN' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.198 NAME 'memberURL' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.199 NAME 'memberCertificateDescription' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.207 NAME 'vlvBase' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape Directory Server' )
@@ -164,7 +165,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.7 NAME 'nsLicenseUser' DESC 'Netscape def
objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' DESC 'LDAP changelog objectclass' SUP top MUST ( targetdn $ changeTime $ changenumber $ changeType ) MAY ( changes $ newrdn $ deleteoldrdn $ newsuperior ) X-ORIGIN 'Changelog Internet Draft' )
objectClasses: ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'LDAP referrals objectclass' SUP top MAY ( ref ) X-ORIGIN 'LDAPv3 referrals Internet Draft' )
objectClasses: ( 2.16.840.1.113730.3.2.12 NAME 'passwordObject' DESC 'Netscape defined password policy objectclass' SUP top MAY ( pwdpolicysubentry $ passwordExpirationTime $ passwordExpWarned $ passwordRetryCount $ retryCountResetTime $ accountUnlockTime $ passwordHistory $ passwordAllowChangeTime $ passwordGraceUserTime ) X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime ) X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordAdminDN $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.30 NAME 'glue' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.32 NAME 'netscapeMachineData' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.38 NAME 'vlvSearch' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ vlvBase $ vlvScope $ vlvFilter ) MAY ( multiLineDescription ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 8a5df7e..9064e41 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -2607,46 +2607,70 @@ slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *value)
char **
slapi_entry_attr_get_charray( const Slapi_Entry* e, const char *type)
{
- char **parray = NULL;
- Slapi_Attr* attr = NULL;
+ int ignore;
+ return slapi_entry_attr_get_charray_ext(e, type, &ignore);
+}
+
+/*
+ * The extension also gathers the number of values.
+ * The caller must free with slapi_ch_array_free
+ */
+char **
+slapi_entry_attr_get_charray_ext( const Slapi_Entry* e, const char *type, int *numVals)
+{
+ char **parray = NULL;
+ Slapi_Attr* attr = NULL;
+ int count = 0;
+
+ if(numVals == NULL){
+ return NULL;
+ }
+
slapi_entry_attr_find(e, type, &attr);
- if(attr!=NULL)
- {
+ if(attr!=NULL){
int hint;
Slapi_Value *v = NULL;
+
for (hint = slapi_attr_first_value(attr, &v);
hint != -1;
hint = slapi_attr_next_value(attr, hint, &v))
{
const struct berval *bvp = slapi_value_get_berval(v);
char *p = slapi_ch_malloc(bvp->bv_len + 1);
+
memcpy(p, bvp->bv_val, bvp->bv_len);
p[bvp->bv_len]= '\0';
charray_add(&parray, p);
+ count++;
}
}
- return parray;
+ *numVals = count;
+
+ return parray;
}
char *
slapi_entry_attr_get_charptr( const Slapi_Entry* e, const char *type)
{
- char *p= NULL;
- Slapi_Attr* attr;
+ char *p= NULL;
+ Slapi_Attr* attr;
+
slapi_entry_attr_find(e, type, &attr);
if(attr!=NULL)
{
Slapi_Value *v;
- const struct berval *bvp;
+ const struct berval *bvp;
+
slapi_valueset_first_value( &attr->a_present_values, &v);
- bvp = slapi_value_get_berval(v);
- p= slapi_ch_malloc(bvp->bv_len + 1);
- memcpy(p, bvp->bv_val, bvp->bv_len);
- p[bvp->bv_len]= '\0';
+ bvp = slapi_value_get_berval(v);
+ p= slapi_ch_malloc(bvp->bv_len + 1);
+ memcpy(p, bvp->bv_val, bvp->bv_len);
+ p[bvp->bv_len]= '\0';
}
- return p;
+ return p;
}
+
int
slapi_entry_attr_get_int( const Slapi_Entry* e, const char *type)
{
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 8103133..b7dadcd 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -248,6 +248,9 @@ static struct config_get_and_set {
{CONFIG_PWPOLICY_LOCAL_ATTRIBUTE, config_set_pwpolicy_local,
NULL, 0,
(void**)&global_slapdFrontendConfig.pwpolicy_local, CONFIG_ON_OFF, NULL},
+ {CONFIG_PW_ADMIN_DN_ATTRIBUTE, config_set_pw_admin_dn,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.pw_policy.pw_admin, CONFIG_STRING, NULL},
{CONFIG_AUDITLOG_MAXLOGDISKSPACE_ATTRIBUTE, NULL,
log_set_maxdiskspace, SLAPD_AUDIT_LOG,
(void**)&global_slapdFrontendConfig.auditlog_maxdiskspace, CONFIG_INT, NULL},
@@ -685,8 +688,7 @@ static struct config_get_and_set {
{CONFIG_DISK_THRESHOLD, config_set_disk_threshold,
NULL, 0,
(void**)&global_slapdFrontendConfig.disk_threshold,
- CONFIG_LONG_LONG, (ConfigGetFunc)config_get_disk_threshold,
- DEFAULT_DISK_THRESHOLD},
+ CONFIG_LONG_LONG, (ConfigGetFunc)config_get_disk_threshold},
{CONFIG_DISK_GRACE_PERIOD, config_set_disk_grace_period,
NULL, 0,
(void**)&global_slapdFrontendConfig.disk_grace_period,
@@ -1122,9 +1124,11 @@ FrontendConfig_init () {
cfg->disk_grace_period = 60; /* 1 hour */
cfg->disk_logging_critical = LDAP_OFF;
cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE;
-
+ cfg->pw_policy.pw_admin = NULL;
+ cfg->pw_policy.pw_admin_user = NULL;
cfg->listen_backlog_size = DAEMON_LISTEN_SIZE;
cfg->ignore_time_skew = LDAP_OFF;
+
#if defined(LINUX)
cfg->malloc_mxfast = DEFAULT_MALLOC_UNSET;
cfg->malloc_trim_threshold = DEFAULT_MALLOC_UNSET;
@@ -2837,6 +2841,20 @@ config_set_dn_validate_strict( const char *attrname, char *value, char *errorbuf
}
int
+config_set_pw_admin_dn( const char *attrname, char *value, char *errorbuf, int apply ) {
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ if ( apply ) {
+ CFG_LOCK_WRITE(slapdFrontendConfig);
+ slapi_sdn_free(&slapdFrontendConfig->pw_policy.pw_admin);
+ slapdFrontendConfig->pw_policy.pw_admin = slapi_sdn_new_dn_byval(value);
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
+ }
+ return retVal;
+}
+
+int
config_set_ds4_compatible_schema( const char *attrname, char *value, char *errorbuf, int apply ) {
int retVal = LDAP_SUCCESS;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index 9db10c5..014be1c 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -1224,11 +1224,9 @@ static int op_shared_allow_pw_change (Slapi_PBlock *pb, LDAPMod *mod, char **old
slapi_pblock_set( pb, SLAPI_BACKEND, slapi_be_select( &sdn ) );
/* Check if ACIs allow password to be changed */
- if ( (res = slapi_acl_check_mods(pb, e, mods, &errtxt)) != LDAP_SUCCESS) {
- if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS))
- {
- if (proxydn)
- {
+ if ( !pw_is_pwp_admin(pb, pwpolicy) && (res = slapi_acl_check_mods(pb, e, mods, &errtxt)) != LDAP_SUCCESS){
+ if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS)){
+ if (proxydn){
proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn);
}
@@ -1240,16 +1238,23 @@ static int op_shared_allow_pw_change (Slapi_PBlock *pb, LDAPMod *mod, char **old
/* Write access is denied to userPassword by ACIs */
if ( pwresponse_req == 1 ) {
- slapi_pwpolicy_make_response_control ( pb, -1, -1,
- LDAP_PWPOLICY_PWDMODNOTALLOWED );
- }
-
- send_ldap_result(pb, res, NULL, errtxt, 0, NULL);
+ slapi_pwpolicy_make_response_control ( pb, -1, -1, LDAP_PWPOLICY_PWDMODNOTALLOWED );
+ }
+ send_ldap_result(pb, res, NULL, errtxt, 0, NULL);
slapi_ch_free_string(&errtxt);
rc = -1;
goto done;
}
+ /*
+ * If this mod is being performed by a password administrator/rootDN,
+ * just return success.
+ */
+ if(pw_is_pwp_admin(pb, pwpolicy)){
+ rc = 1;
+ goto done;
+ }
+
/* Check if password policy allows users to change their passwords.*/
if (!pb->pb_op->o_isroot && slapi_sdn_compare(&sdn, &pb->pb_op->o_sdn)==0 &&
!pb->pb_conn->c_needpw && !pwpolicy->pw_change)
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 1d1db1e..20df245 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -1803,6 +1803,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
}
break;
+ case SLAPI_REQUESTOR_SDN:
+ if(pblock->pb_op != NULL){
+ (*(Slapi_DN **)value) = &pblock->pb_op->o_sdn;
+ }
+ break;
+
case SLAPI_OPERATION_AUTHTYPE:
if (pblock->pb_op != NULL)
{
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 7e53db0..1fb782b 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -348,6 +348,7 @@ int config_set_return_exact_case(const char *attrname, char *value, char *error
int config_set_result_tweak(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_referral_mode(const char *attrname, char *url, char *errorbuf, int apply);
int config_set_conntablesize(const char *attrname, char *url, char *errorbuf, int apply);
+int config_set_pw_admin_dn( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_maxbersize(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_maxsasliosize(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_versionstring(const char *attrname, char *versionstring, char *errorbuf, int apply );
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 27215c4..3a1e4a1 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -73,6 +73,8 @@ static int update_pw_history( Slapi_PBlock *pb, const Slapi_DN *sdn, char *old_p
static int check_trivial_words (Slapi_PBlock *, Slapi_Entry *, Slapi_Value **,
char *attrtype, int toklen, Slapi_Mods *smods );
static int pw_boolean_str2value (const char *str);
+static void pw_get_admin_users(passwdPolicy *pwp);
+
/* static LDAPMod* pw_malloc_mod (char* name, char* value, int mod_op); */
@@ -588,7 +590,7 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
char *timestr;
time_t pw_exp_date;
time_t cur_time;
- const char *dn;
+ const char *target_dn, *bind_dn;
Slapi_DN *sdn = NULL;
passwdPolicy *pwpolicy = NULL;
int internal_op = 0;
@@ -598,10 +600,11 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
internal_op = slapi_operation_is_flag_set(operation, SLAPI_OP_FLAG_INTERNAL);
cur_time = current_time();
+ slapi_pblock_get( pb, SLAPI_REQUESTOR_NDN, &bind_dn);
slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
- dn = slapi_sdn_get_dn(sdn);
+ target_dn = slapi_sdn_get_dn(sdn);
- pwpolicy = new_passwdPolicy(pb, dn);
+ pwpolicy = new_passwdPolicy(pb, target_dn);
/* update passwordHistory */
if ( old_pw != NULL && pwpolicy->pw_history == 1 ) {
@@ -643,7 +646,8 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
* we stuff the actual user who initiated the password change in pb_conn. We check
* for this special case to ensure we reset the expiration date properly. */
if ((internal_op && pwpolicy->pw_must_change && (!pb->pb_conn || slapi_dn_isroot(pb->pb_conn->c_dn))) ||
- (!internal_op && pwpolicy->pw_must_change && (pb->pb_requestor_isroot == 1))) {
+ (!internal_op && pwpolicy->pw_must_change &&
+ ((target_dn && bind_dn && strcasecmp(target_dn, bind_dn)) && pw_is_pwp_admin(pb, pwpolicy)))){
pw_exp_date = NO_TIME;
} else if ( pwpolicy->pw_exp == 1 ) {
Slapi_Entry *pse = NULL;
@@ -836,7 +840,7 @@ check_pw_syntax_ext ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
* case for the password modify extended operation. */
if (slapi_is_encoded((char *)slapi_value_get_string(vals[i]))) {
if ((!is_replication && ((internal_op && pb->pb_conn && !slapi_dn_isroot(pb->pb_conn->c_dn)) ||
- (!internal_op && !pb->pb_requestor_isroot)))) {
+ (!internal_op && !pw_is_pwp_admin(pb, pwpolicy))))) {
PR_snprintf( errormsg, BUFSIZ,
"invalid password syntax - passwords with storage scheme are not allowed");
if ( pwresponse_req == 1 ) {
@@ -1527,6 +1531,97 @@ pw_add_allowchange_aci(Slapi_Entry *e, int pw_prohibit_change) {
slapi_ch_free((void **) &aci_pw);
}
+int
+pw_is_pwp_admin(Slapi_PBlock *pb, passwdPolicy *pwp)
+{
+ Slapi_DN *bind_sdn = NULL;
+ int i;
+
+ /* first check if it's root */
+ if(pb->pb_requestor_isroot){
+ return 1;
+ }
+ /* now check if it's a Password Policy Administrator */
+ slapi_pblock_get(pb, SLAPI_REQUESTOR_SDN, &bind_sdn);
+ if(bind_sdn == NULL){
+ return 0;
+ }
+ for(i = 0; pwp->pw_admin_user && pwp->pw_admin_user[i]; i++){
+ if(slapi_sdn_compare(bind_sdn, pwp->pw_admin_user[i]) == 0){
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+pw_get_admin_users(passwdPolicy *pwp)
+{
+ Slapi_PBlock *pb = NULL;
+ const Slapi_DN *sdn = pwp->pw_admin;
+ char **uniquemember_vals = NULL;
+ char **member_vals = NULL;
+ const char *binddn = slapi_sdn_get_dn(sdn);
+ int uniquemember_count = 0;
+ int member_count = 0;
+ int nentries = 0;
+ int count = 0;
+ int res;
+ int i;
+
+ if(binddn == NULL){
+ return;
+ }
+ pb = slapi_pblock_new();
+ /*
+ * Check if the DN exists and has "group" objectclasses
+ */
+ slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,"(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
+ NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
+ slapi_search_internal_pb(pb);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
+ if (res != LDAP_SUCCESS) {
+ slapi_pblock_destroy(pb);
+ LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - Password Policy Administrators can not be set\n",
+ slapi_sdn_get_dn(sdn), res, 0);
+ return;
+ }
+ /*
+ * Ok, we know we have a valid DN, and nentries will tell us if its a group or a user
+ */
+ slapi_pblock_get(pb, SLAPI_NENTRIES, &nentries);
+ if ( nentries > 0 ){
+ /*
+ * It's a group DN, gather all the members
+ */
+ Slapi_Entry **entries = NULL;
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ uniquemember_vals = slapi_entry_attr_get_charray_ext(entries[0], "uniquemember", &uniquemember_count);
+ member_vals = slapi_entry_attr_get_charray_ext(entries[0], "member", &member_count);
+ pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1), sizeof(Slapi_DN *));
+ if(uniquemember_count > 0){
+ for(i = 0; i < uniquemember_count; i++){
+ pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(uniquemember_vals[i]);
+ }
+ }
+ if(member_count > 0){
+ for(i = 0; i < member_count; i++){
+ pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(member_vals[i]);
+ }
+ }
+ slapi_ch_free((void**)&uniquemember_vals);
+ slapi_ch_free((void**)&member_vals);
+ } else {
+ /* It's a single user */
+ pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc(2, sizeof(Slapi_DN *));
+ pwp->pw_admin_user[0] = slapi_sdn_dup(sdn);
+ }
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+}
+
/* This function creates a passwdPolicy structure, loads it from either
* slapdFrontendconfig or the entry pointed by pwdpolicysubentry and
* returns the structure.
@@ -1831,6 +1926,13 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
pw_boolean_str2value(slapi_value_get_string(*sval));
}
}
+ else
+ if (!strcasecmp(attr_name, "passwordAdminDN")) {
+ if ((sval = attr_get_present_values(attr))) {
+ pwdpolicy->pw_admin = slapi_sdn_new_dn_byval(slapi_value_get_string(*sval));
+ pw_get_admin_users(pwdpolicy);
+ }
+ }
} /* end of for() loop */
if (pw_entry) {
slapi_entry_free(pw_entry);
@@ -1851,6 +1953,8 @@ done:
*pwdscheme = *slapdFrontendConfig->pw_storagescheme;
pwdscheme->pws_name = strdup( slapdFrontendConfig->pw_storagescheme->pws_name );
pwdpolicy->pw_storagescheme = pwdscheme;
+ pwdpolicy->pw_admin = slapi_sdn_dup(slapdFrontendConfig->pw_policy.pw_admin);
+ pw_get_admin_users(pwdpolicy);
return pwdpolicy;
@@ -1861,6 +1965,15 @@ delete_passwdPolicy( passwdPolicy **pwpolicy)
{
if (pwpolicy && *pwpolicy) {
free_pw_scheme( (*(*pwpolicy)).pw_storagescheme );
+ slapi_sdn_free(&(*(*pwpolicy)).pw_admin);
+ if((*(*pwpolicy)).pw_admin_user){
+ int i = 0;
+ while((*(*pwpolicy)).pw_admin_user[i]){
+ slapi_sdn_free(&(*(*pwpolicy)).pw_admin_user[i]);
+ i++;
+ }
+ slapi_ch_free((void **)&(*(*pwpolicy)).pw_admin_user);
+ }
slapi_ch_free((void **)pwpolicy);
}
}
diff --git a/ldap/servers/slapd/pw.h b/ldap/servers/slapd/pw.h
index a470fdd..9bb5cc7 100644
--- a/ldap/servers/slapd/pw.h
+++ b/ldap/servers/slapd/pw.h
@@ -86,6 +86,7 @@ int pw_encodevals_ext( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals
int checkPrefix(char *cipher, char *schemaName, char **encrypt);
struct passwordpolicyarray *new_passwdPolicy ( Slapi_PBlock *pb, const char *dn );
void delete_passwdPolicy( struct passwordpolicyarray **pwpolicy);
+int pw_is_pwp_admin(Slapi_PBlock *pb, struct passwordpolicyarray *pwp);
/* function for checking the values of fine grained password policy attributes */
int check_pw_duration_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf );
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 2465500..2c8b2a6 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2015,6 +2015,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_SASL_MAXBUFSIZE "nsslapd-sasl-max-buffer-size"
#define CONFIG_LISTEN_BACKLOG_SIZE "nsslapd-listen-backlog-size"
#define CONFIG_IGNORE_TIME_SKEW "nsslapd-ignore-time-skew"
+#define CONFIG_PW_ADMIN_DN_ATTRIBUTE "passwordAdminDN"
/* getenv alternative */
#define CONFIG_MALLOC_MXFAST "nsslapd-malloc-mxfast"
@@ -2078,6 +2079,8 @@ typedef struct passwordpolicyarray {
int pw_is_legacy;
int pw_track_update_time;
struct pw_scheme *pw_storagescheme;
+ Slapi_DN *pw_admin;
+ Slapi_DN **pw_admin_user;
} passwdPolicy;
typedef struct _slapdFrontendConfig {
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 521de6a..f0dd555 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -1622,6 +1622,38 @@ int slapi_entry_attr_delete( Slapi_Entry *e, const char *type );
* be \c NULL terminated so that they can be used safely in a string context. If there
* are no values, \c NULL will be returned. Because the array is \c NULL terminated,
* the usage should be similar to the sample shown below:
+ *
+ * \code
+ * char **ary = slapi_entry_attr_get_charray(e, someattr);
+ * int ii;
+ * for (ii = 0; ary && ary[ii]; ++ii) {
+ * char *strval = ary[ii];
+ * ...
+ * }
+ * slapi_ch_array_free(ary);
+ * \endcode
+ *
+ * \param e Entry from which you want to get the values.
+ * \param type Attribute type from which you want to get the values.
+ * \param numVals The number of attribute values will be stored in this variable.
+ * \return A copy of all the values of the attribute.
+ * \return \c NULL if the entry does not contain the attribute or if the attribute
+ * has no values.
+ * \warning When you are done working with the values, free them from memory by calling
+ * the slapi_ch_array_free() function.
+ * \see slapi_entry_attr_get_charptr()
+ */
+char **slapi_entry_attr_get_charray_ext( const Slapi_Entry* e, const char *type, int *numVals);
+
+/**
+ * Gets the values of a multi-valued attribute of an entry.
+ *
+ * This function is very similar to slapi_entry_attr_get_charptr(), except that it
+ * returns a <tt>char **</tt> array for multi-valued attributes. The array and all
+ * values are copies. Even if the attribute values are not strings, they will still
+ * be \c NULL terminated so that they can be used safely in a string context. If there
+ * are no values, \c NULL will be returned. Because the array is \c NULL terminated,
+ * the usage should be similar to the sample shown below:
*
* \code
* char **ary = slapi_entry_attr_get_charray(e, someattr);
10 years, 3 months
Branch '389-ds-base-1.2.11' - 4 commits - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/attr.c | 95 --
ldap/servers/slapd/attrlist.c | 2
ldap/servers/slapd/attrsyntax.c | 197 ++++
ldap/servers/slapd/back-ldbm/import-threads.c | 2
ldap/servers/slapd/back-ldbm/index.c | 26
ldap/servers/slapd/back-ldbm/ldbm_attr.c | 6
ldap/servers/slapd/computed.c | 2
ldap/servers/slapd/entry.c | 177 +---
ldap/servers/slapd/entrywsi.c | 20
ldap/servers/slapd/proto-slap.h | 13
ldap/servers/slapd/schema.c | 105 --
ldap/servers/slapd/slap.h | 8
ldap/servers/slapd/slapi-plugin.h | 15
ldap/servers/slapd/slapi-private.h | 5
ldap/servers/slapd/valueset.c | 1102 ++++++++++++--------------
15 files changed, 900 insertions(+), 875 deletions(-)
New commits:
commit 8252d02654cc616beb4558421cd292d470b150cf
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Feb 24 16:42:36 2014 -0800
Ticket #47455 - valgrind - value mem leaks, uninit mem usage
Backported the valueset.c part of commit 3adc242bcc8c6d0d05d5d9773f32b4f81afb6e6d.
Author: Rich Megginson <rmeggins(a)redhat.com>
https://fedorahosted.org/389/ticket/47455
Fix Description: The problem was that slapi_valueset_add_attr_valuearray_ext
was assuming the caller was going to free the entire given vs upon failure.
This is fine for the value replace case but not for the add 1 value case.
Callers of slapi_valueset_add_attr_valuearray_ext must provide
the dup_index parameter if using SLAPI_VALUE_FLAG_PASSIN and
SLAPI_VALUE_FLAG_DUPCHECK, and if there is more than one value. The caller
needs to know which of the values from addvals is in vs to properly clean up
with no memory leaks.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit 3adc242bcc8c6d0d05d5d9773f32b4f81afb6e6d)
(cherry picked from commit 6357ced2e4380def053966e849eac45e44009662)
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
index 4ee2938..29078d4 100644
--- a/ldap/servers/slapd/valueset.c
+++ b/ldap/servers/slapd/valueset.c
@@ -1014,6 +1014,15 @@ valueset_insert_value_to_sorted(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_V
}
+/*
+ * If this function returns an error, it is safe to do both
+ * slapi_valueset_done(vs);
+ * and
+ * valuearray_free(&addvals);
+ * if there is an error and the PASSIN flag is used, the addvals array will own all of the values
+ * vs will own none of the values - so you should do both slapi_valueset_done(vs) and valuearray_free(&add
+ * to clean up
+ */
int
slapi_valueset_add_attr_valuearray_ext(const Slapi_Attr *a, Slapi_ValueSet *vs,
Slapi_Value **addvals, int naddvals, unsigned long flags, int *dup_index)
@@ -1086,8 +1095,13 @@ slapi_valueset_add_attr_valuearray_ext(const Slapi_Attr *a, Slapi_ValueSet *vs,
if (dup < 0 ) {
rc = LDAP_TYPE_OR_VALUE_EXISTS;
if (dup_index) *dup_index = i;
- if ( !passin)
+ if (passin) {
+ PR_ASSERT((i == 0) || dup_index);
+ /* caller must provide dup_index to know how far we got in addvals */
+ (vs->va)[vs->num] = NULL;
+ } else {
slapi_value_free(&(vs->va)[vs->num]);
+ }
break;
}
} else {
@@ -1310,31 +1324,42 @@ valueset_replace_valuearray_ext(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value *
vs->max = vals_count + 1;
} else {
/* verify the given values are not duplicated. */
+ unsigned long flags = SLAPI_VALUE_FLAG_PASSIN|SLAPI_VALUE_FLAG_DUPCHECK;
+ int dupindex = 0;
Slapi_ValueSet *vs_new = slapi_valueset_new();
- rc = slapi_valueset_add_attr_valuearray_ext (a, vs_new, valstoreplace, vals_count, 0, NULL);
+ rc = slapi_valueset_add_attr_valuearray_ext (a, vs_new, valstoreplace, vals_count, flags, &dupindex);
if ( rc == LDAP_SUCCESS )
{
+ /* used passin, so vs_new owns all of the Slapi_Value* in valstoreplace
+ * so tell valuearray_free_ext to start at index vals_count, which is
+ * NULL, then just free valstoreplace
+ */
+ valuearray_free_ext(&valstoreplace, vals_count);
/* values look good - replace the values in the attribute */
- if(!valuearray_isempty(vs->va))
- {
- /* remove old values */
- slapi_valueset_done(vs);
- }
- vs->va = vs_new->va;
+ if(!valuearray_isempty(vs->va))
+ {
+ /* remove old values */
+ slapi_valueset_done(vs);
+ }
+ vs->va = vs_new->va;
vs_new->va = NULL;
- vs->sorted = vs_new->sorted;
+ vs->sorted = vs_new->sorted;
vs_new->sorted = NULL;
- vs->num = vs_new->num;
- vs->max = vs_new->max;
+ vs->num = vs_new->num;
+ vs->max = vs_new->max;
slapi_valueset_free (vs_new);
}
else
{
- /* caller expects us to own valstoreplace - since we cannot
- use them, just delete them */
- slapi_valueset_free(vs_new);
- valuearray_free(&valstoreplace);
+ /* caller expects us to own valstoreplace - since we cannot
+ use them, just delete them */
+ /* using PASSIN, some of the Slapi_Value* are in vs_new, and the rest
+ * after dupindex are in valstoreplace
+ */
+ slapi_valueset_free(vs_new);
+ valuearray_free_ext(&valstoreplace, dupindex);
+ PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
}
}
return rc;
commit 8a6b75fefccb9daf238d26fcc6f320d4505f8251
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Jul 31 10:52:21 2013 -0600
fix coverity 11915 - dead code - introduced with fix for ticket 346
just get rid of unused variable was_present_null
reviewed by: nhosoi (Thanks!)
(cherry picked from commit ba70aac1991a04455ba83362e22c33f7f6ab227a)
(cherry picked from commit fcf4154b73681752a5ac32954a1d25771a75478e)
diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c
index 9894393..983e286 100644
--- a/ldap/servers/slapd/attr.c
+++ b/ldap/servers/slapd/attr.c
@@ -811,7 +811,6 @@ attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn)
int i = 0;
int numofvals = 0;
int duplicate_index = -1;
- int was_present_null = 0;
int rc = LDAP_SUCCESS;
if (valuearray_isempty(vals)) {
@@ -868,7 +867,7 @@ attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn)
duplicate_string,
a->a_type,
dn ? dn : "<null>",
- (was_present_null ? "duplicate new value" : "value exists"));
+ "value exists");
}
return( rc );
}
commit e4ddba7fb35bec4aa3b7352d13d283fb17b14755
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Wed Feb 26 11:07:00 2014 -0800
Ticket 47369 version2 - provide default syntax plugin
Backported commit d779853f5fa6eeeea436627801718070824ca795
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Bug Description: syntax plugins are laoded during bootstrapping, but
in that phase already attributes are handled
eg in dse.ldif and schema files and no proper way
to normalize or comare values is provided.
This became visible with teh fix for ticket #346
where large attribute sets will be sorted
Fix Description: when the first attribute syntax init is done, create a plugin
for directory string syntax and register it with a dummy
attribute name. if for any attribute the syntax lookup fails
fall back to using this plugin.
It will only be used until the syntax plugins are loaded
and in the startup phase it is acceptable to use directory
string.
The impelemenation of the default plugin is reduce to the
necessary minimum not to duplicate the code of the syntax
plugins.
A more rigorus solution would be to refactor the code and
and move the common code from the syntax plugin to the
slapd level and reuse it in the default plugin.
But this would be a major change and should only be done
with a review of the syntax plugin code, whic could probabyly
be optimized.
https://fedorahosted.org/389/ticket/47369
Reviewed by: RichM
(cherry picked from commit 62d0dbf548e1d2b0d7f7e09809456393034e34a5)
(cherry picked from commit ecafacefd47c20dcc01cb0c69b378b4203f77d0b)
Note: removed SLAPI_ATTR_FLAG_NOEXPOSE
diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c
index 158b0c7..9894393 100644
--- a/ldap/servers/slapd/attr.c
+++ b/ldap/servers/slapd/attr.c
@@ -230,7 +230,7 @@ slapi_attr_init(Slapi_Attr *a, const char *type)
}
int
-slapi_attr_init_syntax(Slapi_Attr *a)
+slapi_attr_init_syntax(Slapi_Attr *a)
{
int rc = 1;
struct asyntaxinfo *asi = NULL;
@@ -436,6 +436,10 @@ slapi_attr_value_find( const Slapi_Attr *a, const struct berval *v )
return( -1 );
}
+ if ( a->a_flags == 0 && a->a_plugin == NULL ) {
+ slapi_attr_init_syntax ((Slapi_Attr *)a);
+ }
+
ava.ava_type = a->a_type;
ava.ava_value = *v;
if (a->a_flags & SLAPI_ATTR_FLAG_NORMALIZED) {
@@ -547,6 +551,9 @@ attr_get_present_values(const Slapi_Attr *a)
int
slapi_attr_get_flags( const Slapi_Attr *a, unsigned long *flags )
{
+ if ( a->a_flags == 0 && a->a_plugin == NULL ) {
+ slapi_attr_init_syntax ((Slapi_Attr *)a);
+ }
*flags = a->a_flags;
return( 0 );
}
@@ -554,6 +561,9 @@ slapi_attr_get_flags( const Slapi_Attr *a, unsigned long *flags )
int
slapi_attr_flag_is_set( const Slapi_Attr *a, unsigned long flag )
{
+ if ( a->a_flags == 0 && a->a_plugin == NULL ) {
+ slapi_attr_init_syntax ((Slapi_Attr *)a);
+ }
return( a->a_flags & flag );
}
@@ -565,6 +575,10 @@ slapi_attr_value_cmp( const Slapi_Attr *a, const struct berval *v1, const struct
Slapi_Value *cvals[2];
Slapi_Value tmpcval;
+ if ( a->a_flags == 0 && a->a_plugin == NULL ) {
+ slapi_attr_init_syntax ((Slapi_Attr *)a);
+ }
+
cvals[0] = &tmpcval;
cvals[0]->v_csnset = NULL;
cvals[0]->bv = *v1;
@@ -587,6 +601,10 @@ slapi_attr_value_cmp_ext(const Slapi_Attr *a, Slapi_Value *v1, Slapi_Value *v2)
unsigned long v2_flags = v2->v_flags;
const struct berval *bv2 = slapi_value_get_berval(v2);
+ if ( a->a_flags == 0 && a->a_plugin == NULL ) {
+ slapi_attr_init_syntax ((Slapi_Attr *)a);
+ }
+
cvals[0] = v1;
cvals[1] = NULL;
a2.a_present_values.va = cvals;
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index c70a9bb..79736b5 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -74,6 +74,7 @@ static Slapi_RWLock *name2asi_lock = NULL;
#define AS_UNLOCK_WRITE(l) slapi_rwlock_unlock(l)
+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,
@@ -330,6 +331,8 @@ attr_syntax_get_by_name_with_default(const char *name)
asi = attr_syntax_get_by_name_locking_optional(name, PR_TRUE);
if (asi == NULL)
asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX);
+ if ( asi == NULL )
+ asi = default_asi;
return asi;
}
@@ -547,6 +550,154 @@ attr_syntax_exists(const char *attr_name)
return 0;
}
+static void default_dirstring_normalize_int(char *s, int trim_spaces);
+
+static
+int default_dirstring_filter_ava( struct berval *bvfilter, Slapi_Value **bvals,int ftype, Slapi_Value **retVal )
+{
+ return(0);
+}
+
+static
+int default_dirstring_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,Slapi_Value ***ivals, int ftype )
+{
+ int numbvals = 0;
+ Slapi_Value **nbvals, **nbvlp;
+ Slapi_Value **bvlp;
+ char *c;
+
+ if (NULL == ivals) {
+ return 1;
+ }
+ *ivals = NULL;
+ if (NULL == bvals) {
+ return 1;
+ }
+ switch ( ftype ) {
+ case LDAP_FILTER_EQUALITY:
+ /* allocate a new array for the normalized values */
+ for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) {
+ numbvals++;
+ }
+ nbvals = (Slapi_Value **) slapi_ch_calloc( (numbvals + 1), sizeof(Slapi_Value *));
+
+ for ( bvlp = bvals, nbvlp = nbvals; bvlp && *bvlp; bvlp++, nbvlp++ ) {
+ c = slapi_ch_strdup(slapi_value_get_string(*bvlp));
+ default_dirstring_normalize_int( c, 1 );
+ *nbvlp = slapi_value_new_string_passin(c);
+ c = NULL;
+ }
+ *ivals = nbvals;
+ break;
+
+ case LDAP_FILTER_APPROX:
+ case LDAP_FILTER_SUBSTRINGS:
+ default:
+ /* default plugin only handles equality so far */
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "default_dirstring_values2keys: unsupported ftype 0x%x\n",
+ ftype, 0, 0 );
+ break;
+ }
+ return(0);
+}
+
+static
+int default_dirstring_assertion2keys_ava(Slapi_PBlock *pb,Slapi_Value *val,Slapi_Value ***ivals,int ftype )
+{
+ return(0);
+}
+
+static
+int default_dirstring_cmp(struct berval *v1,struct berval *v2, int normalize)
+{
+ return(0);
+}
+
+static
+void default_dirstring_normalize(Slapi_PBlock *pb, char *s, int trim_spaces, char **alt)
+{
+ default_dirstring_normalize_int(s, trim_spaces);
+}
+
+static
+void default_dirstring_normalize_int(char *s, int trim_spaces)
+{
+ char *head = s;
+ char *d;
+ int prevspace, curspace;
+
+ if (NULL == s) {
+ return;
+ }
+ d = s;
+ if (trim_spaces) {
+ /* strip leading blanks */
+ while (ldap_utf8isspace(s)) {
+ LDAP_UTF8INC(s);
+ }
+ }
+
+ /* handle value of all spaces - turn into single space */
+ if ( *s == '\0' && s != d ) {
+ *d++ = ' ';
+ *d = '\0';
+ return;
+ }
+ prevspace = 0;
+ while ( *s ) {
+ int ssz, dsz;
+ curspace = ldap_utf8isspace(s);
+
+ /* compress multiple blanks */
+ if ( prevspace && curspace ) {
+ LDAP_UTF8INC(s);
+ continue;
+ }
+ prevspace = curspace;
+ slapi_utf8ToLower((unsigned char*)s, (unsigned char *)d, &ssz, &dsz);
+ s += ssz;
+ d += dsz;
+ }
+ *d = '\0';
+ /* strip trailing blanks */
+ if (prevspace && trim_spaces) {
+ char *nd;
+
+ nd = ldap_utf8prev(d);
+ while (nd && nd >= head && ldap_utf8isspace(nd)) {
+ d = nd;
+ nd = ldap_utf8prev(d);
+ *d = '\0';
+ }
+ }
+}
+
+static struct slapdplugin *
+attr_syntax_default_plugin ( const char *nameoroid )
+{
+
+ struct slapdplugin *pi = NULL;
+ /*
+ * create a new plugin structure and
+ * set the plugin function pointers.
+ */
+ pi = (struct slapdplugin *)slapi_ch_calloc(1, sizeof(struct slapdplugin));
+
+ pi->plg_dn = slapi_ch_strdup("default plugin for directory string syntax");
+ pi->plg_closed = 0;
+ pi->plg_syntax_oid = slapi_ch_strdup(nameoroid);
+
+
+ pi->plg_syntax_filter_ava = (IFP) default_dirstring_filter_ava;
+ pi->plg_syntax_values2keys = (IFP) default_dirstring_values2keys;
+ pi->plg_syntax_assertion2keys_ava = (IFP) default_dirstring_assertion2keys_ava;
+ pi->plg_syntax_compare = (IFP) default_dirstring_cmp;
+ pi->plg_syntax_normalize = (VFPV) default_dirstring_normalize;
+
+ return (pi);
+
+}
/* check syntax */
static void *
@@ -565,11 +716,14 @@ attr_syntax_get_plugin_by_name_with_default( const char *type )
* attribute type that has that syntax.
*/
asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX);
+ if (asi == NULL)
+ asi = default_asi;
}
if ( NULL != asi ) {
plugin = asi->asi_plugin;
attr_syntax_return( asi );
}
+
return( plugin );
}
@@ -683,6 +837,32 @@ cleanup_and_return:
return rc;
}
+static int
+attr_syntax_create_default( const char *name, const char *oid,
+ const char *syntax, unsigned long extraflags )
+{
+ int rc = 0;
+ char *names[2];
+ unsigned long std_flags = SLAPI_ATTR_FLAG_STD_ATTR | SLAPI_ATTR_FLAG_OPATTR;
+
+ names[0] = (char *)name;
+ names[1] = NULL;
+
+ if (default_asi)
+ return (rc);
+
+ rc = attr_syntax_create( oid, names, 1,
+ "internal server defined attribute type",
+ NULL, /* superior */
+ NULL, NULL, NULL, /* matching rules */
+ NULL, syntax,
+ SLAPI_SYNTAXLENGTH_NONE,
+ std_flags | extraflags,
+ &default_asi );
+ if ( rc == 0 && default_asi->asi_plugin == 0)
+ default_asi->asi_plugin = attr_syntax_default_plugin (syntax );
+ return (rc);
+}
/*
* Returns an LDAP result code.
@@ -1113,6 +1293,8 @@ attr_syntax_delete_all_for_schemareload(unsigned long flag)
(void *)&fi);
}
+#define ATTR_DEFAULT_SYNTAX_OID "1.1"
+#define ATTR_DEFAULT_SYNTAX "defaultdirstringsyntax"
static int
attr_syntax_init(void)
{
@@ -1144,6 +1326,12 @@ attr_syntax_init(void)
"slapi_new_rwlock() for oid2asi lock failed\n" );
return 1;
}
+ /* 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 );
}
return 0;
}
commit 890fc22687821279f3862fc0862a4e8d93c00291
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Mar 4 09:35:29 2014 -0800
Ticket 346 - version 4 Slow ldapmodify operation time for large quantities of multi-valued attribute values
Description: Backported commit f6ef7dc23352c82f45c41dfd5e9392971a164a23
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Bug Description: The reason for the performance degradation is that
for operations like add and delete of values and for updating the
index for each values a check has tobe done if it exists in the
current attribute. if the number of values grows the seaqrch time
increases.
Fix Description: Keep a secondary array of the indexes of the
valuearray which is sorted. To locate a value, a binary search
can be used.
A design doc is available at: http://port389.org/wiki/Static_group_performance
https://fedorahosted.org/389/ticket/346
diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c
index 0dd0393..158b0c7 100644
--- a/ldap/servers/slapd/attr.c
+++ b/ldap/servers/slapd/attr.c
@@ -351,11 +351,9 @@ Slapi_Attr *
slapi_attr_dup(const Slapi_Attr *attr)
{
Slapi_Attr *newattr= slapi_attr_new();
- Slapi_Value **present_va= valueset_get_valuearray(&attr->a_present_values); /* JCM Mucking about inside the value set */
- Slapi_Value **deleted_va= valueset_get_valuearray(&attr->a_deleted_values); /* JCM Mucking about inside the value set */
slapi_attr_init(newattr, attr->a_type);
- valueset_add_valuearray( &newattr->a_present_values, present_va );
- valueset_add_valuearray( &newattr->a_deleted_values, deleted_va );
+ slapi_valueset_set_valueset( &newattr->a_deleted_values, &attr->a_deleted_values );
+ slapi_valueset_set_valueset( &newattr->a_present_values, &attr->a_present_values );
newattr->a_deletioncsn= csn_dup(attr->a_deletioncsn);
return newattr;
}
@@ -806,67 +804,25 @@ attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn)
}
/*
- * determine whether we should use an AVL tree of values or not
+ * add values and check for duplicate values
*/
- for ( i = 0; vals[i] != NULL; i++ ) ;
- numofvals = i;
-
- /*
- * detect duplicate values
- */
- if ( numofvals > 1 ) {
- /*
- * Several values to add: use an AVL tree to detect duplicates.
- */
- LDAPDebug( LDAP_DEBUG_TRACE,
- "slapi_entry_add_values: using an AVL tree to "
- "detect duplicate values\n", 0, 0, 0 );
-
- if (valueset_isempty(&a->a_present_values)) {
- /* if the attribute contains no values yet, just check the
- * input vals array for duplicates
- */
- Avlnode *vtree = NULL;
- rc= valuetree_add_valuearray(a, vals, &vtree, &duplicate_index);
- valuetree_free(&vtree);
- was_present_null = 1;
+ numofvals = valuearray_count(vals);
+ rc = slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, vals, numofvals, SLAPI_VALUE_FLAG_DUPCHECK, &duplicate_index);
+ if ( rc != LDAP_SUCCESS) {
+ if (is_type_forbidden(a->a_type)) {
+ /* If the attr is in the forbidden list
+ * (e.g., unhashed password),
+ * we don't return any useful info to the clients. */
+ rc = LDAP_OTHER;
} else {
- /* the attr and vals both contain values, check intersection */
- rc= valueset_intersectswith_valuearray(&a->a_present_values, a, vals, &duplicate_index);
- }
-
- } else if ( !valueset_isempty(&a->a_present_values) ) {
- /*
- * One or no value to add: don't bother constructing
- * an AVL tree, etc. since it probably isn't worth the time.
- */
- for ( i = 0; vals[i] != NULL; ++i ) {
- if ( slapi_attr_value_find( a, slapi_value_get_berval(vals[i]) ) == 0 ) {
- duplicate_index = i;
- if (is_type_forbidden(a->a_type)) {
- /* If the attr is in the forbidden list
- * (e.g., unhashed password),
- * we don't return any useful info to the clients. */
- rc = LDAP_OTHER;
- } else {
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- }
- break;
- }
+ rc = LDAP_TYPE_OR_VALUE_EXISTS;
}
}
- /*
- * add values if no duplicates detected
- */
- if(rc==LDAP_SUCCESS) {
- valueset_add_valuearray( &a->a_present_values, vals );
- }
-
/* In the case of duplicate value, rc == LDAP_TYPE_OR_VALUE_EXISTS or
* LDAP_OPERATIONS_ERROR
*/
- else if ( duplicate_index >= 0 ) {
+ if ( duplicate_index >= 0 ) {
char bvvalcopy[BUFSIZ];
char *duplicate_string = "null or non-ASCII";
@@ -907,7 +863,7 @@ attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn)
*/
int attr_replace(Slapi_Attr *a, Slapi_Value **vals)
{
- return valueset_replace(a, &a->a_present_values, vals);
+ return valueset_replace_valuearray(a, &a->a_present_values, vals);
}
int
diff --git a/ldap/servers/slapd/attrlist.c b/ldap/servers/slapd/attrlist.c
index e365f3d..cedf9ea 100644
--- a/ldap/servers/slapd/attrlist.c
+++ b/ldap/servers/slapd/attrlist.c
@@ -112,7 +112,7 @@ attrlist_merge_valuearray(Slapi_Attr **alist, const char *type, Slapi_Value **va
Slapi_Attr **a= NULL;
if (!vals) return;
attrlist_find_or_create(alist, type, &a);
- valueset_add_valuearray( &(*a)->a_present_values, vals );
+ slapi_valueset_add_valuearray( *a, &(*a)->a_present_values, vals );
}
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index cc2f226..c70a9bb 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -870,11 +870,20 @@ slapi_attr_is_dn_syntax_attr(Slapi_Attr *attr)
const char *syntaxoid = NULL;
int dn_syntax = 0; /* not DN, by default */
+ if (attr && attr->a_flags & SLAPI_ATTR_FLAG_SYNTAX_IS_DN)
+ /* it was checked before */
+ return(1);
+
+ if (attr && attr->a_plugin == NULL) {
+ slapi_attr_init_syntax (attr);
+ }
if (attr && attr->a_plugin) { /* If not set, there is no way to get the info */
if ((syntaxoid = attr_get_syntax_oid(attr))) {
dn_syntax = ((0 == strcmp(syntaxoid, NAMEANDOPTIONALUID_SYNTAX_OID))
|| (0 == strcmp(syntaxoid, DN_SYNTAX_OID)));
}
+ if (dn_syntax)
+ attr->a_flags |= SLAPI_ATTR_FLAG_SYNTAX_IS_DN;
}
return dn_syntax;
}
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
index 5667acb..c7d3444 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -2274,7 +2274,7 @@ import_foreman(void *param)
/* Setting new entrydn attribute value */
slapi_attr_init(new_entrydn, "entrydn");
- valueset_add_string(&new_entrydn->a_present_values,
+ valueset_add_string(new_entrydn, &new_entrydn->a_present_values,
/* new_dn: duped in valueset_add_string */
(const char *)new_dn,
CSN_TYPE_UNKNOWN, NULL);
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index 66d6e7e..2d5b535 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -547,7 +547,7 @@ index_add_mods(
for (curr_attr = newe->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
if (slapi_attr_type_cmp( basetype, curr_attr->a_type, SLAPI_TYPE_CMP_BASE ) == 0) {
- valueset_add_valuearray(all_vals, attr_get_present_values(curr_attr));
+ slapi_valueset_join_attr_valueset(curr_attr, all_vals, &curr_attr->a_present_values);
}
}
@@ -568,7 +568,7 @@ index_add_mods(
for (curr_attr = olde->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
- valueset_add_valuearray(mod_vals, attr_get_present_values(curr_attr));
+ slapi_valueset_join_attr_valueset(curr_attr, mod_vals, &curr_attr->a_present_values);
}
}
@@ -586,7 +586,7 @@ index_add_mods(
slapi_entry_attr_find( olde->ep_entry, mods[i]->mod_type, &curr_attr );
if ( mods_valueArray != NULL ) {
for ( j = 0; mods_valueArray[j] != NULL; j++ ) {
- Slapi_Value *rval = valuearray_remove_value(curr_attr, evals, mods_valueArray[j]);
+ Slapi_Value *rval = valueset_remove_value(curr_attr, all_vals, mods_valueArray[j]);
slapi_value_free( &rval );
}
}
@@ -595,12 +595,12 @@ index_add_mods(
* they don't exist, delete the equality index.
*/
for ( j = 0; deleted_valueArray[j] != NULL; j++ ) {
- if (valuearray_find(curr_attr, evals, deleted_valueArray[j]) == -1) {
+ if ( !slapi_valueset_find(curr_attr, all_vals, deleted_valueArray[j])) {
if (!(flags & BE_INDEX_EQUALITY)) {
flags |= BE_INDEX_EQUALITY;
}
} else {
- Slapi_Value *rval = valuearray_remove_value(curr_attr, deleted_valueArray, deleted_valueArray[j]);
+ Slapi_Value *rval = valueset_remove_value(curr_attr, mod_vals, deleted_valueArray[j]);
slapi_value_free( &rval );
j--;
/* indicates there was some conflict */
@@ -639,8 +639,8 @@ index_add_mods(
if (curr_attr) { /* found the type */
for (j = 0; mods_valueArray[j] != NULL; j++) {
/* mods_valueArray[j] is in curr_attr ==> return 0 */
- if (slapi_attr_value_find(curr_attr,
- slapi_value_get_berval(mods_valueArray[j]))) {
+ if ( !slapi_valueset_find(curr_attr, &curr_attr->a_present_values,
+ mods_valueArray[j])) {
/* The value is NOT in newe, remove it. */
Slapi_Value *rval;
rval = valuearray_remove_value(curr_attr,
@@ -678,9 +678,9 @@ index_add_mods(
mod_vals = slapi_valueset_new();
for (curr_attr = olde->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
- if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
- valueset_add_valuearray(mod_vals, attr_get_present_values(curr_attr));
- }
+ if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
+ slapi_valueset_join_attr_valueset(curr_attr, mod_vals, &curr_attr->a_present_values);
+ }
}
deleted_valueArray = valueset_get_valuearray(mod_vals);
@@ -696,14 +696,14 @@ index_add_mods(
* also exist in a subtype.
*/
for (j = 0; deleted_valueArray && deleted_valueArray[j]; j++) {
- if ( valuearray_find(curr_attr, evals, deleted_valueArray[j]) == -1 ) {
+ if ( !slapi_valueset_find(curr_attr, all_vals, deleted_valueArray[j])) {
/* If the equality flag isn't already set, set it */
if (!(flags & BE_INDEX_EQUALITY)) {
flags |= BE_INDEX_EQUALITY;
}
} else {
/* Remove duplicate value from the mod list */
- Slapi_Value *rval = valuearray_remove_value(curr_attr, deleted_valueArray, deleted_valueArray[j]);
+ Slapi_Value *rval = valueset_remove_value(curr_attr, mod_vals, deleted_valueArray[j]);
slapi_value_free( &rval );
j--;
}
@@ -752,7 +752,7 @@ index_add_mods(
if (curr_attr) {
int found = 0;
for (j = 0; mods_valueArray[j] != NULL; j++ ) {
- if ( valuearray_find(curr_attr, evals, mods_valueArray[j]) > -1 ) {
+ if ( slapi_valueset_find(curr_attr, all_vals, mods_valueArray[j])) {
/* The same value found in evals.
* We don't touch the equality index. */
found = 1;
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_attr.c b/ldap/servers/slapd/back-ldbm/ldbm_attr.c
index fa18550..16ffa42 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_attr.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_attr.c
@@ -931,7 +931,7 @@ ldbm_compute_evaluator(computed_attr_context *c,char* type,Slapi_Entry *e,slapi_
Slapi_Attr our_attr;
slapi_attr_init(&our_attr, numsubordinates);
our_attr.a_flags = SLAPI_ATTR_FLAG_OPATTR;
- valueset_add_string(&our_attr.a_present_values,"0",CSN_TYPE_UNKNOWN,NULL);
+ valueset_add_string(&our_attr, &our_attr.a_present_values,"0",CSN_TYPE_UNKNOWN,NULL);
rc = (*outputfn) (c, &our_attr, e);
attr_done(&our_attr);
return (rc);
@@ -948,9 +948,9 @@ ldbm_compute_evaluator(computed_attr_context *c,char* type,Slapi_Entry *e,slapi_
rc = slapi_entry_attr_find( e, numsubordinates, &read_attr );
if ( (0 != rc) || slapi_entry_attr_hasvalue(e,numsubordinates,"0") ) {
/* If not, or present and zero, we return FALSE, otherwise TRUE */
- valueset_add_string(&our_attr.a_present_values,"FALSE",CSN_TYPE_UNKNOWN,NULL);
+ valueset_add_string(&our_attr, &our_attr.a_present_values,"FALSE",CSN_TYPE_UNKNOWN,NULL);
} else {
- valueset_add_string(&our_attr.a_present_values,"TRUE",CSN_TYPE_UNKNOWN,NULL);
+ valueset_add_string(&our_attr, &our_attr.a_present_values,"TRUE",CSN_TYPE_UNKNOWN,NULL);
}
rc = (*outputfn) (c, &our_attr, e);
attr_done(&our_attr);
diff --git a/ldap/servers/slapd/computed.c b/ldap/servers/slapd/computed.c
index 353d375..b82e2e8 100644
--- a/ldap/servers/slapd/computed.c
+++ b/ldap/servers/slapd/computed.c
@@ -124,7 +124,7 @@ compute_stock_evaluator(computed_attr_context *c,char* type,Slapi_Entry *e,slapi
Slapi_Attr our_attr;
slapi_attr_init(&our_attr, subschemasubentry);
our_attr.a_flags = SLAPI_ATTR_FLAG_OPATTR;
- valueset_add_string(&our_attr.a_present_values,SLAPD_SCHEMA_DN,CSN_TYPE_UNKNOWN,NULL);
+ valueset_add_string(&our_attr, &our_attr.a_present_values,SLAPD_SCHEMA_DN,CSN_TYPE_UNKNOWN,NULL);
rc = (*outputfn) (c, &our_attr, e);
attr_done(&our_attr);
return (rc);
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 29fe075..8a5df7e 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -223,8 +223,6 @@ str2entry_fast( const char *rawdn, char *s, int flags, int read_stateinfo )
int freeval = 0;
int value_state= VALUE_NOTFOUND;
int attr_state= ATTRIBUTE_NOTFOUND;
- int maxvals;
- int del_maxvals;
if ( *s == '\n' || *s == '\0' ) {
break;
@@ -266,9 +264,7 @@ str2entry_fast( const char *rawdn, char *s, int flags, int read_stateinfo )
slapi_ch_free_string(&ptype);
ptype=PL_strndup(type.bv_val, type.bv_len);
nvals = 0;
- maxvals = 0;
del_nvals = 0;
- del_maxvals = 0;
a = NULL;
}
@@ -484,25 +480,21 @@ str2entry_fast( const char *rawdn, char *s, int flags, int read_stateinfo )
if(value_state==VALUE_DELETED)
{
/* consumes the value */
- valuearray_add_value_fast(
- &(*a)->a_deleted_values.va, /* JCM .va is private */
- svalue,
- del_nvals,
- &del_maxvals,
- 0/*!Exact*/,
- 1/*Passin*/ );
+ slapi_valueset_add_attr_value_ext(
+ *a,
+ &(*a)->a_deleted_values,
+ svalue,
+ SLAPI_VALUE_FLAG_PASSIN );
del_nvals++;
}
else
{
/* consumes the value */
- valuearray_add_value_fast(
- &(*a)->a_present_values.va, /* JCM .va is private */
- svalue,
- nvals,
- &maxvals,
- 0 /*!Exact*/,
- 1 /*Passin*/ );
+ slapi_valueset_add_attr_value_ext(
+ *a,
+ &(*a)->a_present_values,
+ svalue,
+ SLAPI_VALUE_FLAG_PASSIN);
nvals++;
}
if(attributedeletioncsn!=NULL)
@@ -582,8 +574,8 @@ typedef struct _entry_attrs {
typedef struct _str2entry_attr {
char *sa_type;
int sa_state;
- struct valuearrayfast sa_present_values;
- struct valuearrayfast sa_deleted_values;
+ struct slapi_value_set sa_present_values;
+ struct slapi_value_set sa_deleted_values;
int sa_numdups;
value_compare_fn_type sa_comparefn;
Avlnode *sa_vtree;
@@ -594,13 +586,13 @@ typedef struct _str2entry_attr {
static void
entry_attr_init(str2entry_attr *sa, const char *type, int state)
{
- sa->sa_type= slapi_ch_strdup(type);
+ sa->sa_type= slapi_ch_strdup(type);
sa->sa_state= state;
- valuearrayfast_init(&sa->sa_present_values,NULL);
- valuearrayfast_init(&sa->sa_deleted_values,NULL);
- sa->sa_numdups= 0;
+ slapi_valueset_init(&sa->sa_present_values);
+ slapi_valueset_init(&sa->sa_deleted_values);
+ sa->sa_numdups= 0;
sa->sa_comparefn = NULL;
- sa->sa_vtree= NULL;
+ sa->sa_vtree= NULL;
sa->sa_attributedeletioncsn= NULL;
slapi_attr_init(&sa->sa_attr, type);
}
@@ -733,28 +725,26 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo )
char *type;
struct berval bvtype;
str2entry_attr *sa;
- int i, j;
+ int i;
char *next=NULL;
char *valuecharptr=NULL;
struct berval bvvalue;
int rc;
- int fast_dup_check = 0;
- entry_attrs *ea = NULL;
- int tree_attr_checking = 0;
- int big_entry_attr_presence_check = 0;
- int check_for_duplicate_values =
- ( 0 != ( flags & SLAPI_STR2ENTRY_REMOVEDUPVALS ));
- Slapi_Value *value = 0;
- CSN *attributedeletioncsn= NULL;
- CSNSet *valuecsnset= NULL;
- CSN *maxcsn= NULL;
- char *normdn = NULL;
- int strict = 0;
+ entry_attrs *ea = NULL;
+ int tree_attr_checking = 0;
+ int big_entry_attr_presence_check = 0;
+ int check_for_duplicate_values = (0 != (flags & SLAPI_STR2ENTRY_REMOVEDUPVALS));
+ Slapi_Value *value = 0;
+ CSN *attributedeletioncsn= NULL;
+ CSNSet *valuecsnset= NULL;
+ CSN *maxcsn= NULL;
+ char *normdn = NULL;
+ int strict = 0;
/* Check if we should be performing strict validation. */
strict = config_get_dn_validate_strict();
- LDAPDebug( LDAP_DEBUG_TRACE, "=> str2entry_dupcheck\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> str2entry_dupcheck\n", 0, 0, 0 );
e = slapi_entry_alloc();
slapi_entry_init(e,NULL,NULL);
@@ -977,7 +967,6 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo )
if ( prev_attr==NULL )
{
/* Haven't seen this type yet */
- fast_dup_check = 1;
if ( nattrs == maxattrs )
{
/* Out of space - reallocate */
@@ -1009,15 +998,6 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo )
/* Get the comparison function for later use */
attr_get_value_cmp_fn( &attrs[nattrs].sa_attr, &(attrs[nattrs].sa_comparefn));
/*
- * If the compare function wasn't available,
- * we have to revert to AVL-tree-based dup checking,
- * which uses index keys for comparisons
- */
- if (NULL == attrs[nattrs].sa_comparefn)
- {
- fast_dup_check = 0;
- }
- /*
* If we are maintaining the attribute tree,
* then add the new attribute to the tree.
*/
@@ -1073,66 +1053,20 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo )
{
/*
* for deleted values, we do not want to perform a dupcheck against
- * existing values. Also, we do not want to add it to the
- * avl tree (if one is being maintained)
- *
+ * existing values.
*/
- rc = 0; /* Presume no duplicate */
+ rc = slapi_valueset_add_attr_value_ext(&sa->sa_attr, &sa->sa_deleted_values,value, SLAPI_VALUE_FLAG_PASSIN);
}
- else if ( !check_for_duplicate_values )
+ else
{
- rc = LDAP_SUCCESS; /* presume no duplicate */
- } else {
- /* For value dup checking, we either use brute-force, if there's a small number */
- /* Or a tree-based approach if there's a large number. */
- /* The tree code is expensive, which is why we don't use it unless there's many attributes */
- rc = 0; /* Presume no duplicate */
- if (fast_dup_check)
- {
- /* Fast dup-checking */
- /* Do we now have so many values that we should switch to tree-based checking ? */
- if (sa->sa_present_values.num > STR2ENTRY_VALUE_DUPCHECK_THRESHOLD)
- {
- /* Make the tree from the existing attr values */
- rc= valuetree_add_valuearray( &sa->sa_attr, sa->sa_present_values.va, &sa->sa_vtree, NULL);
- /* Check if the value already exists, in the tree. */
- rc= valuetree_add_value( &sa->sa_attr, value, &sa->sa_vtree);
- fast_dup_check = 0;
- }
- else
- {
- /* JCM - need an efficient valuearray function to do this */
- /* Brute-force check */
- for ( j = 0; j < sa->sa_present_values.num; j++ )/* JCM innards */
- {
- if (0 == sa->sa_comparefn(slapi_value_get_berval(value),slapi_value_get_berval(sa->sa_present_values.va[j])))/* JCM innards */
- {
- /* Oops---this value matches one already present */
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- break;
- }
- }
- }
- }
- else
- {
- /* Check if the value already exists, in the tree. */
- rc = valuetree_add_value( &sa->sa_attr, value, &sa->sa_vtree);
- }
+ int flags = SLAPI_VALUE_FLAG_PASSIN;
+ if (check_for_duplicate_values) flags |= SLAPI_VALUE_FLAG_DUPCHECK;
+ rc = slapi_valueset_add_attr_value_ext(&sa->sa_attr, &sa->sa_present_values,value, flags);
}
if ( rc==LDAP_SUCCESS )
{
- if(value_state==VALUE_DELETED)
- {
- valuearrayfast_add_value_passin(&sa->sa_deleted_values,value);
- value= NULL; /* value was consumed */
- }
- else
- {
- valuearrayfast_add_value_passin(&sa->sa_present_values,value);
- value= NULL; /* value was consumed */
- }
+ value= NULL; /* value was consumed */
if(attributedeletioncsn!=NULL)
{
sa->sa_attributedeletioncsn= attributedeletioncsn;
@@ -1147,7 +1081,7 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo )
else
{
/* Failure adding to value tree */
- LDAPDebug( LDAP_DEBUG_ANY, "str2entry_dupcheck: unexpected failure %d constructing value tree\n", rc, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_ANY, "str2entry_dupcheck: unexpected failure %d adding value\n", rc, 0, 0 );
slapi_entry_free( e ); e = NULL;
goto free_and_return;
}
@@ -1212,27 +1146,21 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo )
}
if(alist!=NULL)
{
- int maxvals = 0;
Slapi_Attr **a= NULL;
attrlist_find_or_create_locking_optional(alist, sa->sa_type, &a, PR_FALSE);
- valuearray_add_valuearray_fast( /* JCM should be calling a valueset function */
- &(*a)->a_present_values.va, /* JCM .va is private */
- sa->sa_present_values.va,
- 0, /* Currently there are no present values on the attribute */
- sa->sa_present_values.num,
- &maxvals,
- 1/*Exact*/,
- 1/*Passin*/);
+ slapi_valueset_add_attr_valuearray_ext(
+ *a,
+ &(*a)->a_present_values,
+ sa->sa_present_values.va,
+ sa->sa_present_values.num,
+ SLAPI_VALUE_FLAG_PASSIN, NULL);
sa->sa_present_values.num= 0; /* The values have been consumed */
- maxvals = 0;
- valuearray_add_valuearray_fast( /* JCM should be calling a valueset function */
- &(*a)->a_deleted_values.va, /* JCM .va is private */
- sa->sa_deleted_values.va,
- 0, /* Currently there are no deleted values on the attribute */
- sa->sa_deleted_values.num,
- &maxvals,
- 1/*Exact*/,
- 1/*Passin*/);
+ slapi_valueset_add_attr_valuearray_ext(
+ *a,
+ &(*a)->a_deleted_values,
+ sa->sa_deleted_values.va,
+ sa->sa_deleted_values.num,
+ SLAPI_VALUE_FLAG_PASSIN, NULL);
sa->sa_deleted_values.num= 0; /* The values have been consumed */
if(sa->sa_attributedeletioncsn!=NULL)
{
@@ -1279,9 +1207,8 @@ free_and_return:
for ( i = 0; i < nattrs; i++ )
{
slapi_ch_free((void **) &(attrs[ i ].sa_type));
- valuearrayfast_done(&attrs[ i ].sa_present_values);
- valuearrayfast_done(&attrs[ i ].sa_deleted_values);
- valuetree_free( &attrs[ i ].sa_vtree );
+ slapi_ch_free((void **) &(attrs[ i ].sa_present_values.va));
+ slapi_ch_free((void **) &(attrs[ i ].sa_deleted_values.va));
attr_done( &attrs[ i ].sa_attr );
}
if (tree_attr_checking)
@@ -2663,7 +2590,7 @@ slapi_entry_add_string(Slapi_Entry *e, const char *type, const char *value)
{
Slapi_Attr **a= NULL;
attrlist_find_or_create(&e->e_attrs, type, &a);
- valueset_add_string ( &(*a)->a_present_values, value, CSN_TYPE_UNKNOWN, NULL);
+ valueset_add_string ( *a, &(*a)->a_present_values, value, CSN_TYPE_UNKNOWN, NULL);
return 0;
}
diff --git a/ldap/servers/slapd/entrywsi.c b/ldap/servers/slapd/entrywsi.c
index cca615d..8cee986 100644
--- a/ldap/servers/slapd/entrywsi.c
+++ b/ldap/servers/slapd/entrywsi.c
@@ -464,7 +464,10 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **b
/* Append the pending values to a->a_present_values */
valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
- valueset_add_valuearray_ext(&a->a_present_values, valuestoadd, SLAPI_VALUE_FLAG_PASSIN);
+ slapi_valueset_add_attr_valuearray_ext(a, &a->a_present_values,
+ valuestoadd,
+ valuearray_count(valuestoadd),
+ SLAPI_VALUE_FLAG_PASSIN, NULL);
slapi_ch_free ( (void **)&valuestoadd );
/*
@@ -502,7 +505,10 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **b
Slapi_ValueSet vs;
/* Add each deleted value to the present list */
valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_UPDATED,csn);
- valueset_add_valuearray_ext(&a->a_present_values, deletedvalues, SLAPI_VALUE_FLAG_PASSIN);
+ slapi_valueset_add_attr_valuearray_ext(a, &a->a_present_values,
+ deletedvalues,
+ valuearray_count(deletedvalues),
+ SLAPI_VALUE_FLAG_PASSIN, NULL);
/* Remove the deleted values from the values to add */
valueset_set_valuearray_passin(&vs,valuestoadd);
valueset_remove_valuearray(&vs, a, deletedvalues, SLAPI_VALUE_FLAG_IGNOREERROR, &v);
@@ -583,7 +589,10 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
valuearray_free(&valuesupdated);
valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
- valueset_add_valuearray_ext(&a->a_deleted_values, valuestodelete, SLAPI_VALUE_FLAG_PASSIN);
+ slapi_valueset_add_attr_valuearray_ext(a, &a->a_deleted_values,
+ valuestodelete,
+ valuearray_count(valuestodelete),
+ SLAPI_VALUE_FLAG_PASSIN, NULL);
/* all the elements in valuestodelete are passed;
* should free valuestodelete only (don't call valuearray_free)
* [622023] */
@@ -602,7 +611,10 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
/* We don't maintain a deleted value list for single valued attributes */
/* Add each deleted value to the deleted set */
valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_DELETED,csn);
- valueset_add_valuearray_ext(&a->a_deleted_values, deletedvalues, SLAPI_VALUE_FLAG_PASSIN);
+ slapi_valueset_add_attr_valuearray_ext(a, &a->a_deleted_values,
+ deletedvalues,
+ valuearray_count(deletedvalues),
+ SLAPI_VALUE_FLAG_PASSIN, NULL);
slapi_ch_free((void **)&deletedvalues);
}
else {
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index fcdbf2a..7e53db0 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -167,13 +167,6 @@ int valuearray_first_value( Slapi_Value **va, Slapi_Value **v );
void valuearrayfast_init(struct valuearrayfast *vaf,Slapi_Value **va);
void valuearrayfast_done(struct valuearrayfast *vaf);
-void valuearrayfast_add_value(struct valuearrayfast *vaf,const Slapi_Value *v);
-void valuearrayfast_add_value_passin(struct valuearrayfast *vaf,Slapi_Value *v);
-void valuearrayfast_add_valuearrayfast(struct valuearrayfast *vaf,const struct valuearrayfast *vaf_add);
-
-int valuetree_add_value( const Slapi_Attr *sattr, const Slapi_Value *va, Avlnode **valuetreep);
-int valuetree_add_valuearray( const Slapi_Attr *sattr, Slapi_Value **va, Avlnode **valuetreep, int *duplicate_index);
-void valuetree_free( Avlnode **valuetreep );
/* Valueset functions */
@@ -184,15 +177,17 @@ int valueset_remove_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Va
int valueset_purge(Slapi_ValueSet *vs, const CSN *csn);
Slapi_Value **valueset_get_valuearray(const Slapi_ValueSet *vs);
size_t valueset_size(const Slapi_ValueSet *vs);
+void slapi_valueset_add_valuearray(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **addvals);
void valueset_add_valuearray(Slapi_ValueSet *vs, Slapi_Value **addvals);
void valueset_add_valuearray_ext(Slapi_ValueSet *vs, Slapi_Value **addvals, PRUint32 flags);
-void valueset_add_string(Slapi_ValueSet *vs, const char *s, CSNType t, const CSN *csn);
+void valueset_add_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s, CSNType t, const CSN *csn);
void valueset_update_csn(Slapi_ValueSet *vs, CSNType t, const CSN *csn);
void valueset_add_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2);
int valueset_intersectswith_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **values, int *duplicate_index);
Slapi_ValueSet *valueset_dup(const Slapi_ValueSet *dupee);
void valueset_remove_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s);
-int valueset_replace(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **vals);
+int valueset_replace_valuearray(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **vals);
+int valueset_replace_valuearray_ext(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **vals, int dupcheck);
void valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated);
void valueset_set_valuearray_byval(Slapi_ValueSet *vs, Slapi_Value **addvals);
void valueset_set_valuearray_passin(Slapi_ValueSet *vs, Slapi_Value **addvals);
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 258f6eb..045989d 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -4707,11 +4707,11 @@ va_locate_oc_val( Slapi_Value **va, const char *oc_name, const char *oc_oid )
* oc_unlock();
*/
static void
-va_expand_one_oc( const char *dn, Slapi_Value ***vap, const char *ocs )
+va_expand_one_oc( const char *dn, const Slapi_Attr *a, Slapi_ValueSet *vs, const char *ocs )
{
struct objclass *this_oc, *sup_oc;
- int p,i;
- Slapi_Value **newva;
+ int p;
+ Slapi_Value **va = vs->va;
this_oc = oc_find_nolock( ocs );
@@ -4728,29 +4728,18 @@ va_expand_one_oc( const char *dn, Slapi_Value ***vap, const char *ocs )
return; /* superior is unknown -- ignore */
}
- p = va_locate_oc_val( *vap, sup_oc->oc_name, sup_oc->oc_oid );
+ p = va_locate_oc_val( va, sup_oc->oc_name, sup_oc->oc_oid );
if ( p != -1 ) {
return; /* value already present -- done! */
}
- /* parent was not found. add to the end */
- for ( i = 0; (*vap)[i] != NULL; i++ ) {
- ;
- }
-
- /* prevent loops: stop if more than 1000 OC values are present */
- if ( i > 1000 ) {
+ if ( slapi_valueset_count(vs) > 1000 ) {
return;
}
- newva = (Slapi_Value **)slapi_ch_realloc( (char *)*vap,
- ( i + 2 )*sizeof(Slapi_Value *));
-
- newva[i] = slapi_value_new_string(sup_oc->oc_name);
- newva[i+1] = NULL;
-
- *vap = newva;
+ slapi_valueset_add_attr_value_ext(a, vs, slapi_value_new_string(sup_oc->oc_name), SLAPI_VALUE_FLAG_PASSIN);
+
LDAPDebug( LDAP_DEBUG_TRACE,
"Entry \"%s\": added missing objectClass value %s\n",
dn, sup_oc->oc_name, 0 );
@@ -4762,11 +4751,12 @@ va_expand_one_oc( const char *dn, Slapi_Value ***vap, const char *ocs )
* All missing superior classes are added to the objectClass attribute, as
* is 'top' if it is missing.
*/
-void
-slapi_schema_expand_objectclasses( Slapi_Entry *e )
+static void
+schema_expand_objectclasses_ext( Slapi_Entry *e, int lock)
{
Slapi_Attr *sa;
- Slapi_Value **va;
+ Slapi_Value *v;
+ Slapi_ValueSet *vs;
const char *dn = slapi_entry_get_dn_const( e );
int i;
@@ -4774,76 +4764,41 @@ slapi_schema_expand_objectclasses( Slapi_Entry *e )
return; /* no OC values -- nothing to do */
}
- va = attr_get_present_values( sa );
-
- if ( va == NULL || va[0] == NULL ) {
+ vs = &sa->a_present_values;
+ if ( slapi_valueset_isempty(vs) ) {
return; /* no OC values -- nothing to do */
}
- oc_lock_read();
+ if (lock)
+ oc_lock_read();
/*
* This loop relies on the fact that bv_expand_one_oc()
* always adds to the end
*/
- for ( i = 0; va[i] != NULL; ++i ) {
- if ( NULL != slapi_value_get_string(va[i]) ) {
- va_expand_one_oc( dn, &va, slapi_value_get_string(va[i]) );
- }
+ i = slapi_valueset_first_value(vs,&v);
+ while ( v != NULL) {
+ if ( NULL != slapi_value_get_string(v) ) {
+ va_expand_one_oc( dn, sa, &sa->a_present_values, slapi_value_get_string(v) );
+ }
+ i = slapi_valueset_next_value(vs, i, &v);
}
/* top must always be present */
- va_expand_one_oc( dn, &va, "top" );
-
- /*
- * Reset the present values in the set because we may have realloc'd it.
- * Note that this is the counterpart to the attr_get_present_values()
- * call we made above... nothing new has been allocated, but sa holds
- * a pointer to the original (pre realloc) va.
- */
- sa->a_present_values.va = va;
-
- oc_unlock();
+ va_expand_one_oc( dn, sa, &sa->a_present_values, "top" );
+ if (lock)
+ oc_unlock();
+}
+void
+slapi_schema_expand_objectclasses( Slapi_Entry *e )
+{
+ schema_expand_objectclasses_ext( e, 1);
}
void
schema_expand_objectclasses_nolock( Slapi_Entry *e )
{
- Slapi_Attr *sa;
- Slapi_Value **va;
- const char *dn = slapi_entry_get_dn_const( e );
- int i;
-
- if ( 0 != slapi_entry_attr_find( e, SLAPI_ATTR_OBJECTCLASS, &sa )) {
- return; /* no OC values -- nothing to do */
- }
-
- va = attr_get_present_values( sa );
-
- if ( va == NULL || va[0] == NULL ) {
- return; /* no OC values -- nothing to do */
- }
-
- /*
- * This loop relies on the fact that bv_expand_one_oc()
- * always adds to the end
- */
- for ( i = 0; va[i] != NULL; ++i ) {
- if ( NULL != slapi_value_get_string(va[i]) ) {
- va_expand_one_oc( dn, &va, slapi_value_get_string(va[i]) );
- }
- }
-
- /* top must always be present */
- va_expand_one_oc( dn, &va, "top" );
-
- /*
- * Reset the present values in the set because we may have realloc'd it.
- * Note that this is the counterpart to the attr_get_present_values()
- * call we made above... nothing new has been allocated, but sa holds
- * a pointer to the original (pre realloc) va.
- */
- sa->a_present_values.va = va;
+ schema_expand_objectclasses_ext( e, 0);
}
/* lock to protect both objectclass and schema_dse */
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 9a05da9..2465500 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -439,8 +439,14 @@ struct slapi_value
* struct slapi_value_tree *vt;
* };
*/
+
+/* It is a useless layer, always use the valuarray fast version */
+#define VALUE_SORT_THRESHOLD 10
struct slapi_value_set
{
+ int num; /* The number of values in the array */
+ int max; /* The number of slots in the array */
+ int *sorted; /* sorted array of indices, if NULL va is not sorted */
struct slapi_value **va;
};
@@ -511,6 +517,8 @@ typedef struct asyntaxinfo {
#define SLAPI_ATTR_FLAG_NOLOCKING 0x0020 /* the init code doesn't lock the
tables */
#define SLAPI_ATTR_FLAG_KEEP 0x8000 /* keep when replacing all */
+#define SLAPI_ATTR_FLAG_SYNTAX_LOOKUP_DONE 0x010000 /* syntax lookup done, flag set */
+#define SLAPI_ATTR_FLAG_SYNTAX_IS_DN 0x020000 /* syntax lookup done, flag set */
/* This is the type of the function passed into attr_syntax_enumerate_attrs */
typedef int (*AttrEnumFunc)(struct asyntaxinfo *asi, void *arg);
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 5c29b0c..521de6a 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -4598,6 +4598,7 @@ void slapi_ber_bvcpy(struct berval *bvd, const struct berval *bvs);
#define SLAPI_VALUE_FLAG_IGNOREERROR 0x2
#define SLAPI_VALUE_FLAG_PRESERVECSNSET 0x4
#define SLAPI_VALUE_FLAG_USENEWVALUE 0x8 /* see valueset_remove_valuearray */
+#define SLAPI_VALUE_FLAG_DUPCHECK 0x10 /* used in valueset_add... */
/**
* Creates an empty \c Slapi_ValueSet structure.
@@ -4691,7 +4692,8 @@ void slapi_valueset_add_value(Slapi_ValueSet *vs, const Slapi_Value *addval);
* \see slapi_valueset_first_value()
* \see slapi_valueset_next_value()
*/
-void slapi_valueset_add_value_ext(Slapi_ValueSet *vs, Slapi_Value *addval, unsigned long flags);
+void slapi_valueset_add_value_ext(Slapi_ValueSet *vs, const Slapi_Value *addval, unsigned long flags);
+int slapi_valueset_add_attr_value_ext(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value *addval, unsigned long flags);
/**
* Gets the first value in a \c Slapi_ValueSet structure.
@@ -4747,6 +4749,16 @@ int slapi_valueset_next_value( Slapi_ValueSet *vs, int index, Slapi_Value **v);
int slapi_valueset_count( const Slapi_ValueSet *vs);
/**
+ * Checks if a \c Slapi_ValueSet structure has values
+ *
+ * \param vs Pointer to the \c Slapi_ValueSet structure of which
+ * you wish to get the count.
+ * \return 1 if there are no values contained in the \c Slapi_ValueSet structure.
+ * \return 0 if there are values contained in the \c Slapi_ValueSet structure.
+ */
+int slapi_valueset_isempty( const Slapi_ValueSet *vs);
+
+/**
* Initializes a \c Slapi_ValueSet with copies of the values of a \c Slapi_Mod structure.
*
* \param vs Pointer to the \c Slapi_ValueSet structure into which
@@ -4777,6 +4789,7 @@ void slapi_valueset_set_from_smod(Slapi_ValueSet *vs, Slapi_Mod *smod);
* \see slapi_valueset_done()
*/
void slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2);
+void slapi_valueset_join_attr_valueset(const Slapi_Attr *a, Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2);
/**
* Finds a requested value in a valueset.
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 8184843..11f10e8 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -834,9 +834,12 @@ int charray_normdn_add(char ***chararray, char *dn, char *errstr);
* the very least before we make them public.
*/
void valuearray_add_value(Slapi_Value ***vals, const Slapi_Value *addval);
-void valuearray_add_value_fast(Slapi_Value ***vals, Slapi_Value *addval, int nvals, int *maxvals, int exact, int passin);
void valuearray_add_valuearray( Slapi_Value ***vals, Slapi_Value **addvals, PRUint32 flags );
void valuearray_add_valuearray_fast( Slapi_Value ***vals, Slapi_Value **addvals, int nvals, int naddvals, int *maxvals, int exact, int passin );
+Slapi_Value * valueset_find_sorted (const Slapi_Attr *a, const Slapi_ValueSet *vs, const Slapi_Value *v, int *index);
+int valueset_insert_value_to_sorted(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value *vi, int dupcheck);
+void valueset_array_to_sorted (const Slapi_Attr *a, Slapi_ValueSet *vs);
+int slapi_valueset_add_attr_valuearray_ext(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **addval, int nvals, unsigned long flags, int *dup_index);
int valuearray_find(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v);
int valuearray_dn_normalize_value(Slapi_Value **vals);
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
index 732b411..4ee2938 100644
--- a/ldap/servers/slapd/valueset.c
+++ b/ldap/servers/slapd/valueset.c
@@ -469,7 +469,8 @@ valuearray_purge(Slapi_Value ***va, const CSN *csn)
*va= NULL;
}
- return(0);
+ /* return the number of remaining values */
+ return(i);
}
size_t
@@ -498,51 +499,6 @@ valuearray_update_csn(Slapi_Value **va, CSNType t, const CSN *csn)
}
}
-/*
- * Shunt up the values to cover the empty slots.
- *
- * "compressed" means "contains no NULL's"
- *
- * Invariant for the outer loop:
- * va[0..i] is compressed &&
- * va[n..numvalues] contains just NULL's
- *
- * Invariant for the inner loop:
- * i<j<=k<=n && va[j..k] has been shifted left by (j-i) places &&
- * va[k..n] remains to be shifted left by (j-i) places
- *
- */
-void
-valuearray_compress(Slapi_Value **va,int numvalues)
-{
- int i = 0;
- int n= numvalues;
- while(i<n)
- {
- if ( va[i] != NULL ) {
- i++;
- } else {
- int k,j;
- j = i + 1;
- /* Find the length of the next run of NULL's */
- while( j<n && va[j] == NULL) { j++; }
- /* va[i..j] is all NULL && j<= n */
- for ( k = j; k<n; k++ )
- {
- va[k - (j-i)] = va[k];
- va[k] = NULL;
- }
- /* va[i..n] has been shifted down by j-i places */
- n = n - (j-i);
- /*
- * If va[i] in now non null, then bump i,
- * if not then we are done anyway (j==n) so can bump it.
- */
- i++;
- }
- }
-}
-
/* <=========================== Value Array Fast ==========================> */
void
@@ -583,237 +539,11 @@ valuearrayfast_add_value_passin(struct valuearrayfast *vaf,Slapi_Value *v)
vaf->num++;
}
-void
-valuearrayfast_add_valuearrayfast(struct valuearrayfast *vaf,const struct valuearrayfast *vaf_add)
-{
- valuearray_add_valuearray_fast(&vaf->va,vaf_add->va,vaf->num,vaf_add->num,&vaf->max,0/*Exact*/,0/*!PassIn*/);
- vaf->num+= vaf_add->num;
-}
-
-/* <=========================== ValueArrayIndexTree =======================> */
-
-static int valuetree_dupvalue_disallow( caddr_t d1, caddr_t d2 );
-static int valuetree_node_cmp( caddr_t d1, caddr_t d2 );
-static int valuetree_node_free( caddr_t data );
-
-/*
- * structure used within AVL value trees.
- */
-typedef struct valuetree_node
-{
- int index; /* index into the value array */
- Slapi_Value *sval; /* the actual value */
-} valuetree_node;
-
-/*
- * Create or update an AVL tree of values that can be used to speed up value
- * lookups. We store the index keys for the values in the AVL tree so
- * we can use a trivial comparison function.
- *
- * Returns:
- * LDAP_SUCCESS on success,
- * LDAP_TYPE_OR_VALUE_EXISTS if the value already exists,
- * LDAP_OPERATIONS_ERROR for some unexpected failure.
- *
- * Sets *valuetreep to the root of the AVL tree that was created. If a
- * non-zero value is returned, the tree is freed if free_on_error is non-zero
- * and *valuetreep is set to NULL.
- */
-int
-valuetree_add_valuearray( const Slapi_Attr *sattr, Slapi_Value **va, Avlnode **valuetreep, int *duplicate_index )
-{
- int rc= LDAP_SUCCESS;
-
- PR_ASSERT(sattr!=NULL);
- PR_ASSERT(valuetreep!=NULL);
-
- if ( duplicate_index ) {
- *duplicate_index = -1;
- }
-
- if ( !valuearray_isempty(va) )
- {
- Slapi_Value **keyvals;
- /* Convert the value array into key values */
- if ( slapi_attr_values2keys_sv( sattr, (Slapi_Value**)va, &keyvals, LDAP_FILTER_EQUALITY ) != 0 ) /* jcm cast */
- {
- LDAPDebug( LDAP_DEBUG_ANY,"slapi_attr_values2keys_sv for attribute %s failed\n", sattr->a_type, 0, 0 );
- rc= LDAP_OPERATIONS_ERROR;
- }
- else
- {
- int i;
- valuetree_node *vaip;
- for ( i = 0; rc==LDAP_SUCCESS && va[i] != NULL; ++i )
- {
- if ( keyvals[i] == NULL )
- {
- LDAPDebug( LDAP_DEBUG_ANY,"slapi_attr_values2keys_sv for attribute %s did not return enough key values\n", sattr->a_type, 0, 0 );
- rc= LDAP_OPERATIONS_ERROR;
- }
- else
- {
- vaip = (valuetree_node *)slapi_ch_malloc( sizeof( valuetree_node ));
- vaip->index = i;
- vaip->sval = keyvals[i];
- if (( rc = avl_insert( valuetreep, vaip, valuetree_node_cmp, valuetree_dupvalue_disallow )) != 0 )
- {
- slapi_ch_free( (void **)&vaip );
- /* Value must already be in there */
- rc= LDAP_TYPE_OR_VALUE_EXISTS;
- if ( duplicate_index ) {
- *duplicate_index = i;
- }
- }
- else
- {
- keyvals[i]= NULL;
- }
- }
- }
- /* start freeing at index i - the rest of them have already
- been moved into valuetreep
- the loop iteration will always do the +1, so we have
- to remove it if so */
- i = (i > 0) ? i-1 : 0;
- valuearray_free_ext( &keyvals, i );
- }
- }
- if(rc!=0)
- {
- valuetree_free( valuetreep );
- }
-
- return rc;
-}
-
-int
-valuetree_add_value( const Slapi_Attr *sattr, const Slapi_Value *v, Avlnode **valuetreep)
-{
- Slapi_Value *va[2];
- va[0]= (Slapi_Value*)v;
- va[1]= NULL;
- return valuetree_add_valuearray( sattr, va, valuetreep, NULL);
-}
-
-
-/*
- *
- * Find value "v" using AVL tree "valuetree"
- *
- * returns LDAP_SUCCESS if "v" was found, LDAP_NO_SUCH_ATTRIBUTE
- * if "v" was not found and LDAP_OPERATIONS_ERROR if some unexpected error occurs.
- */
-static int
-valuetree_find( const struct slapi_attr *a, const Slapi_Value *v, Avlnode *valuetree, int *index)
-{
- const Slapi_Value *oneval[2];
- Slapi_Value **keyvals;
- valuetree_node *vaip, tmpvain;
-
- PR_ASSERT(a!=NULL);
- PR_ASSERT(a->a_plugin!=NULL);
- PR_ASSERT(v!=NULL);
- PR_ASSERT(valuetree!=NULL);
- PR_ASSERT(index!=NULL);
-
- if ( a == NULL || v == NULL || valuetree == NULL )
- {
- return( LDAP_OPERATIONS_ERROR );
- }
-
- keyvals = NULL;
- oneval[0] = v;
- oneval[1] = NULL;
- if ( slapi_attr_values2keys_sv( a, (Slapi_Value**)oneval, &keyvals, LDAP_FILTER_EQUALITY ) != 0 /* jcm cast */
- || keyvals == NULL
- || keyvals[0] == NULL )
- {
- LDAPDebug( LDAP_DEBUG_ANY, "valuetree_find_and_replace: "
- "slapi_attr_values2keys_sv failed for type %s\n",
- a->a_type, 0, 0 );
- return( LDAP_OPERATIONS_ERROR );
- }
-
- tmpvain.index = 0;
- tmpvain.sval = keyvals[0];
- vaip = (valuetree_node *)avl_find( valuetree, &tmpvain, valuetree_node_cmp );
-
- if ( keyvals != NULL )
- {
- valuearray_free( &keyvals );
- }
-
- if (vaip == NULL)
- {
- return( LDAP_NO_SUCH_ATTRIBUTE );
- }
- else
- {
- *index= vaip->index;
- }
-
- return( LDAP_SUCCESS );
-}
-
-static int
-valuetree_dupvalue_disallow( caddr_t d1, caddr_t d2 )
-{
- return( 1 );
-}
-
-
-void
-valuetree_free( Avlnode **valuetreep )
-{
- if ( valuetreep != NULL && *valuetreep != NULL )
- {
- avl_free( *valuetreep, valuetree_node_free );
- *valuetreep = NULL;
- }
-}
-
-
-static int
-valuetree_node_free( caddr_t data )
-{
- if ( data!=NULL )
- {
- valuetree_node *vaip = (valuetree_node *)data;
-
- slapi_value_free(&vaip->sval);
- slapi_ch_free( (void **)&data );
- }
- return( 0 );
-}
-
-
-static int
-valuetree_node_cmp( caddr_t d1, caddr_t d2 )
-{
- const struct berval *bv1, *bv2;
- int rc;
-
- bv1 = slapi_value_get_berval(((valuetree_node *)d1)->sval);
- bv2 = slapi_value_get_berval(((valuetree_node *)d2)->sval);
-
- if ( bv1->bv_len < bv2->bv_len ) {
- rc = -1;
- } else if ( bv1->bv_len > bv2->bv_len ) {
- rc = 1;
- } else {
- rc = memcmp( bv1->bv_val, bv2->bv_val, bv1->bv_len );
- }
-
- return( rc );
-}
-
/* <=========================== Value Set =======================> */
-/*
- * JCM: All of these valueset functions are just forwarded to the
- * JCM: valuearray functions... waste of time. Inline them!
- */
+#define VALUESET_ARRAY_SORT_THRESHOLD 10
+#define VALUESET_ARRAY_MINSIZE 2
+#define VALUESET_ARRAY_MAXINCREMENT 4096
Slapi_ValueSet *
slapi_valueset_new()
@@ -832,6 +562,9 @@ slapi_valueset_init(Slapi_ValueSet *vs)
if(vs!=NULL)
{
vs->va= NULL;
+ vs->sorted = NULL;
+ vs->num = 0;
+ vs->max = 0;
}
}
@@ -845,6 +578,13 @@ slapi_valueset_done(Slapi_ValueSet *vs)
valuearray_free(&vs->va);
vs->va= NULL;
}
+ if (vs->sorted != NULL)
+ {
+ slapi_ch_free ((void **)&vs->sorted);
+ vs->sorted = NULL;
+ }
+ vs->num = 0;
+ vs->max = 0;
}
}
@@ -869,8 +609,22 @@ slapi_valueset_set_from_smod(Slapi_ValueSet *vs, Slapi_Mod *smod)
void
valueset_set_valuearray_byval(Slapi_ValueSet *vs, Slapi_Value **addvals)
{
- slapi_valueset_init(vs);
- valueset_add_valuearray(vs,addvals);
+ int i, j=0;
+ slapi_valueset_init(vs);
+ vs->num = valuearray_count(addvals);
+ vs->max = vs->num + 1;
+ vs->va = (Slapi_Value **) slapi_ch_malloc( vs->max * sizeof(Slapi_Value *));
+ for ( i = 0, j = 0; i < vs->num; i++)
+ {
+ if ( addvals[i]!=NULL )
+ {
+ /* We copy the values */
+ vs->va[j] = slapi_value_dup(addvals[i]);
+ j++;
+ }
+ }
+ vs->va[j] = NULL;
+
}
void
@@ -878,6 +632,8 @@ valueset_set_valuearray_passin(Slapi_ValueSet *vs, Slapi_Value **addvals)
{
slapi_valueset_init(vs);
vs->va= addvals;
+ vs->num = valuearray_count(addvals);
+ vs->max = vs->num + 1;
}
void
@@ -887,6 +643,15 @@ slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
valueset_add_valueset(vs1,vs2);
}
+void
+slapi_valueset_join_attr_valueset(const Slapi_Attr *a, Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
+{
+ if (slapi_valueset_isempty(vs1))
+ valueset_add_valueset(vs1,vs2);
+ else
+ slapi_valueset_add_attr_valuearray_ext (a, vs1, vs2->va, vs2->num, 0, NULL);
+}
+
int
slapi_valueset_first_value( Slapi_ValueSet *vs, Slapi_Value **v )
{
@@ -914,21 +679,21 @@ slapi_valueset_next_value( Slapi_ValueSet *vs, int index, Slapi_Value **v)
int
slapi_valueset_count( const Slapi_ValueSet *vs)
{
- int r=0;
if (NULL != vs)
{
- if(!valuearray_isempty(vs->va))
- {
- r= valuearray_count(vs->va);
- }
+ return (vs->num);
}
- return r;
+ return 0;
}
int
-slapi_valueset_isempty(const Slapi_ValueSet *vs)
+slapi_valueset_isempty( const Slapi_ValueSet *vs)
{
- return valueset_isempty(vs);
+ if (NULL != vs)
+ {
+ return (vs->num == 0);
+ }
+ return 1;
}
int
@@ -945,12 +710,14 @@ Slapi_Value *
slapi_valueset_find(const Slapi_Attr *a, const Slapi_ValueSet *vs, const Slapi_Value *v)
{
Slapi_Value *r= NULL;
- if(vs && !valuearray_isempty(vs->va))
- {
- int i= valuearray_find(a,vs->va,v);
- if(i!=-1)
- {
- r= vs->va[i];
+ if(vs->num > 0) {
+ if (vs->sorted) {
+ r = valueset_find_sorted(a,vs,v,NULL);
+ } else {
+ int i= valuearray_find(a,vs->va,v);
+ if(i!=-1) {
+ r= vs->va[i];
+ }
}
}
return r;
@@ -959,17 +726,46 @@ slapi_valueset_find(const Slapi_Attr *a, const Slapi_ValueSet *vs, const Slapi_V
/*
* The value is found in the set, removed and returned.
* The caller is responsible for freeing the value.
+ *
+ * The _sorted function also handles the cleanup of the sorted array
*/
Slapi_Value *
-valueset_remove_value(const Slapi_Attr *a, Slapi_ValueSet *vs, const Slapi_Value *v)
+valueset_remove_value_sorted(const Slapi_Attr *a, Slapi_ValueSet *vs, const Slapi_Value *v)
{
Slapi_Value *r= NULL;
- if(!valuearray_isempty(vs->va))
- {
- r= valuearray_remove_value(a, vs->va, v);
+ int i, position = 0;
+ r = valueset_find_sorted(a,vs,v,&position);
+ if (r) {
+ /* the value was found, remove from valuearray */
+ int index = vs->sorted[position];
+ memmove(&vs->sorted[position],&vs->sorted[position+1],(vs->num - position)*sizeof(int));
+ memmove(&vs->va[index],&vs->va[index+1],(vs->num - index)*sizeof(Slapi_Value *));
+ vs->num--;
+ /* unfortunately the references in the sorted array
+ * to values past the removed one are no longer correct
+ * need to adjust */
+ for (i=0; i < vs->num; i++) {
+ if (vs->sorted[i] > index) vs->sorted[i]--;
+ }
}
return r;
}
+Slapi_Value *
+valueset_remove_value(const Slapi_Attr *a, Slapi_ValueSet *vs, const Slapi_Value *v)
+{
+ if (vs->sorted) {
+ return (valueset_remove_value_sorted(a, vs, v));
+ } else {
+ Slapi_Value *r= NULL;
+ if(!valuearray_isempty(vs->va))
+ {
+ r= valuearray_remove_value(a, vs->va, v);
+ if (r)
+ vs->num--;
+ }
+ return r;
+ }
+}
/*
* Remove any values older than the CSN.
@@ -978,11 +774,25 @@ int
valueset_purge(Slapi_ValueSet *vs, const CSN *csn)
{
int r= 0;
- if(!valuearray_isempty(vs->va))
- {
+ if(!valuearray_isempty(vs->va)) {
+ /* valuearray_purge is not valueset and sorting aware,
+ * maybe need to rewrite, at least keep the valueset
+ * consistent
+ */
r= valuearray_purge(&vs->va, csn);
+ vs->num = r;
+ if (vs->va == NULL) {
+ /* va was freed */
+ vs->max = 0;
+ }
+ /* we can no longer rely on the sorting */
+ if (vs->sorted != NULL)
+ {
+ slapi_ch_free ((void **)&vs->sorted);
+ vs->sorted = NULL;
+ }
}
- return r;
+ return 0;
}
Slapi_Value **
@@ -1005,11 +815,20 @@ valueset_size(const Slapi_ValueSet *vs)
* The value array is passed in by value.
*/
void
+slapi_valueset_add_valuearray(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **addvals)
+{
+ if(!valuearray_isempty(addvals))
+ {
+ slapi_valueset_add_attr_valuearray_ext (a, vs, addvals, valuearray_count(addvals), 0, NULL);
+ }
+}
+
+void
valueset_add_valuearray(Slapi_ValueSet *vs, Slapi_Value **addvals)
{
if(!valuearray_isempty(addvals))
{
- valuearray_add_valuearray(&vs->va, addvals, 0);
+ slapi_valueset_add_attr_valuearray_ext (NULL, vs, addvals, valuearray_count(addvals), 0, NULL);
}
}
@@ -1018,7 +837,7 @@ valueset_add_valuearray_ext(Slapi_ValueSet *vs, Slapi_Value **addvals, PRUint32
{
if(!valuearray_isempty(addvals))
{
- valuearray_add_valuearray(&vs->va, addvals, flags);
+ slapi_valueset_add_attr_valuearray_ext (NULL, vs, addvals, valuearray_count(addvals), flags, NULL);
}
}
@@ -1028,28 +847,281 @@ valueset_add_valuearray_ext(Slapi_ValueSet *vs, Slapi_Value **addvals, PRUint32
void
slapi_valueset_add_value(Slapi_ValueSet *vs, const Slapi_Value *addval)
{
- valuearray_add_value(&vs->va,addval);
+ slapi_valueset_add_value_ext(vs, addval, 0);
+}
+
+void
+slapi_valueset_add_value_ext(Slapi_ValueSet *vs, const Slapi_Value *addval, unsigned long flags)
+{
+ Slapi_Value *oneval[2];
+ oneval[0]= (Slapi_Value*)addval;
+ oneval[1]= NULL;
+ slapi_valueset_add_attr_valuearray_ext(NULL, vs, oneval, 1, flags, NULL);
+}
+
+
+/* find value v in the sorted array of values, using syntax of attribut a for comparison
+ *
+ */
+static int
+valueset_value_syntax_cmp( const Slapi_Attr *a, const Slapi_Value *v1, const Slapi_Value *v2 )
+{
+ /* this looks like a huge overhead, but there are no simple functions to normalize and
+ * compare available
+ */
+ const Slapi_Value *oneval[3];
+ Slapi_Value **keyvals;
+ int rc = -1;
+
+ keyvals = NULL;
+ oneval[0] = v1;
+ oneval[1] = v2;
+ oneval[2] = NULL;
+ if ( slapi_attr_values2keys_sv( a, (Slapi_Value**)oneval, &keyvals, LDAP_FILTER_EQUALITY ) != 0
+ || keyvals == NULL
+ || keyvals[0] == NULL || keyvals[1] == NULL)
+ {
+ /* this should never happen since always a syntax plugin to
+ * generate the keys will be found (there exists a default plugin)
+ * log an error and continue.
+ */
+ LDAPDebug( LDAP_DEBUG_ANY, "valueset_value_syntax_cmp: "
+ "slapi_attr_values2keys_sv failed for type %s\n",
+ a->a_type, 0, 0 );
+ } else {
+ struct berval *bv1, *bv2;
+ bv1 = &keyvals[0]->bv;
+ bv2 = &keyvals[1]->bv;
+ if ( bv1->bv_len < bv2->bv_len ) {
+ rc = -1;
+ } else if ( bv1->bv_len > bv2->bv_len ) {
+ rc = 1;
+ } else {
+ rc = memcmp( bv1->bv_val, bv2->bv_val, bv1->bv_len );
+ }
+ }
+ if (keyvals != NULL)
+ valuearray_free( &keyvals );
+ return (rc);
+
+}
+static int
+valueset_value_cmp( const Slapi_Attr *a, const Slapi_Value *v1, const Slapi_Value *v2 )
+{
+
+ if ( a == NULL || slapi_attr_is_dn_syntax_attr((Slapi_Attr *)a)) {
+ /* if no attr is provided just do a utf8compare */
+ /* for all the values the first step of normalization is done,
+ * case folding still needs to be done
+ */
+ /* would this be enough ?: return (strcasecmp(v1->bv.bv_val, v2->bv.bv_val)); */
+ return (slapi_utf8casecmp((unsigned char*)v1->bv.bv_val, (unsigned char*)v2->bv.bv_val));
+ } else {
+ /* slapi_value_compare doesn't work, it only returns 0 or -1
+ return (slapi_value_compare(a, v1, v2));
+ * use special compare, base on what valuetree_find did
+ */
+ return(valueset_value_syntax_cmp(a, v1, v2));
+ }
+}
+/* find a value in the sorted valuearray.
+ * If the value is found the pointer to the value is returned and if index is provided
+ * it will return the index of the value in the valuearray
+ * If the value is not found, index will contain the place where the value would be inserted
+ */
+Slapi_Value *
+valueset_find_sorted (const Slapi_Attr *a, const Slapi_ValueSet *vs, const Slapi_Value *v, int *index)
+{
+ int cmp = -1;
+ int bot = -1;
+ int top;
+
+ if (vs->num == 0) {
+ /* empty valueset */
+ if (index) *index = 0;
+ return (NULL);
+ } else {
+ top = vs->num;
+ }
+ while (top - bot > 1) {
+ int mid = (top + bot)/2;
+ if ( (cmp = valueset_value_cmp(a, v, vs->va[vs->sorted[mid]])) > 0)
+ bot = mid;
+ else
+ top = mid;
+ }
+ if (index) *index = top;
+ /* check if the value is found */
+ if ( top < vs->num && (0 == valueset_value_cmp(a, v, vs->va[vs->sorted[top]])))
+ return (vs->va[vs->sorted[top]]);
+ else
+ return (NULL);
}
void
-slapi_valueset_add_value_ext(Slapi_ValueSet *vs, Slapi_Value *addval, unsigned long flags)
+valueset_array_to_sorted (const Slapi_Attr *a, Slapi_ValueSet *vs)
+{
+ int i, j, swap;
+
+ /* initialize sort array */
+ for (i = 0; i < vs->num; i++)
+ vs->sorted[i] = i;
+
+ /* now sort it, use a simple insertion sort as the array will always
+ * be very small when initially sorted
+ */
+ for (i = 1; i < vs->num; i++) {
+ swap = vs->sorted[i];
+ j = i -1;
+
+ while ( j >= 0 && valueset_value_cmp (a, vs->va[vs->sorted[j]], vs->va[swap]) > 0 ) {
+ vs->sorted[j+1] = vs->sorted[j];
+ j--;
+ }
+ vs->sorted[j+1] = swap;
+ }
+}
+/* insert a value into a sorted array, if dupcheck is set no duplicate values will be accepted
+ * (is there a reason to allow duplicates ? LK
+ * if the value is inserted the the function returns the index where it was inserted
+ * if the value already exists -index is returned to indicate anerror an the index of the existing value
+ */
+int
+valueset_insert_value_to_sorted(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value *vi, int dupcheck)
+{
+ int index = -1;
+ Slapi_Value *v;
+ /* test for pre sorted array and to avoid boundary condition */
+ if (vs->num == 0) {
+ vs->sorted[0] = 0;
+ vs->num++;
+ return(0);
+ } else if (valueset_value_cmp (a, vi, vs->va[vs->sorted[vs->num-1]]) > 0 ) {
+ vs->sorted[vs->num] = vs->num;
+ vs->num++;
+ return (vs->num);
+ }
+ v = valueset_find_sorted (a, vs, vi, &index);
+ if (v && dupcheck) {
+ /* value already exists, do not insert duplicates */
+ return (-1);
+ } else {
+ memmove(&vs->sorted[index+1],&vs->sorted[index],(vs->num - index)* sizeof(int));
+ vs->sorted[index] = vs->num;
+ vs->num++;
+ return(index);
+ }
+
+}
+
+int
+slapi_valueset_add_attr_valuearray_ext(const Slapi_Attr *a, Slapi_ValueSet *vs,
+ Slapi_Value **addvals, int naddvals, unsigned long flags, int *dup_index)
+{
+ int rc = LDAP_SUCCESS;
+ int i, dup;
+ int allocate = 0;
+ int need;
+ int passin = flags & SLAPI_VALUE_FLAG_PASSIN;
+ int dupcheck = flags & SLAPI_VALUE_FLAG_DUPCHECK;
+
+ if (naddvals == 0)
+ return (rc);
+
+ need = vs->num + naddvals + 1;
+ if (need > vs->max) {
+ /* Expand the array */
+ allocate= vs->max;
+ if ( allocate == 0 ) /* initial allocation */
+ allocate = VALUESET_ARRAY_MINSIZE;
+ while ( allocate < need )
+ {
+ if (allocate > VALUESET_ARRAY_MAXINCREMENT )
+ /* do not grow exponentially */
+ allocate += VALUESET_ARRAY_MAXINCREMENT;
+ else
+ allocate *= 2;
+
+ }
+ }
+ if(allocate>0)
+ {
+ if(vs->va==NULL)
+ {
+ vs->va = (Slapi_Value **) slapi_ch_malloc( allocate * sizeof(Slapi_Value *));
+ }
+ else
+ {
+ vs->va = (Slapi_Value **) slapi_ch_realloc( (char *) vs->va, allocate * sizeof(Slapi_Value *));
+ if (vs->sorted) {
+ vs->sorted = (int *) slapi_ch_realloc( (char *) vs->sorted, allocate * sizeof(int));
+ }
+ }
+ vs->max= allocate;
+ }
+
+ if ( (vs->num + naddvals > VALUESET_ARRAY_SORT_THRESHOLD || dupcheck ) &&
+ !vs->sorted ) {
+ /* initialize sort array and do initial sort */
+ vs->sorted = (int *) slapi_ch_malloc( vs->max* sizeof(int));
+ valueset_array_to_sorted (a, vs);
+ }
+
+ for ( i = 0; i < naddvals; i++)
+ {
+ if ( addvals[i]!=NULL )
+ {
+ if(passin)
+ {
+ /* We consume the values */
+ (vs->va)[vs->num] = addvals[i];
+ }
+ else
+ {
+ /* We copy the values */
+ (vs->va)[vs->num] = slapi_value_dup(addvals[i]);
+ }
+ if (vs->sorted) {
+ dup = valueset_insert_value_to_sorted(a, vs, (vs->va)[vs->num], dupcheck);
+ if (dup < 0 ) {
+ rc = LDAP_TYPE_OR_VALUE_EXISTS;
+ if (dup_index) *dup_index = i;
+ if ( !passin)
+ slapi_value_free(&(vs->va)[vs->num]);
+ break;
+ }
+ } else {
+ vs->num++;
+ }
+ }
+ }
+ (vs->va)[vs->num] = NULL;
+
+ return (rc);
+}
+
+int
+slapi_valueset_add_attr_value_ext(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value *addval, unsigned long flags)
{
+
Slapi_Value *oneval[2];
+ int rc;
oneval[0]= (Slapi_Value*)addval;
oneval[1]= NULL;
- valuearray_add_valuearray(&vs->va, oneval, flags);
+ rc = slapi_valueset_add_attr_valuearray_ext(a, vs, oneval, 1, flags, NULL );
+ return (rc);
}
/*
* The string is passed in by value.
*/
void
-valueset_add_string(Slapi_ValueSet *vs, const char *s, CSNType t, const CSN *csn)
+valueset_add_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s, CSNType t, const CSN *csn)
{
Slapi_Value v;
value_init(&v,NULL,t,csn);
slapi_value_set_string(&v,s);
- valuearray_add_value(&vs->va,&v);
+ slapi_valueset_add_attr_value_ext(a, vs, &v, 0 );
value_done(&v);
}
@@ -1059,8 +1131,30 @@ valueset_add_string(Slapi_ValueSet *vs, const char *s, CSNType t, const CSN *csn
void
valueset_add_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
{
- if (vs1 && vs2)
- valueset_add_valuearray(vs1, vs2->va);
+ int i;
+
+ if (vs1 && vs2) {
+ if (vs2->va) {
+ /* need to copy valuearray */
+ if (vs2->max == 0) {
+ /* temporary hack, not all valuesets were created properly. fix it now */
+ vs1->num = valuearray_count(vs2->va);
+ vs1->max = vs1->num + 1;
+ } else {
+ vs1->num = vs2->num;
+ vs1->max = vs2->max;
+ }
+ vs1->va = (Slapi_Value **) slapi_ch_malloc( vs1->max * sizeof(Slapi_Value *));
+ for (i=0; i< vs1->num;i++) {
+ vs1->va[i] = slapi_value_dup(vs2->va[i]);
+ }
+ vs1->va[vs1->num] = NULL;
+ }
+ if (vs2->sorted) {
+ vs1->sorted = (int *) slapi_ch_malloc( vs1->max* sizeof(int));
+ memcpy(&vs1->sorted[0],&vs2->sorted[0],vs1->num* sizeof(int));
+ }
+ }
}
void
@@ -1070,7 +1164,7 @@ valueset_remove_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s)
Slapi_Value *removed;
value_init(&v,NULL,CSN_TYPE_NONE,NULL);
slapi_value_set_string(&v,s);
- removed = valuearray_remove_value(a, vs->va, &v);
+ removed = valueset_remove_value(a, vs, &v);
if(removed) {
slapi_value_free(&removed);
}
@@ -1109,158 +1203,59 @@ int
valueset_remove_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestodelete, int flags, Slapi_Value ***va_out)
{
int rc= LDAP_SUCCESS;
- if(!valuearray_isempty(vs->va))
+ if(vs->num > 0)
{
- int numberofvaluestodelete= valuearray_count(valuestodelete);
+ int i;
struct valuearrayfast vaf_out;
+
if ( va_out )
{
valuearrayfast_init(&vaf_out,*va_out);
}
/*
- * If there are more then one values, build an AVL tree to check
- * the duplicated values.
+ * For larger valuesets the valuarray is sorted, values can be deleted individually
+ *
*/
- if ( numberofvaluestodelete > 1 )
+ for ( i = 0; rc==LDAP_SUCCESS && valuestodelete[i] != NULL; ++i )
{
- /*
- * Several values to delete: first build an AVL tree that
- * holds all of the existing values and use that to find
- * the values we want to delete.
- */
- Avlnode *vtree = NULL;
- int numberofexistingvalues= slapi_valueset_count(vs);
- rc= valuetree_add_valuearray( a, vs->va, &vtree, NULL );
- if ( rc!=LDAP_SUCCESS )
- {
- /*
- * failed while constructing AVL tree of existing
- * values... something bad happened.
- */
- rc= LDAP_OPERATIONS_ERROR;
- }
- else
+ Slapi_Value *found = valueset_remove_value(a, vs, valuestodelete[i]);
+ if(found!=NULL)
{
- int i;
- /*
- * find and mark all the values that are to be deleted
- */
- for ( i = 0; rc == LDAP_SUCCESS && valuestodelete[i] != NULL; ++i )
+ if ( va_out )
{
- int index= 0;
- rc = valuetree_find( a, valuestodelete[i], vtree, &index );
- if(rc==LDAP_SUCCESS)
- {
- if(vs->va[index]!=NULL)
- {
- /* Move the value to be removed to the out array */
- if ( va_out )
- {
- if (vs->va[index]->v_csnset &&
- (flags & (SLAPI_VALUE_FLAG_PRESERVECSNSET|
- SLAPI_VALUE_FLAG_USENEWVALUE)))
- {
- valuestodelete[i]->v_csnset = csnset_dup (vs->va[index]->v_csnset);
- }
- if (flags & SLAPI_VALUE_FLAG_USENEWVALUE)
- {
- valuearrayfast_add_value_passin(&vaf_out,valuestodelete[i]);
- valuestodelete[i] = vs->va[index];
- vs->va[index] = NULL;
- }
- else
- {
- valuearrayfast_add_value_passin(&vaf_out,vs->va[index]);
- vs->va[index] = NULL;
- }
- }
- else
- {
- if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET)
- {
- valuestodelete[i]->v_csnset = vs->va[index]->v_csnset;
- vs->va[index]->v_csnset = NULL;
- }
- slapi_value_free ( & vs->va[index] );
- }
- }
- else
- {
- /* We already deleted this value... */
- if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0)
- {
- /* ...that's an error. */
- rc= LDAP_NO_SUCH_ATTRIBUTE;
- }
- }
- }
- else
+ if (found->v_csnset &&
+ (flags & (SLAPI_VALUE_FLAG_PRESERVECSNSET|
+ SLAPI_VALUE_FLAG_USENEWVALUE)))
{
- /* Couldn't find the value to be deleted */
- if(rc==LDAP_NO_SUCH_ATTRIBUTE && (flags & SLAPI_VALUE_FLAG_IGNOREERROR ))
- {
- rc= LDAP_SUCCESS;
- }
+ valuestodelete[i]->v_csnset = csnset_dup (found->v_csnset);
}
- }
- valuetree_free( &vtree );
-
- if ( rc != LDAP_SUCCESS )
- {
- LDAPDebug( LDAP_DEBUG_ANY,"could not find value %d for attr %s (%s)\n", i-1, a->a_type, ldap_err2string( rc ));
- }
- else
- {
- /* Shunt up all the remaining values to cover the deleted ones. */
- valuearray_compress(vs->va,numberofexistingvalues);
- }
- }
- }
- else
- {
- /* We delete one or no value, so we use brute force. */
- int i;
- for ( i = 0; rc==LDAP_SUCCESS && valuestodelete[i] != NULL; ++i )
- {
- Slapi_Value *found= valueset_remove_value(a, vs, valuestodelete[i]);
- if(found!=NULL)
- {
- if ( va_out )
+ if (flags & SLAPI_VALUE_FLAG_USENEWVALUE)
{
- if (found->v_csnset &&
- (flags & (SLAPI_VALUE_FLAG_PRESERVECSNSET|
- SLAPI_VALUE_FLAG_USENEWVALUE)))
- {
- valuestodelete[i]->v_csnset = csnset_dup (found->v_csnset);
- }
- if (flags & SLAPI_VALUE_FLAG_USENEWVALUE)
- {
- valuearrayfast_add_value_passin(&vaf_out,valuestodelete[i]);
- valuestodelete[i] = found;
- }
- else
- {
- valuearrayfast_add_value_passin(&vaf_out,found);
- }
+ valuearrayfast_add_value_passin(&vaf_out,valuestodelete[i]);
+ valuestodelete[i] = found;
}
else
{
- if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET)
- {
- valuestodelete[i]->v_csnset = found->v_csnset;
- found->v_csnset = NULL;
- }
- slapi_value_free ( & found );
+ valuearrayfast_add_value_passin(&vaf_out,found);
}
}
else
{
- if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0)
+ if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET)
{
- LDAPDebug( LDAP_DEBUG_ARGS,"could not find value %d for attr %s\n", i-1, a->a_type, 0 );
- rc= LDAP_NO_SUCH_ATTRIBUTE;
+ valuestodelete[i]->v_csnset = found->v_csnset;
+ found->v_csnset = NULL;
}
+ slapi_value_free ( & found );
+ }
+ }
+ else
+ {
+ if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0)
+ {
+ LDAPDebug( LDAP_DEBUG_ARGS,"could not find value %d for attr %s\n", i-1, a->a_type, 0 );
+ rc= LDAP_NO_SUCH_ATTRIBUTE;
}
}
}
@@ -1276,88 +1271,13 @@ valueset_remove_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value
return rc;
}
-/*
- * Check if the set of values in the valueset and the valuearray intersect.
- *
- * Returns
- * LDAP_SUCCESS - No intersection.
- * LDAP_NO_SUCH_ATTRIBUTE - There is an intersection.
- * LDAP_OPERATIONS_ERROR - There are duplicate values in the value set already.
- */
-int
-valueset_intersectswith_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **values, int *duplicate_index )
-{
- int rc= LDAP_SUCCESS;
-
- if ( duplicate_index ) {
- *duplicate_index = -1;
- }
-
- if(valuearray_isempty(vs->va))
- {
- /* No intersection */
- }
- else
- {
- int numberofvalues= valuearray_count(values);
- /*
- * determine whether we should use an AVL tree of values or not
- */
- if (numberofvalues==0)
- {
- /* No intersection */
- }
- else if ( numberofvalues > 1 )
- {
- /*
- * Several values to add: use an AVL tree to detect duplicates.
- */
- Avlnode *vtree = NULL;
- rc= valuetree_add_valuearray( a, vs->va, &vtree, duplicate_index );
- if(rc==LDAP_OPERATIONS_ERROR)
- {
- /* There were already duplicate values in the value set */
- }
- else
- {
- rc= valuetree_add_valuearray( a, values, &vtree, duplicate_index );
- /*
- * Returns LDAP_OPERATIONS_ERROR if something very bad happens.
- * Or LDAP_TYPE_OR_VALUE_EXISTS if a value already exists.
- */
- }
- valuetree_free( &vtree );
- }
- else
- {
- /*
- * One value to add: don't bother constructing
- * an AVL tree, etc. since it probably isn't worth the time.
- *
- * JCM - This is actually quite slow because the comparison function is looked up many times.
- */
- int i;
- for ( i = 0; rc == LDAP_SUCCESS && values[i] != NULL; ++i )
- {
- if(valuearray_find(a, vs->va, values[i])!=-1)
- {
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- *duplicate_index = i;
- break;
- }
- }
- }
- }
- return rc;
-}
-
Slapi_ValueSet *
valueset_dup(const Slapi_ValueSet *dupee)
{
- Slapi_ValueSet *duped= (Slapi_ValueSet *)slapi_ch_calloc(1,sizeof(Slapi_ValueSet));
+ Slapi_ValueSet *duped = slapi_valueset_new();
if (NULL!=duped)
{
- valueset_add_valuearray( duped, dupee->va );
+ valueset_set_valuearray_byval(duped,dupee->va);
}
return duped;
}
@@ -1369,43 +1289,53 @@ valueset_dup(const Slapi_ValueSet *dupee)
* : LDAP_OPERATIONS_ERROR - duplicated values given
*/
int
-valueset_replace(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **valstoreplace)
+valueset_replace_valuearray(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **valstoreplace)
+{
+ return (valueset_replace_valuearray_ext(a, vs,valstoreplace, 1));
+}
+int
+valueset_replace_valuearray_ext(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **valstoreplace, int dupcheck)
{
int rc = LDAP_SUCCESS;
- int numberofvalstoreplace= valuearray_count(valstoreplace);
- /* verify the given values are not duplicated.
- if replacing with one value, no need to check. just replace it.
- */
- if (numberofvalstoreplace > 1)
- {
- Avlnode *vtree = NULL;
- rc = valuetree_add_valuearray( a, valstoreplace, &vtree, NULL );
- valuetree_free(&vtree);
- if ( LDAP_SUCCESS != rc &&
- /* bz 247413: don't override LDAP_TYPE_OR_VALUE_EXISTS */
- LDAP_TYPE_OR_VALUE_EXISTS != rc )
- {
- /* There were already duplicate values in the value set */
- rc = LDAP_OPERATIONS_ERROR;
- }
- }
-
- if ( rc == LDAP_SUCCESS )
- {
- /* values look good - replace the values in the attribute */
- if(!valuearray_isempty(vs->va))
- {
- /* remove old values */
- slapi_valueset_done(vs);
- }
- /* we now own valstoreplace */
- vs->va = valstoreplace;
- }
- else
- {
- /* caller expects us to own valstoreplace - since we cannot
- use them, just delete them */
- valuearray_free(&valstoreplace);
+ int vals_count = valuearray_count(valstoreplace);
+
+ if (vals_count == 0) {
+ /* no new values, just clear the valueset */
+ slapi_valueset_done(vs);
+ } else if (vals_count == 1 || !dupcheck) {
+ /* just repelace the valuearray and adjus num, max */
+ slapi_valueset_done(vs);
+ vs->va = valstoreplace;
+ vs->num = vals_count;
+ vs->max = vals_count + 1;
+ } else {
+ /* verify the given values are not duplicated. */
+ Slapi_ValueSet *vs_new = slapi_valueset_new();
+ rc = slapi_valueset_add_attr_valuearray_ext (a, vs_new, valstoreplace, vals_count, 0, NULL);
+
+ if ( rc == LDAP_SUCCESS )
+ {
+ /* values look good - replace the values in the attribute */
+ if(!valuearray_isempty(vs->va))
+ {
+ /* remove old values */
+ slapi_valueset_done(vs);
+ }
+ vs->va = vs_new->va;
+ vs_new->va = NULL;
+ vs->sorted = vs_new->sorted;
+ vs_new->sorted = NULL;
+ vs->num = vs_new->num;
+ vs->max = vs_new->max;
+ slapi_valueset_free (vs_new);
+ }
+ else
+ {
+ /* caller expects us to own valstoreplace - since we cannot
+ use them, just delete them */
+ slapi_valueset_free(vs_new);
+ valuearray_free(&valstoreplace);
+ }
}
return rc;
}
@@ -1422,46 +1352,33 @@ valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slap
if(!valuearray_isempty(valuestoupdate) &&
!valuearray_isempty(vs->va))
{
- /*
- * determine whether we should use an AVL tree of values or not
- */
struct valuearrayfast vaf_valuesupdated;
- int numberofvaluestoupdate= valuearray_count(valuestoupdate);
valuearrayfast_init(&vaf_valuesupdated,*valuesupdated);
- if (numberofvaluestoupdate > 1) /* multiple values to update */
+ int i;
+ int del_index = -1, del_count = 0;
+ for (i=0;valuestoupdate[i]!=NULL;++i)
{
- int i;
- Avlnode *vtree = NULL;
- int rc= valuetree_add_valuearray( a, vs->va, &vtree, NULL );
- PR_ASSERT(rc==LDAP_SUCCESS);
- for (i=0;valuestoupdate[i]!=NULL;++i)
+ int index= valuearray_find(a, vs->va, valuestoupdate[i]);
+ if(index!=-1)
{
- int index= 0;
- rc = valuetree_find( a, valuestoupdate[i], vtree, &index );
- if(rc==LDAP_SUCCESS)
- {
- value_update_csn(vs->va[index],t,csn);
- valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
- valuestoupdate[i] = NULL;
- }
+ value_update_csn(vs->va[index],t,csn);
+ valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
+ valuestoupdate[i]= NULL;
+ del_count++;
+ if (del_index < 0) del_index = i;
}
- valuetree_free(&vtree);
- }
- else
- {
- int i;
- for (i=0;valuestoupdate[i]!=NULL;++i)
- {
- int index= valuearray_find(a, vs->va, valuestoupdate[i]);
- if(index!=-1)
- {
- value_update_csn(vs->va[index],t,csn);
- valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
- valuestoupdate[i]= NULL;
+ else
+ { /* keep the value in valuestoupdate, to keep array compressed, move to first free slot*/
+ if (del_index >= 0) {
+ valuestoupdate[del_index] = valuestoupdate[i];
+ del_index++;
}
}
}
- valuearray_compress(valuestoupdate,numberofvaluestoupdate);
+ /* complete compression */
+ for (i=0; i<del_count;i++)
+ valuestoupdate[del_index+i]= NULL;
+
*valuesupdated= vaf_valuesupdated.va;
}
}
10 years, 3 months
ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5.h | 1
ldap/servers/plugins/replication/repl5_agmt.c | 30 ++++++++++++++++++++++
ldap/servers/plugins/replication/repl5_agmtlist.c | 19 +++++++++++++
3 files changed, 50 insertions(+)
New commits:
commit d4e13f59c12384d608d6c54b1eecea646650f70c
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Mar 4 11:16:59 2014 -0500
Ticket 47727 - Updating nsds5ReplicaHost attribute in a replication agreement fails with error 53
Description: Allow the modification of the nsds5ReplicaHost in replication agreements.
https://fedorahosted.org/389/ticket/47727
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 04d5a82..9aee2b5 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -353,6 +353,7 @@ int agmt_set_binddn_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_bind_method_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_transportinfo_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
int agmt_set_port_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
+int agmt_set_host_from_entry(Repl_Agmt *ra, const Slapi_Entry *e);
const char *agmt_get_long_name(const Repl_Agmt *ra);
int agmt_initialize_replica(const Repl_Agmt *agmt);
void agmt_replica_init_done (const Repl_Agmt *agmt);
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index 4f0fa35..8fb5a02 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -1198,6 +1198,36 @@ agmt_set_port_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
return return_value;
}
+/*
+ * Reset the hostname of the remote replica.
+ *
+ * Returns 0 if hostname is set, or -1 if an error occurred.
+ */
+int
+agmt_set_host_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
+{
+ Slapi_Attr *sattr = NULL;
+ int return_value = -1;
+
+ PR_ASSERT(NULL != ra);
+ slapi_entry_attr_find(e, type_nsds5ReplicaHost, &sattr);
+ PR_Lock(ra->lock);
+ if (NULL != sattr)
+ {
+ Slapi_Value *sval = NULL;
+ slapi_attr_first_value(sattr, &sval);
+ if (NULL != sval)
+ {
+ ra->hostname = (char *)slapi_value_get_string(sval);
+ return_value = 0;
+ }
+ }
+ PR_Unlock(ra->lock);
+ prot_notify_agmt_changed(ra->protocol, ra->long_name);
+
+ return return_value;
+}
+
static int
agmt_parse_excluded_attrs_filter(const char *attr_string, size_t *offset)
{
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 53c12a9..8a70055 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -368,6 +368,25 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
rc = SLAPI_DSE_CALLBACK_ERROR;
}
}
+ else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaHost))
+ {
+ /* New replica host */
+ if (agmt_set_host_from_entry(agmt, e) != 0)
+ {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "agmtlist_modify_callback: "
+ "failed to update host for agreement %s\n",
+ agmt_get_long_name(agmt));
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rc = SLAPI_DSE_CALLBACK_ERROR;
+ } else {
+ /*
+ * Changing the host invalidates the agmt maxcsn, so remove it.
+ * The next update will add the correct maxcsn back to the agmt/local ruv.
+ */
+ agmt_remove_maxcsn(agmt);
+ }
+ }
else if (slapi_attr_types_equivalent(mods[i]->mod_type,
type_nsds5ReplicaPort))
{
10 years, 3 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/daemon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 22fd3c28ca62d080b42f25f4d7c0fb711c1a011c
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Mar 3 16:07:21 2014 -0800
Ticket #47725 - compiler error on daemon.c
Description: This syntax is invalid for Solaris Studio Compiler:
while((0 = getmntent(fp, &mnt))){
Applied the patch provided by cgrzemba (Thanks!!)
https://fedorahosted.org/389/ticket/47725
Reviewed by nhosoi(a)redhat.com.
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 7594d53..b0cdcc1 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -498,7 +498,7 @@ disk_mon_get_mount_point(char *dir)
dev_id = s.st_dev;
- while((0 = getmntent(fp, &mnt))){
+ while((0 == getmntent(fp, &mnt))){
if (stat(mnt.mnt_mountp, &s) != 0) {
continue;
}
10 years, 3 months