mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-03-01 14:15:49 +08:00
use Paged Results when talking to targets (in response to ITS#6664)
This commit is contained in:
parent
6460f957af
commit
342980d116
@ -311,6 +311,18 @@ underlying libldap, with rebinding eventually performed if the
|
||||
If set before any target specification, it affects all targets, unless
|
||||
overridden by any per-target directive.
|
||||
|
||||
.TP
|
||||
.B client\-pr {accept-unsolicited|DISABLE|<size>}
|
||||
This feature allows to use RFC 2696 Paged Results control when performing
|
||||
search operations with a specific target.
|
||||
When set to a numeric value, Paged Results control is always
|
||||
used with \fIsize\fP as the page size.
|
||||
When set to \fIaccept-unsolicited\fP, unsolicited Paged Results
|
||||
control responses are accepted and honored.
|
||||
By default, Paged Results control is not used and responses are not accepted.
|
||||
If set before any target specification, it affects all targets, unless
|
||||
overridden by any per-target directive.
|
||||
|
||||
.TP
|
||||
.B default\-target [<target>]
|
||||
The "default\-target" directive can also be used during target specification.
|
||||
|
@ -27,6 +27,10 @@
|
||||
#ifndef SLAPD_META_H
|
||||
#define SLAPD_META_H
|
||||
|
||||
#ifdef LDAP_DEVEL
|
||||
#define SLAPD_META_CLIENT_PR 1
|
||||
#endif /* LDAP_DEVEL */
|
||||
|
||||
#include "proto-meta.h"
|
||||
|
||||
/* String rewrite library */
|
||||
@ -335,6 +339,19 @@ typedef struct metatarget_t {
|
||||
slap_mask_t mt_rep_flags;
|
||||
|
||||
int mt_version;
|
||||
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
/*
|
||||
* client-side paged results:
|
||||
* -1: accept unsolicited paged results responses
|
||||
* 0: off
|
||||
* >0: always request paged results with size == mt_ps
|
||||
*/
|
||||
#define META_CLIENT_PR_DISABLE (0)
|
||||
#define META_CLIENT_PR_ACCEPT_UNSOLICITED (-1)
|
||||
ber_int_t mt_ps;
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
time_t mt_network_timeout;
|
||||
struct timeval mt_bind_timeout;
|
||||
#define META_BIND_TIMEOUT LDAP_BACK_RESULT_UTIMEOUT
|
||||
@ -411,6 +428,12 @@ typedef struct metainfo_t {
|
||||
#define META_BACK_QUARANTINE(mi) LDAP_BACK_ISSET( (mi), LDAP_BACK_F_QUARANTINE )
|
||||
|
||||
int mi_version;
|
||||
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
ber_int_t mi_ps;
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
|
||||
time_t mi_network_timeout;
|
||||
time_t mi_conn_ttl;
|
||||
time_t mi_idle_timeout;
|
||||
|
@ -168,6 +168,9 @@ meta_back_db_config(
|
||||
}
|
||||
mt->mt_flags = mi->mi_flags;
|
||||
mt->mt_version = mi->mi_version;
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
mt->mt_ps = mi->mi_ps;
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
mt->mt_network_timeout = mi->mi_network_timeout;
|
||||
mt->mt_bind_timeout = mi->mi_bind_timeout;
|
||||
for ( c = 0; c < SLAP_OP_LAST; c++ ) {
|
||||
@ -1532,6 +1535,33 @@ idassert-authzFrom "dn:<rootdn>"
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
} else if ( strcasecmp( argv[ 0 ], "client-pr" ) == 0 ) {
|
||||
int *ps = mi->mi_ntargets ?
|
||||
&mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_ps
|
||||
: &mi->mi_ps;
|
||||
|
||||
if ( argc != 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: \"client-pr {accept-unsolicited|disable|<size>}\" needs 1 argument.\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( strcasecmp( argv[ 1 ], "accept-unsolicited" ) == 0 ) {
|
||||
*ps = META_CLIENT_PR_ACCEPT_UNSOLICITED;
|
||||
|
||||
} else if ( strcasecmp( argv[ 1 ], "disable" ) == 0 ) {
|
||||
*ps = META_CLIENT_PR_DISABLE;
|
||||
|
||||
} else if ( lutil_atoi( ps, argv[ 1 ] ) || *ps < -1 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: \"client-pr {accept-unsolicited|disable|<size>}\" invalid arg \"%s\".\n",
|
||||
fname, lineno, argv[ 1 ] );
|
||||
return( 1 );
|
||||
}
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
/* anything else */
|
||||
} else {
|
||||
return SLAP_CONF_UNKNOWN;
|
||||
|
@ -446,7 +446,9 @@ meta_back_search_start(
|
||||
dncookie *dc,
|
||||
metaconn_t **mcp,
|
||||
int candidate,
|
||||
SlapReply *candidates )
|
||||
SlapReply *candidates,
|
||||
struct berval *prcookie,
|
||||
ber_int_t prsize )
|
||||
{
|
||||
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
|
||||
metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||
@ -461,6 +463,9 @@ meta_back_search_start(
|
||||
struct timeval tv, *tvp = NULL;
|
||||
int nretries = 1;
|
||||
LDAPControl **ctrls = NULL;
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
LDAPControl **save_ctrls = NULL;
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
/* this should not happen; just in case... */
|
||||
if ( msc->msc_ld == NULL ) {
|
||||
@ -614,6 +619,85 @@ meta_back_search_start(
|
||||
tvp = &tv;
|
||||
}
|
||||
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
save_ctrls = op->o_ctrls;
|
||||
{
|
||||
LDAPControl *pr_c = NULL, **next_c = NULL;
|
||||
int i = 0, nc = 0;
|
||||
|
||||
if ( save_ctrls ) {
|
||||
for ( ; save_ctrls[i] != NULL; i++ );
|
||||
nc = i;
|
||||
pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, save_ctrls, &next_c );
|
||||
}
|
||||
|
||||
if ( pr_c != NULL ) nc--;
|
||||
if ( mt->mt_ps > 0 || prcookie != NULL ) nc++;
|
||||
|
||||
if ( mt->mt_ps > 0 || prcookie != NULL || pr_c != NULL ) {
|
||||
int src = 0, dst = 0;
|
||||
BerElementBuffer berbuf;
|
||||
BerElement *ber = (BerElement *)&berbuf;
|
||||
struct berval val = BER_BVNULL;
|
||||
ber_len_t len;
|
||||
|
||||
len = sizeof( LDAPControl * )*( nc + 1 ) + sizeof( LDAPControl );
|
||||
|
||||
if ( mt->mt_ps > 0 || prcookie != NULL ) {
|
||||
struct berval nullcookie = BER_BVNULL;
|
||||
ber_tag_t tag;
|
||||
|
||||
if ( prsize == 0 && mt->mt_ps > 0 ) prsize = mt->mt_ps;
|
||||
if ( prcookie == NULL ) prcookie = &nullcookie;
|
||||
|
||||
ber_init2( ber, NULL, LBER_USE_DER );
|
||||
tag = ber_printf( ber, "{iO}", prsize, prcookie );
|
||||
if ( tag == LBER_ERROR ) {
|
||||
/* error */
|
||||
(void) ber_free_buf( ber );
|
||||
goto done_pr;
|
||||
}
|
||||
|
||||
tag = ber_flatten2( ber, &val, 0 );
|
||||
if ( tag == LBER_ERROR ) {
|
||||
/* error */
|
||||
(void) ber_free_buf( ber );
|
||||
goto done_pr;
|
||||
}
|
||||
|
||||
len += val.bv_len + 1;
|
||||
}
|
||||
|
||||
op->o_ctrls = op->o_tmpalloc( len, op->o_tmpmemctx );
|
||||
if ( save_ctrls ) {
|
||||
for ( ; save_ctrls[ src ] != NULL; src++ ) {
|
||||
if ( save_ctrls[ src ] != pr_c ) {
|
||||
op->o_ctrls[ dst ] = save_ctrls[ src ];
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( mt->mt_ps > 0 || prcookie != NULL ) {
|
||||
op->o_ctrls[ dst ] = (LDAPControl *)&op->o_ctrls[ nc + 1 ];
|
||||
|
||||
op->o_ctrls[ dst ]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
|
||||
op->o_ctrls[ dst ]->ldctl_iscritical = 1;
|
||||
|
||||
op->o_ctrls[ dst ]->ldctl_value.bv_val = (char *)&op->o_ctrls[ dst ][ 1 ];
|
||||
AC_MEMCPY( op->o_ctrls[ dst ]->ldctl_value.bv_val, val.bv_val, val.bv_len + 1 );
|
||||
op->o_ctrls[ dst ]->ldctl_value.bv_len = val.bv_len;
|
||||
dst++;
|
||||
|
||||
(void)ber_free_buf( ber );
|
||||
}
|
||||
|
||||
op->o_ctrls[ dst ] = NULL;
|
||||
}
|
||||
done_pr:;
|
||||
}
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
retry:;
|
||||
ctrls = op->o_ctrls;
|
||||
if ( meta_back_controls_add( op, rs, *mcp, candidate, &ctrls )
|
||||
@ -660,6 +744,12 @@ retry:;
|
||||
|
||||
done:;
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
if ( save_ctrls != op->o_ctrls ) {
|
||||
op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
|
||||
op->o_ctrls = save_ctrls;
|
||||
}
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
if ( mapped_attrs ) {
|
||||
ber_memfree_x( mapped_attrs, op->o_tmpmemctx );
|
||||
@ -742,6 +832,7 @@ getconn:;
|
||||
candidates[ i ].sr_text = NULL;
|
||||
candidates[ i ].sr_ref = NULL;
|
||||
candidates[ i ].sr_ctrls = NULL;
|
||||
candidates[ i ].sr_nentries = 0;
|
||||
|
||||
/* get largest timeout among candidates */
|
||||
if ( mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ]
|
||||
@ -758,7 +849,7 @@ getconn:;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) )
|
||||
{
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
@ -975,7 +1066,7 @@ getconn:;
|
||||
|
||||
case META_SEARCH_CANDIDATE:
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) )
|
||||
{
|
||||
case META_SEARCH_CANDIDATE:
|
||||
assert( candidates[ i ].sr_msgid >= 0 );
|
||||
@ -1062,7 +1153,7 @@ really_bad:;
|
||||
|
||||
if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) )
|
||||
{
|
||||
/* means that failed but onerr == continue */
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
@ -1142,6 +1233,9 @@ really_bad:;
|
||||
candidates[ i ].sr_type = REP_RESULT;
|
||||
}
|
||||
|
||||
/* count entries returned by target */
|
||||
candidates[ i ].sr_nentries++;
|
||||
|
||||
is_ok++;
|
||||
|
||||
e = ldap_first_entry( msc->msc_ld, msg );
|
||||
@ -1285,6 +1379,7 @@ really_bad:;
|
||||
} else if ( rc == LDAP_RES_SEARCH_RESULT ) {
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
char **references = NULL;
|
||||
LDAPControl **ctrls = NULL;
|
||||
|
||||
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
||||
/* don't retry any more... */
|
||||
@ -1308,7 +1403,7 @@ really_bad:;
|
||||
(char **)&candidates[ i ].sr_matched,
|
||||
(char **)&candidates[ i ].sr_text,
|
||||
&references,
|
||||
NULL /* &candidates[ i ].sr_ctrls (unused) */ ,
|
||||
&ctrls /* &candidates[ i ].sr_ctrls (unused) */ ,
|
||||
0 );
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
candidates[ i ].sr_err = rs->sr_err;
|
||||
@ -1403,7 +1498,7 @@ really_bad:;
|
||||
|
||||
/* cleanup */
|
||||
ber_memvfree( (void **)references );
|
||||
|
||||
|
||||
sres = slap_map_api2result( rs );
|
||||
|
||||
if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
|
||||
@ -1436,6 +1531,93 @@ really_bad:;
|
||||
break;
|
||||
|
||||
case LDAP_SUCCESS:
|
||||
if ( ctrls != NULL && ctrls[0] != NULL ) {
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
LDAPControl *pr_c, **next_c;
|
||||
|
||||
pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, &next_c );
|
||||
if ( pr_c != NULL ) {
|
||||
BerElementBuffer berbuf;
|
||||
BerElement *ber = (BerElement *)&berbuf;
|
||||
ber_tag_t tag;
|
||||
ber_int_t prsize;
|
||||
struct berval prcookie;
|
||||
|
||||
/* unsolicited, do not accept */
|
||||
if ( mi->mi_targets[i]->mt_ps == 0 ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
goto err_pr;
|
||||
}
|
||||
|
||||
ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER );
|
||||
|
||||
tag = ber_scanf( ber, "{im}", &prsize, &prcookie );
|
||||
if ( tag == LBER_ERROR ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
goto err_pr;
|
||||
}
|
||||
|
||||
/* more pages? new search request */
|
||||
if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) {
|
||||
if ( mi->mi_targets[i]->mt_ps > 0 ) {
|
||||
/* ignore size if specified */
|
||||
prsize = 0;
|
||||
|
||||
} else if ( prsize == 0 ) {
|
||||
/* guess the page size from the entries returned so far */
|
||||
prsize = candidates[ i ].sr_nentries;
|
||||
}
|
||||
|
||||
candidates[ i ].sr_nentries = 0;
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
candidates[ i ].sr_type = REP_INTERMEDIATE;
|
||||
|
||||
assert( candidates[ i ].sr_matched == NULL );
|
||||
assert( candidates[ i ].sr_text == NULL );
|
||||
assert( candidates[ i ].sr_ref == NULL );
|
||||
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, &prcookie, prsize ) )
|
||||
{
|
||||
case META_SEARCH_CANDIDATE:
|
||||
assert( candidates[ i ].sr_msgid >= 0 );
|
||||
ldap_controls_free( ctrls );
|
||||
goto free_message;
|
||||
|
||||
case META_SEARCH_ERR:
|
||||
err_pr:;
|
||||
candidates[ i ].sr_err = rs->sr_err;
|
||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
||||
savepriv = op->o_private;
|
||||
op->o_private = (void *)i;
|
||||
send_ldap_result( op, rs );
|
||||
op->o_private = savepriv;
|
||||
ldap_controls_free( ctrls );
|
||||
goto finish;
|
||||
}
|
||||
/* fallthru */
|
||||
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
/* means that meta_back_search_start()
|
||||
* failed but onerr == continue */
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
assert( ncandidates > 0 );
|
||||
--ncandidates;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* impossible */
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
ldap_controls_free( ctrls );
|
||||
}
|
||||
/* fallthru */
|
||||
|
||||
case LDAP_REFERRAL:
|
||||
is_ok++;
|
||||
break;
|
||||
@ -1499,7 +1681,7 @@ really_bad:;
|
||||
retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, msg );
|
||||
if ( retcode == META_SEARCH_CANDIDATE ) {
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates );
|
||||
retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 );
|
||||
}
|
||||
|
||||
switch ( retcode ) {
|
||||
|
Loading…
Reference in New Issue
Block a user