Branch '389-ds-base-1.3.1' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/import-threads.c | 40 ++++++++++++++++----------
ldap/servers/slapd/dn.c | 16 ++++++++++
ldap/servers/slapd/slapi-private.h | 1
3 files changed, 42 insertions(+), 15 deletions(-)
New commits:
commit 286b09d62dd17cc3eef9dfa058521e4c863cdb80
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Sun Apr 28 22:24:40 2013 -0700
Ticket #529 - dn normalization must handle multiple space
characters in attributes
Bug Description: Commit 69ff83598d517bed84922b1c7dd67cab023b4d99
had a flaw -- handling normdn in upgradedn_producer had a
problem. The string was passed to the Slapi_DN in the entry
using slapi_sdn_init_dn_passin, while the string could be
modified at other places.
Fix Description: This patch manages the normdn string more
carefully.
https://fedorahosted.org/389/ticket/529
Reviewed by Rich (Thank you!!)
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
index 3cb25d3..79a5984 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -1523,6 +1523,7 @@ upgradedn_producer(void *param)
finished = 0;
while (!finished) {
ID temp_id;
+ int dn_in_cache;
if (job->flags & FLAG_ABORT) {
goto error;
@@ -1580,6 +1581,7 @@ upgradedn_producer(void *param)
do_dn_norm = 0;
do_dn_norm_sp = 0;
rdn_has_spaces = 0;
+ dn_in_cache = 0;
if (entryrdn_get_switch()) {
/* original rdn is allocated in get_value_from_string */
@@ -1591,10 +1593,12 @@ upgradedn_producer(void *param)
} else {
bdn = dncache_find_id(&inst->inst_dncache, temp_id);
if (bdn) {
- /* don't free dn */
+ /* don't free normdn */
normdn = (char *)slapi_sdn_get_dn(bdn->dn_sdn);
CACHE_RETURN(&inst->inst_dncache, &bdn);
+ dn_in_cache = 1;
} else {
+ /* free normdn */
rc = entryrdn_lookup_dn(be, rdn, temp_id,
(char **)&normdn, NULL, NULL);
if (rc) {
@@ -1639,6 +1643,7 @@ upgradedn_producer(void *param)
continue;
}
}
+ /* free normdn */
normdn = slapi_ch_smprintf("%s%s%s",
rdn, pdn?",":"", pdn?pdn:"");
slapi_ch_free_string(&pdn);
@@ -1648,14 +1653,18 @@ upgradedn_producer(void *param)
* we need to put the new value to cache.*/
/* dn is dup'ed in slapi_sdn_new_dn_byval.
* It's set to bdn and put in the dn cache. */
- sdn = slapi_sdn_new_normdn_byref(normdn);
+ /* normdn is allocated in this scope.
+ * Thus, we can just passin. */
+ sdn = slapi_sdn_new_normdn_passin(normdn);
bdn = backdn_init(sdn, temp_id, 0);
CACHE_ADD( &inst->inst_dncache, bdn, NULL );
CACHE_RETURN(&inst->inst_dncache, &bdn);
+ /* don't free this normdn */
normdn = slapi_sdn_get_dn(sdn);
slapi_log_error(SLAPI_LOG_CACHE, "uptradedn",
"entryrdn_lookup_dn returned: %s, "
"and set to dn cache\n", normdn);
+ dn_in_cache = 1;
}
}
e = slapi_str2entry_ext(normdn, NULL, data.dptr,
@@ -1691,11 +1700,7 @@ upgradedn_producer(void *param)
* -- normalize it with the new format
*/
if (!normdn) {
- get_value_from_string((const char *)ecopy, "dn", (char **)&normdn);
- }
- if (normdn) {
- slapi_sdn_done(&(e->e_sdn));
- slapi_sdn_init_dn_passin(&(e->e_sdn), normdn);
+ /* No rdn in id2entry or entrydn */
normdn = slapi_sdn_get_dn(&(e->e_sdn));
}
@@ -1807,13 +1812,16 @@ upgradedn_producer(void *param)
normdn, temp_id, alt_id);
LDAPDebug2Args(LDAP_DEBUG_ANY, "Renaming \"%s\" to \"%s\"\n",
rdn, newrdn);
+ if (!dn_in_cache) {
+ /* If not in dn cache, normdn needs to be freed. */
+ slapi_ch_free_string(&normdn);
+ }
normdn = slapi_ch_smprintf("%s,%s", newrdn, parentdn);
slapi_ch_free_string(&newrdn);
slapi_ch_free_string(&parentdn);
/* Reset DN and RDN in the entry */
slapi_sdn_done(&(e->e_sdn));
- slapi_sdn_init_normdn_passin(&(e->e_sdn), normdn);
- /* normdn = slapi_sdn_get_dn(&(e->e_sdn)); */
+ slapi_sdn_init_normdn_byval(&(e->e_sdn), normdn);
}
info_state |= DN_NORM_SP;
upgradedn_add_to_list(&ud_list,
@@ -1834,12 +1842,14 @@ upgradedn_producer(void *param)
* It's set to bdn and put in the dn cache. */
/* Waited to put normdn into dncache until it could be modified in
* chk_dn_norm_sp. */
- sdn = slapi_sdn_new_normdn_byref(normdn);
- bdn = backdn_init(sdn, temp_id, 0);
- CACHE_ADD(&inst->inst_dncache, bdn, NULL);
- CACHE_RETURN(&inst->inst_dncache, &bdn);
- slapi_log_error(SLAPI_LOG_CACHE, "uptradedn",
- "set dn %s to dn cache\n", normdn);
+ if (!dn_in_cache) {
+ sdn = slapi_sdn_new_normdn_passin(normdn);
+ bdn = backdn_init(sdn, temp_id, 0);
+ CACHE_ADD(&inst->inst_dncache, bdn, NULL);
+ CACHE_RETURN(&inst->inst_dncache, &bdn);
+ slapi_log_error(SLAPI_LOG_CACHE, "uptradedn",
+ "set dn %s to dn cache\n", normdn);
+ }
/* Check DN syntax attr values if it contains '\\' or not */
/* Start from the rdn */
if (chk_dn_norm) {
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index 3043ee6..9261bd8 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -1915,6 +1915,22 @@ slapi_sdn_init_normdn_byref(Slapi_DN *sdn, const char *dn)
} else {
sdn->ndn_len = strlen(dn);
sdn->dn = dn;
+ sdn->flag = slapi_unsetbit_uchar(sdn->flag, FLAG_DN);
+ }
+ return sdn;
+}
+
+/* use when dn is already normalized (but case is yet touched) */
+Slapi_DN *
+slapi_sdn_init_normdn_byval(Slapi_DN *sdn, const char *dn)
+{
+ slapi_sdn_init(sdn);
+ if(dn == NULL) {
+ sdn->ndn_len = 0;
+ } else {
+ sdn->ndn_len = strlen(dn);
+ sdn->dn= slapi_ch_strdup(dn);
+ sdn->flag = slapi_setbit_uchar(sdn->flag, FLAG_DN);
}
return sdn;
}
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 375c33f..faf110d 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -384,6 +384,7 @@ Slapi_DN *slapi_sdn_init_dn_passin(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_ndn_byref(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_ndn_byval(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_normdn_byref(Slapi_DN *sdn, const char *dn);
+Slapi_DN *slapi_sdn_init_normdn_byval(Slapi_DN *sdn, const char *dn);
Slapi_DN *slapi_sdn_init_normdn_ndn_passin(Slapi_DN *sdn, const char *dn);
Slapi_DN *slapi_sdn_init_normdn_passin(Slapi_DN *sdn, const char *dn);
char *slapi_dn_normalize_original( char *dn );
10 years, 12 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/import-threads.c | 40 ++++++++++++++++----------
ldap/servers/slapd/dn.c | 16 ++++++++++
ldap/servers/slapd/slapi-private.h | 1
3 files changed, 42 insertions(+), 15 deletions(-)
New commits:
commit a68952f9a8e6d3ff9fea1b4b485acc63f77b3ce6
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Sun Apr 28 22:24:40 2013 -0700
Ticket #529 - dn normalization must handle multiple space characters in attributes
Bug Description: Commit 69ff83598d517bed84922b1c7dd67cab023b4d99
had a flaw -- handling normdn in upgradedn_producer had a
problem. The string was passed to the Slapi_DN in the entry
using slapi_sdn_init_dn_passin, while the string could be
modified at other places.
Fix Description: This patch manages the normdn string more
carefully.
https://fedorahosted.org/389/ticket/529
Reviewed by Rich (Thank you!!)
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
index 3cb25d3..79a5984 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -1523,6 +1523,7 @@ upgradedn_producer(void *param)
finished = 0;
while (!finished) {
ID temp_id;
+ int dn_in_cache;
if (job->flags & FLAG_ABORT) {
goto error;
@@ -1580,6 +1581,7 @@ upgradedn_producer(void *param)
do_dn_norm = 0;
do_dn_norm_sp = 0;
rdn_has_spaces = 0;
+ dn_in_cache = 0;
if (entryrdn_get_switch()) {
/* original rdn is allocated in get_value_from_string */
@@ -1591,10 +1593,12 @@ upgradedn_producer(void *param)
} else {
bdn = dncache_find_id(&inst->inst_dncache, temp_id);
if (bdn) {
- /* don't free dn */
+ /* don't free normdn */
normdn = (char *)slapi_sdn_get_dn(bdn->dn_sdn);
CACHE_RETURN(&inst->inst_dncache, &bdn);
+ dn_in_cache = 1;
} else {
+ /* free normdn */
rc = entryrdn_lookup_dn(be, rdn, temp_id,
(char **)&normdn, NULL, NULL);
if (rc) {
@@ -1639,6 +1643,7 @@ upgradedn_producer(void *param)
continue;
}
}
+ /* free normdn */
normdn = slapi_ch_smprintf("%s%s%s",
rdn, pdn?",":"", pdn?pdn:"");
slapi_ch_free_string(&pdn);
@@ -1648,14 +1653,18 @@ upgradedn_producer(void *param)
* we need to put the new value to cache.*/
/* dn is dup'ed in slapi_sdn_new_dn_byval.
* It's set to bdn and put in the dn cache. */
- sdn = slapi_sdn_new_normdn_byref(normdn);
+ /* normdn is allocated in this scope.
+ * Thus, we can just passin. */
+ sdn = slapi_sdn_new_normdn_passin(normdn);
bdn = backdn_init(sdn, temp_id, 0);
CACHE_ADD( &inst->inst_dncache, bdn, NULL );
CACHE_RETURN(&inst->inst_dncache, &bdn);
+ /* don't free this normdn */
normdn = slapi_sdn_get_dn(sdn);
slapi_log_error(SLAPI_LOG_CACHE, "uptradedn",
"entryrdn_lookup_dn returned: %s, "
"and set to dn cache\n", normdn);
+ dn_in_cache = 1;
}
}
e = slapi_str2entry_ext(normdn, NULL, data.dptr,
@@ -1691,11 +1700,7 @@ upgradedn_producer(void *param)
* -- normalize it with the new format
*/
if (!normdn) {
- get_value_from_string((const char *)ecopy, "dn", (char **)&normdn);
- }
- if (normdn) {
- slapi_sdn_done(&(e->e_sdn));
- slapi_sdn_init_dn_passin(&(e->e_sdn), normdn);
+ /* No rdn in id2entry or entrydn */
normdn = slapi_sdn_get_dn(&(e->e_sdn));
}
@@ -1807,13 +1812,16 @@ upgradedn_producer(void *param)
normdn, temp_id, alt_id);
LDAPDebug2Args(LDAP_DEBUG_ANY, "Renaming \"%s\" to \"%s\"\n",
rdn, newrdn);
+ if (!dn_in_cache) {
+ /* If not in dn cache, normdn needs to be freed. */
+ slapi_ch_free_string(&normdn);
+ }
normdn = slapi_ch_smprintf("%s,%s", newrdn, parentdn);
slapi_ch_free_string(&newrdn);
slapi_ch_free_string(&parentdn);
/* Reset DN and RDN in the entry */
slapi_sdn_done(&(e->e_sdn));
- slapi_sdn_init_normdn_passin(&(e->e_sdn), normdn);
- /* normdn = slapi_sdn_get_dn(&(e->e_sdn)); */
+ slapi_sdn_init_normdn_byval(&(e->e_sdn), normdn);
}
info_state |= DN_NORM_SP;
upgradedn_add_to_list(&ud_list,
@@ -1834,12 +1842,14 @@ upgradedn_producer(void *param)
* It's set to bdn and put in the dn cache. */
/* Waited to put normdn into dncache until it could be modified in
* chk_dn_norm_sp. */
- sdn = slapi_sdn_new_normdn_byref(normdn);
- bdn = backdn_init(sdn, temp_id, 0);
- CACHE_ADD(&inst->inst_dncache, bdn, NULL);
- CACHE_RETURN(&inst->inst_dncache, &bdn);
- slapi_log_error(SLAPI_LOG_CACHE, "uptradedn",
- "set dn %s to dn cache\n", normdn);
+ if (!dn_in_cache) {
+ sdn = slapi_sdn_new_normdn_passin(normdn);
+ bdn = backdn_init(sdn, temp_id, 0);
+ CACHE_ADD(&inst->inst_dncache, bdn, NULL);
+ CACHE_RETURN(&inst->inst_dncache, &bdn);
+ slapi_log_error(SLAPI_LOG_CACHE, "uptradedn",
+ "set dn %s to dn cache\n", normdn);
+ }
/* Check DN syntax attr values if it contains '\\' or not */
/* Start from the rdn */
if (chk_dn_norm) {
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index 3043ee6..9261bd8 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -1915,6 +1915,22 @@ slapi_sdn_init_normdn_byref(Slapi_DN *sdn, const char *dn)
} else {
sdn->ndn_len = strlen(dn);
sdn->dn = dn;
+ sdn->flag = slapi_unsetbit_uchar(sdn->flag, FLAG_DN);
+ }
+ return sdn;
+}
+
+/* use when dn is already normalized (but case is yet touched) */
+Slapi_DN *
+slapi_sdn_init_normdn_byval(Slapi_DN *sdn, const char *dn)
+{
+ slapi_sdn_init(sdn);
+ if(dn == NULL) {
+ sdn->ndn_len = 0;
+ } else {
+ sdn->ndn_len = strlen(dn);
+ sdn->dn= slapi_ch_strdup(dn);
+ sdn->flag = slapi_setbit_uchar(sdn->flag, FLAG_DN);
}
return sdn;
}
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index a77c9f4..49ecb52 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -384,6 +384,7 @@ Slapi_DN *slapi_sdn_init_dn_passin(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_ndn_byref(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_ndn_byval(Slapi_DN *sdn,const char *dn);
Slapi_DN *slapi_sdn_init_normdn_byref(Slapi_DN *sdn, const char *dn);
+Slapi_DN *slapi_sdn_init_normdn_byval(Slapi_DN *sdn, const char *dn);
Slapi_DN *slapi_sdn_init_normdn_ndn_passin(Slapi_DN *sdn, const char *dn);
Slapi_DN *slapi_sdn_init_normdn_passin(Slapi_DN *sdn, const char *dn);
char *slapi_dn_normalize_original( char *dn );
10 years, 12 months
Branch '389-ds-base-1.3.1' - 3 commits - ldap/servers
by thierry bordaz
ldap/servers/plugins/replication/repl5_connection.c | 2 +-
ldap/servers/plugins/replication/repl5_protocol.c | 4 ++--
ldap/servers/slapd/ldaputil.c | 18 +++++++++++++++---
3 files changed, 18 insertions(+), 6 deletions(-)
New commits:
commit 3e8c2a470941365e72073870513e56e085aeb96d
Author: Thierry bordaz (tbordaz) <tbordaz(a)redhat.com>
Date: Wed Apr 10 18:45:17 2013 +0200
Ticket 47325 - Crash at shutdown on a replica aggrement
Bug Description:
This is a followup of the ticket https://fedorahosted.org/389/ticket/618
The RA thread are waited by the main daemon at shutdown.
The problem is that the RA thread are not created with the right flag so they are not
joinable.
Fix Description:
Use the correct creation flag PR_JOINABLE_THREAD
In addition this fix introduce a bind timeout for the RA. It will take the one defined in
the protocol (10 min per default).
Ticket: https://fedorahosted.org/389/ticket/47325
Reviewed by: Mark Reynolds (thank you Mark !)
Platforms tested: Fedora 17
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c
index b8b542e..668abda 100644
--- a/ldap/servers/plugins/replication/repl5_connection.c
+++ b/ldap/servers/plugins/replication/repl5_connection.c
@@ -1782,7 +1782,7 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
const char *mech = bind_method_to_mech(conn->bindmethod);
rc = slapi_ldap_bind(conn->ld, binddn, password, mech, NULL,
- &ctrls, NULL, NULL);
+ &ctrls, &conn->timeout, NULL);
if ( rc == LDAP_SUCCESS )
{
diff --git a/ldap/servers/plugins/replication/repl5_protocol.c b/ldap/servers/plugins/replication/repl5_protocol.c
index 76e018a..8373ba6 100644
--- a/ldap/servers/plugins/replication/repl5_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_protocol.c
@@ -369,9 +369,9 @@ prot_start(Repl_Protocol *rp)
{
rp->agmt_thread = PR_CreateThread(PR_USER_THREAD, prot_thread_main, (void *)rp,
#if defined(__hpux) && defined(__ia64)
- PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 524288L );
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 524288L );
#else
- PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
#endif
if (rp->agmt_thread == NULL)
{
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 3ca1139..5ac2fdd 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -1126,7 +1126,19 @@ slapi_ldap_bind(
if (msgidp) { /* let caller process result */
*msgidp = mymsgid;
} else { /* process results */
- rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, timeout, &result);
+ struct timeval default_timeout, *bind_timeout;
+
+ if ((timeout == NULL) || ((timeout->tv_sec == 0) && (timeout->tv_usec == 0))) {
+ /* Let's wait 1 min max to bind */
+ default_timeout.tv_sec = 60;
+ default_timeout.tv_usec = 0;
+
+ bind_timeout = &default_timeout;
+ } else {
+ /* take the one provided by the caller. It should be the one defined in the protocol */
+ bind_timeout = timeout;
+ }
+ rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, bind_timeout, &result);
if (-1 == rc) { /* error */
rc = slapi_ldap_get_lderrno(ld, NULL, NULL);
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
@@ -1141,8 +1153,8 @@ slapi_ldap_bind(
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: timeout after [%ld.%ld] seconds reading "
"bind response for [%s] authentication mechanism [%s]\n",
- timeout ? timeout->tv_sec : 0,
- timeout ? timeout->tv_usec : 0,
+ bind_timeout ? bind_timeout->tv_sec : 0,
+ bind_timeout ? bind_timeout->tv_usec : 0,
bindid ? bindid : "(anon)",
mech ? mech : "SIMPLE");
goto done;
commit cf0249ac55a7f5e61ed94fd8bfc1e1a00ac4a273
Merge: c7fc203 78f029f
Author: Thierry bordaz (tbordaz) <tbordaz(a)redhat.com>
Date: Mon Apr 29 15:12:01 2013 +0200
Merge branch '389-ds-base-1.3.1' of ssh://git.fedorahosted.org/git/389/ds into 389-ds-base-1.3.1
commit c7fc203ffe09809e430ff1217ec352db95d636a0
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Apr 24 11:44:40 2013 -0600
Ticket #47348 - add etimes to per second/minute stats
https://fedorahosted.org/389/ticket/47348
Reviewed by: mreynolds (Thanks!)
Branch: 389-ds-base-1.3.1
Fix Description: Add an "ElapsedTime" column to the -m/-M output. This column
is the cumulative etimes of all operations during that time period.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: yes
(cherry picked from commit 9813b219ad2aa7b7194d9295dd529e12889a8534)
Ticket #47349 - DS instance crashes under a high load
https://fedorahosted.org/389/ticket/47349
Reviewed by: nkinder (Thanks!)
Branch: 389-ds-base-1.3.1
Fix Description: handle_new_connection initializes the connection object,
then calls connection_table_move_connection_on_to_active_list to put it
on the list of active connections, then unlocks the c_mutex, then calls
connection_new_private to allocate c_private. If another thread
interrupts after the conn has been moved to the active list, but before
c_private has been allocated, the new conn will be available via
connection_table_iterate_active_connections where table_iterate_function
will attempt to dereference the NULL c_private.
The fix is to move connection_new_private inside the c_mutex lock, and to
move connection_table_move_connection_on_to_active_list to be the very last
thing before releasing the c_mutex lock. Once the conn is on the active
list it is live and we cannot do anything else to it.
Note: I have still not been able to reproduce the problem in a non-debug
optimized build.
Platforms tested: RHEL6 x86_64
Note: Before patch, server would crash within 5 minutes. After patch, server
has been running for several days in customer environment.
Flag Day: no
Doc impact: no
(cherry picked from commit 05d209432571dc64b242ae47113ae4cbb43607d2)
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
index 3b8adc5..efc5970 100755
--- a/ldap/admin/src/logconv.pl
+++ b/ldap/admin/src/logconv.pl
@@ -2042,7 +2042,7 @@ sub parseLineNormal
if ($1 ne "0"){ $errorCount++;}
else { $successCount++;}
}
- if ($_ =~ /etime= *([0-9.]+)/ ) { writeFile($ETIME, $1);}
+ if ($_ =~ /etime= *([0-9.]+)/ ) { writeFile($ETIME, $1); inc_stats_val('etime',$1,$s_stats,$m_stats); }
if ($_ =~ / tag=101 / || $_ =~ / tag=111 / || $_ =~ / tag=100 / || $_ =~ / tag=115 /){
if ($_ =~ / nentries= *([0-9]+)/i ){ writeFile($NENTRIES, $1); }
}
@@ -2197,6 +2197,7 @@ reset_stats_block
$stats->{'anonbind'}=0;
$stats->{'unbind'}=0;
$stats->{'notesu'}=0;
+ $stats->{'etime'}=0;
return;
}
@@ -2241,12 +2242,13 @@ print_stats_block
$stats->{'bind'},
$stats->{'anonbind'},
$stats->{'unbind'},
- $stats->{'notesu'} ),
+ $stats->{'notesu'},
+ $stats->{'etime'}),
"\n" );
} else {
$stats->{'fh'}->print(
"Time,time_t,Results,Search,Add,Mod,Modrdn,Moddn,Compare,Delete,Abandon,".
- "Connections,SSL Conns,Bind,Anon Bind,Unbind,Unindexed\n"
+ "Connections,SSL Conns,Bind,Anon Bind,Unbind,Unindexed,ElapsedTime\n"
);
}
}
@@ -2265,6 +2267,20 @@ inc_stats
return;
}
+# like inc_stats, but increments the block counter with the given value e.g.
+# 'statname1', val, statblock1, statblock2, ...
+sub
+inc_stats_val
+{
+ my $n = shift;
+ my $val = shift;
+ foreach(@_){
+ $_->{$n} += $val
+ if exists $_->{$n};
+ }
+ return;
+}
+
sub
displayBindReport
{
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index fa19312..66677d2 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -2686,16 +2686,6 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
/* Call the plugin extension constructors */
conn->c_extension = factory_create_extension(connection_type,conn,NULL /* Parent */);
-
- /* Add this connection slot to the doubly linked list of active connections. This
- * list is used to find the connections that should be used in the poll call. This
- * connection will be added directly after slot 0 which serves as the head of the list */
- if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL )
- {
- /* Now give the new connection to the connection code */
- connection_table_move_connection_on_to_active_list(the_connection_table,conn);
- }
-
#if defined(ENABLE_LDAPI)
#if !defined( XP_WIN32 )
/* ldapi */
@@ -2708,10 +2698,21 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
#endif
#endif /* ENABLE_LDAPI */
- PR_Unlock( conn->c_mutex );
-
connection_new_private(conn);
+ /* Add this connection slot to the doubly linked list of active connections. This
+ * list is used to find the connections that should be used in the poll call. This
+ * connection will be added directly after slot 0 which serves as the head of the list.
+ * This must be done as the very last thing before we unlock the mutex, because once it
+ * is added to the active list, it is live. */
+ if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL )
+ {
+ /* Now give the new connection to the connection code */
+ connection_table_move_connection_on_to_active_list(the_connection_table,conn);
+ }
+
+ PR_Unlock( conn->c_mutex );
+
g_increment_current_conn_count();
return 0;
10 years, 12 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/filterindex.c | 11 +
ldap/servers/slapd/back-ldbm/ldbm_search.c | 117 ++++++++++----------
ldap/servers/slapd/back-ldbm/vlv.c | 2
ldap/servers/slapd/daemon.c | 13 +-
ldap/servers/slapd/operation.c | 9 -
ldap/servers/slapd/opshared.c | 87 +++++++++------
ldap/servers/slapd/pagedresults.c | 165 ++++++++++++++++++++++++++---
ldap/servers/slapd/proto-slap.h | 46 +++++---
ldap/servers/slapd/slap.h | 2
ldap/servers/slapd/sort.c | 6 -
10 files changed, 321 insertions(+), 137 deletions(-)
New commits:
commit d53e8221f77ac325123e3bb4f61cf6de67dce646
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Apr 26 15:24:22 2013 -0700
Ticket #47347 - Simple paged results should support async search
Bug description: Simple paged results serialized the request
even for a series of asynchronous search requests, and it
returned error 53 (unwilling to perform) if the second request
comes in while the first one is being processed.
Fix description: This patch implements the asynchronous support
for the Simple paged results search.
- Removed pagedresults_check_or_set_processing which was
used to Simple paged results requests exclusive. Instead,
pagedresults_lock is introduced to protect the PagedResults
object from the other threads sharing the same cookie.
- If any error including hitting the sizelimit or timelimit,
search result set was released immediately in ldbm_back_
next_search_entry_ext, which could cause the race condition
among multiple asynchronous search requests. To prevent it,
the search result set is untouched if the operation is a
Simple paged result search, and let its clean up function
to handle it.
- Sizelimit was evaluated in the accumulative way instead of
on the each page size. For instance, if the sizelimit was
101 AND the page size is 100, as soon as getting the 2nd page,
it hit the sizelimit and the search failed. This patch fixes
it so that as long as the requested page size is less than 101,
the requests successfully continue without getting an error 4
(LDAP_SIZELIMIT_EXCEEDED). To fulfill the requirement, the
current size needs to be managed per operation instead of the
search result set or PagedResults object. For the purpose,
introduced o_pagedresults_sizelimit to Slapi_Operation.
- When shutting down, connection_table_free could use backend
callback (e.g., be_search_results_release). Therefore, moved
be_cleanupall after connection_table_free.
- Each Simple paged results helper functions checks if the
operation is really a Simple paged result request control is
associated with to prevent any unexpected behaviour.
https://fedorahosted.org/389/ticket/47347
Reviewed by Rich (Thank you!!)
diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c
index 865f8ab..64b4e2d 100644
--- a/ldap/servers/slapd/back-ldbm/filterindex.c
+++ b/ldap/servers/slapd/back-ldbm/filterindex.c
@@ -317,7 +317,7 @@ ava_candidates(
if ( unindexed ) {
unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED;
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
}
/* We don't use valuearray_free here since the valueset, berval
@@ -349,7 +349,7 @@ ava_candidates(
if ( unindexed ) {
unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED;
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
}
valuearray_free( &ivals );
LDAPDebug( LDAP_DEBUG_TRACE, "<= ava_candidates %lu\n",
@@ -390,7 +390,7 @@ presence_candidates(
unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED;
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed(pb->pb_conn, pb->pb_op, pr_idx);
}
if (idl != NULL && ALLIDS(idl) && strcasecmp(type, "nscpentrydn") == 0) {
@@ -504,6 +504,7 @@ extensible_candidates(
SLAPI_PAGED_RESULTS_INDEX,
&pr_idx );
pagedresults_set_unindexed( glob_pb->pb_conn,
+ glob_pb->pb_op,
pr_idx );
}
if (idl2 == NULL)
@@ -951,7 +952,7 @@ substring_candidates(
slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
if ( ivals == NULL || *ivals == NULL ) {
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
LDAPDebug( LDAP_DEBUG_TRACE,
"<= sub_candidates ALLIDS (no keys)\n", 0, 0, 0 );
return( idl_allids( be ) );
@@ -965,7 +966,7 @@ substring_candidates(
idl = keys2idl( be, type, indextype_SUB, ivals, err, &unindexed, &txn, allidslimit );
if ( unindexed ) {
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
}
valuearray_free( &ivals );
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c
index 70a2ee3..be4b63c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
@@ -55,7 +55,7 @@ static int build_candidate_list( Slapi_PBlock *pb, backend *be,
static IDList *base_candidates( Slapi_PBlock *pb, struct backentry *e );
static IDList *onelevel_candidates( Slapi_PBlock *pb, backend *be, const char *base, struct backentry *e, Slapi_Filter *filter, int managedsait, int *lookup_returned_allidsp, int *err );
static back_search_result_set* new_search_result_set(IDList* idl,int vlv, int lookthroughlimit);
-static void delete_search_result_set( back_search_result_set **sr );
+static void delete_search_result_set(Slapi_PBlock *pb, back_search_result_set **sr);
static int can_skip_filter_test( Slapi_PBlock *pb, struct slapi_filter *f,
int scope, IDList *idl );
@@ -167,6 +167,7 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb,
int estimate = 0; /* estimated search result count */
backend *be;
ldbm_instance *inst;
+ back_search_result_set *sr = NULL;
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
inst = (ldbm_instance *) be->be_instance_info;
@@ -183,19 +184,14 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb,
{
slapi_send_ldap_result( pb, ldap_result, NULL, ldap_result_description, 0, NULL );
}
- {
- /* hack hack --- code to free the result set if we don't need it */
- /* We get it and check to see if the structure was ever used */
- back_search_result_set *sr = NULL;
- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
- if ( (NULL != sr) && (function_result != 0) ) {
- int pr_idx = -1;
- slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx );
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
- delete_search_result_set(&sr);
+ /* code to free the result set if we don't need it */
+ /* We get it and check to see if the structure was ever used */
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
+ if (sr) {
+ if (function_result) {
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
+ delete_search_result_set(pb, &sr);
}
}
if (vlv_request_control)
@@ -898,7 +894,7 @@ ldbm_back_search( Slapi_PBlock *pb )
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
}
sr->sr_candidates = candidates;
@@ -1386,13 +1382,24 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
int estimate = 0; /* estimated search result count */
back_txn txn = {NULL};
int pr_idx = -1;
+ Slapi_Connection *conn;
+ Slapi_Operation *op;
+ slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &basesdn );
+ if (NULL == basesdn) {
+ slapi_send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL,
+ "Null target DN", 0, NULL );
+ return( -1 );
+ }
+ slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
+ if (NULL == sr) {
+ goto bail;
+ }
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
slapi_pblock_get( pb, SLAPI_MANAGEDSAIT, &managedsait );
slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
- slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &basesdn );
slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries );
slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &slimit );
slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
@@ -1400,32 +1407,30 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
slapi_pblock_get( pb, SLAPI_SEARCH_REFERRALS, &urls );
slapi_pblock_get( pb, SLAPI_TARGET_UNIQUEID, &target_uniqueid );
- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
slapi_pblock_get( pb, SLAPI_TXN, &txn.back_txn_txn );
- slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx );
+ slapi_pblock_get( pb, SLAPI_CONNECTION, &conn );
+ slapi_pblock_get( pb, SLAPI_OPERATION, &op );
if ( !txn.back_txn_txn ) {
dblayer_txn_init( li, &txn );
slapi_pblock_set( pb, SLAPI_TXN, txn.back_txn_txn );
}
- if (NULL == sr) {
- goto bail;
- }
-
if (sr->sr_norm_filter) {
int val = 1;
slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &val );
filter = sr->sr_norm_filter;
}
- if (NULL == basesdn) {
- slapi_send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL,
- "Null target DN", 0, NULL );
- return( -1 );
- }
-
- if (sr->sr_current_sizelimit >= 0) {
+ if (op_is_pagedresults(op)) {
+ int myslimit;
+ /* On Simple Paged Results search, sizelimit is appied for each page. */
+ slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
+ myslimit = pagedresults_get_sizelimit(conn, op, pr_idx);
+ if (myslimit >= 0) {
+ slimit = myslimit;
+ }
+ } else if (sr->sr_current_sizelimit >= 0) {
/*
* sr_current_sizelimit contains the current sizelimit.
* In case of paged results, getting one page is one operation,
@@ -1442,8 +1447,7 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
/* Return to the cache the entry we handed out last time */
/* If we are using the extension, the front end will tell
* us when to do this so we don't do it now */
- if ( !use_extension )
- {
+ if (sr->sr_entry && !use_extension) {
CACHE_RETURN( &inst->inst_cache, &(sr->sr_entry) );
sr->sr_entry = NULL;
}
@@ -1467,15 +1471,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
/* check for abandon */
if ( slapi_op_abandoned( pb ) || (NULL == sr) )
{
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
if ( use_extension ) {
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
}
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
rc = SLAPI_FAIL_GENERAL;
goto bail;
}
@@ -1484,15 +1485,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
curtime = current_time();
if ( tlimit != -1 && curtime > stoptime )
{
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
if ( use_extension ) {
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
}
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
rc = SLAPI_FAIL_GENERAL;
slapi_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, urls );
goto bail;
@@ -1501,15 +1499,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
/* check lookthrough limit */
if ( llimit != -1 && sr->sr_lookthroughcount >= llimit )
{
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
if ( use_extension ) {
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
}
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
rc = SLAPI_FAIL_GENERAL;
slapi_send_ldap_result( pb, LDAP_ADMINLIMIT_EXCEEDED, NULL, NULL, nentries, urls );
goto bail;
@@ -1521,15 +1516,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
{
/* No more entries */
/* destroy back_search_result_set */
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
if ( use_extension ) {
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
}
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
rc = 0;
goto bail;
}
@@ -1662,17 +1654,20 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
{
if ( --slimit < 0 ) {
CACHE_RETURN( &inst->inst_cache, &e );
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL,
- 0, pr_idx);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
slapi_send_ldap_result( pb, LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, nentries, urls );
rc = SLAPI_FAIL_GENERAL;
goto bail;
}
slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, &slimit );
+ if (op_is_pagedresults(op)) {
+ /*
+ * On Simple Paged Results search,
+ * sizelimit is appied to each page.
+ */
+ pagedresults_set_sizelimit(conn, op, slimit, pr_idx);
+ }
sr->sr_current_sizelimit = slimit;
}
if ( (filter_test != 0) && sr->sr_virtuallistview)
@@ -1779,13 +1774,20 @@ new_search_result_set(IDList *idl, int vlv, int lookthroughlimit)
}
static void
-delete_search_result_set( back_search_result_set **sr )
+delete_search_result_set( Slapi_PBlock *pb, back_search_result_set **sr )
{
int rc = 0, filt_errs = 0;
- if ( NULL == sr || NULL == *sr)
+ if ( NULL == sr || NULL == *sr )
{
return;
}
+ if (pb) {
+ if (op_is_pagedresults(pb->pb_op)) {
+ /* If the op is pagedresults, let the module clean up sr. */
+ return;
+ }
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
+ }
if ( NULL != (*sr)->sr_candidates )
{
idl_free( (*sr)->sr_candidates );
@@ -1800,12 +1802,17 @@ delete_search_result_set( back_search_result_set **sr )
slapi_filter_free((*sr)->sr_norm_filter, 1);
memset( *sr, 0, sizeof( back_search_result_set ) );
slapi_ch_free( (void**)sr );
+ return;
}
+/*
+ * This function is called from pagedresults free/cleanup functions.
+ */
void
ldbm_back_search_results_release( void **sr )
{
- delete_search_result_set( (back_search_result_set **)sr );
+ /* passing NULL pb forces to delete the search result set */
+ delete_search_result_set( NULL, (back_search_result_set **)sr );
}
int
diff --git a/ldap/servers/slapd/back-ldbm/vlv.c b/ldap/servers/slapd/back-ldbm/vlv.c
index 389a5ec..5e5d0a5 100644
--- a/ldap/servers/slapd/back-ldbm/vlv.c
+++ b/ldap/servers/slapd/back-ldbm/vlv.c
@@ -1156,7 +1156,7 @@ vlv_search_build_candidate_list(Slapi_PBlock *pb, const Slapi_DN *base, int *vlv
slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx );
slapi_rwlock_unlock(be->vlvSearchList_lock);
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
rc = VLV_FIND_SEARCH_FAILED;
} else if((*vlv_rc=vlvIndex_accessallowed(pi, pb)) != LDAP_SUCCESS) {
slapi_rwlock_unlock(be->vlvSearchList_lock);
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index db64950..3121e01 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1367,14 +1367,19 @@ void slapd_daemon( daemon_ports_t *ports )
mapping_tree_free ();
}
+ /*
+ * connection_table_free could use callbacks in the backend.
+ * (e.g., be_search_results_release)
+ * Thus, it needs to be called before be_cleanupall.
+ */
+ connection_table_free(the_connection_table);
+ the_connection_table= NULL;
+
be_cleanupall ();
- LDAPDebug( LDAP_DEBUG_TRACE, "slapd shutting down - backends closed down\n",
+ LDAPDebug( LDAP_DEBUG_TRACE, "slapd shutting down - backends closed down\n",
0, 0, 0 );
referrals_free();
- connection_table_free(the_connection_table);
- the_connection_table= NULL;
-
/* tell the time thread to shutdown and then wait for it */
time_shutdown = 1;
PR_JoinThread( time_thread_p );
diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c
index e47e4de..8ac413f 100644
--- a/ldap/servers/slapd/operation.c
+++ b/ldap/servers/slapd/operation.c
@@ -181,10 +181,11 @@ operation_init(Slapi_Operation *o, int flags)
o->o_next = NULL;
o->o_flags= flags;
if ( config_get_accesslog_level() & LDAP_DEBUG_TIMING ) {
- o->o_interval = PR_IntervalNow();
- } else {
- o->o_interval = (PRIntervalTime)0;
- }
+ o->o_interval = PR_IntervalNow();
+ } else {
+ o->o_interval = (PRIntervalTime)0;
+ }
+ o->o_pagedresults_sizelimit = -1;
}
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 42b0935..e7f6135 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -53,7 +53,7 @@ static void compute_limits (Slapi_PBlock *pb);
/* attributes that no clients are allowed to add or modify */
static char *protected_attrs_all [] = { PSEUDO_ATTR_UNHASHEDUSERPASSWORD,
- NULL };
+ NULL };
static char *pwpolicy_lock_attrs_all [] = { "passwordRetryCount",
"retryCountResetTime",
"accountUnlockTime",
@@ -239,7 +239,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
int internal_op;
Slapi_DN *basesdn = NULL;
Slapi_DN *sdn = NULL;
- Slapi_Operation *operation;
+ Slapi_Operation *operation = NULL;
Slapi_Entry *referral = NULL;
char *proxydn = NULL;
char *proxystr = NULL;
@@ -265,7 +265,6 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
int curr_search_count = 0;
Slapi_Backend *pr_be = NULL;
void *pr_search_result = NULL;
- int pr_reset_processing = 0;
int pr_idx = -1;
Slapi_DN *orig_sdn = NULL;
int free_sdn = 0;
@@ -469,23 +468,16 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
if ((LDAP_SUCCESS == rc) ||
(LDAP_CANCELLED == rc) || (0 == pagesize)) {
unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED;
- if (pagedresults_check_or_set_processing(pb->pb_conn, pr_idx)) {
- send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM,
- NULL, "Simple Paged Results Search "
- "already in progress on this connection",
- 0, NULL);
- goto free_and_return_nolock;
- }
- /* need to reset after we are done with this op */
- pr_reset_processing = 1;
op_set_pagedresults(operation);
pr_be = pagedresults_get_current_be(pb->pb_conn, pr_idx);
pr_search_result = pagedresults_get_search_result(pb->pb_conn,
+ operation,
pr_idx);
estimate =
pagedresults_get_search_result_set_size_estimate(pb->pb_conn,
+ operation,
pr_idx);
- if (pagedresults_get_unindexed(pb->pb_conn, pr_idx)) {
+ if (pagedresults_get_unindexed(pb->pb_conn, operation, pr_idx)) {
opnote |= SLAPI_OP_NOTE_UNINDEXED;
}
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
@@ -640,7 +632,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
time_up = (tlimit==-1 ? -1 : optime + tlimit); /* -1: no time limit */
- pagedresults_set_timelimit(pb->pb_conn, time_up, pr_idx);
+ pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, time_up, pr_idx);
}
/* PAR: now filters have been rewritten, we can assign plugins to work on them */
@@ -694,12 +686,25 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
if (op_is_pagedresults(operation) && pr_search_result) {
void *sr = NULL;
/* PAGED RESULTS and already have the search results from the prev op */
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
- rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat);
+ pagedresults_lock(pb->pb_conn, pr_idx);
+ /*
+ * In async paged result case, the search result might be released
+ * by other theads. We need to double check it in the locked region.
+ */
+ pr_search_result = pagedresults_get_search_result(pb->pb_conn,
+ operation,
+ pr_idx);
+ if (pr_search_result) {
+ slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
+ rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat);
- /* search result could be reset in the backend/dse */
- slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
- pagedresults_set_search_result(pb->pb_conn, sr, 0, pr_idx);
+ /* search result could be reset in the backend/dse */
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
+ pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx);
+ } else {
+ pr_stat = PAGEDRESULTS_SEARCH_END;
+ }
+ pagedresults_unlock(pb->pb_conn, pr_idx);
if (PAGEDRESULTS_SEARCH_END == pr_stat) {
/* no more entries to send in the backend */
@@ -720,14 +725,18 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
}
pagedresults_set_response_control(pb, 0, estimate,
curr_search_count, pr_idx);
- if (pagedresults_get_with_sort(pb->pb_conn, pr_idx)) {
+ if (pagedresults_get_with_sort(pb->pb_conn, operation, pr_idx)) {
sort_make_sort_response_control(pb, CONN_GET_SORT_RESULT_CODE, NULL);
}
pagedresults_set_search_result_set_size_estimate(pb->pb_conn,
+ operation,
estimate, pr_idx);
next_be = NULL; /* to break the loop */
if (curr_search_count == -1) {
- pagedresults_free_one(pb->pb_conn, pr_idx);
+ pagedresults_lock(pb->pb_conn, pr_idx);
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
+ pagedresults_free_one(pb->pb_conn, operation, pr_idx);
+ pagedresults_unlock(pb->pb_conn, pr_idx);
}
} else {
/* be_suffix null means that we are searching the default backend
@@ -849,7 +858,11 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
int with_sort = operation->o_flags & OP_FLAG_SERVER_SIDE_SORTING;
curr_search_count = pnentries;
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
if (PAGEDRESULTS_SEARCH_END == pr_stat) {
+ if (sr) { /* in case a left over sr is found, clean it up */
+ be->be_search_results_release(&sr);
+ }
if (NULL == next_be) {
/* no more entries && no more backends */
curr_search_count = -1;
@@ -861,24 +874,31 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
}
} else {
curr_search_count = pnentries;
- slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
- if (pagedresults_set_current_be(pb->pb_conn, be, pr_idx) < 0 ||
- pagedresults_set_search_result(pb->pb_conn, sr, 0, pr_idx) < 0 ||
- pagedresults_set_search_result_count(pb->pb_conn,
- curr_search_count, pr_idx) < 0 ||
- pagedresults_set_search_result_set_size_estimate(pb->pb_conn,
- estimate, pr_idx) < 0 ||
- pagedresults_set_with_sort(pb->pb_conn, with_sort, pr_idx) < 0) {
+ pagedresults_lock(pb->pb_conn, pr_idx);
+ if ((pagedresults_set_current_be(pb->pb_conn, be, pr_idx) < 0) ||
+ (pagedresults_set_search_result(pb->pb_conn, operation,
+ sr, 0, pr_idx) < 0) ||
+ (pagedresults_set_search_result_count(pb->pb_conn, operation,
+ curr_search_count,
+ pr_idx) < 0) ||
+ (pagedresults_set_search_result_set_size_estimate(pb->pb_conn,
+ operation,
+ estimate,
+ pr_idx) < 0) ||
+ (pagedresults_set_with_sort(pb->pb_conn, operation,
+ with_sort, pr_idx) < 0)) {
+ pagedresults_unlock(pb->pb_conn, pr_idx);
goto free_and_return;
}
+ pagedresults_unlock(pb->pb_conn, pr_idx);
}
pagedresults_set_response_control(pb, 0, estimate,
curr_search_count, pr_idx);
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
next_be = NULL; /* to break the loop */
if (curr_search_count == -1) {
- pagedresults_free_one(pb->pb_conn, pr_idx);
+ pagedresults_free_one(pb->pb_conn, operation, pr_idx);
}
}
@@ -1007,9 +1027,6 @@ free_and_return_nolock:
slapi_ch_free_string(&proxydn);
slapi_ch_free_string(&proxystr);
- if (pr_reset_processing) {
- pagedresults_reset_processing(pb->pb_conn, pr_idx);
- }
}
/* Returns 1 if this processing on this entry is finished
@@ -1257,7 +1274,7 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result,
*pnentries = 0;
- while (!done)
+ while (!done)
{
Slapi_Entry *gerentry = NULL;
Slapi_Operation *operation;
@@ -1275,7 +1292,7 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result,
operation_out_of_disk_space();
}
pr_stat = PAGEDRESULTS_SEARCH_END;
- pagedresults_set_timelimit(pb->pb_conn, 0, pr_idx);
+ pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, 0, pr_idx);
rval = -1;
done = 1;
continue;
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
index 9b294eb..78bd6b0 100644
--- a/ldap/servers/slapd/pagedresults.c
+++ b/ldap/servers/slapd/pagedresults.c
@@ -131,6 +131,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
}
}
conn->c_pagedresults.prl_count++;
+ conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock();
} else {
/* Repeated paged results request.
* PagedResults is already allocated. */
@@ -140,6 +141,8 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
*index = strtol(ptr, NULL, 10);
slapi_ch_free_string(&ptr);
}
+ /* reset sizelimit */
+ op->o_pagedresults_sizelimit = -1;
slapi_ch_free((void **)&cookie.bv_val);
if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) {
@@ -243,10 +246,13 @@ bailout:
}
int
-pagedresults_free_one( Connection *conn, int index )
+pagedresults_free_one( Connection *conn, Operation *op, int index )
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return 0; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_free_one: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -256,13 +262,19 @@ pagedresults_free_one( Connection *conn, int index )
"conn=%d paged requests list count is %d\n",
conn->c_connid, conn->c_pagedresults.prl_count);
} else if (index < conn->c_pagedresults.prl_maxlen) {
+ PRLock *prmutex = NULL;
PagedResults *prp = conn->c_pagedresults.prl_list + index;
if (prp && prp->pr_current_be &&
prp->pr_current_be->be_search_results_release &&
prp->pr_search_result_set) {
prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
}
+ if (prp->pr_mutex) {
+ /* pr_mutex is reused; back it up and reset it. */
+ prmutex = prp->pr_mutex;
+ }
memset(prp, '\0', sizeof(PagedResults));
+ prp->pr_mutex = prmutex;
conn->c_pagedresults.prl_count--;
rc = 0;
}
@@ -348,9 +360,12 @@ pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index)
}
void *
-pagedresults_get_search_result(Connection *conn, int index)
+pagedresults_get_search_result(Connection *conn, Operation *op, int index)
{
void *sr = NULL;
+ if (!op_is_pagedresults(op)) {
+ return sr; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_search_result: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -366,20 +381,31 @@ pagedresults_get_search_result(Connection *conn, int index)
}
int
-pagedresults_set_search_result(Connection *conn, void *sr,
+pagedresults_set_search_result(Connection *conn, Operation *op, void *sr,
int locked, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return 0; /* noop */
+ }
LDAPDebug2Args(LDAP_DEBUG_TRACE,
"--> pagedresults_set_search_result: idx=%d, sr=%p\n",
index, sr);
if (conn && (index > -1)) {
if (!locked) PR_Lock(conn->c_mutex);
if (index < conn->c_pagedresults.prl_maxlen) {
- conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
+ if (sr) { /* set */
+ if (NULL ==
+ conn->c_pagedresults.prl_list[index].pr_search_result_set) {
+ conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
+ rc = 0;
+ }
+ } else { /* reset */
+ conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
+ rc = 0;
+ }
}
if (!locked) PR_Unlock(conn->c_mutex);
- rc = 0;
}
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"<-- pagedresults_set_search_result: %d\n", rc);
@@ -387,9 +413,12 @@ pagedresults_set_search_result(Connection *conn, void *sr,
}
int
-pagedresults_get_search_result_count(Connection *conn, int index)
+pagedresults_get_search_result_count(Connection *conn, Operation *op, int index)
{
int count = 0;
+ if (!op_is_pagedresults(op)) {
+ return count; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_search_result_count: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -405,9 +434,13 @@ pagedresults_get_search_result_count(Connection *conn, int index)
}
int
-pagedresults_set_search_result_count(Connection *conn, int count, int index)
+pagedresults_set_search_result_count(Connection *conn, Operation *op,
+ int count, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_search_result_count: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -424,9 +457,14 @@ pagedresults_set_search_result_count(Connection *conn, int count, int index)
}
int
-pagedresults_get_search_result_set_size_estimate(Connection *conn, int index)
+pagedresults_get_search_result_set_size_estimate(Connection *conn,
+ Operation *op,
+ int index)
{
int count = 0;
+ if (!op_is_pagedresults(op)) {
+ return count; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_search_result_set_size_estimate: "
"idx=%d\n", index);
@@ -445,9 +483,13 @@ pagedresults_get_search_result_set_size_estimate(Connection *conn, int index)
int
pagedresults_set_search_result_set_size_estimate(Connection *conn,
+ Operation *op,
int count, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_search_result_set_size_estimate: "
"idx=%d\n", index);
@@ -466,9 +508,12 @@ pagedresults_set_search_result_set_size_estimate(Connection *conn,
}
int
-pagedresults_get_with_sort(Connection *conn, int index)
+pagedresults_get_with_sort(Connection *conn, Operation *op, int index)
{
int flags = 0;
+ if (!op_is_pagedresults(op)) {
+ return flags; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_with_sort: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -484,9 +529,13 @@ pagedresults_get_with_sort(Connection *conn, int index)
}
int
-pagedresults_set_with_sort(Connection *conn, int flags, int index)
+pagedresults_set_with_sort(Connection *conn, Operation *op,
+ int flags, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_with_sort: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -505,9 +554,12 @@ pagedresults_set_with_sort(Connection *conn, int flags, int index)
}
int
-pagedresults_get_unindexed(Connection *conn, int index)
+pagedresults_get_unindexed(Connection *conn, Operation *op, int index)
{
int flags = 0;
+ if (!op_is_pagedresults(op)) {
+ return flags; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_unindexed: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -523,9 +575,12 @@ pagedresults_get_unindexed(Connection *conn, int index)
}
int
-pagedresults_set_unindexed(Connection *conn, int index)
+pagedresults_set_unindexed(Connection *conn, Operation *op, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_unindexed: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -543,9 +598,12 @@ pagedresults_set_unindexed(Connection *conn, int index)
}
int
-pagedresults_get_sort_result_code(Connection *conn, int index)
+pagedresults_get_sort_result_code(Connection *conn, Operation *op, int index)
{
int code = LDAP_OPERATIONS_ERROR;
+ if (!op_is_pagedresults(op)) {
+ return code; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_sort_result_code: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -561,9 +619,13 @@ pagedresults_get_sort_result_code(Connection *conn, int index)
}
int
-pagedresults_set_sort_result_code(Connection *conn, int code, int index)
+pagedresults_set_sort_result_code(Connection *conn, Operation *op,
+ int code, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_sort_result_code: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -580,9 +642,13 @@ pagedresults_set_sort_result_code(Connection *conn, int code, int index)
}
int
-pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index)
+pagedresults_set_timelimit(Connection *conn, Operation *op,
+ time_t timelimit, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_timelimit: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -597,6 +663,35 @@ pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index)
return rc;
}
+int
+pagedresults_set_sizelimit(Connection *conn, Operation *op,
+ int sizelimit, int index)
+{
+ int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+ "--> pagedresults_set_sizelimit: idx=%d\n", index);
+ op->o_pagedresults_sizelimit = sizelimit;
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_set_sizelimit: %d\n", rc);
+ return rc;
+}
+
+int
+pagedresults_get_sizelimit(Connection *conn, Operation *op, int index)
+{
+ int sizelimit = -1;
+ if (!op_is_pagedresults(op)) {
+ return sizelimit; /* noop */
+ }
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+ "--> pagedresults_get_sizelimit: idx=%d\n", index);
+ sizelimit = op->o_pagedresults_sizelimit;
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_get_sizelimit\n");
+ return sizelimit;
+}
+
/*
* pagedresults_cleanup cleans up the pagedresults list;
* it does not free the list.
@@ -629,6 +724,9 @@ pagedresults_cleanup(Connection *conn, int needlock)
prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
rc = 1;
}
+ if (prp->pr_mutex) {
+ PR_DestroyLock(prp->pr_mutex);
+ }
memset(prp, '\0', sizeof(PagedResults));
}
conn->c_pagedresults.prl_count = 0;
@@ -665,6 +763,9 @@ pagedresults_cleanup_all(Connection *conn, int needlock)
for (i = 0; conn->c_pagedresults.prl_list &&
i < conn->c_pagedresults.prl_maxlen; i++) {
prp = conn->c_pagedresults.prl_list + i;
+ if (prp->pr_mutex) {
+ PR_DestroyLock(prp->pr_mutex);
+ }
if (prp->pr_current_be && prp->pr_search_result_set &&
prp->pr_current_be->be_search_results_release) {
prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
@@ -681,6 +782,7 @@ pagedresults_cleanup_all(Connection *conn, int needlock)
return rc;
}
+#if 0 /* Stopped using it (#47347) */
/*
* check to see if this connection is currently processing
* a pagedresults search - if it is, return True - if not,
@@ -734,6 +836,7 @@ pagedresults_reset_processing(Connection *conn, int index)
"<-- pagedresults_reset_processing: %d\n", ret);
return ret;
}
+#endif
/* Are all the paged results requests timed out? */
int
@@ -819,3 +922,35 @@ op_set_pagedresults(Operation *op)
}
op->o_flags |= OP_FLAG_PAGED_RESULTS;
}
+
+/*
+ * pagedresults_lock/unlock -- introduced to protect search results for the
+ * asynchronous searches.
+ */
+void
+pagedresults_lock( Connection *conn, int index )
+{
+ PagedResults *prp;
+ if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
+ return;
+ }
+ prp = conn->c_pagedresults.prl_list + index;
+ if (prp->pr_mutex) {
+ PR_Lock(prp->pr_mutex);
+ }
+ return;
+}
+
+void
+pagedresults_unlock( Connection *conn, int index )
+{
+ PagedResults *prp;
+ if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
+ return;
+ }
+ prp = conn->c_pagedresults.prl_list + index;
+ if (prp->pr_mutex) {
+ PR_Unlock(prp->pr_mutex);
+ }
+ return;
+}
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 9b0072b..10dec7a 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1442,34 +1442,48 @@ void pagedresults_set_response_control(Slapi_PBlock *pb, int iscritical,
int curr_search_count, int index);
Slapi_Backend *pagedresults_get_current_be(Connection *conn, int index);
int pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index);
-void *pagedresults_get_search_result(Connection *conn, int index);
-int pagedresults_set_search_result(Connection *conn, void *sr,
+void *pagedresults_get_search_result(Connection *conn, Operation *op,
+ int index);
+int pagedresults_set_search_result(Connection *conn, Operation *op, void *sr,
int locked, int index);
-int pagedresults_get_search_result_count(Connection *conn, int index);
-int pagedresults_set_search_result_count(Connection *conn, int cnt, int index);
-int pagedresults_get_search_result_set_size_estimate(Connection *conn,
+int pagedresults_get_search_result_count(Connection *conn, Operation *op,
+ int index);
+int pagedresults_set_search_result_count(Connection *conn, Operation *op, int cnt, int index);
+int pagedresults_get_search_result_set_size_estimate(Connection *conn,
+ Operation *op,
int index);
-int pagedresults_set_search_result_set_size_estimate(Connection *conn, int cnt,
+int pagedresults_set_search_result_set_size_estimate(Connection *conn,
+ Operation *op, int cnt,
int index);
-int pagedresults_get_with_sort(Connection *conn, int index);
-int pagedresults_set_with_sort(Connection *conn, int flags, int index);
-int pagedresults_get_unindexed(Connection *conn, int index);
-int pagedresults_set_unindexed(Connection *conn, int index);
-int pagedresults_get_sort_result_code(Connection *conn, int index);
-int pagedresults_set_sort_result_code(Connection *conn, int code, int index);
-int pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index);
+int pagedresults_get_with_sort(Connection *conn, Operation *op, int index);
+int pagedresults_set_with_sort(Connection *conn, Operation *op,
+ int flags, int index);
+int pagedresults_get_unindexed(Connection *conn, Operation *op, int index);
+int pagedresults_set_unindexed(Connection *conn, Operation *op, int index);
+int pagedresults_get_sort_result_code(Connection *conn, Operation *op,
+ int index);
+int pagedresults_set_sort_result_code(Connection *conn, Operation *op,
+ int code, int index);
+int pagedresults_set_timelimit(Connection *conn, Operation *op,
+ time_t timelimit, int index);
+int pagedresults_get_sizelimit(Connection *conn, Operation *op, int index);
+int pagedresults_set_sizelimit(Connection *conn, Operation *op,
+ int sizelimit, int index);
int pagedresults_cleanup(Connection *conn, int needlock);
+#if 0 /* Stopped using it (#47347) */
int pagedresults_check_or_set_processing(Connection *conn, int index);
int pagedresults_reset_processing(Connection *conn, int index);
+#endif
int pagedresults_is_timedout_nolock(Connection *conn);
int pagedresults_reset_timedout_nolock(Connection *conn);
int pagedresults_in_use_nolock(Connection *conn);
-int pagedresults_free_one(Connection *conn, int index);
-int pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid );
+int pagedresults_free_one(Connection *conn, Operation *op, int index);
+int pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid);
int op_is_pagedresults(Operation *op);
int pagedresults_cleanup_all(Connection *conn, int needlock);
void op_set_pagedresults(Operation *op);
-
+void pagedresults_lock(Connection *conn, int index);
+void pagedresults_unlock(Connection *conn, int index);
/*
* sort.c
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 1f37e3d..b0ac7b3 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1367,6 +1367,7 @@ typedef struct op {
unsigned long o_abandoned_op; /* operation abandoned by this operation - used to decide which plugins to invoke */
struct slapi_operation_parameters o_params;
struct slapi_operation_results o_results;
+ int o_pagedresults_sizelimit;
} Operation;
/*
@@ -1395,6 +1396,7 @@ typedef struct _paged_results {
time_t pr_timelimit; /* time limit for this request */
int pr_flags;
ber_int_t pr_msgid; /* msgid of the request; to abandon */
+ PRLock *pr_mutex; /* protect each conn structure */
} PagedResults;
/* array of simple paged structure stashed in connection */
diff --git a/ldap/servers/slapd/sort.c b/ldap/servers/slapd/sort.c
index 903fa6f..72c9ec9 100644
--- a/ldap/servers/slapd/sort.c
+++ b/ldap/servers/slapd/sort.c
@@ -58,12 +58,14 @@ sort_make_sort_response_control ( Slapi_PBlock *pb, int code, char *error_type)
slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
if (code == CONN_GET_SORT_RESULT_CODE) {
- code = pagedresults_get_sort_result_code(pb->pb_conn, pr_idx);
+ code = pagedresults_get_sort_result_code(pb->pb_conn,
+ pb->pb_op, pr_idx);
} else {
Slapi_Operation *operation;
slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
if (op_is_pagedresults(operation)) {
- pagedresults_set_sort_result_code(pb->pb_conn, code, pr_idx);
+ pagedresults_set_sort_result_code(pb->pb_conn,
+ pb->pb_op, code, pr_idx);
}
}
11 years
Branch '389-ds-base-1.3.1' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/daemon.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
New commits:
commit 78f029f66344eabb32be2421b953bbdbb754d5a0
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Apr 24 20:36:37 2013 -0600
Ticket #47349 - DS instance crashes under a high load
https://fedorahosted.org/389/ticket/47349
Reviewed by: nkinder (Thanks!)
Branch: 389-ds-base-1.3.1
Fix Description: handle_new_connection initializes the connection object,
then calls connection_table_move_connection_on_to_active_list to put it
on the list of active connections, then unlocks the c_mutex, then calls
connection_new_private to allocate c_private. If another thread
interrupts after the conn has been moved to the active list, but before
c_private has been allocated, the new conn will be available via
connection_table_iterate_active_connections where table_iterate_function
will attempt to dereference the NULL c_private.
The fix is to move connection_new_private inside the c_mutex lock, and to
move connection_table_move_connection_on_to_active_list to be the very last
thing before releasing the c_mutex lock. Once the conn is on the active
list it is live and we cannot do anything else to it.
Note: I have still not been able to reproduce the problem in a non-debug
optimized build.
Platforms tested: RHEL6 x86_64
Note: Before patch, server would crash within 5 minutes. After patch, server
has been running for several days in customer environment.
Flag Day: no
Doc impact: no
(cherry picked from commit 05d209432571dc64b242ae47113ae4cbb43607d2)
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index fa19312..66677d2 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -2686,16 +2686,6 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
/* Call the plugin extension constructors */
conn->c_extension = factory_create_extension(connection_type,conn,NULL /* Parent */);
-
- /* Add this connection slot to the doubly linked list of active connections. This
- * list is used to find the connections that should be used in the poll call. This
- * connection will be added directly after slot 0 which serves as the head of the list */
- if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL )
- {
- /* Now give the new connection to the connection code */
- connection_table_move_connection_on_to_active_list(the_connection_table,conn);
- }
-
#if defined(ENABLE_LDAPI)
#if !defined( XP_WIN32 )
/* ldapi */
@@ -2708,10 +2698,21 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
#endif
#endif /* ENABLE_LDAPI */
- PR_Unlock( conn->c_mutex );
-
connection_new_private(conn);
+ /* Add this connection slot to the doubly linked list of active connections. This
+ * list is used to find the connections that should be used in the poll call. This
+ * connection will be added directly after slot 0 which serves as the head of the list.
+ * This must be done as the very last thing before we unlock the mutex, because once it
+ * is added to the active list, it is live. */
+ if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL )
+ {
+ /* Now give the new connection to the connection code */
+ connection_table_move_connection_on_to_active_list(the_connection_table,conn);
+ }
+
+ PR_Unlock( conn->c_mutex );
+
g_increment_current_conn_count();
return 0;
11 years
ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/daemon.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
New commits:
commit 05d209432571dc64b242ae47113ae4cbb43607d2
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Apr 24 20:36:37 2013 -0600
Ticket #47349 - DS instance crashes under a high load
https://fedorahosted.org/389/ticket/47349
Reviewed by: nkinder (Thanks!)
Branch: master
Fix Description: handle_new_connection initializes the connection object,
then calls connection_table_move_connection_on_to_active_list to put it
on the list of active connections, then unlocks the c_mutex, then calls
connection_new_private to allocate c_private. If another thread
interrupts after the conn has been moved to the active list, but before
c_private has been allocated, the new conn will be available via
connection_table_iterate_active_connections where table_iterate_function
will attempt to dereference the NULL c_private.
The fix is to move connection_new_private inside the c_mutex lock, and to
move connection_table_move_connection_on_to_active_list to be the very last
thing before releasing the c_mutex lock. Once the conn is on the active
list it is live and we cannot do anything else to it.
Note: I have still not been able to reproduce the problem in a non-debug
optimized build.
Platforms tested: RHEL6 x86_64
Note: Before patch, server would crash within 5 minutes. After patch, server
has been running for several days in customer environment.
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 962699a..db64950 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -2686,16 +2686,6 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
/* Call the plugin extension constructors */
conn->c_extension = factory_create_extension(connection_type,conn,NULL /* Parent */);
-
- /* Add this connection slot to the doubly linked list of active connections. This
- * list is used to find the connections that should be used in the poll call. This
- * connection will be added directly after slot 0 which serves as the head of the list */
- if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL )
- {
- /* Now give the new connection to the connection code */
- connection_table_move_connection_on_to_active_list(the_connection_table,conn);
- }
-
#if defined(ENABLE_LDAPI)
#if !defined( XP_WIN32 )
/* ldapi */
@@ -2708,10 +2698,21 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
#endif
#endif /* ENABLE_LDAPI */
- PR_Unlock( conn->c_mutex );
-
connection_new_private(conn);
+ /* Add this connection slot to the doubly linked list of active connections. This
+ * list is used to find the connections that should be used in the poll call. This
+ * connection will be added directly after slot 0 which serves as the head of the list.
+ * This must be done as the very last thing before we unlock the mutex, because once it
+ * is added to the active list, it is live. */
+ if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL )
+ {
+ /* Now give the new connection to the connection code */
+ connection_table_move_connection_on_to_active_list(the_connection_table,conn);
+ }
+
+ PR_Unlock( conn->c_mutex );
+
g_increment_current_conn_count();
return 0;
11 years
ldap/servers
by Ludwig Krispenz
ldap/servers/slapd/entry.c | 10
ldap/servers/slapd/entrywsi.c | 553 +++++++++++++++++++++++++---------------
ldap/servers/slapd/proto-slap.h | 1
ldap/servers/slapd/valueset.c | 9
4 files changed, 378 insertions(+), 195 deletions(-)
New commits:
commit c7f6f161f4967635d6f02b029be571d88ec61961
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Wed Mar 20 14:46:33 2013 +0100
Reduce replication meta data stored in entry, cf ticket 569
Reviewed by richm, thanks
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 01446ff..6ca4c72 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -1718,6 +1718,16 @@ entry2str_internal_put_attrlist( const Slapi_Attr *attrlist, int attr_state, int
else
{
/* There were no present values on which to place the ADCSN, so we put it on the first deleted value. */
+ if ( valueset_isempty(&a->a_deleted_values)) {
+ /* this means the entry is deleted and has no more attributes,
+ * when writing the attr to disk we would loose the AD-csn.
+ * Add an empty value to the set of deleted values. This will
+ * never be seen by any client. It will never be moved to the
+ * present values and is only used to preserve the AD-csn
+ */
+ valueset_add_string (&a->a_deleted_values, "", CSN_TYPE_VALUE_DELETED, a->a_deletioncsn);
+ }
+
entry2str_internal_put_valueset(a->a_type, a->a_deletioncsn, CSN_TYPE_ATTRIBUTE_DELETED, attr_state, &a->a_deleted_values, VALUE_DELETED, ecur, typebuf, typebuf_len, entry2str_ctrl);
}
}
diff --git a/ldap/servers/slapd/entrywsi.c b/ldap/servers/slapd/entrywsi.c
index 578cb4f..c786b87 100644
--- a/ldap/servers/slapd/entrywsi.c
+++ b/ldap/servers/slapd/entrywsi.c
@@ -419,25 +419,129 @@ entry_add_present_attribute_wsi(Slapi_Entry *e, Slapi_Attr *a)
* Preserves LDAP Information Model constraints,
* returning an LDAP result code.
*/
+static void resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state);
+static void resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate);
+static void resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate);
+static void resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate, int attribute_state);
+static int entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags);
+static int entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags);
static int
entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
{
+ int retVal = LDAP_SUCCESS;
+ Slapi_Attr *a= NULL;
+ int attr_state= entry_attr_find_wsi(e, type, &a);
+ if (ATTRIBUTE_NOTFOUND == attr_state)
+ {
+ /* Create a new attribute */
+ a = slapi_attr_new();
+ slapi_attr_init(a, type);
+ attrlist_add(&e->e_attrs, a);
+ }
+
+ if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
+ {
+ retVal = entry_add_present_values_wsi_single_valued( e, type, bervals, csn, urp, 0 );
+ }
+ else
+ {
+ retVal = entry_add_present_values_wsi_multi_valued( e, type, bervals, csn, urp, 0 );
+ }
+ return retVal;
+}
+static int
+entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
+{
int retVal= LDAP_SUCCESS;
- Slapi_Value **valuestoadd = NULL;
- valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
+ Slapi_Value **valuestoadd = NULL;
+ valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
if(!valuearray_isempty(valuestoadd))
{
Slapi_Attr *a= NULL;
long a_flags_orig;
int attr_state= entry_attr_find_wsi(e, type, &a);
- if (ATTRIBUTE_NOTFOUND == attr_state)
+ a_flags_orig = a->a_flags;
+ a->a_flags |= flags;
+ /* Check if the type of the to-be-added values has DN syntax or not. */
+ if (slapi_attr_is_dn_syntax_attr(a)) {
+ valuearray_dn_normalize_value(valuestoadd);
+ a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
+ }
+ if(urp)
{
- /* Create a new attribute */
- a = slapi_attr_new();
- slapi_attr_init(a, type);
- attrlist_add(&e->e_attrs, a);
+ valueset_remove_valuearray (&a->a_present_values, a, valuestoadd,
+ SLAPI_VALUE_FLAG_IGNOREERROR |
+ SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
+ valueset_remove_valuearray (&a->a_deleted_values, a, valuestoadd,
+ SLAPI_VALUE_FLAG_IGNOREERROR |
+ SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
+ valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
+ valueset_add_valuearray_ext(&a->a_present_values, valuestoadd, SLAPI_VALUE_FLAG_PASSIN);
+ slapi_ch_free ( (void **)&valuestoadd );
+
+ /*
+ * Now delete non-RDN values from a->a_present_values; and
+ * restore possible RDN values from a->a_deleted_values
+ */
+ resolve_attribute_state_single_valued(e, a, attr_state);
+ retVal= LDAP_SUCCESS;
}
- a_flags_orig = a->a_flags;
+ else
+ {
+ Slapi_Value **deletedvalues= NULL;
+ switch(attr_state)
+ {
+ case ATTRIBUTE_PRESENT:
+ /* The attribute is already on the present list */
+ break;
+ case ATTRIBUTE_DELETED:
+ /* Move the deleted attribute onto the present list */
+ entry_deleted_attribute_to_present_attribute(e, a);
+ break;
+ case ATTRIBUTE_NOTFOUND:
+ /* No-op - attribute was initialized & added to entry above */
+ break;
+ }
+ /* Check if any of the values to be added are on the deleted list */
+ valueset_remove_valuearray(&a->a_deleted_values,
+ a, valuestoadd,
+ SLAPI_VALUE_FLAG_IGNOREERROR|SLAPI_VALUE_FLAG_USENEWVALUE,
+ &deletedvalues); /* JCM Check return code */
+ if(deletedvalues!=NULL && deletedvalues[0]!=NULL)
+ {
+ /* Some of the values to be added were on the deleted list */
+ Slapi_Value **v= NULL;
+ 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);
+ /* 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);
+ valuestoadd= valueset_get_valuearray(&vs);
+ valuearray_free(&v);
+ slapi_ch_free((void **)&deletedvalues);
+ }
+ valuearray_update_csn(valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
+ retVal= attr_add_valuearray(a, valuestoadd, slapi_entry_get_dn_const(e));
+ valuearray_free(&valuestoadd);
+ }
+ a->a_flags = a_flags_orig;
+ }
+ return(retVal);
+}
+static int
+entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
+{
+ int retVal= LDAP_SUCCESS;
+ Slapi_Value **valuestoadd = NULL;
+ valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
+ if(!valuearray_isempty(valuestoadd))
+ {
+ Slapi_Attr *a= NULL;
+ long a_flags_orig;
+ int attr_state= entry_attr_find_wsi(e, type, &a);
+ a_flags_orig = a->a_flags;
a->a_flags |= flags;
/* Check if the type of the to-be-added values has DN syntax or not. */
if (slapi_attr_is_dn_syntax_attr(a)) {
@@ -462,16 +566,14 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **b
SLAPI_VALUE_FLAG_IGNOREERROR |
SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
- /* Append the pending values to a->a_present_values */
+ /* Now add the values in values to add to present or deleted
+ * values, depending on their csnset */
valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
- valueset_add_valuearray_ext(&a->a_present_values, valuestoadd, SLAPI_VALUE_FLAG_PASSIN);
+
+ resolve_attribute_state_to_present_or_deleted(e, a, valuestoadd, attr_state);
+
slapi_ch_free ( (void **)&valuestoadd );
- /*
- * Now delete non-RDN values from a->a_present_values; and
- * restore possible RDN values from a->a_deleted_values
- */
- resolve_attribute_state(e, a, attr_state, 0);
retVal= LDAP_SUCCESS;
}
else
@@ -526,13 +628,155 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **b
* returning an LDAP result code.
*/
static int
+entry_delete_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals);
+static int
+entry_delete_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals);
+static int
entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
{
int retVal= LDAP_SUCCESS;
Slapi_Attr *a= NULL;
int attr_state= entry_attr_find_wsi(e, type, &a);
+
if(attr_state==ATTRIBUTE_PRESENT || (attr_state==ATTRIBUTE_DELETED && urp))
{
+ if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
+ retVal = entry_delete_present_values_wsi_single_valued(e, type, vals, csn, urp, mod_op, replacevals);
+ else
+ retVal = entry_delete_present_values_wsi_multi_valued(e, type, vals, csn, urp, mod_op, replacevals);
+ }
+ else if (attr_state==ATTRIBUTE_DELETED)
+ {
+#if defined(USE_OLD_UNHASHED)
+ if (is_type_forbidden(type)) {
+ retVal = LDAP_SUCCESS;
+ } else {
+ retVal= LDAP_NO_SUCH_ATTRIBUTE;
+ }
+#else
+ retVal= LDAP_NO_SUCH_ATTRIBUTE;
+#endif
+ }
+ else if (attr_state==ATTRIBUTE_NOTFOUND)
+ {
+#if defined(USE_OLD_UNHASHED)
+ if (is_type_protected(type) || is_type_forbidden(type))
+#else
+ if (is_type_protected(type))
+#endif
+ {
+ retVal = LDAP_SUCCESS;
+ } else {
+ if (!urp) {
+ LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
+ type);
+ }
+ retVal = LDAP_NO_SUCH_ATTRIBUTE;
+ }
+ if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
+ {
+ /* Create a new attribute and set the adcsn */
+ Slapi_Attr *a = slapi_attr_new();
+ slapi_attr_init(a, type);
+ attr_set_deletion_csn(a,csn);
+ entry_add_deleted_attribute_wsi(e, a);
+ }
+ }
+ return retVal;
+}
+static int
+entry_delete_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
+{
+ int retVal= LDAP_SUCCESS;
+ Slapi_Attr *a= NULL;
+ int attr_state= entry_attr_find_wsi(e, type, &a);
+ /* The attribute is on the present list, or the deleted list and we're doing URP */
+ if ( vals == NULL || vals[0] == NULL )
+ {
+ /* delete the entire attribute */
+ LDAPDebug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", type, 0, 0 );
+ attr_set_deletion_csn(a,csn);
+ if(urp)
+ {
+ resolve_attribute_state_single_valued(e, a, attr_state);
+ /* resolve attr state single valued */
+ /* keep_present = check_attr_single_value_is_distingiuished(&a->a_present_values);
+ if ( !keep_present) {
+ slapi_valueset_done(&a->a_present_values);
+ entry_present_attribute_to_deleted_attribute(e, a);
+ }
+ */
+ }
+ else
+ {
+ slapi_valueset_done(&a->a_present_values);
+ entry_present_attribute_to_deleted_attribute(e, a);
+ }
+ retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present */
+ }
+ else
+ {
+ /* delete some specific values */
+ Slapi_Value **valuestodelete= NULL;
+ valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
+ /* Check if the type of the to-be-deleted values has DN syntax
+ * or not. */
+ if (slapi_attr_is_dn_syntax_attr(a)) {
+ valuearray_dn_normalize_value(valuestodelete);
+ a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
+ }
+ if(urp)
+ {
+ Slapi_Value **valuesupdated= NULL;
+ valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
+ if( valuesupdated && *valuesupdated)
+ {
+ attr_set_deletion_csn(a,csn);
+ }
+ /* resolve attr state single valued */
+ valuearray_free(&valuesupdated);
+ 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_ch_free((void **)&valuestodelete);
+ resolve_attribute_state_single_valued(e, a, attr_state);
+ retVal= LDAP_SUCCESS;
+ }
+ else
+ {
+ Slapi_Value **deletedvalues= NULL;
+ retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0 /* Do Not Ignore Errors */,&deletedvalues);
+ if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
+ {
+ valuearray_free(&deletedvalues);
+ /* The attribute is single valued and the value was successful deleted */
+ entry_present_attribute_to_deleted_attribute(e, a);
+ }
+ else if (retVal != LDAP_SUCCESS)
+ {
+ /* Failed
+ * - Value not found
+ * - Operations error
+ */
+ if ( retVal==LDAP_OPERATIONS_ERROR )
+ {
+ LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
+ "value for attribute type %s found in "
+ "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
+ }
+ }
+ valuearray_free(&valuestodelete);
+ }
+ }
+ return( retVal );
+}
+static int
+entry_delete_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
+{
+ int retVal= LDAP_SUCCESS;
+ Slapi_Attr *a= NULL;
+ int attr_state= entry_attr_find_wsi(e, type, &a);
/* The attribute is on the present list, or the deleted list and we're doing URP */
if ( vals == NULL || vals[0] == NULL )
{
@@ -541,16 +785,19 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
attr_set_deletion_csn(a,csn);
if(urp)
{
- resolve_attribute_state(e, a, attr_state, 1 /* set delete priority */); /* ABSOLVED */
+ /* there might be values added or specifically deleted later than
+ * the current attr delete operation. These values need to be
+ * preserved, all others can be removed, purging should o the job.
+ */
+ valueset_purge(&a->a_present_values, csn);
+ valueset_purge(&a->a_deleted_values, csn);
+ if(valueset_isempty(&a->a_present_values))
+ entry_present_attribute_to_deleted_attribute(e, a);
}
else
{
- if(!slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
- {
- /* We don't maintain a deleted value list for single valued attributes */
- valueset_add_valueset(&a->a_deleted_values, &a->a_present_values); /* JCM Would be better to passin the valuestodelete */
- }
slapi_valueset_done(&a->a_present_values);
+ slapi_valueset_done(&a->a_deleted_values);
entry_present_attribute_to_deleted_attribute(e, a);
}
retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present */
@@ -558,8 +805,8 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
else
{
/* delete some specific values */
- Slapi_Value **valuestodelete= NULL;
- valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
+ Slapi_Value **valuestodelete= NULL;
+ valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
/* Check if the type of the to-be-deleted values has DN syntax
* or not. */
if (slapi_attr_is_dn_syntax_attr(a)) {
@@ -568,47 +815,43 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
}
if(urp)
{
+ /* check if values to delete are in present values
+ * if v in present values and VU-csn<csn and v not distinguished move to deleted values
+ * if v not in present values, check deleted values and update csn, if distinguisehed at csn
+ * move back to present values
+ */
+
+
Slapi_Value **valuesupdated= NULL;
- valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
- /* if we removed the last value, we need to mark the attribute as deleted
- the resolve_attribute_state() code will "resurrect" the attribute if
- there are present values with a later CSN - otherwise, even though
- the value will be updated with a VDCSN which is later than the VUCSN,
- the attribute will not be deleted */
- if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE) && valuesupdated &&
- *valuesupdated)
- {
- attr_set_deletion_csn(a,csn);
- }
+ valueset_update_csn_for_valuearray_ext(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
+ resolve_attribute_state_present_to_deleted(e, a, valuesupdated);
valuearray_free(&valuesupdated);
- valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
+
+ valueset_update_csn_for_valuearray_ext(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
+ resolve_attribute_state_deleted_to_present(e, a, 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);
/* all the elements in valuestodelete are passed;
* should free valuestodelete only (don't call valuearray_free)
* [622023] */
slapi_ch_free((void **)&valuestodelete);
- resolve_attribute_state(e, a, attr_state, 0);
retVal= LDAP_SUCCESS;
}
else
{
+ /* find the values to delete in present values,
+ * update the csns and add to the deleted values
+ */
Slapi_Value **deletedvalues= NULL;
retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0 /* Do Not Ignore Errors */,&deletedvalues);
if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
{
- if(!slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
- {
- /* 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_ch_free((void **)&deletedvalues);
- }
- else {
- valuearray_free(&deletedvalues);
- }
+ /* 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_ch_free((void **)&deletedvalues);
if(valueset_isempty(&a->a_present_values))
{
/* There are no present values, so move the
@@ -619,7 +862,6 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
else if (retVal != LDAP_SUCCESS)
{
/* Failed
- * - Duplicate value
* - Value not found
* - Operations error
*/
@@ -633,69 +875,6 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
valuearray_free(&valuestodelete);
}
}
- }
- else if (attr_state==ATTRIBUTE_DELETED)
- {
- /* If the type is in the forbidden attr list (e.g., unhashed password),
- * we don't return the reason of the failure to the clients. */
-#if defined(USE_OLD_UNHASHED)
- if (is_type_forbidden(type)) {
- retVal = LDAP_SUCCESS;
- } else {
- retVal= LDAP_NO_SUCH_ATTRIBUTE;
- }
-#else
- retVal= LDAP_NO_SUCH_ATTRIBUTE;
-#endif
- }
- else if (attr_state==ATTRIBUTE_NOTFOUND)
- {
- /*
- * If type is in the protected_attrs_all list, we could ignore the
- * failure, as the attribute could only exist in the entry in the
- * memory when the add/mod operation is done, while the retried entry
- * from the db does not contain the attribute.
- * So is in the forbidden_attrs list. We don't return the reason
- * of the failure.
- */
-#if defined(USE_OLD_UNHASHED)
- if (is_type_protected(type) || is_type_forbidden(type))
-#else
- if (is_type_protected(type))
-#endif
- {
- retVal = LDAP_SUCCESS;
- } else {
- if (!urp) {
- /* Only warn if not urping */
- LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
- type);
- }
- retVal = LDAP_NO_SUCH_ATTRIBUTE;
- }
- /* NOTE: LDAP says that a MOD REPLACE with no vals of a non-existent
- attribute is a no-op - MOD REPLACE with some vals will add the attribute */
- /* if we are doing a replace with actual values, meaning the result
- of the mod is that the attribute will have some values, we need to create
- a dummy attribute for entry_add_present_values_wsi to use, and set
- the deletion csn to the csn of the current operation */
- /* note that if LDAP_MOD_REPLACE == mod_op then vals is NULL -
- see entry_replace_present_values_wsi */
- if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
- {
- /* Create a new attribute and set the adcsn */
- Slapi_Attr *a = slapi_attr_new();
- slapi_attr_init(a, type);
- attr_set_deletion_csn(a,csn);
- /* mark the attribute as deleted - it does not really
- exist yet - the code in entry_add_present_values_wsi
- will add it back to the present list in the non urp case,
- or determine if the attribute needs to be added
- or not in the urp case
- */
- entry_add_deleted_attribute_wsi(e, a);
- }
- }
return( retVal );
}
@@ -825,7 +1004,7 @@ entry_apply_mods_wsi(Slapi_Entry *e, Slapi_Mods *smods, const CSN *csn, int urp)
and the csn doesn't already have a subsequence
if the csn already has a subsequence, assume it was generated
on another replica in the correct order */
- if (urp && (csn_get_subseqnum(csn) == 0)) {
+ if (csn_get_subseqnum(csn) == 0) {
csn_increment_subsequence(&localcsn);
}
}
@@ -1043,87 +1222,54 @@ value_distinguished_at_csn(const Slapi_Entry *e, const Slapi_Attr *original_attr
return r;
}
+/* This call ensures that the value does not contain a deletion_csn which is before the presence_csn or distinguished_csn of the value. */
static void
-resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority)
+resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate)
{
- int i;
+ const CSN *vdcsn;
+ const CSN *vucsn;
+ const CSN *deletedcsn;
const CSN *adcsn= attr_get_deletion_csn(a);
- Slapi_ValueSet *vs= valueset_dup(&a->a_present_values); /* JCM This is slow... but otherwise we end up iterating through a changing array */
- Slapi_Value *v;
-
- /* Loop over the present attribute values */
- i= slapi_valueset_first_value( vs, &v );
- while(v!=NULL)
- {
- const CSN *vdcsn;
- const CSN *vucsn;
- const CSN *deletedcsn;
- /* This call ensures that the value does not contain a deletion_csn
- * which is before the presence_csn or distinguished_csn of the value.
- */
- purge_attribute_state_multi_valued(a, v);
- vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
- vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
- deletedcsn= csn_max(vdcsn, adcsn);
-
- /* Check if the attribute or value was deleted after the value was
- * last updated. If the value update CSN and the deleted CSN are
- * the same (meaning they are separate mods from the same exact
- * operation), we should only delete the value if delete priority
- * is set. Delete priority should only be set when we are deleting
- * all value of an attribute. This prevents us from leaving a value
- * that was added as a previous mod in the same exact modify
- * operation as the subsequent delete.*/
- if((csn_compare(vucsn,deletedcsn)<0) ||
- (delete_priority && (csn_compare(vucsn,deletedcsn) == 0)))
- {
- if(!value_distinguished_at_csn(e, a, v, deletedcsn))
+ int i;
+ if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
+ for (i=0;valuestoupdate[i]!=NULL;++i) {
+ purge_attribute_state_multi_valued(a, valuestoupdate[i]);
+ vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
+ vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
+ deletedcsn= csn_max(vdcsn, adcsn);
+ if((csn_compare(vucsn,deletedcsn)>=0) ||
+ value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
{
- entry_present_value_to_deleted_value(a,v);
+ entry_deleted_value_to_present_value(a,valuestoupdate[i]);
}
+ valuestoupdate[i]->v_csnset = NULL;
}
- i= slapi_valueset_next_value( vs, i, &v );
}
- slapi_valueset_free(vs);
-
- /* Loop over the deleted attribute values */
- vs= valueset_dup(&a->a_deleted_values); /* JCM This is slow... but otherwise we end up iterating through a changing array */
- i= slapi_valueset_first_value( vs, &v );
- while(v!=NULL)
- {
- const CSN *vdcsn;
- const CSN *vucsn;
- const CSN *deletedcsn;
- /* This call ensures that the value does not contain a deletion_csn which is before the presence_csn or distinguished_csn of the value. */
- purge_attribute_state_multi_valued(a, v);
- vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
- vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
- deletedcsn= csn_max(vdcsn, adcsn);
+}
- /* check if the attribute or value was deleted after the value was last updated */
- /* When a replace operation happens, the entry_replace_present_values_wsi() function
- * first calls entry_delete_present_values_wsi with vals == NULL to essentially delete
- * the attribute and set the deletion csn. If the urp flag is set (urp in this case
- * meaning the operation is a replicated op), entry_delete_present_values_wsi will
- * call this function which will move the present values to the deleted values
- * (see above - delete_priority will be 1) then the below code will move the
- * attribute to the deleted list.
- * next, entry_replace_present_values_wsi will call entry_add_present_values_wsi
- * to add the values provided in the replace operation. We need to be able to
- * "resurrect" these deleted values and resurrect the deleted attribute. In the
- * replace case, the deletedcsn will be the same as the vucsn of the values that
- * should be present values.
- */
- if((csn_compare(vucsn,deletedcsn)>0) ||
- ((delete_priority == 0) && (csn_compare(vucsn,deletedcsn)==0)) ||
- value_distinguished_at_csn(e, a, v, deletedcsn))
- {
- entry_deleted_value_to_present_value(a,v);
+static void
+resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate, int attribute_state)
+{
+ const CSN *vdcsn;
+ const CSN *vucsn;
+ const CSN *deletedcsn;
+ const CSN *adcsn= attr_get_deletion_csn(a);
+ int i;
+ if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
+ for (i=0;valuestoupdate[i]!=NULL;++i) {
+ purge_attribute_state_multi_valued(a, valuestoupdate[i]);
+ vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
+ vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
+ deletedcsn= csn_max(vdcsn, adcsn);
+ if((csn_compare(vucsn,deletedcsn)>=0) ||
+ value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
+ {
+ slapi_valueset_add_value_ext(&a->a_present_values, valuestoupdate[i], SLAPI_VALUE_FLAG_PASSIN);
+ } else {
+ slapi_valueset_add_value_ext(&a->a_deleted_values, valuestoupdate[i], SLAPI_VALUE_FLAG_PASSIN);
+ }
}
- i= slapi_valueset_next_value( vs, i, &v );
}
- slapi_valueset_free(vs);
-
if(valueset_isempty(&a->a_present_values))
{
if(attribute_state==ATTRIBUTE_PRESENT)
@@ -1141,6 +1287,35 @@ resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribut
}
static void
+resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate)
+{
+ const CSN *vdcsn;
+ const CSN *vucsn;
+ const CSN *deletedcsn;
+ const CSN *adcsn= attr_get_deletion_csn(a);
+ int i;
+ if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
+ for (i=0;valuestoupdate[i]!=NULL;++i) {
+ /* This call ensures that the value does not contain a deletion_csn
+ * which is before the presence_csn or distinguished_csn of the value.
+ */
+ purge_attribute_state_multi_valued(a, valuestoupdate[i]);
+ vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
+ vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
+ deletedcsn= csn_max(vdcsn, adcsn);
+ if(csn_compare(vucsn,deletedcsn)<0)
+ {
+ if(!value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
+ {
+ entry_present_value_to_deleted_value(a,valuestoupdate[i]);
+ }
+ }
+ valuestoupdate[i]->v_csnset = NULL;
+ }
+ }
+}
+
+static void
resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state)
{
Slapi_Value *current_value= NULL;
@@ -1292,15 +1467,3 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu
}
}
-static void
-resolve_attribute_state(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority)
-{
- if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
- {
- resolve_attribute_state_single_valued(e,a,attribute_state);
- }
- else
- {
- resolve_attribute_state_multi_valued(e,a,attribute_state, delete_priority);
- }
-}
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 2f16618..9b0072b 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -195,6 +195,7 @@ 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);
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_update_csn_for_valuearray_ext(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated, int csnref_updated);
void valueset_set_valuearray_byval(Slapi_ValueSet *vs, Slapi_Value **addvals);
void valueset_set_valuearray_passin(Slapi_ValueSet *vs, Slapi_Value **addvals);
int valuearray_subtract_bvalues(Slapi_Value **va, struct berval **bvals);
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
index 6bc3ffa..c041714 100644
--- a/ldap/servers/slapd/valueset.c
+++ b/ldap/servers/slapd/valueset.c
@@ -1428,6 +1428,11 @@ valueset_replace(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **valstoreplace)
void
valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated)
{
+ valueset_update_csn_for_valuearray_ext(vs, a, valuestoupdate, t, csn, valuesupdated, 0);
+}
+void
+valueset_update_csn_for_valuearray_ext(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated, int csnref_updated)
+{
if(!valuearray_isempty(valuestoupdate) &&
!valuearray_isempty(vs->va))
{
@@ -1450,6 +1455,8 @@ valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slap
if(rc==LDAP_SUCCESS)
{
value_update_csn(vs->va[index],t,csn);
+ if (csnref_updated)
+ valuestoupdate[i]->v_csnset = value_get_csnset(vs->va[index]);
valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
valuestoupdate[i] = NULL;
}
@@ -1465,6 +1472,8 @@ valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slap
if(index!=-1)
{
value_update_csn(vs->va[index],t,csn);
+ if (csnref_updated)
+ valuestoupdate[i]->v_csnset = value_get_csnset(vs->va[index]);
valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
valuestoupdate[i]= NULL;
}
11 years
ldap/servers
by thierry bordaz
ldap/servers/plugins/acl/acl.c | 28 ++++++++++++++++++++++++++--
ldap/servers/plugins/acl/acl.h | 1 +
ldap/servers/plugins/acl/aclparse.c | 19 +++++++++++++++++++
3 files changed, 46 insertions(+), 2 deletions(-)
New commits:
commit 79346deb255ca8d7889d7590534d308d4e3a78da
Author: Thierry bordaz (tbordaz) <tbordaz(a)redhat.com>
Date: Mon Apr 22 14:15:33 2013 +0200
Ticket 47331 - Self entry access ACI not working properly
Bug Description:
There are two issues in that bug.
The first one is that for a given entry, the rights related to an attribute are evaluated and cached. Reusing this evaluation for a different entry is erronous.
The second one is that for each deny/allow aci, the results of the evaluation of the aci is cached. These results
are reset for aci type that are entry related. The parsing of the rule self entry access miss the setting
of ACI_USERDN_SELFRULE.
This flag allows to reset (in result cache) a result obtained on a previous entry. The consequence is that
a previous result was erronously reused.
Fix Description:
The fix for the first issue, is to prevent acl__match_handlesFromCache to reuse already evaluated attributes.
A new flag make acl__match_handlesFromCache to return if the evaluation is entry related.
The second fix is to set ACI_USERDN_SELFRULE, when we have a rule like 'userdn = ldap:///self'
https://fedorahosted.org/389/ticket/47331
Reviewed by: Noriko Hosoi, Ludwig Krispenz
Platforms tested: fedora 17
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
index 79213b3..2f417f3 100644
--- a/ldap/servers/plugins/acl/acl.c
+++ b/ldap/servers/plugins/acl/acl.c
@@ -2799,6 +2799,11 @@ acl__TestRights(Acl_PBlock *aclpb,int access, char **right, char ** map_generic,
if (access & ( SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) {
+ /* We can not reused results obtained on a other entry */
+ if (aci->aci_type & ACI_CACHE_RESULT_PER_ENTRY) {
+ aclpb->aclpb_state |= ACLPB_CACHE_RESULT_PER_ENTRY_SKIP;
+ }
+
/*
* aclpb->aclpb_cache_result[0..aclpb->aclpb_last_cache_result] is
* a cache of info about whether applicable acis
@@ -3010,6 +3015,10 @@ acl__TestRights(Acl_PBlock *aclpb,int access, char **right, char ** map_generic,
if (access & ( SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) {
+ /* We can not reused results obtained on a other entry */
+ if (aci->aci_type & ACI_CACHE_RESULT_PER_ENTRY) {
+ aclpb->aclpb_state |= ACLPB_CACHE_RESULT_PER_ENTRY_SKIP;
+ }
/*
* aclpb->aclpb_cache_result[0..aclpb->aclpb_last_cache_result] is
* a cache of info about whether applicable acis
@@ -3810,8 +3819,23 @@ acl__match_handlesFromCache ( Acl_PBlock *aclpb, char *attr, int access)
} else {
context_type = ACLPB_EVALCONTEXT_PREV;
c_evalContext = &aclpb->aclpb_prev_entryEval_context;
- }
-
+ }
+
+ /* we can not reused access evaluation done on a previous entry
+ * so just skip that cache
+ */
+ if (aclpb->aclpb_state & ACLPB_CACHE_RESULT_PER_ENTRY_SKIP) {
+ aclpb->aclpb_state &= ~ACLPB_MATCHES_ALL_ACLS;
+ aclpb->aclpb_state |= ACLPB_UPD_ACLCB_CACHE;
+ /* Did not match */
+ if (context_type == ACLPB_EVALCONTEXT_ACLCB) {
+ aclpb->aclpb_state &= ~ACLPB_HAS_ACLCB_EVALCONTEXT;
+ } else {
+ aclpb->aclpb_state |= ACLPB_COPY_EVALCONTEXT;
+ c_evalContext->acle_numof_tmatched_handles = 0;
+ }
+ return -1;
+ }
if ( aclpb->aclpb_res_type & (ACLPB_NEW_ENTRY | ACLPB_EFFECTIVE_RIGHTS) ) {
aclpb->aclpb_state |= ACLPB_MATCHES_ALL_ACLS;
diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h
index 0eb8570..ef375c2 100644
--- a/ldap/servers/plugins/acl/acl.h
+++ b/ldap/servers/plugins/acl/acl.h
@@ -470,6 +470,7 @@ struct acl_pblock {
#define ACLPB_UPD_ACLCB_CACHE 0x100000
#define ACLPB_ATTR_RULE_EVALUATED 0x200000
#define ACLPB_DONOT_EVALUATE_PROXY 0x400000
+#define ACLPB_CACHE_RESULT_PER_ENTRY_SKIP 0x800000
#define ACLPB_RESET_MASK ( ACLPB_ACCESS_ALLOWED_ON_A_ATTR | ACLPB_ACCESS_DENIED_ON_ALL_ATTRS | \
diff --git a/ldap/servers/plugins/acl/aclparse.c b/ldap/servers/plugins/acl/aclparse.c
index 28c01b9..5941b2a 100644
--- a/ldap/servers/plugins/acl/aclparse.c
+++ b/ldap/servers/plugins/acl/aclparse.c
@@ -800,6 +800,8 @@ normalize_nextACERule:
goto error;
}
} else if ( 0 == strncmp ( s, DS_LAS_USERDN, 6 )) {
+ char *prefix;
+
p = PL_strnchr (s, '=', end - s);
if (NULL == p) {
goto error;
@@ -824,6 +826,23 @@ normalize_nextACERule:
goto error;
}
+ /* skip the ldap prefix */
+ prefix = PL_strncasestr(p, LDAP_URL_prefix, end - p);
+ if (prefix) {
+ prefix += strlen(LDAP_URL_prefix);
+ } else {
+ prefix = PL_strncasestr(p, LDAPS_URL_prefix, end - p);
+ if (prefix) {
+ prefix += strlen(LDAPS_URL_prefix);
+ }
+ }
+ if (prefix == NULL) {
+ /* userdn value does not starts with LDAP(S)_URL_prefix */
+ goto error;
+ }
+ p = prefix;
+
+
/* we have a rule like userdn = "ldap:///blah". s points to blah now.
** let's find if we have a SELF rule like userdn = "ldap:///self".
** Since the resource changes on entry basis, we can't cache the
11 years
ldap/admin
by Richard Allen Megginson
ldap/admin/src/logconv.pl | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
New commits:
commit 68cb916826a491ddfc9ad883e288e1d159373ed4
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Apr 24 11:44:40 2013 -0600
Ticket #47348 - add etimes to per second/minute stats
https://fedorahosted.org/389/ticket/47348
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description: Add an "ElapsedTime" column to the -m/-M output. This column
is the cumulative etimes of all operations during that time period.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: yes
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
index 3b8adc5..efc5970 100755
--- a/ldap/admin/src/logconv.pl
+++ b/ldap/admin/src/logconv.pl
@@ -2042,7 +2042,7 @@ sub parseLineNormal
if ($1 ne "0"){ $errorCount++;}
else { $successCount++;}
}
- if ($_ =~ /etime= *([0-9.]+)/ ) { writeFile($ETIME, $1);}
+ if ($_ =~ /etime= *([0-9.]+)/ ) { writeFile($ETIME, $1); inc_stats_val('etime',$1,$s_stats,$m_stats); }
if ($_ =~ / tag=101 / || $_ =~ / tag=111 / || $_ =~ / tag=100 / || $_ =~ / tag=115 /){
if ($_ =~ / nentries= *([0-9]+)/i ){ writeFile($NENTRIES, $1); }
}
@@ -2197,6 +2197,7 @@ reset_stats_block
$stats->{'anonbind'}=0;
$stats->{'unbind'}=0;
$stats->{'notesu'}=0;
+ $stats->{'etime'}=0;
return;
}
@@ -2241,12 +2242,13 @@ print_stats_block
$stats->{'bind'},
$stats->{'anonbind'},
$stats->{'unbind'},
- $stats->{'notesu'} ),
+ $stats->{'notesu'},
+ $stats->{'etime'}),
"\n" );
} else {
$stats->{'fh'}->print(
"Time,time_t,Results,Search,Add,Mod,Modrdn,Moddn,Compare,Delete,Abandon,".
- "Connections,SSL Conns,Bind,Anon Bind,Unbind,Unindexed\n"
+ "Connections,SSL Conns,Bind,Anon Bind,Unbind,Unindexed,ElapsedTime\n"
);
}
}
@@ -2265,6 +2267,20 @@ inc_stats
return;
}
+# like inc_stats, but increments the block counter with the given value e.g.
+# 'statname1', val, statblock1, statblock2, ...
+sub
+inc_stats_val
+{
+ my $n = shift;
+ my $val = shift;
+ foreach(@_){
+ $_->{$n} += $val
+ if exists $_->{$n};
+ }
+ return;
+}
+
sub
displayBindReport
{
11 years
ldap/servers
by Mark Reynolds
ldap/servers/slapd/libglobs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 1838c0bf04a4ffcf1d98f332f98855e69626b966
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Wed Apr 24 14:21:49 2013 -0400
Ticket 205 - Fix compiler warning
https://fedorahosted.org/389/ticket/205
Reviewed by: nhosoi(Thanks Noriko!)
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index d3a3497..675c08c 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -2011,7 +2011,7 @@ config_set_snmp_index(const char *attrname, char *value, char *errorbuf, int app
snmp_index = strtol(value, &endp, 10);
if (*endp != '\0' || errno == ERANGE || snmp_index < snmp_index_disable) {
- PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: invalid value \"%s\", %s must be greater or equal to %d (%d means disabled)",
+ PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: invalid value \"%s\", %s must be greater or equal to %lu (%lu means disabled)",
attrname, value, CONFIG_SNMP_INDEX_ATTRIBUTE, snmp_index_disable, snmp_index_disable);
retVal = LDAP_OPERATIONS_ERROR;
}
11 years