Branch '389-ds-base-1.3.1' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/import-threads.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
New commits:
commit 3a7c7271a4972910a4250c140096cfd402e98566
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Apr 30 14:58:03 2013 -0700
Ticket #529 - dn normalization must handle multiple space characters in attributes
Fix Description: Fixing a 2 compiler warnings introduced by commit
a68952f9a8e6d3ff9fea1b4b485acc63f77b3ce6.
https://fedorahosted.org/389/ticket/529
(cherry picked from commit 5a0e057940bddd6e076186845a0cacf99c6c0143)
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
index 79a5984..3828080 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -1448,7 +1448,7 @@ upgradedn_producer(void *param)
struct upgradedn_attr *ud_ptr = NULL;
Slapi_Attr *ud_attr = NULL;
char *ecopy = NULL;
- const char *normdn = NULL;
+ char *normdn = NULL;
char *rdn = NULL; /* original rdn */
int is_dryrun = 0; /* FLAG_DRYRUN */
int chk_dn_norm = 0; /* FLAG_UPGRADEDNFORMAT */
@@ -1660,7 +1660,7 @@ upgradedn_producer(void *param)
CACHE_ADD( &inst->inst_dncache, bdn, NULL );
CACHE_RETURN(&inst->inst_dncache, &bdn);
/* don't free this normdn */
- normdn = slapi_sdn_get_dn(sdn);
+ normdn = (char *)slapi_sdn_get_dn(sdn);
slapi_log_error(SLAPI_LOG_CACHE, "uptradedn",
"entryrdn_lookup_dn returned: %s, "
"and set to dn cache\n", normdn);
@@ -1701,7 +1701,7 @@ upgradedn_producer(void *param)
*/
if (!normdn) {
/* No rdn in id2entry or entrydn */
- normdn = slapi_sdn_get_dn(&(e->e_sdn));
+ normdn = (char *)slapi_sdn_get_dn(&(e->e_sdn));
}
/*
10 years, 5 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/import-threads.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
New commits:
commit 5a0e057940bddd6e076186845a0cacf99c6c0143
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Apr 30 14:58:03 2013 -0700
Ticket #529 - dn normalization must handle multiple space characters in attributes
Fix Description: Fixing a 2 compiler warnings introduced by commit
a68952f9a8e6d3ff9fea1b4b485acc63f77b3ce6.
https://fedorahosted.org/389/ticket/529
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
index 79a5984..3828080 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -1448,7 +1448,7 @@ upgradedn_producer(void *param)
struct upgradedn_attr *ud_ptr = NULL;
Slapi_Attr *ud_attr = NULL;
char *ecopy = NULL;
- const char *normdn = NULL;
+ char *normdn = NULL;
char *rdn = NULL; /* original rdn */
int is_dryrun = 0; /* FLAG_DRYRUN */
int chk_dn_norm = 0; /* FLAG_UPGRADEDNFORMAT */
@@ -1660,7 +1660,7 @@ upgradedn_producer(void *param)
CACHE_ADD( &inst->inst_dncache, bdn, NULL );
CACHE_RETURN(&inst->inst_dncache, &bdn);
/* don't free this normdn */
- normdn = slapi_sdn_get_dn(sdn);
+ normdn = (char *)slapi_sdn_get_dn(sdn);
slapi_log_error(SLAPI_LOG_CACHE, "uptradedn",
"entryrdn_lookup_dn returned: %s, "
"and set to dn cache\n", normdn);
@@ -1701,7 +1701,7 @@ upgradedn_producer(void *param)
*/
if (!normdn) {
/* No rdn in id2entry or entrydn */
- normdn = slapi_sdn_get_dn(&(e->e_sdn));
+ normdn = (char *)slapi_sdn_get_dn(&(e->e_sdn));
}
/*
10 years, 5 months
ldap/servers
by Noriko Hosoi
ldap/servers/plugins/acl/acl.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 86fea4b326b28912cd0d8de0d0cb3a2f8dea423e
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Apr 30 10:22:59 2013 -0700
Ticket 47331 - Self entry access ACI not working properly
Description: Additional change to
commit 79346deb255ca8d7889d7590534d308d4e3a78da
which added a macro ACLPB_CACHE_RESULT_PER_ENTRY_SKIP, but
ACLPB_STATE_ALL was not updated to cover the bit.
This patch updates ACLPB_STATE_ALL to support the new bit.
diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h
index ef375c2..6dbb68f 100644
--- a/ldap/servers/plugins/acl/acl.h
+++ b/ldap/servers/plugins/acl/acl.h
@@ -477,7 +477,7 @@ struct acl_pblock {
ACLPB_ACCESS_ALLOWED_ON_ENTRY | ACLPB_ATTR_STAR_MATCHED | \
ACLPB_FOUND_ATTR_RULE | ACLPB_EVALUATING_FIRST_ATTR | \
ACLPB_FOUND_A_ENTRY_TEST_RULE )
-#define ACLPB_STATE_ALL 0x3fffff
+#define ACLPB_STATE_ALL 0xffffff
int aclpb_res_type;
10 years, 5 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/auth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit a78448611711c34ca5f1bfdc6b084cd81fedcf88
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Apr 30 10:12:48 2013 -0700
Ticket #47320 - put conn on work_q not poll list if conn has buffered more_data
Description: Additional change to
commit ed88c40218c3fb8944618927e7865d74bc922c02
to fix the self-deadlock.
Replacing bind_credentials_set with bind_credentials_set_nolock
in handle_handshake_done. The handle_handshake_done is only
called from connection_read_operation, where lock on c_mutex
is already obtained. Thus, the replacement is safe.
https://fedorahosted.org/389/ticket/47320
diff --git a/ldap/servers/slapd/auth.c b/ldap/servers/slapd/auth.c
index 4976406..7075acd 100644
--- a/ldap/servers/slapd/auth.c
+++ b/ldap/servers/slapd/auth.c
@@ -539,7 +539,7 @@ handle_handshake_done (PRFileDesc *prfd, void* clientData)
* Associate the new credentials with the connection. Note that
* clientDN and clientCert may be NULL.
*/
- bind_credentials_set( conn, SLAPD_AUTH_SSL, clientDN,
+ bind_credentials_set_nolock( conn, SLAPD_AUTH_SSL, clientDN,
SLAPD_AUTH_SSL, clientDN, clientCert , NULL);
done:
slapi_ch_free_string(&subject);
10 years, 5 months
Branch '389-ds-base-1.3.1' - ldap/admin
by Mark Reynolds
ldap/admin/src/scripts/DSSharedLib.in | 58 ++++++++++------------------------
ldap/admin/src/scripts/DSUtil.pm.in | 15 ++++----
ldap/admin/src/scripts/db2ldif.in | 7 +---
3 files changed, 29 insertions(+), 51 deletions(-)
New commits:
commit e5c70f829a349aed7b185283d91e674f6f3918a2
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Apr 30 11:39:11 2013 -0400
Ticket 47299 - fix config file and server id processing
Bug Description: get_init_file() was not returning the config file, normalize_server_id()
was not properly extracting the server ID, get_server_id() was not
returning the default instance and need to remove the newline character
from the CONFIG_DIR value, and fixed some wrong variable names.
https://fedorahosted.org/389/ticket/47299
Reviewed by: richm(Thanks!)
(cherry picked from commit 694f914b8d4d149eb2021443e9fd4a21f064316b)
diff --git a/ldap/admin/src/scripts/DSSharedLib.in b/ldap/admin/src/scripts/DSSharedLib.in
index 8d2edc4..3683696 100644
--- a/ldap/admin/src/scripts/DSSharedLib.in
+++ b/ldap/admin/src/scripts/DSSharedLib.in
@@ -4,30 +4,15 @@ libpath_add()
LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$1
}
-# pass in a string that ends in dirsrv-name or slapd-name
+# pass in a string that ends in dirsrv-name or slapd-name,
# and convert it to just "name"
-# the string could be a path name or not
-# if the string did not match @package_name@-name or slapd-name it
-# will be returned as is
-# want to be able to handle weird cases like /slapd-@package_name@-foo
-# that should normalize to the strange @package_name@-foo e.g.
-# someone named the instance "@package_name@-foo"
normalize_server_id()
{
- echo "$1" | sed '
-# save the current line
-h
-# delete leading path components if any (i.e. basename)
-s/^.*\///;ta
-:a
-# begins with @package_name@- ; remove it and exit
-s/^@package_name@-//;tx
-# begins with slapd- ; remove it and exit
-s/^slapd-//;tx
-# no match - return original string
-g
-:x
-'
+ servid=$1
+ servid=`echo "$servid" | sed 's/^.*\///'`
+ servid=`echo "$servid" | sed 's/^dirsrv-//'`
+ servid=`echo "$servid" | sed 's/^slapd-//'`
+ echo $servid
}
# look for all initconfig files in the given directory
@@ -40,6 +25,7 @@ g
# if not running as root, look for non-system instances in
# $HOME/.dirsrv
# ignore the dirsrv-admin admin server config file
+#
get_initconfig_files()
{
dir=${1:-@initconfigdir@}
@@ -101,7 +87,6 @@ get_init_file()
first="yes"
inst_count=0
instances="<none>"
- rc=0
# normalize servid, if given
if [ -n "$servid" ]
@@ -109,14 +94,14 @@ get_init_file()
servid=`normalize_server_id $servid`
fi
- for i in `get_initconfig_files $dir`
+ for configfile in `get_initconfig_files $dir`
do
inst_count=`expr $inst_count + 1`
- id=`normalize_server_id $i`
+ id=`normalize_server_id $configfile`
if [ -n "$servid" -a "$id" = "$servid" ]
then
# found it
- echo $i
+ echo $configfile
exit 0
fi
if [ $first == "yes" ]
@@ -126,27 +111,20 @@ get_init_file()
else
instances=$instances", $id"
fi
- name=$i
done
- if [ -n $servid ] ; then
- # if we got here, we did not find a match
- echo $instances
- exit 1
- fi
-
# server id not provided, check if there is only one instance
- if [ $inst_count -eq 1 ]
+ if [ -z "$servid" -a $inst_count -eq 1 ]
then
- servid=$name
+ # return the file
+ echo $configfile
+ exit 0
else
- # multiple instances, can not set server id. Return list of instances
- servid=$instances
- rc=1
+ # Either we have an invalid name, or more than one instance is available
+ # Return the available instances instead of the config file
+ echo $instances
+ exit 1;
fi
-
- echo $servid
- exit $rc
}
#
diff --git a/ldap/admin/src/scripts/DSUtil.pm.in b/ldap/admin/src/scripts/DSUtil.pm.in
index e439ea4..b971dac 100644
--- a/ldap/admin/src/scripts/DSUtil.pm.in
+++ b/ldap/admin/src/scripts/DSUtil.pm.in
@@ -1285,6 +1285,7 @@ sub get_server_id {
my $first = "yes";
my $instances = "<none>";
my $name;
+ my $inst;
my $file;
my @extra = ();
my $extradir = "";
@@ -1325,7 +1326,7 @@ sub get_server_id {
# skip admin server
if($file =~ m,/@package_name@-([^/]+)$, && $file !~ m,/@package_name@-admin$,){
$name = $file;
- my $inst = $1;
+ $inst = $1;
$instance_count++;
if ($servid && ($servid eq $inst)) {
$found = 1;
@@ -1351,21 +1352,20 @@ sub get_server_id {
exit (1);
}
- if ($instance_count > 1){
+ if (!$servid && $instance_count > 1){
print "You must supply a valid server instance identifier. Use -Z to specify instance name\n";
print "Available instances: $instances\n";
exit (1);
}
-
- unless ( -e "$file" ){
+ unless ( -e "$name" ){
print (STDERR "Invalid server identifer: $servid\n");
print (STDERR "Available instances in $dir $extradir: $instances\n");
exit (1);
}
# now grab the CONFIG_DIR from the file $name
- if (open(INSTFILE, "$name")) {
- print (STDERR "Error: could not open $name: $!");
+ if (!open(INSTFILE, "$name")) {
+ print (STDERR "Error: could not open $name: ");
exit (1);
}
@@ -1375,6 +1375,7 @@ sub get_server_id {
s/^CONFIG_DIR=//;
s/ ; export CONFIG_DIR//;
$confdir = $_;
+ chomp($confdir);
last;
}
}
@@ -1385,7 +1386,7 @@ sub get_server_id {
exit (1);
}
- return ($servid, $confdir);
+ return ($inst, $confdir);
}
#
diff --git a/ldap/admin/src/scripts/db2ldif.in b/ldap/admin/src/scripts/db2ldif.in
index cca4e95..d7e0ff0 100755
--- a/ldap/admin/src/scripts/db2ldif.in
+++ b/ldap/admin/src/scripts/db2ldif.in
@@ -97,8 +97,8 @@ then
usage
exit 1
fi
-
-while getopts "hZ:n:s:x:a:NrCuUmM1qvd:D:ESt:oc:" flag
+
+while getopts "hZ:vd:D:ENa:rs:x:CSut:n:UmMo1qc:" flag
do
case $flag in
h) usage
@@ -110,8 +110,7 @@ do
required_param="yes";;
x) excludeSuffix="-x $OPTARG";;
a) outputFile="-a $OPTARG";;
- d) outputFile="-d $OPTARG";;
- t) outputFile="-t $OPTARG";;
+ d) args=$args" -d $OPTARG";;
D) args=$args" -D $OPTARG";;
N) args=$args" -N";;
E) args=$args" -E";;
10 years, 5 months
ldap/admin
by Mark Reynolds
ldap/admin/src/scripts/DSSharedLib.in | 58 ++++++++++------------------------
ldap/admin/src/scripts/DSUtil.pm.in | 15 ++++----
ldap/admin/src/scripts/db2ldif.in | 7 +---
3 files changed, 29 insertions(+), 51 deletions(-)
New commits:
commit 694f914b8d4d149eb2021443e9fd4a21f064316b
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Apr 30 11:39:11 2013 -0400
Ticket 47299 - fix config file and server id processing
Bug Description: get_init_file() was not returning the config file, normalize_server_id()
was not properly extracting the server ID, get_server_id() was not
returning the default instance and need to remove the newline character
from the CONFIG_DIR value, and fixed some wrong variable names.
https://fedorahosted.org/389/ticket/47299
Reviewed by: richm(Thanks!)
diff --git a/ldap/admin/src/scripts/DSSharedLib.in b/ldap/admin/src/scripts/DSSharedLib.in
index 8d2edc4..3683696 100644
--- a/ldap/admin/src/scripts/DSSharedLib.in
+++ b/ldap/admin/src/scripts/DSSharedLib.in
@@ -4,30 +4,15 @@ libpath_add()
LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$1
}
-# pass in a string that ends in dirsrv-name or slapd-name
+# pass in a string that ends in dirsrv-name or slapd-name,
# and convert it to just "name"
-# the string could be a path name or not
-# if the string did not match @package_name@-name or slapd-name it
-# will be returned as is
-# want to be able to handle weird cases like /slapd-@package_name@-foo
-# that should normalize to the strange @package_name@-foo e.g.
-# someone named the instance "@package_name@-foo"
normalize_server_id()
{
- echo "$1" | sed '
-# save the current line
-h
-# delete leading path components if any (i.e. basename)
-s/^.*\///;ta
-:a
-# begins with @package_name@- ; remove it and exit
-s/^@package_name@-//;tx
-# begins with slapd- ; remove it and exit
-s/^slapd-//;tx
-# no match - return original string
-g
-:x
-'
+ servid=$1
+ servid=`echo "$servid" | sed 's/^.*\///'`
+ servid=`echo "$servid" | sed 's/^dirsrv-//'`
+ servid=`echo "$servid" | sed 's/^slapd-//'`
+ echo $servid
}
# look for all initconfig files in the given directory
@@ -40,6 +25,7 @@ g
# if not running as root, look for non-system instances in
# $HOME/.dirsrv
# ignore the dirsrv-admin admin server config file
+#
get_initconfig_files()
{
dir=${1:-@initconfigdir@}
@@ -101,7 +87,6 @@ get_init_file()
first="yes"
inst_count=0
instances="<none>"
- rc=0
# normalize servid, if given
if [ -n "$servid" ]
@@ -109,14 +94,14 @@ get_init_file()
servid=`normalize_server_id $servid`
fi
- for i in `get_initconfig_files $dir`
+ for configfile in `get_initconfig_files $dir`
do
inst_count=`expr $inst_count + 1`
- id=`normalize_server_id $i`
+ id=`normalize_server_id $configfile`
if [ -n "$servid" -a "$id" = "$servid" ]
then
# found it
- echo $i
+ echo $configfile
exit 0
fi
if [ $first == "yes" ]
@@ -126,27 +111,20 @@ get_init_file()
else
instances=$instances", $id"
fi
- name=$i
done
- if [ -n $servid ] ; then
- # if we got here, we did not find a match
- echo $instances
- exit 1
- fi
-
# server id not provided, check if there is only one instance
- if [ $inst_count -eq 1 ]
+ if [ -z "$servid" -a $inst_count -eq 1 ]
then
- servid=$name
+ # return the file
+ echo $configfile
+ exit 0
else
- # multiple instances, can not set server id. Return list of instances
- servid=$instances
- rc=1
+ # Either we have an invalid name, or more than one instance is available
+ # Return the available instances instead of the config file
+ echo $instances
+ exit 1;
fi
-
- echo $servid
- exit $rc
}
#
diff --git a/ldap/admin/src/scripts/DSUtil.pm.in b/ldap/admin/src/scripts/DSUtil.pm.in
index e439ea4..b971dac 100644
--- a/ldap/admin/src/scripts/DSUtil.pm.in
+++ b/ldap/admin/src/scripts/DSUtil.pm.in
@@ -1285,6 +1285,7 @@ sub get_server_id {
my $first = "yes";
my $instances = "<none>";
my $name;
+ my $inst;
my $file;
my @extra = ();
my $extradir = "";
@@ -1325,7 +1326,7 @@ sub get_server_id {
# skip admin server
if($file =~ m,/@package_name@-([^/]+)$, && $file !~ m,/@package_name@-admin$,){
$name = $file;
- my $inst = $1;
+ $inst = $1;
$instance_count++;
if ($servid && ($servid eq $inst)) {
$found = 1;
@@ -1351,21 +1352,20 @@ sub get_server_id {
exit (1);
}
- if ($instance_count > 1){
+ if (!$servid && $instance_count > 1){
print "You must supply a valid server instance identifier. Use -Z to specify instance name\n";
print "Available instances: $instances\n";
exit (1);
}
-
- unless ( -e "$file" ){
+ unless ( -e "$name" ){
print (STDERR "Invalid server identifer: $servid\n");
print (STDERR "Available instances in $dir $extradir: $instances\n");
exit (1);
}
# now grab the CONFIG_DIR from the file $name
- if (open(INSTFILE, "$name")) {
- print (STDERR "Error: could not open $name: $!");
+ if (!open(INSTFILE, "$name")) {
+ print (STDERR "Error: could not open $name: ");
exit (1);
}
@@ -1375,6 +1375,7 @@ sub get_server_id {
s/^CONFIG_DIR=//;
s/ ; export CONFIG_DIR//;
$confdir = $_;
+ chomp($confdir);
last;
}
}
@@ -1385,7 +1386,7 @@ sub get_server_id {
exit (1);
}
- return ($servid, $confdir);
+ return ($inst, $confdir);
}
#
diff --git a/ldap/admin/src/scripts/db2ldif.in b/ldap/admin/src/scripts/db2ldif.in
index cca4e95..d7e0ff0 100755
--- a/ldap/admin/src/scripts/db2ldif.in
+++ b/ldap/admin/src/scripts/db2ldif.in
@@ -97,8 +97,8 @@ then
usage
exit 1
fi
-
-while getopts "hZ:n:s:x:a:NrCuUmM1qvd:D:ESt:oc:" flag
+
+while getopts "hZ:vd:D:ENa:rs:x:CSut:n:UmMo1qc:" flag
do
case $flag in
h) usage
@@ -110,8 +110,7 @@ do
required_param="yes";;
x) excludeSuffix="-x $OPTARG";;
a) outputFile="-a $OPTARG";;
- d) outputFile="-d $OPTARG";;
- t) outputFile="-t $OPTARG";;
+ d) args=$args" -d $OPTARG";;
D) args=$args" -D $OPTARG";;
N) args=$args" -N";;
E) args=$args" -E";;
10 years, 5 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/attrsyntax.c | 50 -
ldap/servers/slapd/charray.c | 9
ldap/servers/slapd/proto-slap.h | 10
ldap/servers/slapd/schema.c | 1776 ++++++++++++++++++++++++++++----------
ldap/servers/slapd/slap.h | 40
ldap/servers/slapd/slapi-plugin.h | 15
6 files changed, 1397 insertions(+), 503 deletions(-)
New commits:
commit 305dac5202b43448069ce7fa9715f62dab2b10bd
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Apr 30 11:49:54 2013 -0400
Ticket 153 - use openldap's schema parser
Bug Description: After running ol-schema-migrate.pl(which converts openldap schema to
389 DS schema format), 389 still doesn't parse the schema correctly as
it expects the syntax to be in a certain order.
Fix Description: First, instead of only recording the "X-ORIGIN" values, I have created a
linked list for all the schema extensions, not just "X-ORIGIN". Then on
systems that have openldap, we use the openldap schema parser. On
systems that only have mozldap, we use the old parser.
Also did some code cleanup.
https://fedorahosted.org/389/ticket/153
Reviewed by: richm(Thanks!)
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index 4326f03..05aca7d 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -208,7 +208,7 @@ attr_syntax_free( struct asyntaxinfo *a )
slapi_ch_free( (void **)&a->asi_mr_equality );
slapi_ch_free( (void **)&a->asi_mr_ordering );
slapi_ch_free( (void **)&a->asi_mr_substring );
- cool_charray_free( a->asi_origin );
+ schema_free_extensions(a->asi_extensions);
slapi_ch_free( (void **) &a );
}
@@ -584,7 +584,7 @@ attr_syntax_dup( struct asyntaxinfo *a )
newas->asi_mr_equality = slapi_ch_strdup( a->asi_mr_equality );
newas->asi_mr_ordering = slapi_ch_strdup( a->asi_mr_ordering );
newas->asi_mr_substring = slapi_ch_strdup( a->asi_mr_substring );
- newas->asi_origin = cool_charray_dup( a->asi_origin );
+ newas->asi_extensions = schema_copy_extensions( a->asi_extensions );
newas->asi_plugin = a->asi_plugin;
newas->asi_flags = a->asi_flags;
newas->asi_oid = slapi_ch_strdup( a->asi_oid);
@@ -622,9 +622,9 @@ attr_syntax_add( struct asyntaxinfo *asip )
goto cleanup_and_return;
}
}
-
- /* make sure the primary name is unique OR, if override is allowed, that
- * the primary name and OID point to the same schema definition.
+ /*
+ * Make sure the primary name is unique OR, if override is allowed, that
+ * the primary name and OID point to the same schema definition.
*/
if ( NULL != ( oldas_from_name = attr_syntax_get_by_name_locking_optional(
asip->asi_name, !nolock))) {
@@ -687,23 +687,22 @@ cleanup_and_return:
*/
int
attr_syntax_create(
- const char *attr_oid,
- char *const *attr_names,
- int num_names,
- const char *attr_desc,
- const char *attr_superior,
- const char *mr_equality,
- const char *mr_ordering,
- const char *mr_substring,
- char *const *attr_origins,
- const char *attr_syntax,
- int syntaxlength,
+ const char *attr_oid,
+ char *const *attr_names,
+ const char *attr_desc,
+ const char *attr_superior,
+ const char *mr_equality,
+ const char *mr_ordering,
+ const char *mr_substring,
+ schemaext *extensions,
+ const char *attr_syntax,
+ int syntaxlength,
unsigned long flags,
struct asyntaxinfo **asip
)
{
- char *s;
- struct asyntaxinfo a;
+ char *s;
+ struct asyntaxinfo a;
int rc = LDAP_SUCCESS;
/* XXXmcs: had to cast away const in many places below */
@@ -719,7 +718,7 @@ attr_syntax_create(
a.asi_mr_equality = (char*)mr_equality;
a.asi_mr_ordering = (char*)mr_ordering;
a.asi_mr_substring = (char*)mr_substring;
- a.asi_origin = (char **)attr_origins;
+ a.asi_extensions = extensions;
a.asi_plugin = plugin_syntax_find( attr_syntax );
a.asi_syntaxlength = syntaxlength;
/* ideally, we would report an error and fail to start if there was some problem
@@ -905,6 +904,8 @@ attr_syntax_printnode(PLHashEntry *he, PRIntn i, void *arg)
{
char *alias = (char *)he->key;
struct asyntaxinfo *a = (struct asyntaxinfo *)he->value;
+ schemaext *ext = a->asi_extensions;
+
printf( " name: %s\n", a->asi_name );
printf( "\t flags : 0x%x\n", a->asi_flags );
printf( "\t alias : %s\n", alias );
@@ -914,10 +915,11 @@ attr_syntax_printnode(PLHashEntry *he, PRIntn i, void *arg)
printf( "\t mr_equality : %s\n", a->asi_mr_equality );
printf( "\t mr_ordering : %s\n", a->asi_mr_ordering );
printf( "\t mr_substring: %s\n", a->asi_mr_substring );
- if ( NULL != a->asi_origin ) {
- for ( i = 0; NULL != a->asi_origin[i]; ++i ) {
- printf( "\t origin : %s\n", a->asi_origin[i] );
+ while( ext ) {
+ for ( i = 0; ext->values && ext->values[i]; i++ ) {
+ printf( "\t %s : %s\n", ext->term, ext->values[i]);
}
+ ext = ext->next;
}
printf( "\tplugin: %p\n", a->asi_plugin );
printf( "--------------\n" );
@@ -1236,11 +1238,11 @@ slapi_add_internal_attr_syntax( const char *name, const char *oid,
origins[0] = SLAPD_VERSION_STR;
origins[1] = NULL;
- rc = attr_syntax_create( oid, names, 1,
+ rc = attr_syntax_create( oid, names,
"internal server defined attribute type",
NULL, /* superior */
mr_equality, NULL, NULL, /* matching rules */
- origins, syntax,
+ NULL, syntax,
SLAPI_SYNTAXLENGTH_NONE,
std_flags | extraflags,
&asip );
diff --git a/ldap/servers/slapd/charray.c b/ldap/servers/slapd/charray.c
index 7df9a08..f86ddc2 100644
--- a/ldap/servers/slapd/charray.c
+++ b/ldap/servers/slapd/charray.c
@@ -56,6 +56,13 @@ charray_add(
char *s
)
{
+ slapi_ch_array_add_ext(a, s);
+}
+
+/* return the total number of elements that are now in the array */
+int
+slapi_ch_array_add_ext(char ***a, char *s)
+{
int n;
if ( *a == NULL ) {
@@ -81,10 +88,10 @@ charray_add(
#endif
/* Putting code back so that thread conflict can be made visible */
-
(*a)[n++] = s;
(*a)[n] = NULL;
+ return n;
}
void
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 10dec7a..9fe26ff 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -121,11 +121,10 @@ int attr_syntax_exists (const char *attr_name);
void attr_syntax_delete ( struct asyntaxinfo *asip );
#define SLAPI_SYNTAXLENGTH_NONE (-1) /* for syntaxlength parameter */
int attr_syntax_create( const char *attr_oid, char *const*attr_names,
- int num_names, const char *attr_desc, const char *attr_superior,
+ const char *attr_desc, const char *attr_superior,
const char *mr_equality, const char *mr_ordering,
- const char *mr_substring, char *const *attr_origins,
- const char *attr_syntax, int syntaxlength, unsigned long flags,
- struct asyntaxinfo **asip );
+ const char *mr_substring, schemaext *extensions, const char *attr_syntax,
+ int syntaxlength, unsigned long flags, struct asyntaxinfo **asip );
void attr_syntax_free( struct asyntaxinfo *a );
int attr_syntax_add( struct asyntaxinfo *asip );
char *attr_syntax_normalize_no_lookup( const char *s );
@@ -1000,7 +999,8 @@ void slapi_schema_expand_objectclasses( Slapi_Entry *e );
int slapi_validate_schema_files(char *schemadir);
/* API to reload the schema files */
int slapi_reload_schema_files(char *schemadir);
-
+void schema_free_extensions(schemaext *extensions);
+schemaext *schema_copy_extensions(schemaext *extensions);
/*
* schemaparse.c
*/
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index dc56534..7b33593 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -51,17 +51,18 @@
#include <plhash.h>
#include "slap.h"
+#if defined(USE_OPENLDAP)
+#include <ldap_schema.h> /* openldap schema parser */
+#endif
+
typedef struct sizedbuffer
{
char *buffer;
size_t size;
} sizedbuffer;
-
typedef char *(*schema_strstr_fn_t)( const char *big, const char *little);
-
-
/*
* The schema_oc_kind_strings array is indexed by oc_kind values, i.e.,
* OC_KIND_STRUCTURAL (0), OC_KIND_AUXILIARY (1), or OC_KIND_ABSTRACT (2).
@@ -69,9 +70,9 @@ typedef char *(*schema_strstr_fn_t)( const char *big, const char *little);
*/
#define SCHEMA_OC_KIND_COUNT 3
static char *schema_oc_kind_strings_with_spaces[] = {
+ " ABSTRACT ",
" STRUCTURAL ",
" AUXILIARY ",
- " ABSTRACT ",
};
/* constant strings (used in a few places) */
@@ -96,7 +97,6 @@ static int oc_delete_nolock (char *ocname);
static int oc_replace_nolock(const char *ocname, struct objclass *newoc);
static int oc_check_required(Slapi_PBlock *, Slapi_Entry *,struct objclass *);
static int oc_check_allowed_sv(Slapi_PBlock *, Slapi_Entry *e, const char *type, struct objclass **oclist );
-static char **read_dollar_values ( char *vals);
static int schema_delete_objectclasses ( Slapi_Entry *entryBefore,
LDAPMod *mod, char *errorbuf, size_t errorbufsize,
int schema_ds4x_compat );
@@ -110,9 +110,6 @@ static int schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod,
char *errorbuf, size_t errorbufsize );
static int schema_replace_objectclasses ( Slapi_PBlock *pb, LDAPMod *mod,
char *errorbuf, size_t errorbufsize );
-static int read_oc_ldif ( const char *input, struct objclass **oc,
- char *errorbuf, size_t errorbufsize, PRUint32 flags, int is_user_defined,
- int schema_ds4x_compat );
static int schema_check_name(char *name, PRBool isAttribute, char *errorbuf,
size_t errorbufsize );
static int schema_check_oid(const char *name, const char *oid,
@@ -120,27 +117,14 @@ static int schema_check_oid(const char *name, const char *oid,
static int isExtensibleObjectclass(const char *objectclass);
static int strip_oc_options ( struct objclass *poc );
static char *stripOption (char *attr);
-static int read_at_ldif(const char *input, struct asyntaxinfo **asipp,
- char *errorbuf, size_t errorbufsize, PRUint32 flags,
- int is_user_defined, int schema_ds4x_compat, int is_remote);
-static char **parse_qdlist(const char *s, int *n, int strip_options);
-static void free_qdlist(char **vals, int n);
-static char **parse_qdescrs(const char *s, int *n);
-static char **parse_qdstrings(const char *s, int *n);
-static int get_flag_keyword( const char *keyword, int flag_value,
- const char **inputp, schema_strstr_fn_t strstr_fn );
-static char *get_tagged_oid( const char *tag, const char **inputp,
- schema_strstr_fn_t strstr_fn );
+static int schema_extension_cmp(schemaext *e1, schemaext *e2);
static int put_tagged_oid( char *outp, const char *tag, const char *oid,
const char *suffix, int enquote );
static void strcat_oids( char *buf, char *prefix, char **oids,
int schema_ds4x_compat );
-static size_t strcat_qdlist( char *buf, char *prefix, char **qdlist );
+static size_t strcat_extensions( char *buf, schemaext *extension );
static size_t strlen_null_ok(const char *s);
static int strcpy_count( char *dst, const char *src );
-static int element_is_user_defined( char * const * origins );
-static char **parse_origin_list( const char *schema_value, int *num_originsp,
- char **default_list );
static int refresh_user_defined_schema(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg);
static int schema_check_oc_attrs ( struct objclass *poc, char *errorbuf,
size_t errorbufsize, int stripOptions );
@@ -156,20 +140,56 @@ static int schema_strcmp_array( char **sa1, char **sa2,
static PRBool schema_type_is_interesting( const char *type );
static void schema_create_errormsg( char *errorbuf, size_t errorbufsize,
const char *prefix, const char *name, const char *fmt, ... )
-#ifdef __GNUC__
+#ifdef __GNUC__
__attribute__ ((format (printf, 5, 6)));
#else
;
#endif
+static int parse_at_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize,
+ PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote);
+static int extension_is_user_defined( schemaext *extensions );
+static size_t strcat_qdlist( char *buf, char *prefix, char **qdlist );
+#if defined (USE_OPENLDAP)
+/*
+ * openldap
+ */
+static int parse_attr_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize,
+ PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote);
+static int parse_objclass_str(const char *input, struct objclass **oc, char *errorbuf, size_t errorbufsize,
+ PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat );
+
+#else
+/*
+ * mozldap
+ */
+static char **parse_qdescrs(const char *s, int *n);
+static char **parse_qdstrings(const char *s, int *n);
+static char **parse_qdlist(const char *s, int *n, int strip_options);
+static void free_qdlist(char **vals, int n);
+static int read_at_ldif(const char *input, struct asyntaxinfo **asipp,
+ char *errorbuf, size_t errorbufsize, PRUint32 flags,
+ int is_user_defined, int schema_ds4x_compat, int is_remote);
+static int read_oc_ldif ( const char *input, struct objclass **oc,
+ char *errorbuf, size_t errorbufsize, PRUint32 flags, int is_user_defined,
+ int schema_ds4x_compat );
+static int get_flag_keyword( const char *keyword, int flag_value,
+ const char **inputp, schema_strstr_fn_t strstr_fn );
+static char *get_tagged_oid( const char *tag, const char **inputp,
+ schema_strstr_fn_t strstr_fn );
+static char **read_dollar_values ( char *vals);
+static schemaext *parse_extensions( const char *schema_value, char **default_list );
+#endif
-/* Some utility functions for dealing with a dynamic buffer */
+
+/*
+ * Some utility functions for dealing with a dynamic buffer
+ */
static struct sizedbuffer *sizedbuffer_construct(size_t size);
static void sizedbuffer_destroy(struct sizedbuffer *p);
static void sizedbuffer_allocate(struct sizedbuffer *p, size_t sizeneeded);
-
/*
* Constant strings that we pass to schema_create_errormsg().
*/
@@ -196,6 +216,27 @@ static Slapi_RWLock *schema_dse_lock = NULL;
*/
static PRCallOnceType schema_dse_mandatory_init_callonce = { 0, 0, 0 };
+static int parse_at_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize,
+ PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote)
+{
+#ifdef USE_OPENLDAP
+ return parse_attr_str(input, asipp, errorbuf, errorbufsize, schema_flags, is_user_defined,schema_ds4x_compat,is_remote);
+#else
+ return read_at_ldif(input, asipp, errorbuf, errorbufsize, schema_flags, is_user_defined,schema_ds4x_compat,is_remote);
+#endif
+}
+
+static int parse_oc_str(const char *input, struct objclass **oc, char *errorbuf,
+ size_t errorbufsize, PRUint32 schema_flags, int is_user_defined,
+ int schema_ds4x_compat )
+{
+#ifdef USE_OPENLDAP
+ return parse_objclass_str (input, oc, errorbuf, errorbufsize, schema_flags, is_user_defined, schema_ds4x_compat );
+#else
+ return read_oc_ldif (input, oc, errorbuf, errorbufsize, schema_flags, is_user_defined, schema_ds4x_compat );
+#endif
+}
+
/* Essential initialization. Returns PRSuccess if successful */
static PRStatus
@@ -250,6 +291,7 @@ dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int
return SLAPI_DSE_CALLBACK_ERROR;
}
+#if !defined(USE_OPENLDAP)
static const char *
skipWS(const char *s)
{
@@ -281,8 +323,6 @@ strchr_skip_quoted_strings( char *s, int c )
return( NULL );
}
-
-
/**
* parses a string containing a qdescrs or qdstrings (as described by
* RFC 2252, section 4.1) into an array of strings; the second parameter
@@ -381,17 +421,6 @@ parse_qdlist(const char *s, int *n, int strip_options)
return retval;
}
-
-static void
-free_qdlist(char **vals, int n)
-{
- int ii;
- for (ii = 0; ii < n; ++ii)
- slapi_ch_free((void **)&(vals[ii]));
- slapi_ch_free((void **)&vals);
-}
-
-
/**
* parses a string containing a qdescrs (as described by RFC 2252, section 4.1)
* into an array of strings; the second parameter will hold the actual number
@@ -415,6 +444,16 @@ parse_qdstrings(const char *s, int *n)
return parse_qdlist( s, n, 0 /* DO NOT strip attribute options */ );
}
+static void
+free_qdlist(char **vals, int n)
+{
+ int ii;
+ for (ii = 0; ii < n; ++ii)
+ slapi_ch_free((void **)&(vals[ii]));
+ slapi_ch_free((void **)&vals);
+}
+
+#endif /* not openldap */
/*
* slapi_entry_schema_check - check that entry e conforms to the schema
@@ -960,8 +999,7 @@ oc_equal( struct objclass *oc1, struct objclass *oc2 )
NULL ) != 0
|| schema_strcmp_array( oc1->oc_orig_allowed, oc2->oc_orig_allowed,
NULL ) != 0
- || schema_strcmp_array( oc1->oc_origin, oc2->oc_origin,
- schema_user_defined_origin[0] ) != 0 ) {
+ || schema_extension_cmp( oc1->oc_extensions, oc2->oc_extensions ) != 0 ) {
return PR_FALSE;
}
@@ -995,6 +1033,114 @@ oc_print( struct objclass *oc )
}
#endif
+/*
+ * Compare the X-ORIGIN extension, other extensions can be ignored
+ */
+static int
+schema_extension_cmp(schemaext *e1, schemaext *e2)
+{
+ schemaext *e1_head = e1;
+ schemaext *e2_head = e2;
+ int found = 0;
+ int e1_has_origin = 0;
+ int e2_has_origin = 0;
+ int i, ii;
+
+ if(e1 == NULL && e2 == NULL){
+ return 0; /* match */
+ } else if (e1 == NULL || e2 == NULL){
+ return -1;
+ }
+ while(e1){
+ if(strcmp(e1->term, "X-ORIGIN")){
+ e1 = e1->next;
+ continue;
+ }
+ e1_has_origin = 1;
+ while(e2){
+ if(strcmp(e1->term, e2->term) == 0)
+ {
+ e2_has_origin = 1;
+ if(e1->values == NULL && e2->values == NULL){
+ return 0;
+ } else if (e1->values == NULL || e2->values == NULL){
+ return -1;
+ }
+ for (i = 0; e1->values[i]; i++)
+ {
+ found = 0;
+ for(ii = 0; e2->values[ii]; ii++)
+ {
+ if(strcmp(e1->values[i], e2->values[ii]) == 0){
+ found = 1;
+ break;
+ }
+ }
+ if(!found){
+ return -1;
+ }
+ }
+ /* So far so good, move on to the next check */
+ goto next;
+ }
+ e2 = e2->next;
+ }
+ e2 = e2_head;
+ e1 = e1->next;
+ }
+
+ if(e1_has_origin != e2_has_origin){
+ return -1;
+ } else if (e1_has_origin == 0 && e2_has_origin == 0){
+ return 0;
+ }
+
+next:
+ /*
+ * We know that e2 has the same extensions as e1, but does e1 have all the extensions as e2?
+ * Run the compare in reverse...
+ */
+ found = 0;
+ e1 = e1_head;
+ e2 = e2_head;
+
+ while(e2){
+ if(strcmp(e2->term, "X-ORIGIN")){
+ e2 = e2->next;
+ continue;
+ }
+ while(e1){
+ if(strcmp(e2->term, e1->term) == 0)
+ {
+ if(e2->values == NULL && e1->values == NULL){
+ return 0;
+ } else if (e1->values == NULL || e2->values == NULL){
+ return -1;
+ }
+ for (i = 0; e2->values[i]; i++)
+ {
+ found = 0;
+ for(ii = 0; e1->values[ii]; ii++)
+ {
+ if(strcmp(e2->values[i], e1->values[ii]) == 0){
+ found = 1;
+ break;
+ }
+ }
+ if(!found){
+ return -1;
+ }
+ }
+ return 0;
+ }
+ e1 = e1->next;
+ }
+ e1 = e1_head;
+ e2 = e2->next;
+ }
+
+ return 0;
+}
/*
* Compare two attrsyntax definitions for equality. Return PR_TRUE if
@@ -1028,8 +1174,7 @@ attr_syntax_equal( struct asyntaxinfo *asi1, struct asyntaxinfo *asi2 )
}
if ( schema_strcmp_array( asi1->asi_aliases, asi2->asi_aliases, NULL ) != 0
- || schema_strcmp_array( asi1->asi_origin, asi2->asi_origin,
- schema_user_defined_origin[0] ) != 0
+ || schema_extension_cmp (asi1->asi_extensions, asi2->asi_extensions) != 0
|| asi1->asi_plugin != asi2->asi_plugin
|| ( asi1->asi_flags & flagmask ) !=
( asi2->asi_flags & flagmask )
@@ -1196,7 +1341,7 @@ schema_attr_enum_callback(struct asyntaxinfo *asip, void *arg)
strlen_null_ok(asip->asi_mr_equality) +
strlen_null_ok(asip->asi_mr_ordering) +
strlen_null_ok(asip->asi_mr_substring) +
- strcat_qdlist( NULL, "X-ORIGIN", asip->asi_origin ));
+ strcat_extensions( NULL, asip->asi_extensions ));
/*
* Overall strategy is to maintain a pointer to the next location in
@@ -1257,9 +1402,8 @@ schema_attr_enum_callback(struct asyntaxinfo *asip, void *arg)
outp += strcpy_count(outp, "USAGE directoryOperation ");
}
- outp += strcat_qdlist( outp, "X-ORIGIN", asip->asi_origin );
+ outp += strcat_extensions( outp, asip->asi_extensions );
}
-
outp += strcpy_count(outp, ")");
val.bv_val = aew->psbAttrTypes->buffer;
@@ -1410,213 +1554,203 @@ read_schema_dse(
char *returntext /* not used */,
void *arg /* not used */ )
{
- struct berval val;
- struct berval *vals[2];
- int i;
- struct objclass *oc;
- struct matchingRuleList *mrl=NULL;
- struct sizedbuffer *psbObjectClasses= sizedbuffer_construct(BUFSIZ);
- struct sizedbuffer *psbAttrTypes= sizedbuffer_construct(BUFSIZ);
- struct sizedbuffer *psbMatchingRule= sizedbuffer_construct(BUFSIZ);
- struct sizedbuffer *psbSyntaxDescription = sizedbuffer_construct(BUFSIZ);
- struct attr_enum_wrapper aew;
- struct syntax_enum_wrapper sew;
- int enquote_sup_oc = config_get_enquote_sup_oc();
- PRUint32 schema_flags = 0;
- int user_defined_only = 0;
- char **allowed, **required;
- char *mr_desc, *mr_name, *oc_description;
- int schema_ds4x_compat = config_get_ds4_compatible_schema();
- const CSN *csn;
+ struct berval val;
+ struct berval *vals[2];
+ struct objclass *oc;
+ struct matchingRuleList *mrl=NULL;
+ struct sizedbuffer *psbObjectClasses= sizedbuffer_construct(BUFSIZ);
+ struct sizedbuffer *psbAttrTypes= sizedbuffer_construct(BUFSIZ);
+ struct sizedbuffer *psbMatchingRule= sizedbuffer_construct(BUFSIZ);
+ struct sizedbuffer *psbSyntaxDescription = sizedbuffer_construct(BUFSIZ);
+ struct attr_enum_wrapper aew;
+ struct syntax_enum_wrapper sew;
+ const CSN *csn;
+ char *mr_desc, *mr_name, *oc_description;
+ char **allowed, **required;
+ PRUint32 schema_flags = 0;
+ int enquote_sup_oc = config_get_enquote_sup_oc();
+ int schema_ds4x_compat = config_get_ds4_compatible_schema();
+ int user_defined_only = 0;
+ int i;
- vals[0] = &val;
- vals[1] = NULL;
+ vals[0] = &val;
+ vals[1] = NULL;
- slapi_pblock_get(pb, SLAPI_SCHEMA_FLAGS, (void*)&schema_flags);
- user_defined_only = (schema_flags & DSE_SCHEMA_USER_DEFINED_ONLY) ? 1 : 0;
+ slapi_pblock_get(pb, SLAPI_SCHEMA_FLAGS, (void*)&schema_flags);
+ user_defined_only = (schema_flags & DSE_SCHEMA_USER_DEFINED_ONLY) ? 1 : 0;
- attrlist_delete (&pschema_info_e->e_attrs, "objectclasses");
- attrlist_delete (&pschema_info_e->e_attrs, "attributetypes");
- attrlist_delete (&pschema_info_e->e_attrs, "matchingRules");
- attrlist_delete (&pschema_info_e->e_attrs, "ldapSyntaxes");
- /*
- attrlist_delete (&pschema_info_e->e_attrs, "matchingRuleUse");
- */
+ attrlist_delete (&pschema_info_e->e_attrs, "objectclasses");
+ attrlist_delete (&pschema_info_e->e_attrs, "attributetypes");
+ attrlist_delete (&pschema_info_e->e_attrs, "matchingRules");
+ attrlist_delete (&pschema_info_e->e_attrs, "ldapSyntaxes");
+ /*
+ * attrlist_delete (&pschema_info_e->e_attrs, "matchingRuleUse");
+ */
- schema_dse_lock_read();
+ schema_dse_lock_read();
+ oc_lock_read();
- /* return the objectclasses */
- oc_lock_read();
- for (oc = g_get_global_oc_nolock(); oc != NULL; oc = oc->oc_next)
- {
- size_t size= 0;
- int need_extra_space = 1;
+ /* return the objectclasses */
+ for (oc = g_get_global_oc_nolock(); oc != NULL; oc = oc->oc_next)
+ {
+ size_t size= 0;
+ int need_extra_space = 1;
- if (user_defined_only &&
- !(oc->oc_flags & OC_FLAG_USER_OC ||
- oc->oc_flags & OC_FLAG_REDEFINED_OC)) {
- continue;
- }
+ if (user_defined_only &&
+ !((oc->oc_flags & OC_FLAG_USER_OC) ||
+ (oc->oc_flags & OC_FLAG_REDEFINED_OC) ))
+ {
+ continue;
+ }
+ /*
+ * XXX: 256 is a magic number... it must be large enough to fit
+ * all of the fixed size items including description (DESC),
+ * kind (STRUCTURAL, AUXILIARY, or ABSTRACT), and the OBSOLETE flag.
+ */
+ if ( schema_ds4x_compat ) {
+ oc_description = (oc->oc_flags & OC_FLAG_STANDARD_OC) ?
+ OC_STANDARD_STRING : OC_USERDEF_STRING;
+ } else {
+ oc_description = oc->oc_desc;
+ }
+ size = 256+strlen_null_ok(oc->oc_oid) + strlen(oc->oc_name) +
+ strlen_null_ok(oc_description) + strcat_extensions( NULL, oc->oc_extensions );
+ required = schema_ds4x_compat ? oc->oc_required : oc->oc_orig_required;
+ if (required && required[0]) {
+ for (i = 0 ; required[i]; i++)
+ size+= 16 + strlen(required[i]);
+ }
+ allowed = schema_ds4x_compat ? oc->oc_allowed : oc->oc_orig_allowed;
+ if (allowed && allowed[0]) {
+ for (i = 0 ; allowed[i]; i++)
+ size+= 16 + strlen(allowed[i]);
+ }
+ sizedbuffer_allocate(psbObjectClasses,size);
+ /* put the OID and the NAME */
+ sprintf (psbObjectClasses->buffer, "( %s NAME '%s'", (oc->oc_oid) ? oc->oc_oid : "", oc->oc_name);
+ /* The DESC (description) is OPTIONAL */
+ if (oc_description) {
+ strcat(psbObjectClasses->buffer, " DESC '");
+ /*
+ * We want to list an empty description
+ * element if it was defined that way.
+ */
+ if (*oc_description) {
+ strcat(psbObjectClasses->buffer, oc_description);
+ }
+ strcat(psbObjectClasses->buffer, "'");
+ need_extra_space = 1;
+ }
+ /* put the OBSOLETE keyword */
+ if (!schema_ds4x_compat && (oc->oc_flags & OC_FLAG_OBSOLETE)) {
+ strcat(psbObjectClasses->buffer, schema_obsolete_with_spaces);
+ need_extra_space = 0;
+ }
+ /* put the SUP superior objectclass */
+ if (0 != strcasecmp(oc->oc_name, "top")) { /* top has no SUP */
+ /*
+ * Some AUXILIARY AND ABSTRACT objectclasses may not have a SUP either
+ * for compatability, every objectclass other than top must have a SUP
+ */
+ if (schema_ds4x_compat || (oc->oc_superior && *oc->oc_superior)) {
+ if (need_extra_space) {
+ strcat(psbObjectClasses->buffer, " ");
+ }
+ strcat(psbObjectClasses->buffer, "SUP ");
+ strcat(psbObjectClasses->buffer, (enquote_sup_oc ? "'" : ""));
+ strcat(psbObjectClasses->buffer, ((oc->oc_superior && *oc->oc_superior) ?
+ oc->oc_superior : "top"));
+ strcat(psbObjectClasses->buffer, (enquote_sup_oc ? "'" : ""));
+ need_extra_space = 1;
+ }
+ }
+ /* put the kind of objectclass */
+ if (schema_ds4x_compat) {
+ if (need_extra_space) {
+ strcat(psbObjectClasses->buffer, " ");
+ }
+ } else {
- /*
- * XXX: 256 is a magic number... it must be large enough to fit
- * all of the fixed size items including description (DESC),
- * kind (STRUCTURAL, AUXILIARY, or ABSTRACT), and the OBSOLETE flag.
- */
- if ( schema_ds4x_compat ) {
- oc_description = (oc->oc_flags & OC_FLAG_STANDARD_OC) ?
- OC_STANDARD_STRING : OC_USERDEF_STRING;
- } else {
- oc_description = oc->oc_desc;
- }
-
- size= 256+strlen_null_ok(oc->oc_oid) + strlen(oc->oc_name) +
- strlen_null_ok(oc_description) +
- strcat_qdlist( NULL, "X-ORIGIN", oc->oc_origin );
- required = schema_ds4x_compat ? oc->oc_required : oc->oc_orig_required;
- if (required && required[0]) {
- for (i = 0 ; required[i]; i++)
- size+= 16 + strlen(required[i]);
- }
- allowed = schema_ds4x_compat ? oc->oc_allowed : oc->oc_orig_allowed;
- if (allowed && allowed[0]) {
- for (i = 0 ; allowed[i]; i++)
- size+= 16 + strlen(allowed[i]);
+ strcat(psbObjectClasses->buffer, schema_oc_kind_strings_with_spaces[oc->oc_kind]);
+ }
+ strcat_oids( psbObjectClasses->buffer, "MUST", required, schema_ds4x_compat );
+ strcat_oids( psbObjectClasses->buffer, "MAY", allowed, schema_ds4x_compat );
+ if ( !schema_ds4x_compat ) {
+ strcat_extensions( psbObjectClasses->buffer, oc->oc_extensions );
+ }
+ strcat( psbObjectClasses->buffer, ")");
+ val.bv_val = psbObjectClasses->buffer;
+ val.bv_len = strlen (psbObjectClasses->buffer);
+ attrlist_merge (&pschema_info_e->e_attrs, "objectclasses", vals);
}
- sizedbuffer_allocate(psbObjectClasses,size);
- /* put the OID and the NAME */
- sprintf (psbObjectClasses->buffer,
- "( %s NAME '%s'",
- (oc->oc_oid) ? oc->oc_oid : "",
- oc->oc_name);
- /* The DESC (description) is OPTIONAL */
- if (oc_description) {
- strcat(psbObjectClasses->buffer, " DESC '");
- /* We want to list an empty description
- * element if it was defined that way. */
- if (*oc_description) {
- strcat(psbObjectClasses->buffer, oc_description);
- }
- strcat(psbObjectClasses->buffer, "'");
- need_extra_space = 1;
- }
- /* put the OBSOLETE keyword */
- if (!schema_ds4x_compat && (oc->oc_flags & OC_FLAG_OBSOLETE)) {
- strcat(psbObjectClasses->buffer, schema_obsolete_with_spaces);
- need_extra_space = 0;
- }
- /* put the SUP superior objectclass */
- if (0 != strcasecmp(oc->oc_name, "top")) { /* top has no SUP */
- /* some AUXILIARY AND ABSTRACT objectclasses may not have a SUP either */
- /* for compatability, every objectclass other than top must have a SUP */
- if (schema_ds4x_compat || (oc->oc_superior && *oc->oc_superior)) {
- if (need_extra_space) {
- strcat(psbObjectClasses->buffer, " ");
- }
- strcat(psbObjectClasses->buffer, "SUP ");
- strcat(psbObjectClasses->buffer, (enquote_sup_oc ? "'" : ""));
- strcat(psbObjectClasses->buffer,
- ((oc->oc_superior && *oc->oc_superior) ?
- oc->oc_superior : "top"));
- strcat(psbObjectClasses->buffer, (enquote_sup_oc ? "'" : ""));
- need_extra_space = 1;
- }
- }
- /* put the kind of objectclass */
- if (schema_ds4x_compat) {
- if (need_extra_space) {
- strcat(psbObjectClasses->buffer, " ");
- }
- } else {
- strcat(psbObjectClasses->buffer, schema_oc_kind_strings_with_spaces[oc->oc_kind]);
- }
-
- strcat_oids( psbObjectClasses->buffer, "MUST", required,
- schema_ds4x_compat );
- strcat_oids( psbObjectClasses->buffer, "MAY", allowed,
- schema_ds4x_compat );
- if ( !schema_ds4x_compat ) {
- strcat_qdlist( psbObjectClasses->buffer, "X-ORIGIN", oc->oc_origin );
- }
- strcat( psbObjectClasses->buffer, ")");
-
- val.bv_val = psbObjectClasses->buffer;
- val.bv_len = strlen (psbObjectClasses->buffer);
- attrlist_merge (&pschema_info_e->e_attrs, "objectclasses", vals);
- }
- oc_unlock();
-
- /* now return the attrs */
-
- aew.attrs = &pschema_info_e->e_attrs;
- aew.enquote_sup_oc = enquote_sup_oc;
- aew.psbAttrTypes = psbAttrTypes;
- aew.user_defined_only = user_defined_only;
- aew.schema_ds4x_compat = schema_ds4x_compat;
- attr_syntax_enumerate_attrs(schema_attr_enum_callback, &aew, PR_FALSE);
-
- /* return the set of matching rules we support */
- for (mrl = g_get_global_mrl(); !user_defined_only && mrl != NULL; mrl = mrl->mrl_next) {
- mr_name = mrl->mr_entry->mr_name ? mrl->mr_entry->mr_name : "";
- mr_desc = mrl->mr_entry->mr_desc ? mrl->mr_entry->mr_desc : "";
- sizedbuffer_allocate(psbMatchingRule,128+
- strlen_null_ok(mrl->mr_entry->mr_oid) +
- strlen(mr_name)+ strlen(mr_desc)+
- strlen_null_ok(mrl->mr_entry->mr_syntax));
- if ( schema_ds4x_compat ) {
- sprintf(psbMatchingRule->buffer,
- "( %s NAME '%s' DESC '%s' SYNTAX %s%s%s )",
- (mrl->mr_entry->mr_oid ? mrl->mr_entry->mr_oid : ""),
- mr_name, mr_desc,
- enquote_sup_oc ? "'" : "",
- mrl->mr_entry->mr_syntax ? mrl->mr_entry->mr_syntax : "" ,
- enquote_sup_oc ? "'" : "");
- } else if ( NULL != mrl->mr_entry->mr_oid &&
- NULL != mrl->mr_entry->mr_syntax ) {
- char *p;
-
- sprintf(psbMatchingRule->buffer, "( %s ", mrl->mr_entry->mr_oid );
- p = psbMatchingRule->buffer + strlen(psbMatchingRule->buffer);
- if ( *mr_name != '\0' ) {
- sprintf(p, "NAME '%s' ", mr_name );
- p += strlen(p);
- }
- if ( *mr_desc != '\0' ) {
- sprintf(p, "DESC '%s' ", mr_desc );
- p += strlen(p);
- }
- sprintf(p, "SYNTAX %s )", mrl->mr_entry->mr_syntax );
- }
+ oc_unlock();
- val.bv_val = psbMatchingRule->buffer;
- val.bv_len = strlen (psbMatchingRule->buffer);
- attrlist_merge (&pschema_info_e->e_attrs, "matchingRules", vals);
- }
+ /* now return the attrs */
+ aew.attrs = &pschema_info_e->e_attrs;
+ aew.enquote_sup_oc = enquote_sup_oc;
+ aew.psbAttrTypes = psbAttrTypes;
+ aew.user_defined_only = user_defined_only;
+ aew.schema_ds4x_compat = schema_ds4x_compat;
+ attr_syntax_enumerate_attrs(schema_attr_enum_callback, &aew, PR_FALSE);
+
+ /* return the set of matching rules we support */
+ for (mrl = g_get_global_mrl(); !user_defined_only && mrl != NULL; mrl = mrl->mrl_next) {
+ mr_name = mrl->mr_entry->mr_name ? mrl->mr_entry->mr_name : "";
+ mr_desc = mrl->mr_entry->mr_desc ? mrl->mr_entry->mr_desc : "";
+ sizedbuffer_allocate(psbMatchingRule,128 + strlen_null_ok(mrl->mr_entry->mr_oid) +
+ strlen(mr_name)+ strlen(mr_desc) + strlen_null_ok(mrl->mr_entry->mr_syntax));
+ if ( schema_ds4x_compat ) {
+ sprintf(psbMatchingRule->buffer,
+ "( %s NAME '%s' DESC '%s' SYNTAX %s%s%s )",
+ (mrl->mr_entry->mr_oid ? mrl->mr_entry->mr_oid : ""),
+ mr_name, mr_desc, enquote_sup_oc ? "'" : "",
+ mrl->mr_entry->mr_syntax ? mrl->mr_entry->mr_syntax : "" ,
+ enquote_sup_oc ? "'" : "");
+ } else if ( NULL != mrl->mr_entry->mr_oid &&
+ NULL != mrl->mr_entry->mr_syntax ){
+ char *p;
+
+ sprintf(psbMatchingRule->buffer, "( %s ", mrl->mr_entry->mr_oid );
+ p = psbMatchingRule->buffer + strlen(psbMatchingRule->buffer);
+ if ( *mr_name != '\0' ) {
+ sprintf(p, "NAME '%s' ", mr_name );
+ p += strlen(p);
+ }
+ if ( *mr_desc != '\0' ) {
+ sprintf(p, "DESC '%s' ", mr_desc );
+ p += strlen(p);
+ }
+ sprintf(p, "SYNTAX %s )", mrl->mr_entry->mr_syntax );
+ }
+ val.bv_val = psbMatchingRule->buffer;
+ val.bv_len = strlen (psbMatchingRule->buffer);
+ attrlist_merge (&pschema_info_e->e_attrs, "matchingRules", vals);
+ }
+ if ( !schema_ds4x_compat && !user_defined_only ) {
+ /* return the set of syntaxes we support */
+ sew.attrs = &pschema_info_e->e_attrs;
+ sew.psbSyntaxDescription = psbSyntaxDescription;
+ plugin_syntax_enumerate(schema_syntax_enum_callback, &sew);
+ }
+ csn = g_get_global_schema_csn();
+ if (NULL != csn) {
+ char csn_str[CSN_STRSIZE + 1];
- if ( !schema_ds4x_compat && !user_defined_only ) {
- /* return the set of syntaxes we support */
- sew.attrs = &pschema_info_e->e_attrs;
- sew.psbSyntaxDescription = psbSyntaxDescription;
- plugin_syntax_enumerate(schema_syntax_enum_callback, &sew);
- }
+ csn_as_string(csn, PR_FALSE, csn_str);
+ slapi_entry_attr_delete(pschema_info_e, "nsschemacsn");
+ slapi_entry_add_string(pschema_info_e, "nsschemacsn", csn_str);
+ }
- csn = g_get_global_schema_csn();
- if (NULL != csn) {
- char csn_str[CSN_STRSIZE + 1];
- csn_as_string(csn, PR_FALSE, csn_str);
- slapi_entry_attr_delete(pschema_info_e, "nsschemacsn");
- slapi_entry_add_string(pschema_info_e, "nsschemacsn", csn_str);
- }
+ schema_dse_unlock();
- schema_dse_unlock();
+ sizedbuffer_destroy(psbObjectClasses);
+ sizedbuffer_destroy(psbAttrTypes);
+ sizedbuffer_destroy(psbMatchingRule);
+ sizedbuffer_destroy(psbSyntaxDescription);
+ *returncode= LDAP_SUCCESS;
- sizedbuffer_destroy(psbObjectClasses);
- sizedbuffer_destroy(psbAttrTypes);
- sizedbuffer_destroy(psbMatchingRule);
- sizedbuffer_destroy(psbSyntaxDescription);
- *returncode= LDAP_SUCCESS;
- return SLAPI_DSE_CALLBACK_OK;
+ return SLAPI_DSE_CALLBACK_OK;
}
/* helper for deleting mods (we do not want to be applied) from the mods array */
@@ -1985,23 +2119,6 @@ oc_add_nolock(struct objclass *newoc)
newoc->oc_next = NULL;
}
}
-
-
-static char **read_dollar_values ( char *vals) {
- int i,k;
- char **retVal;
- static const char *charsToRemove = " ()";
-
- /* get rid of all the parens and spaces */
- for ( i = 0, k = 0; vals[i]; i++) {
- if (!strchr(charsToRemove, vals[i])) {
- vals[k++] = vals[i];
- }
- }
- vals[k] = '\0';
- retVal = slapi_str2charray (vals, "$");
- return retVal;
-}
/*
* Delete one or more objectClasses from our internal data structure.
@@ -2027,7 +2144,7 @@ schema_delete_objectclasses( Slapi_Entry *entryBefore, LDAPMod *mod,
}
for (i = 0; mod->mod_bvalues[i]; i++) {
- if ( LDAP_SUCCESS != ( rc = read_oc_ldif (
+ if ( LDAP_SUCCESS != ( rc = parse_oc_str (
(const char *)mod->mod_bvalues[i]->bv_val, &delete_oc,
errorbuf, errorbufsize, 0, 0, schema_ds4x_compat))) {
return rc;
@@ -2212,7 +2329,7 @@ schema_add_attribute ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
{
int i;
char *attr_ldif;
-/* LPXXX: Eventually, we should not allocate the buffers in read_at_ldif
+/* LPXXX: Eventually, we should not allocate the buffers in parse_at_str
* for each attribute, but use the same buffer for all.
* This is not done yet, so it's useless to allocate buffers for nothing.
*/
@@ -2226,7 +2343,7 @@ schema_add_attribute ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
PRUint32 nolock = 0; /* lock global resources during normal operation */
attr_ldif = (char *) mod->mod_bvalues[i]->bv_val;
- status = read_at_ldif(attr_ldif, NULL, errorbuf, errorbufsize,
+ status = parse_at_str(attr_ldif, NULL, errorbuf, errorbufsize,
nolock, 1 /* user defined */, schema_ds4x_compat, 1);
if ( LDAP_SUCCESS != status ) {
break; /* stop on first error */
@@ -2422,7 +2539,7 @@ schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
}
for ( i = 0; mod->mod_bvalues[i] != NULL; ++i ) {
- if ( LDAP_SUCCESS != ( rc = read_at_ldif( mod->mod_bvalues[i]->bv_val,
+ if ( LDAP_SUCCESS != ( rc = parse_at_str( mod->mod_bvalues[i]->bv_val,
&newasip, errorbuf, errorbufsize, 0, 1, 0, 0 ))) {
goto clean_up_and_return;
}
@@ -2500,7 +2617,7 @@ schema_add_objectclass ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
for (j = 0; mod->mod_bvalues[j]; j++) {
newoc_ldif = (char *) mod->mod_bvalues[j]->bv_val;
- if ( LDAP_SUCCESS != (rc = read_oc_ldif ( newoc_ldif, &pnew_oc,
+ if ( LDAP_SUCCESS != (rc = parse_oc_str ( newoc_ldif, &pnew_oc,
errorbuf, errorbufsize, 0, 1 /* user defined */,
schema_ds4x_compat))) {
return rc;
@@ -2577,7 +2694,7 @@ schema_replace_objectclasses ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
for ( i = 0; mod->mod_bvalues[i] != NULL; ++i ) {
struct objclass *addocp = NULL;
- if ( LDAP_SUCCESS != ( rc = read_oc_ldif( mod->mod_bvalues[i]->bv_val,
+ if ( LDAP_SUCCESS != ( rc = parse_oc_str( mod->mod_bvalues[i]->bv_val,
&newocp, errorbuf, errorbufsize, DSE_SCHEMA_NO_GLOCK,
1 /* user defined */, 0 /* no DS 4.x compat issues */ ))) {
rc = LDAP_INVALID_SYNTAX;
@@ -2590,7 +2707,7 @@ schema_replace_objectclasses ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf,
/* the names match -- remove from the current list */
if ( tmpocp == curlisthead ) {
curlisthead = tmpocp->oc_next;
- /* The global oc list is scanned in read_oc_ldif above,
+ /* The global oc list is scanned in parse_oc_str above,
if there are multiple objectclasses to be updated.
Needs to maintain the list dynamically. */
g_set_global_oc_nolock( curlisthead );
@@ -2698,6 +2815,66 @@ clean_up_and_return:
return rc;
}
+schemaext *
+schema_copy_extensions(schemaext *extensions)
+{
+ schemaext *ext = NULL, *head = NULL;
+ while(extensions){
+ schemaext *newext = (schemaext *)slapi_ch_calloc(1, sizeof(schemaext));
+ newext->term = slapi_ch_strdup(extensions->term);
+ newext->values = charray_dup(extensions->values);
+ newext->value_count = extensions->value_count;
+ if(ext == NULL){
+ ext = newext;
+ head = newext;
+ } else {
+ ext->next = newext;
+ ext = newext;
+ }
+ extensions = extensions->next;
+ }
+
+ return head;
+}
+
+void
+schema_free_extensions(schemaext *extensions)
+{
+ if(extensions){
+ schemaext *prev;
+
+ while(extensions){
+ slapi_ch_free_string(&extensions->term);
+ charray_free(extensions->values);
+ prev = extensions;
+ extensions = extensions->next;
+ slapi_ch_free( (void **)&prev);
+ }
+ }
+}
+
+static void
+oc_free( struct objclass **ocp )
+{
+ struct objclass *oc;
+
+ if ( NULL != ocp && NULL != *ocp ) {
+ oc = *ocp;
+ slapi_ch_free( (void **)&oc->oc_name );
+ slapi_ch_free( (void **)&oc->oc_desc );
+ slapi_ch_free( (void **)&oc->oc_oid );
+ slapi_ch_free( (void **)&oc->oc_superior );
+ charray_free( oc->oc_required );
+ charray_free( oc->oc_allowed );
+ charray_free( oc->oc_orig_required );
+ charray_free( oc->oc_orig_allowed );
+ schema_free_extensions( oc->oc_extensions );
+ slapi_ch_free( (void **)&oc );
+ *ocp = NULL;
+ }
+}
+
+#if !defined (USE_OPENLDAP)
/*
* read_oc_ldif_return
@@ -2711,14 +2888,11 @@ read_oc_ldif_return( int retVal,
char *oid,
struct sizedbuffer *name,
char *sup,
- char **origins,
- int num_origins,
char *desc )
{
slapi_ch_free((void **)&oid);
sizedbuffer_destroy( name );
slapi_ch_free((void **)&sup);
- free_qdlist( origins, num_origins );
slapi_ch_free((void **)&desc);
return retVal;
}
@@ -2755,17 +2929,17 @@ read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf,
size_t errorbufsize, PRUint32 schema_flags, int is_user_defined,
int schema_ds4x_compat )
{
- int i, j, num_origins;
+ int i, j;
const char *pstart, *nextinput;
struct objclass *pnew_oc, *psup_oc;
char **RequiredAttrsArray, **AllowedAttrsArray;
char **OrigRequiredAttrsArray, **OrigAllowedAttrsArray;
- char **oc_origins;
char *pend, *pOcOid, *pOcSup, *pOcDesc;
struct sizedbuffer *psbOcName= sizedbuffer_construct(BUFSIZ);
PRUint8 kind, flags;
int invalid_syntax_error;
schema_strstr_fn_t keyword_strstr_fn;
+ schemaext *extensions = NULL;
/*
* From RFC 2252 section 4.4:
@@ -2811,8 +2985,6 @@ read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf,
}
flags = 0;
- num_origins = 0;
- oc_origins = NULL;
pOcOid = pOcSup = pOcDesc = NULL;
if ( NULL == input || '\0' == input[0] ) {
@@ -2821,10 +2993,9 @@ read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf,
"One or more values are required for the objectClasses attribute" );
LDAPDebug ( LDAP_DEBUG_ANY, "NULL args passed to read_oc_ldif\n",0,0,0);
return read_oc_ldif_return( LDAP_OPERATIONS_ERROR, pOcOid, psbOcName,
- pOcSup, oc_origins, num_origins, pOcDesc );
+ pOcSup, pOcDesc );
}
-
nextinput = input;
/* look for the OID */
@@ -2833,7 +3004,7 @@ read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf,
schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_oc,
input, "Value is malformed. It must include a \"(\"");
return read_oc_ldif_return( invalid_syntax_error, pOcOid, psbOcName,
- pOcSup, oc_origins, num_origins, pOcDesc );
+ pOcSup, pOcDesc );
}
if ( schema_ds4x_compat || ( strcasecmp(pOcOid, "NAME") == 0))
@@ -2853,15 +3024,14 @@ read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf,
input, "Value is malformed. It must include a single quote around"
" the name" );
return read_oc_ldif_return( invalid_syntax_error, pOcOid, psbOcName,
- pOcSup, oc_origins, num_origins, pOcDesc );
+ pOcSup, pOcDesc );
}
}
- }
- else {
+ } else {
schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_oc,
input, "Value is malformed. It must include a \"NAME '\"");
- return read_oc_ldif_return( invalid_syntax_error, pOcOid, psbOcName,
- pOcSup, oc_origins, num_origins, pOcDesc );
+ return read_oc_ldif_return( invalid_syntax_error, pOcOid, psbOcName,
+ pOcSup, pOcDesc );
}
/*
@@ -2996,27 +3166,15 @@ read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf,
/* look for X-ORIGIN list */
if (is_user_defined) {
/* add X-ORIGIN 'user defined' */
- oc_origins = parse_origin_list( nextinput, &num_origins,
- schema_user_defined_origin );
+ extensions = parse_extensions( nextinput, schema_user_defined_origin );
+ flags |= OC_FLAG_USER_OC;
} else {
/* add nothing */
- oc_origins = parse_origin_list( nextinput, &num_origins, NULL );
- }
-
- /* set remaining flags */
- if ( element_is_user_defined( oc_origins )) {
- flags |= OC_FLAG_USER_OC;
- } else if ( is_user_defined ) {
- flags |= OC_FLAG_USER_OC;
- /* add missing user defined origin string */
- charray_add( &oc_origins, slapi_ch_strdup( schema_user_defined_origin[0] ));
- ++num_origins;
- } else {
- flags |= OC_FLAG_STANDARD_OC;
+ extensions = parse_extensions( nextinput, NULL );
+ flags |= OC_FLAG_STANDARD_OC;
}
/* generate OrigRequiredAttrsArray and OrigAllowedAttrsArray */
-
if (psup_oc) {
int found_it;
@@ -3073,36 +3231,29 @@ read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf,
pnew_oc->oc_allowed = AllowedAttrsArray;
pnew_oc->oc_orig_required = OrigRequiredAttrsArray;
pnew_oc->oc_orig_allowed = OrigAllowedAttrsArray;
- pnew_oc->oc_origin = cool_charray_dup( oc_origins );
+ pnew_oc->oc_extensions = extensions;
pnew_oc->oc_next = NULL;
pnew_oc->oc_flags = flags;
pnew_oc->oc_kind = kind;
*oc = pnew_oc;
- return read_oc_ldif_return( LDAP_SUCCESS, pOcOid, psbOcName, pOcSup,
- oc_origins, num_origins, pOcDesc );
+ return read_oc_ldif_return( LDAP_SUCCESS, pOcOid, psbOcName, pOcSup, pOcDesc );
}
+static char **read_dollar_values ( char *vals) {
+ int i,k;
+ char **retVal;
+ static const char *charsToRemove = " ()";
-static void
-oc_free( struct objclass **ocp )
-{
- struct objclass *oc;
-
- if ( NULL != ocp && NULL != *ocp ) {
- oc = *ocp;
- slapi_ch_free( (void **)&oc->oc_name );
- slapi_ch_free( (void **)&oc->oc_desc );
- slapi_ch_free( (void **)&oc->oc_oid );
- slapi_ch_free( (void **)&oc->oc_superior );
- charray_free( oc->oc_required );
- charray_free( oc->oc_allowed );
- charray_free( oc->oc_orig_required );
- charray_free( oc->oc_orig_allowed );
- cool_charray_free( oc->oc_origin );
- slapi_ch_free( (void **)&oc );
- *ocp = NULL;
+ /* get rid of all the parens and spaces */
+ for ( i = 0, k = 0; vals[i]; i++) {
+ if (!strchr(charsToRemove, vals[i])) {
+ vals[k++] = vals[i];
}
+ }
+ vals[k] = '\0';
+ retVal = slapi_str2charray (vals, "$");
+ return retVal;
}
/*
@@ -3137,14 +3288,13 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
int syntaxlength;
char **attr_names = NULL;
char *first_attr_name = NULL;
- char **attr_origins = NULL;
int num_names = 0;
- int num_origins = 0;
unsigned long flags = SLAPI_ATTR_FLAG_OVERRIDE;
const char *ss = 0;
struct asyntaxinfo *tmpasip;
int invalid_syntax_error;
schema_strstr_fn_t keyword_strstr_fn;
+ schemaext *extensions = NULL;
/*
* From RFC 2252 section 4.2:
@@ -3344,11 +3494,11 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
/* X-ORIGIN list */
if (is_user_defined) {
/* add X-ORIGIN 'user defined' */
- attr_origins = parse_origin_list( nextinput, &num_origins,
- schema_user_defined_origin );
+ extensions = parse_extensions( nextinput, schema_user_defined_origin );
} else {
- /* add nothing */
- attr_origins = parse_origin_list( nextinput, &num_origins, NULL );
+ /* add nothing extra*/
+ extensions = parse_extensions( nextinput, NULL );
+ flags |= SLAPI_ATTR_FLAG_STD_ATTR;
}
/* Do some sanity checking to make sure everything was read correctly */
@@ -3440,17 +3590,6 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
oc_unlock();
}
- if (!status && !element_is_user_defined( attr_origins )) {
- if ( is_user_defined ) {
- /* add missing user defined origin string */
- charray_add( &attr_origins,
- slapi_ch_strdup( schema_user_defined_origin[0] ));
- ++num_origins;
- } else {
- flags |= SLAPI_ATTR_FLAG_STD_ATTR;
- }
- }
-
if (!(schema_flags & DSE_SCHEMA_NO_CHECK) && !status) {
int ii;
/* check to see if the attribute name is valid */
@@ -3492,10 +3631,9 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
if (!status) {
- status = attr_syntax_create( pOid, attr_names, num_names,
+ status = attr_syntax_create( pOid, attr_names,
*psbAttrDesc->buffer == '\0' ? NULL : psbAttrDesc->buffer,
- pSuperior,
- pMREquality, pMROrdering, pMRSubstring, attr_origins,
+ pSuperior, pMREquality, pMROrdering, pMRSubstring, extensions,
pSyntax, syntaxlength, flags, &tmpasip );
}
@@ -3529,7 +3667,6 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
done:
/* free everything */
free_qdlist(attr_names, num_names);
- free_qdlist(attr_origins, num_origins);
sizedbuffer_destroy(psbAttrName);
sizedbuffer_destroy(psbAttrDesc);
slapi_ch_free((void **)&pOid);
@@ -3538,10 +3675,655 @@ read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
slapi_ch_free((void **)&pMROrdering);
slapi_ch_free((void **)&pMRSubstring);
slapi_ch_free((void **)&pSyntax);
+ schema_free_extensions(extensions);
+ return status;
+}
+
+#else /* (USE_OPENLDAP) */
+
+
+/* openldap attribute parser */
+/*
+ * if asipp is NULL, the attribute type is added to the global set of schema.
+ * if asipp is not NULL, the AT is not added but *asipp is set. When you are
+ * finished with *asipp, use attr_syntax_free() to dispose of it.
+ *
+ * schema_flags: Any or none of the following bits could be set
+ * DSE_SCHEMA_NO_CHECK -- schema won't be checked
+ * DSE_SCHEMA_NO_GLOCK -- locking of global resources is turned off;
+ * this saves time during initialization since
+ * the server operates in single threaded mode
+ * at that time or in reload_schemafile_lock.
+ * DSE_SCHEMA_LOCKED -- already locked with reload_schemafile_lock;
+ * no further lock needed
+ *
+ * if is_user_defined is true, force attribute type to be user defined.
+ *
+ * returns an LDAP error code (LDAP_SUCCESS if all goes well)
+*/
+static int
+parse_attr_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
+ size_t errorbufsize, PRUint32 schema_flags, int is_user_defined,
+ int schema_ds4x_compat, int is_remote)
+{
+ struct asyntaxinfo *tmpasip;
+ struct asyntaxinfo *tmpasi;
+ schemaext *extensions = NULL, *head = NULL;
+ struct objclass *poc;
+ LDAPAttributeType *atype = NULL;
+ const char *errp;
+ char *first_attr_name = NULL;
+ char **attr_names = NULL;
+ unsigned long flags = SLAPI_ATTR_FLAG_OVERRIDE;
+ /* If we ever accept openldap schema directly, then make parser_flags configurable */
+ const int parser_flags = LDAP_SCHEMA_ALLOW_NONE | LDAP_SCHEMA_ALLOW_NO_OID;
+ int invalid_syntax_error;
+ int syntaxlength = SLAPI_SYNTAXLENGTH_NONE;
+ int num_names = 0;
+ int status = 0;
+ int rc = 0;
+ int a, aa;
+
+ /*
+ * OpenLDAP AttributeType struct
+ *
+ * typedef struct ldap_attributetype {
+ * char *at_oid; OID
+ * char **at_names; Names
+ * char *at_desc; Description
+ * int at_obsolete; Is obsolete?
+ * char *at_sup_oid; OID of superior type
+ * char *at_equality_oid; OID of equality matching rule
+ * char *at_ordering_oid; OID of ordering matching rule
+ * char *at_substr_oid; OID of substrings matching rule
+ * char *at_syntax_oid; OID of syntax of values
+ * int at_syntax_len; Suggested minimum maximum length
+ * int at_single_value; Is single-valued?
+ * int at_collective; Is collective?
+ * int at_no_user_mod; Are changes forbidden through LDAP?
+ * int at_usage; Usage, see below
+ * LDAPSchemaExtensionItem **at_extensions; Extensions
+ * } LDAPAttributeType;
+ */
+
+ /*
+ * Set the appropriate error code
+ */
+ if ( schema_ds4x_compat ) {
+ invalid_syntax_error = LDAP_OPERATIONS_ERROR;
+ } else {
+ invalid_syntax_error = LDAP_INVALID_SYNTAX;
+ }
+ /*
+ * Verify we have input
+ */
+ if(input == NULL || '\0' == input[0]){
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at, NULL,
+ "One or more values are required for the attributeTypes attribute" );
+ LDAPDebug ( LDAP_DEBUG_ANY, "NULL args passed to parse_attr_str\n",0,0,0);
+ return invalid_syntax_error;
+ }
+ /*
+ * Parse the line and create of attribute structure
+ */
+ while(isspace(*input)){
+ /* trim any leading spaces */
+ input++;
+ }
+ if((atype = ldap_str2attributetype(input, &rc, &errp, parser_flags )) == NULL){
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at, input,
+ "Failed to parse attribute, error(%d - %s) at (%s)", rc, ldap_scherr2str(rc), errp );
+ return invalid_syntax_error;
+ }
+
+ if (schema_flags & DSE_SCHEMA_NO_GLOCK){
+ flags |= SLAPI_ATTR_FLAG_NOLOCKING;
+ }
+ /*
+ * Check the NAME and update our name list
+ */
+ if ( NULL != atype->at_names ) {
+ for(; atype->at_names[num_names]; num_names++){
+ charray_add(&attr_names, slapi_ch_strdup(atype->at_names[num_names]));
+ }
+ first_attr_name = atype->at_names[0];
+ } else { /* NAME followed by nothing violates syntax */
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at, input,
+ "Missing or invalid attribute name" );
+ status = invalid_syntax_error;
+ goto done;
+ }
+ /*
+ * If the attribute type doesn't have an OID, we'll make the oid attrname-oid.
+ */
+ if (NULL == atype->at_oid) {
+ atype->at_oid = slapi_ch_smprintf("%s-oid", first_attr_name );
+ }
+ /*
+ * Set the flags
+ */
+ if(atype->at_obsolete){
+ flags |= SLAPI_ATTR_FLAG_OBSOLETE;
+ }
+ if(atype->at_single_value){
+ flags |= SLAPI_ATTR_FLAG_SINGLE;
+ }
+ if(atype->at_collective){
+ flags |= SLAPI_ATTR_FLAG_COLLECTIVE;
+ }
+ if(atype->at_no_user_mod){
+ flags |= SLAPI_ATTR_FLAG_NOUSERMOD;
+ }
+ if(atype->at_usage == LDAP_SCHEMA_DIRECTORY_OPERATION){
+ flags |= SLAPI_ATTR_FLAG_OPATTR;
+ }
+ /*
+ * Check the superior, and use it fill in any missing oids on this attribute
+ */
+ if (NULL != atype->at_sup_oid) {
+ struct asyntaxinfo *asi_parent;
+
+ asi_parent = attr_syntax_get_by_name(atype->at_sup_oid);
+ /* if we find no match then server won't start or add the attribute type */
+ if (asi_parent == NULL) {
+ LDAPDebug (LDAP_DEBUG_PARSE, "Cannot find parent attribute type \"%s\"\n",
+ atype->at_sup_oid, NULL, NULL);
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at, first_attr_name,
+ "Missing parent attribute syntax OID");
+ status = invalid_syntax_error;
+ goto done;
+
+ } else if ((NULL == atype->at_syntax_oid) || (NULL == atype->at_equality_oid) ||
+ (NULL == atype->at_substr_oid) || (NULL == atype->at_ordering_oid))
+ {
+ /*
+ * We only want to use the parent syntax if a SYNTAX
+ * wasn't explicitly specified for this attribute.
+ */
+ char *pso = asi_parent->asi_plugin->plg_syntax_oid;
+
+ if (pso && (NULL == atype->at_syntax_oid)) {
+ atype->at_syntax_oid = slapi_ch_strdup(pso);
+ LDAPDebug (LDAP_DEBUG_TRACE,
+ "Inheriting syntax %s from parent type %s\n",
+ atype->at_syntax_oid, atype->at_sup_oid,NULL);
+ } else if (NULL == atype->at_syntax_oid) {
+ schema_create_errormsg( errorbuf, errorbufsize,
+ schema_errprefix_at, first_attr_name,
+ "Missing parent attribute syntax OID");
+ status = invalid_syntax_error;
+ goto done;
+ }
+
+ if (NULL == atype->at_equality_oid) {
+ atype->at_equality_oid = slapi_ch_strdup(asi_parent->asi_mr_equality);
+ }
+ if (NULL == atype->at_substr_oid) {
+ atype->at_substr_oid = slapi_ch_strdup(asi_parent->asi_mr_substring);
+ }
+ if (NULL == atype->at_ordering_oid) {
+ atype->at_ordering_oid = slapi_ch_strdup(asi_parent->asi_mr_ordering);
+ }
+ attr_syntax_return( asi_parent );
+ }
+ }
+ /*
+ * Make sure we have a syntax oid set
+ */
+ if (NULL == atype->at_syntax_oid) {
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
+ first_attr_name, "Missing attribute syntax OID");
+ status = invalid_syntax_error;
+ goto done;
+ }
+ /*
+ * Make sure the OID is known
+ */
+ if (!status && (plugin_syntax_find ( atype->at_syntax_oid ) == NULL) ) {
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
+ first_attr_name, "Unknown attribute syntax OID \"%s\"",
+ atype->at_syntax_oid );
+ status = invalid_syntax_error;
+ goto done;
+ }
+ /*
+ * Check to make sure that the OID isn't being used by an objectclass
+ */
+ if (!(schema_flags & DSE_SCHEMA_LOCKED)){
+ oc_lock_read();
+ }
+ poc = oc_find_oid_nolock( atype->at_oid );
+ if ( poc != NULL) {
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at, first_attr_name,
+ "The OID \"%s\" is also used by the object class \"%s\"", atype->at_oid, poc->oc_name);
+ status = LDAP_TYPE_OR_VALUE_EXISTS;
+ }
+ if (!(schema_flags & DSE_SCHEMA_LOCKED)){
+ oc_unlock();
+ }
+ if(status){
+ goto done;
+ }
+ /*
+ * Walk the "at_extensions" and set the schema extensions
+ */
+ for(a = 0; atype->at_extensions && atype->at_extensions[a]; a++){
+ schemaext *newext = (schemaext *)slapi_ch_calloc(1, sizeof (schemaext));
+ newext->term = slapi_ch_strdup(atype->at_extensions[a]->lsei_name);
+ for (aa = 0; atype->at_extensions[a]->lsei_values && atype->at_extensions[a]->lsei_values[aa]; aa++){
+ charray_add(&newext->values, slapi_ch_strdup(atype->at_extensions[a]->lsei_values[aa]));
+ newext->value_count++;
+ }
+ if(extensions == NULL){
+ extensions = newext;
+ head = newext;
+ } else {
+ extensions->next = newext;
+ extensions = newext;
+ }
+ }
+ extensions = head; /* reset to the top of the list */
+ /*
+ * Make sure if we are user-defined, that the attr_origins represents it
+ */
+ if (!extension_is_user_defined( extensions )) {
+ if ( is_user_defined ) {
+ int added = 0;
+ /* see if we have a X-ORIGIN term already */
+ while(extensions){
+ if(strcmp(extensions->term, "X-ORIGIN") == 0){
+ charray_add(&extensions->values, slapi_ch_strdup(schema_user_defined_origin[0]));
+ extensions->value_count++;
+ added = 1;
+ break;
+ }
+ extensions = extensions->next;
+ }
+ if(!added){
+ /* X-ORIGIN is completely missing, add it */
+ extensions = head;
+ schemaext *newext = (schemaext *)slapi_ch_calloc(1, sizeof (schemaext));
+ newext->term = slapi_ch_strdup("X-ORIGIN");
+ charray_add(&newext->values, slapi_ch_strdup(schema_user_defined_origin[0]));
+ newext->value_count++;
+ while(extensions && extensions->next){
+ /* move to the end of the list */
+ extensions = extensions->next;
+ }
+ if(extensions == NULL){
+ extensions = newext;
+ head = extensions;
+ } else {
+ extensions->next = newext;
+ }
+ }
+ } else {
+ flags |= SLAPI_ATTR_FLAG_STD_ATTR;
+ }
+ }
+ extensions = head; /* reset to the top of the list */
+ /*
+ * Check to see if the attribute name is valid
+ */
+ if (!(schema_flags & DSE_SCHEMA_NO_CHECK)) {
+ for (a = 0; a < num_names; ++a) {
+ if ( schema_check_name(attr_names[a], PR_TRUE, errorbuf, errorbufsize) == 0 ) {
+ status = invalid_syntax_error;
+ goto done;
+ } else if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) && attr_syntax_exists(attr_names[a])) {
+ schema_create_errormsg( errorbuf, errorbufsize,
+ schema_errprefix_at, attr_names[a],
+ "Could not be added because it already exists" );
+ status = LDAP_TYPE_OR_VALUE_EXISTS;
+ goto done;
+ }
+ }
+ }
+ /*
+ * Check if the OID is valid
+ */
+ if (!(schema_flags & DSE_SCHEMA_NO_CHECK)) {
+ if ( schema_check_oid ( first_attr_name, atype->at_oid, PR_TRUE, errorbuf,
+ errorbufsize ) == 0 ) {
+ status = invalid_syntax_error;
+ goto done;
+ }
+ }
+ /*
+ * Check if the OID is already being used
+ */
+ if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) && ( NULL != (tmpasi = attr_syntax_get_by_oid(atype->at_oid)))) {
+ schema_create_errormsg( errorbuf, errorbufsize,
+ schema_errprefix_at, first_attr_name,
+ "Could not be added because the OID \"%s\" is already in use", atype->at_oid);
+ status = LDAP_TYPE_OR_VALUE_EXISTS;
+ attr_syntax_return( tmpasi );
+ goto done;
+ }
+ /*
+ * Finally create the attribute
+ */
+ status = attr_syntax_create( atype->at_oid, attr_names, atype->at_desc, atype->at_sup_oid,
+ atype->at_equality_oid, atype->at_ordering_oid, atype->at_substr_oid,
+ extensions, atype->at_syntax_oid, syntaxlength, flags, &tmpasip );
+ if (!status) {
+ if ( NULL != asipp ) {
+ *asipp = tmpasip; /* just return it */
+ } else {
+ /* add the new attribute to the global store */
+ status = attr_syntax_add( tmpasip );
+ if ( LDAP_SUCCESS != status ) {
+ if ( 0 != (flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
+ LDAP_TYPE_OR_VALUE_EXISTS == status ) {
+ /*
+ * This can only occur if the name and OID don't match the
+ * attribute we are trying to override (all other cases of
+ * "type or value exists" were trapped above).
+ */
+ schema_create_errormsg( errorbuf, errorbufsize,
+ schema_errprefix_at, first_attr_name,
+ "Does not match the OID \"%s\". Another attribute "
+ "type is already using the name or OID.", atype->at_oid);
+ } else {
+ schema_create_errormsg( errorbuf, errorbufsize,
+ schema_errprefix_at, first_attr_name,
+ "Could not be added (OID is \"%s\")", atype->at_oid );
+ }
+ attr_syntax_free( tmpasip );
+ }
+ }
+ }
+
+ done:
+ /* free everything */
+ ldap_attributetype_free(atype);
+ charray_free(attr_names);
+ schema_free_extensions(extensions);
return status;
}
+/*
+ * parse_objclass_str
+ *
+ * Read the value of the objectclasses attribute in cn=schema, convert it
+ * into an objectclass struct.
+ *
+ * Arguments:
+ *
+ * input : value of objectclasses attribute to read
+ * oc : pointer write the objectclass to
+ * errorbuf : buffer to write any errors to
+ * is_user_defined : if non-zero, force objectclass to be user defined
+ * schema_flags : Any or none of the following bits could be set
+ * DSE_SCHEMA_NO_CHECK -- schema won't be checked
+ * DSE_SCHEMA_NO_GLOCK -- don't lock global resources
+ * DSE_SCHEMA_LOCKED -- already locked with
+ * reload_schemafile_lock;
+ * no further lock needed
+ * schema_ds4x_compat: if non-zero, act like Netscape DS 4.x
+ *
+ * Returns: an LDAP error code
+ *
+ * LDAP_SUCCESS if the objectclass was sucessfully read, the new
+ * objectclass will be written to oc
+ *
+ * All others: there was an error, an error message will
+ * be written to errorbuf
+ */
+static int
+parse_objclass_str ( const char *input, struct objclass **oc, char *errorbuf,
+ size_t errorbufsize, PRUint32 schema_flags, int is_user_defined,
+ int schema_ds4x_compat )
+{
+ LDAPObjectClass *objClass;
+ struct objclass *pnew_oc = NULL, *psup_oc = NULL;
+ schemaext *extensions = NULL, *head = NULL;
+ const char *errp;
+ char **OrigRequiredAttrsArray, **OrigAllowedAttrsArray;
+ char *first_oc_name = NULL;
+ /* If we ever accept openldap schema directly, then make parser_flags configurable */
+ const int parser_flags = LDAP_SCHEMA_ALLOW_NONE | LDAP_SCHEMA_ALLOW_NO_OID;
+ PRUint8 flags = 0;
+ int invalid_syntax_error;
+ int i, j;
+ int rc = 0;
+
+ /*
+ * openLDAP Objectclass struct
+ *
+ * typedef struct ldap_objectclass {
+ * char *oc_oid; OID
+ * char **oc_names; Names
+ * char *oc_desc; Description
+ * int oc_obsolete; Is obsolete?
+ * char **oc_sup_oids; OIDs of superior classes
+ * int oc_kind; Kind
+ * char **oc_at_oids_must; OIDs of required attribute types
+ * char **oc_at_oids_may; OIDs of optional attribute types
+ * LDAPSchemaExtensionItem **oc_extensions; Extensions
+ * } LDAPObjectClass;
+ */
+
+ /*
+ * Set the appropriate error code
+ */
+ if ( schema_ds4x_compat ) {
+ invalid_syntax_error = LDAP_OPERATIONS_ERROR;
+ } else {
+ invalid_syntax_error = LDAP_INVALID_SYNTAX;
+ }
+ /*
+ * Verify we have input
+ */
+ if ( NULL == input || '\0' == input[0] ) {
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_oc, NULL,
+ "One or more values are required for the objectClasses attribute" );
+ LDAPDebug ( LDAP_DEBUG_ANY, "NULL args passed to read_oc_ldif\n",0,0,0);
+ return LDAP_OPERATIONS_ERROR;
+ }
+ /*
+ * Parse the input and create the openLdap objectclass structure
+ */
+ while(isspace(*input)){
+ /* trim any leading spaces */
+ input++;
+ }
+ if((objClass = ldap_str2objectclass(input, &rc, &errp, parser_flags )) == NULL){
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_oc, input,
+ "Failed to parse objectclass, error(%d) at (%s)", rc, errp );
+ return invalid_syntax_error;
+ }
+ /*
+ * Check the NAME and update our name list
+ */
+ if ( NULL != objClass->oc_names ) {
+ first_oc_name = objClass->oc_names[0];
+ } else { /* NAME followed by nothing violates syntax */
+ schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_oc, input,
+ "Missing or invalid objectclass name" );
+ rc = invalid_syntax_error;
+ goto done;
+ }
+ /*
+ * If the objectclass type doesn't have an OID, we'll make the oid objClass-oid.
+ */
+ if (NULL == objClass->oc_oid) {
+ objClass->oc_oid = slapi_ch_smprintf("%s-oid", first_oc_name );
+ }
+ /*
+ * Check to see if the objectclass name is valid
+ */
+ if (!(schema_flags & DSE_SCHEMA_NO_CHECK)) {
+ for (i = 0; objClass->oc_names[i]; ++i) {
+ if ( schema_check_name(objClass->oc_names[i], PR_TRUE, errorbuf, errorbufsize) == 0 ) {
+ rc = invalid_syntax_error;
+ goto done;
+ }
+ }
+ }
+ /*
+ * Check if the OID is valid
+ */
+ if (!(schema_flags & DSE_SCHEMA_NO_CHECK)) {
+ if ( schema_check_oid ( first_oc_name, objClass->oc_oid, PR_TRUE, errorbuf,
+ errorbufsize ) == 0 ) {
+ rc = invalid_syntax_error;
+ goto done;
+ }
+ }
+ /*
+ * Look for the superior objectclass. We first look for a parenthesized
+ * list and if not found we look for a simple OID.
+ *
+ * XXXmcs: Since we do not yet support multiple superior objectclasses, we
+ * just grab the first OID in a parenthesized list.
+ */
+ if (!(schema_flags & DSE_SCHEMA_NO_GLOCK)) {
+ /* needed because we access the superior oc */
+ oc_lock_read();
+ }
+ if(objClass->oc_sup_oids && objClass->oc_sup_oids[0]){
+ psup_oc = oc_find_nolock ( objClass->oc_sup_oids[0] );
+ }
+ /*
+ * Walk the "oc_extensions" and set the schema extensions
+ */
+ for(i = 0; objClass->oc_extensions && objClass->oc_extensions[i]; i++){
+ schemaext *newext = (schemaext *)slapi_ch_calloc(1, sizeof (schemaext));
+ newext->term = slapi_ch_strdup(objClass->oc_extensions[i]->lsei_name);
+ for (j = 0; objClass->oc_extensions[i]->lsei_values && objClass->oc_extensions[i]->lsei_values[j]; j++){
+ charray_add(&newext->values, slapi_ch_strdup(objClass->oc_extensions[i]->lsei_values[j]));
+ newext->value_count++;
+ }
+ if(extensions == NULL){
+ extensions = newext;
+ head = extensions;
+ } else {
+ extensions->next = newext;
+ extensions = newext;
+ }
+ }
+ extensions = head; /* reset to the top of the list */
+ /*
+ * Set the remaining flags
+ */
+ if(objClass->oc_obsolete){
+ flags |= OC_FLAG_OBSOLETE;
+ }
+ if ( extension_is_user_defined( extensions )) {
+ flags |= OC_FLAG_USER_OC;
+ } else if ( is_user_defined ) {
+ int added = 0;
+ /* see if we have a X-ORIGIN term already */
+ while(extensions){
+ if(strcmp(extensions->term, "X-ORIGIN") == 0){
+ charray_add(&extensions->values, slapi_ch_strdup(schema_user_defined_origin[0]));
+ extensions->value_count++;
+ added = 1;
+ break;
+ }
+ extensions = extensions->next;
+ }
+ if(!added){
+ /* X-ORIGIN is completely missing, add it */
+ extensions = head;
+ schemaext *newext = (schemaext *)slapi_ch_calloc(1, sizeof (schemaext));
+ newext->term = slapi_ch_strdup("X-ORIGIN");
+ charray_add( &newext->values, slapi_ch_strdup( schema_user_defined_origin[0] ));
+ newext->value_count++;
+ while(extensions && extensions->next){
+ extensions = extensions->next;
+ }
+ if(extensions == NULL){
+ extensions = newext;
+ head = extensions;
+ } else {
+ extensions->next = newext;
+ }
+ }
+ flags |= OC_FLAG_USER_OC;
+ } else {
+ flags |= OC_FLAG_STANDARD_OC;
+ }
+ extensions = head; /* reset to the top of the list */
+ /*
+ * Generate OrigRequiredAttrsArray and OrigAllowedAttrsArray from the superior oc
+ */
+ if (psup_oc) {
+ int found_it;
+
+ OrigRequiredAttrsArray = (char **) slapi_ch_malloc (1 * sizeof(char *)) ;
+ OrigRequiredAttrsArray[0] = NULL;
+ OrigAllowedAttrsArray = (char **) slapi_ch_malloc (1 * sizeof(char *)) ;
+ OrigAllowedAttrsArray[0] = NULL;
+ if (psup_oc->oc_required && objClass->oc_at_oids_must) {
+ for (i = 0, found_it = 0; objClass->oc_at_oids_must[i]; i++) {
+ for (j = 0; psup_oc->oc_required[j]; j++) {
+ if (strcasecmp (psup_oc->oc_required[j], objClass->oc_at_oids_must[i]) == 0) {
+ found_it = 1;
+ break;
+ }
+ }
+ if (!found_it) {
+ charray_add (&OrigRequiredAttrsArray, slapi_ch_strdup ( objClass->oc_at_oids_must[i] ) );
+ }
+ }
+ } else {
+ /* we still need to set the originals */
+ OrigRequiredAttrsArray = charray_dup(objClass->oc_at_oids_must);
+ }
+ if (psup_oc->oc_allowed && objClass->oc_at_oids_may) {
+ for (i = 0, found_it = 0; objClass->oc_at_oids_may[i]; i++) {
+ for (j = 0; psup_oc->oc_allowed[j]; j++) {
+ if (strcasecmp (psup_oc->oc_allowed[j], objClass->oc_at_oids_may[i]) == 0) {
+ found_it = 1;
+ break;
+ }
+ }
+ if (!found_it) {
+ charray_add (&OrigAllowedAttrsArray, slapi_ch_strdup (objClass->oc_at_oids_may[i]) );
+ }
+ }
+ } else {
+ /* we still need to set the originals */
+ OrigAllowedAttrsArray = charray_dup(objClass->oc_at_oids_may);
+ }
+ } else {
+ /* if no parent oc */
+ OrigRequiredAttrsArray = charray_dup ( objClass->oc_at_oids_must );
+ OrigAllowedAttrsArray = charray_dup ( objClass->oc_at_oids_may );
+ }
+ if (!(schema_flags & DSE_SCHEMA_NO_GLOCK)) {
+ oc_unlock(); /* we are done accessing superior oc (psup_oc) */
+ }
+ /*
+ * Finally - create new the objectclass
+ */
+ pnew_oc = (struct objclass *) slapi_ch_calloc (1, sizeof (struct objclass));
+ pnew_oc->oc_name = slapi_ch_strdup ( objClass->oc_names[0] );
+ if(objClass->oc_sup_oids){
+ pnew_oc->oc_superior = slapi_ch_strdup( objClass->oc_sup_oids[0] );
+ }
+ pnew_oc->oc_oid = slapi_ch_strdup( objClass->oc_oid );
+ pnew_oc->oc_desc = slapi_ch_strdup( objClass->oc_desc );
+ pnew_oc->oc_required = charray_dup( objClass->oc_at_oids_must );
+ pnew_oc->oc_allowed = charray_dup( objClass->oc_at_oids_may );
+ pnew_oc->oc_orig_required = OrigRequiredAttrsArray;
+ pnew_oc->oc_orig_allowed = OrigAllowedAttrsArray;
+ pnew_oc->oc_kind = objClass->oc_kind;
+ pnew_oc->oc_extensions = extensions;
+ pnew_oc->oc_next = NULL;
+ pnew_oc->oc_flags = flags;
+
+ *oc = pnew_oc;
+
+done:
+ ldap_objectclass_free(objClass);
+
+ return rc;
+}
+#endif
/*
* schema_check_oc_attrs:
@@ -3925,7 +4707,7 @@ load_schema_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *ignored,
if (flags & DSE_SCHEMA_NO_LOAD)
{
struct asyntaxinfo *tmpasip = NULL;
- if ((*returncode = read_at_ldif(s, &tmpasip, returntext,
+ if ((*returncode = parse_at_str(s, &tmpasip, returntext,
SLAPI_DSE_RETURNTEXT_SIZE, flags,
primary_file /* force user defined? */,
schema_ds4x_compat, 0)) != 0)
@@ -3934,7 +4716,7 @@ load_schema_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *ignored,
}
else
{
- if ((*returncode = read_at_ldif(s, NULL, returntext,
+ if ((*returncode = parse_at_str(s, NULL, returntext,
SLAPI_DSE_RETURNTEXT_SIZE, flags,
primary_file /* force user defined? */,
schema_ds4x_compat, 0)) != 0)
@@ -3962,7 +4744,7 @@ load_schema_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *ignored,
const char *s = slapi_value_get_string(v);
if (!s)
continue;
- if ( LDAP_SUCCESS != (*returncode = read_oc_ldif(s, &oc, returntext,
+ if ( LDAP_SUCCESS != (*returncode = parse_oc_str(s, &oc, returntext,
SLAPI_DSE_RETURNTEXT_SIZE, flags,
primary_file /* force user defined? */,
schema_ds4x_compat))) {
@@ -4091,6 +4873,7 @@ init_schema_dse_ext(char *schemadir, Slapi_Backend *be,
if(rc)
{
char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE] = {0};
+ char *attr_str;
int dont_write = 1;
int merge = 1;
int dont_dup_check = 1;
@@ -4108,22 +4891,26 @@ init_schema_dse_ext(char *schemadir, Slapi_Backend *be,
/* add the objectclass attribute so we can do some basic schema
checking during initialization; this will be overridden when
its "real" definition is read from the schema conf files */
+
+#ifdef USE_OPENLDAP
+ attr_str = "( 2.5.4.0 NAME 'objectClass' "
+ "DESC 'Standard schema for LDAP' SYNTAX "
+ "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )";
+#else
+ attr_str = "attributeTypes: ( 2.5.4.0 NAME 'objectClass' "
+ "DESC 'Standard schema for LDAP' SYNTAX "
+ "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )";
+#endif
if (schema_flags & DSE_SCHEMA_NO_LOAD)
{
struct asyntaxinfo *tmpasip = NULL;
- rc = read_at_ldif("attributeTypes: ( 2.5.4.0 NAME 'objectClass' "
- "DESC 'Standard schema for LDAP' SYNTAX "
- "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )",
- &tmpasip, errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+ rc = parse_at_str(attr_str, &tmpasip, errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
DSE_SCHEMA_NO_GLOCK|schema_flags, 0, 0, 0);
attr_syntax_free( tmpasip ); /* trash it */
}
else
{
- rc = read_at_ldif("attributeTypes: ( 2.5.4.0 NAME 'objectClass' "
- "DESC 'Standard schema for LDAP' SYNTAX "
- "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )",
- NULL, errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+ rc = parse_at_str(attr_str, NULL, errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
schema_flags, 0, 0, 0);
}
if (rc)
@@ -4202,6 +4989,127 @@ init_schema_dse(const char *configdir)
return rc;
}
+#if !defined (USE_OPENLDAP)
+
+static char **
+parse_xstring_list( const char *schema_value, const char *name, size_t namelen, int *num_xvalsp,
+ char **default_list )
+{
+ char *start, *end, *xval_tmp;
+ char **xvals = NULL;
+
+ if (( start = PL_strstr ( schema_value, name )) != NULL) {
+ start += namelen+1; /* +1 for space */
+ xval_tmp = slapi_ch_strdup( start );
+ if ( *start == '(' ) {
+ end = strchr( xval_tmp, ')' );
+ } else {
+ end = strchr( xval_tmp + 1, '\'' );
+ }
+ if (end) {
+ *(end+1) = 0;
+ }
+ xvals = parse_qdstrings( xval_tmp, num_xvalsp );
+ slapi_ch_free( (void **)&xval_tmp );
+ } else {
+ xvals = NULL;
+ *num_xvalsp = 0;
+ }
+
+ if ( NULL == xvals && NULL != default_list ) {
+ int i;
+
+ for ( i = 0; default_list[i] != NULL; ++i ) {
+ ;
+ }
+ *num_xvalsp = i;
+ xvals = (char **)slapi_ch_malloc( (i+1) * sizeof(char *));
+ for ( i = 0; default_list[i] != NULL; ++i ) {
+ xvals[i] = slapi_ch_strdup( default_list[i] );
+ }
+ xvals[i] = NULL;
+ }
+
+/* for debugging
+if ( xvals == NULL || xvals[0] == NULL ) {
+ LDAPDebug( LDAP_DEBUG_ANY, "no xstring values for xstring (%s) in (%s)\n", name, schema_value, 0 );
+}
+*/
+
+ return xvals;
+}
+
+/* used by mozldap read_at_ldif() & read_oc_ldif() */
+static schemaext*
+parse_extensions( const char *schema_value, char **default_list )
+{
+ schemaext *extensions = NULL, *head = NULL;
+ char *input, *token, *iter = NULL;
+ int i;
+
+ /*
+ * First make a copy of the input, then grab all the "X-" words,
+ * and extract the values.
+ */
+ input = slapi_ch_strdup(schema_value);
+ token = ldap_utf8strtok_r(input, " ", &iter);
+ while(token){
+ if(strncmp(token,"X-", 2) == 0){
+ /* we have a new extension */
+ schemaext *newext;
+ newext = (schemaext *)slapi_ch_calloc(1, sizeof (schemaext));
+ newext->term = slapi_ch_strdup(token);
+ newext->values = parse_xstring_list(schema_value, token, strlen(token), &newext->value_count, default_list);
+ if(extensions == NULL){
+ extensions = newext;
+ head = newext;
+ } else {
+ extensions->next = newext;
+ extensions = extensions->next;
+ }
+ }
+ token = ldap_utf8strtok_r(iter, " ", &iter);
+ }
+ extensions = head;
+ /*
+ * Ok, if X-ORIGIN was not specified, then add it with the default values
+ */
+ if ( !extension_is_user_defined(extensions) && default_list ) {
+ int added = 0;
+ while(extensions){
+ if(strcmp(extensions->term, "X-ORIGIN") == 0){
+ charray_add(&extensions->values, slapi_ch_strdup(default_list[0]) );
+ extensions->value_count++;
+ added = 1;
+ extensions = head;
+ break;
+ }
+ extensions = extensions->next;
+ }
+ if(!added){
+ schemaext *newext = (schemaext *)slapi_ch_calloc(1, sizeof (schemaext));
+ newext->term = slapi_ch_strdup("X-ORIGIN");
+ for ( i = 0; default_list[i]; ++i ){
+ newext->value_count++;
+ charray_add(&newext->values, slapi_ch_strdup(default_list[i]) );
+ }
+ extensions = head;
+ while(extensions && extensions->next){
+ /* move to the end of the list */
+ extensions = extensions->next;
+ }
+ if(extensions == NULL){
+ extensions = newext;
+ } else {
+ extensions->next = newext;
+ }
+ }
+ }
+ slapi_ch_free_string(&input);
+
+ return extensions;
+}
+
/*
* Look for `keyword' within `*inputp' and return the flag_value if found
* (zero if returned if not found).
@@ -4318,6 +5226,7 @@ get_tagged_oid( const char *tag, const char **inputp,
return( oid );
}
+#endif
/*
* sprintf to `outp' the contents of `tag' followed by `oid' followed by a
@@ -4387,7 +5296,6 @@ strcat_oids( char *buf, char *prefix, char **oids, int schema_ds4x_compat )
}
}
-
/*
* Add to `buf' a string of the form:
*
@@ -4404,49 +5312,62 @@ strcat_oids( char *buf, char *prefix, char **oids, int schema_ds4x_compat )
* is calculated and returned. This is useful if you need to allocate
* space before calling this function will a buffer.
*
- * If qdlist is NULL or an empty array, `buf' is not touched and zero
- * is returned.
*/
static size_t
strcat_qdlist( char *buf, char *prefix, char **qdlist )
{
- int i;
- char *start, *p;
- size_t len = 0;
-
- if ( NULL != qdlist && NULL != qdlist[0] ) {
- if ( NULL == buf ) { /* calculate length only */
- len += strlen( prefix );
- if ( NULL != qdlist[1] ) {
- len += 4; /* surrounding spaces and '(' and ')' */
- }
- for ( i = 0; NULL != qdlist[i]; ++i ) {
- len += 3; /* leading space and quote marks */
- len += strlen(qdlist[i]);
- }
- ++len; /* trailing space */
+ int i;
+ char *start, *p;
+ size_t len = 0;
+
+ if ( NULL != qdlist && NULL != qdlist[0] ) {
+ if ( NULL == buf ) { /* calculate length only */
+ len += strlen( prefix );
+ if ( NULL != qdlist[1] ) {
+ len += 4; /* surrounding spaces and '(' and ')' */
+ }
+ for ( i = 0; NULL != qdlist[i]; ++i ) {
+ len += 3; /* leading space and quote marks */
+ len += strlen(qdlist[i]);
+ }
+ ++len; /* trailing space */
- } else {
- p = start = buf + strlen(buf); /* skip past existing content */
- if ( NULL == qdlist[1] ) { /* just one string */
- p += sprintf( p, "%s '%s' ", prefix, qdlist[0] );
- } else { /* a list of strings */
- p += sprintf( p, "%s (", prefix );
- for ( i = 0; qdlist[i] != NULL; ++i ) {
- p += sprintf( p, " '%s'", qdlist[i] );
- }
- *p++ = ' ';
- *p++ = ')';
- *p++ = ' ';
- *p = '\0';
- }
- len = p - start;
- }
- }
+ } else {
+ p = start = buf + strlen(buf); /* skip past existing content */
+ if ( NULL == qdlist[1] ) { /* just one string */
+ p += sprintf( p, "%s '%s' ", prefix, qdlist[0] );
+ } else { /* a list of strings */
+ p += sprintf( p, "%s (", prefix );
+ for ( i = 0; qdlist[i] != NULL; ++i ) {
+ p += sprintf( p, " '%s'", qdlist[i] );
+ }
+ *p++ = ' ';
+ *p++ = ')';
+ *p++ = ' ';
+ *p = '\0';
+ }
+ len = p - start;
+ }
+ }
- return( len );
+ return( len );
}
+/*
+ * Loop over the extensions calling strcat_qdlist for each one.
+ */
+static size_t
+strcat_extensions( char *buf, schemaext *extension )
+{
+ size_t len = 0;
+
+ while(extension){
+ len += strcat_qdlist(buf, extension->term, extension->values);
+ extension = extension->next;
+ }
+
+ return( len );
+}
/*
* Just like strlen() except that 0 is returned if `s' is NULL.
@@ -4480,83 +5401,23 @@ strcpy_count( char *dst, const char *src )
return( p - dst );
}
-
-/*
- * Look for an X-ORIGIN list in `schema_value' and return a
- * qdstrings array (or NULL if no list is present). *num_originsp is
- * set to a count of the number of origin strings returned.
- *
- * If no X-ORIGIN list is found and `default_list' is non-NULL, a copy
- * of default list is returned.
- */
-static char **
-parse_origin_list( const char *schema_value, int *num_originsp,
- char **default_list )
-{
- char *start, *end, *origin_tmp;
- char **origins = NULL;
-
- if (( start = PL_strstr ( schema_value, "X-ORIGIN ")) != NULL ) {
- start += 9;
- origin_tmp = slapi_ch_strdup( start );
- if ( *start == '(' ) {
- end = strchr( origin_tmp, ')' );
- } else {
- end = strchr( origin_tmp + 1, '\'' );
- }
- if (end) {
- *(end+1) = 0;
- }
- origins = parse_qdstrings( origin_tmp, num_originsp );
- slapi_ch_free( (void **)&origin_tmp );
- } else {
- origins = NULL;
- *num_originsp = 0;
- }
-
- if ( NULL == origins && NULL != default_list ) {
- int i;
-
- for ( i = 0; default_list[i] != NULL; ++i ) {
- ;
- }
- *num_originsp = i;
- origins = (char **)slapi_ch_malloc( (i+1) * sizeof(char *));
- for ( i = 0; default_list[i] != NULL; ++i ) {
- origins[i] = slapi_ch_strdup( default_list[i] );
- }
- origins[i] = NULL;
- }
-
-/* for debugging
-if ( origins == NULL || origins[0] == NULL ) {
- LDAPDebug( LDAP_DEBUG_ANY, "no origin (%s)\n", schema_value, 0, 0 );
-}
-*/
-
- return origins;
-}
-
-
-/*
- * Determine based on origin whether a schema element is standard or
- * user-defined. Algorithm: perform a case insensitive search for
- * "user defined". If found, return 1 (user defined); if not, return 0.
- */
static int
-element_is_user_defined( char * const *origins )
+extension_is_user_defined( schemaext *extensions )
{
- int i;
-
- if ( origins != NULL ) {
- for ( i = 0; origins[i] != NULL; ++i ) {
- if ( 0 == strcasecmp( schema_user_defined_origin[0], origins[i] )) {
- return 1;
- }
- }
- }
+ while(extensions){
+ if(strcasecmp(extensions->term, "X-ORIGIN") == 0 ){
+ int i = 0;
+ while(extensions->values && extensions->values[i]){
+ if(strcasecmp(schema_user_defined_origin[0], extensions->values[i]) == 0) {
+ return 1;
+ }
+ i++;
+ }
+ }
+ extensions = extensions->next;
+ }
- return 0;
+ return 0;
}
@@ -4981,3 +5842,4 @@ slapi_schema_get_superior_name(const char *ocname_or_oid)
oc_unlock();
return superior;
}
+
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index b0ac7b3..b84dd15 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -491,6 +491,14 @@ typedef struct oid_item {
struct oid_item *oi_next;
} oid_item_t;
+/* schema extension item: X-ORIGIN, X-CSN, etc */
+typedef struct schemaext {
+ char *term;
+ char **values;
+ int value_count;
+ struct schemaext *next;
+} schemaext;
+
/* attribute description (represents an attribute, but not the value) */
typedef struct asyntaxinfo {
char *asi_oid; /* OID */
@@ -501,7 +509,7 @@ typedef struct asyntaxinfo {
char *asi_mr_equality; /* equality matching rule */
char *asi_mr_ordering; /* ordering matching rule */
char *asi_mr_substring; /* substring matching rule */
- char **asi_origin; /* X-ORIGIN extension */
+ schemaext *asi_extensions; /* schema extensions (X-ORIGIN, X-?????, ...) */
struct slapdplugin *asi_plugin; /* syntax */
unsigned long asi_flags; /* SLAPI_ATTR_FLAG_... */
int asi_syntaxlength; /* length associated w/syntax */
@@ -676,25 +684,25 @@ extern struct attrs_in_extension attrs_in_extension[];
#define OC_FLAG_OBSOLETE 8
/* values for oc_kind */
-#define OC_KIND_STRUCTURAL 0
-#define OC_KIND_AUXILIARY 1
-#define OC_KIND_ABSTRACT 2
+#define OC_KIND_ABSTRACT 0
+#define OC_KIND_STRUCTURAL 1
+#define OC_KIND_AUXILIARY 2
/* XXXmcs: ../plugins/cos/cos_cache.c has its own copy of this definition! */
struct objclass {
- char *oc_name; /* NAME */
- char *oc_desc; /* DESC */
- char *oc_oid; /* object identifier */
- char *oc_superior; /* SUP -- XXXmcs: should be an array */
- PRUint8 oc_kind; /* ABSTRACT/STRUCTURAL/AUXILIARY */
- PRUint8 oc_flags; /* misc. flags, e.g., OBSOLETE */
- char **oc_required;
- char **oc_allowed;
- char **oc_orig_required; /* MUST */
- char **oc_orig_allowed; /* MAY */
- char **oc_origin; /* X-ORIGIN extension */
- struct objclass *oc_next;
+ char *oc_name; /* NAME */
+ char *oc_desc; /* DESC */
+ char *oc_oid; /* object identifier */
+ char *oc_superior; /* SUP -- XXXmcs: should be an array */
+ PRUint8 oc_kind; /* ABSTRACT/STRUCTURAL/AUXILIARY */
+ PRUint8 oc_flags; /* misc. flags, e.g., OBSOLETE */
+ char **oc_required;
+ char **oc_allowed;
+ char **oc_orig_required; /* MUST */
+ char **oc_orig_allowed; /* MAY */
+ schemaext *oc_extensions; /* schema extensions (X-ORIGIN, X-?????, ...) */
+ struct objclass *oc_next;
};
struct matchingRuleList {
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 05b9742..ffcc928 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5440,6 +5440,21 @@ char ** slapi_ch_array_dup( char **array );
void slapi_ch_array_add( char ***array, char *string );
/**
+ * Add a string to an array of strings
+ *
+ * \param array The array to add the string to
+ * \param string The string to add to the array
+ * \warning The \c string parameter is not copied. If you do not
+ * want to hand the memory used by \c string over to the
+ * array, you should duplicate it first by calling the
+ * slapi_ch_strdup() function.
+ * \warning If \c *a is \c NULL, a new array will be allocated.
+ * \see slapi_ch_array_free()
+ * \return the total number of elements in the array.
+ */
+int slapi_ch_array_add_ext(char ***array, char *string);
+
+/**
* Find a string in an array of strings
*
* \param array The array of strings
10 years, 5 months
Branch '389-ds-base-1.2.11' - 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 | 85 ++++++++------
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, 320 insertions(+), 136 deletions(-)
New commits:
commit 96535a6756b8a556897fb643a31421c7f5068166
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!!)
(cherry picked from commit d53e8221f77ac325123e3bb4f61cf6de67dce646)
diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c
index 27b20ec..995a62e 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)
@@ -916,7 +917,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 ) );
@@ -930,7 +931,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 5fbea24..b9f8688 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
@@ -53,7 +53,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 );
@@ -165,6 +165,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;
@@ -178,19 +179,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)
@@ -853,7 +849,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;
@@ -1341,13 +1337,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 );
@@ -1355,32 +1362,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,
@@ -1397,8 +1402,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;
}
@@ -1422,15 +1426,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;
}
@@ -1439,15 +1440,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;
@@ -1456,15 +1454,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;
@@ -1476,15 +1471,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;
}
@@ -1617,17 +1609,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)
@@ -1734,13 +1729,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 );
@@ -1755,12 +1757,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 2c09531..dcc42fa 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 b611f5c..4a5fd4d 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1365,14 +1365,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 13e05c1..01ebfef 100644
--- a/ldap/servers/slapd/operation.c
+++ b/ldap/servers/slapd/operation.c
@@ -201,10 +201,11 @@ operation_new(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;
}
return o;
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index fabe8a4..a96b950 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -245,7 +245,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;
@@ -271,7 +271,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 0b76b63..63d3e55 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1408,34 +1408,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 7e0faed..8fd8f51 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1339,6 +1339,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;
/*
@@ -1367,6 +1368,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);
}
}
10 years, 5 months
Branch '389-ds-base-1.3.0' - 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 | 85 ++++++++------
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, 320 insertions(+), 136 deletions(-)
New commits:
commit aad3acd58512fee83bf1d78f29c1e14b2c91b997
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!!)
(cherry picked from commit d53e8221f77ac325123e3bb4f61cf6de67dce646)
diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c
index 27b20ec..995a62e 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)
@@ -916,7 +917,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 ) );
@@ -930,7 +931,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 5f085f9..059a151 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
@@ -53,7 +53,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 );
@@ -165,6 +165,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;
@@ -181,19 +182,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)
@@ -859,7 +855,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;
@@ -1347,13 +1343,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 );
@@ -1361,32 +1368,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,
@@ -1403,8 +1408,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;
}
@@ -1428,15 +1432,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;
}
@@ -1445,15 +1446,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;
@@ -1462,15 +1460,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;
@@ -1482,15 +1477,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;
}
@@ -1623,17 +1615,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)
@@ -1740,13 +1735,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 );
@@ -1761,12 +1763,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 e3d2009..b59a195 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 13e05c1..01ebfef 100644
--- a/ldap/servers/slapd/operation.c
+++ b/ldap/servers/slapd/operation.c
@@ -201,10 +201,11 @@ operation_new(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;
}
return o;
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index cadf3b7..0149973 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -247,7 +247,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;
@@ -273,7 +273,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;
@@ -471,23 +470,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 );
@@ -642,7 +634,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 */
@@ -696,12 +688,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 */
@@ -722,14 +727,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
@@ -851,7 +860,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;
@@ -863,24 +876,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);
}
}
@@ -1009,9 +1029,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
@@ -1259,7 +1276,7 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result,
*pnentries = 0;
- while (!done)
+ while (!done)
{
Slapi_Entry *gerentry = NULL;
Slapi_Operation *operation;
@@ -1277,7 +1294,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 e872cec..901b380 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1419,34 +1419,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 7e27a78..43a213e 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1352,6 +1352,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;
/*
@@ -1380,6 +1381,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);
}
}
10 years, 5 months
Branch '389-ds-base-1.3.1' - 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 473fc77f98eafb1062683abee7b7b00c54ea4f13
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!!)
(cherry picked from commit d53e8221f77ac325123e3bb4f61cf6de67dce646)
diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c
index 9dc9cbf..489e85e 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)
@@ -916,7 +917,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 ) );
@@ -930,7 +931,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 66677d2..4dd051d 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 743b9ce..981fc01 100644
--- a/ldap/servers/slapd/operation.c
+++ b/ldap/servers/slapd/operation.c
@@ -201,10 +201,11 @@ operation_new(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;
}
return o;
}
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 a34136f..2508d70 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1433,34 +1433,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 c8381da..384ebfb 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);
}
}
10 years, 5 months