mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-02-09 22:04:12 -05:00
ITS#5191 do all pagedresult control parsing in the frontend, don't
re-parse in the backend. Keep track of pagedresult controls and state in backglue.
This commit is contained in:
parent
e580bd799a
commit
8bc46e741a
5 changed files with 84 additions and 125 deletions
|
|
@ -1123,12 +1123,7 @@ static int search_candidates(
|
|||
static int
|
||||
parse_paged_cookie( Operation *op, SlapReply *rs )
|
||||
{
|
||||
LDAPControl **c;
|
||||
int rc = LDAP_SUCCESS;
|
||||
ber_tag_t tag;
|
||||
ber_int_t size;
|
||||
BerElement *ber;
|
||||
struct berval cookie = BER_BVNULL;
|
||||
PagedResultsState *ps = op->o_pagedresults_state;
|
||||
|
||||
/* this function must be invoked only if the pagedResults
|
||||
|
|
@ -1136,53 +1131,17 @@ parse_paged_cookie( Operation *op, SlapReply *rs )
|
|||
* by the frontend */
|
||||
assert( get_pagedresults( op ) > SLAP_CONTROL_IGNORED );
|
||||
|
||||
/* look for the appropriate ctrl structure */
|
||||
for ( c = op->o_ctrls; c[0] != NULL; c++ ) {
|
||||
if ( strcmp( c[0]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS ) == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( c[0] == NULL ) {
|
||||
rs->sr_text = "missing pagedResults control";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Tested by frontend */
|
||||
assert( c[0]->ldctl_value.bv_len > 0 );
|
||||
|
||||
/* Parse the control value
|
||||
* realSearchControlValue ::= SEQUENCE {
|
||||
* size INTEGER (0..maxInt),
|
||||
* -- requested page size from client
|
||||
* -- result set size estimate from server
|
||||
* cookie OCTET STRING
|
||||
* }
|
||||
*/
|
||||
ber = ber_init( &c[0]->ldctl_value );
|
||||
if ( ber == NULL ) {
|
||||
rs->sr_text = "internal error";
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
tag = ber_scanf( ber, "{im}", &size, &cookie );
|
||||
|
||||
/* Tested by frontend */
|
||||
assert( tag != LBER_ERROR );
|
||||
assert( size >= 0 );
|
||||
|
||||
/* cookie decoding/checks deferred to backend... */
|
||||
if ( cookie.bv_len ) {
|
||||
if ( ps->ps_cookieval.bv_len ) {
|
||||
PagedResultsCookie reqcookie;
|
||||
if( cookie.bv_len != sizeof( reqcookie ) ) {
|
||||
if( ps->ps_cookieval.bv_len != sizeof( reqcookie ) ) {
|
||||
/* bad cookie */
|
||||
rs->sr_text = "paged results cookie is invalid";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie ));
|
||||
AC_MEMCPY( &reqcookie, ps->ps_cookieval.bv_val, sizeof( reqcookie ));
|
||||
|
||||
if ( reqcookie > ps->ps_cookie ) {
|
||||
/* bad cookie */
|
||||
|
|
@ -1198,22 +1157,11 @@ parse_paged_cookie( Operation *op, SlapReply *rs )
|
|||
|
||||
} else {
|
||||
/* Initial request. Initialize state. */
|
||||
#if 0
|
||||
if ( op->o_conn->c_pagedresults_state.ps_cookie != 0 ) {
|
||||
/* There's another pagedResults control on the
|
||||
* same connection; reject new pagedResults controls
|
||||
* (allowed by RFC2696) */
|
||||
rs->sr_text = "paged results cookie unavailable; try later";
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
ps->ps_cookie = 0;
|
||||
ps->ps_count = 0;
|
||||
}
|
||||
|
||||
done:;
|
||||
(void)ber_free( ber, 1 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2668,12 +2668,7 @@ backsql_entry_release(
|
|||
static int
|
||||
parse_paged_cookie( Operation *op, SlapReply *rs )
|
||||
{
|
||||
LDAPControl **c;
|
||||
int rc = LDAP_SUCCESS;
|
||||
ber_tag_t tag;
|
||||
ber_int_t size;
|
||||
BerElement *ber;
|
||||
struct berval cookie = BER_BVNULL;
|
||||
PagedResultsState *ps = op->o_pagedresults_state;
|
||||
|
||||
/* this function must be invoked only if the pagedResults
|
||||
|
|
@ -2681,53 +2676,17 @@ parse_paged_cookie( Operation *op, SlapReply *rs )
|
|||
* by the frontend */
|
||||
assert( get_pagedresults( op ) > SLAP_CONTROL_IGNORED );
|
||||
|
||||
/* look for the appropriate ctrl structure */
|
||||
for ( c = op->o_ctrls; c[0] != NULL; c++ ) {
|
||||
if ( strcmp( c[0]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS ) == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( c[0] == NULL ) {
|
||||
rs->sr_text = "missing pagedResults control";
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Tested by frontend */
|
||||
assert( c[0]->ldctl_value.bv_len > 0 );
|
||||
|
||||
/* Parse the control value
|
||||
* realSearchControlValue ::= SEQUENCE {
|
||||
* size INTEGER (0..maxInt),
|
||||
* -- requested page size from client
|
||||
* -- result set size estimate from server
|
||||
* cookie OCTET STRING
|
||||
* }
|
||||
*/
|
||||
ber = ber_init( &c[0]->ldctl_value );
|
||||
if ( ber == NULL ) {
|
||||
rs->sr_text = "internal error";
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
tag = ber_scanf( ber, "{im}", &size, &cookie );
|
||||
|
||||
/* Tested by frontend */
|
||||
assert( tag != LBER_ERROR );
|
||||
assert( size >= 0 );
|
||||
|
||||
/* cookie decoding/checks deferred to backend... */
|
||||
if ( cookie.bv_len ) {
|
||||
if ( ps->ps_cookieval.bv_len ) {
|
||||
PagedResultsCookie reqcookie;
|
||||
if( cookie.bv_len != sizeof( reqcookie ) ) {
|
||||
if( ps->ps_cookieval.bv_len != sizeof( reqcookie ) ) {
|
||||
/* bad cookie */
|
||||
rs->sr_text = "paged results cookie is invalid";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie ));
|
||||
AC_MEMCPY( &reqcookie, ps->ps_cookieval.bv_val, sizeof( reqcookie ));
|
||||
|
||||
if ( reqcookie > ps->ps_cookie ) {
|
||||
/* bad cookie */
|
||||
|
|
@ -2743,22 +2702,11 @@ parse_paged_cookie( Operation *op, SlapReply *rs )
|
|||
|
||||
} else {
|
||||
/* Initial request. Initialize state. */
|
||||
#if 0
|
||||
if ( op->o_conn->c_pagedresults_state.ps_cookie != 0 ) {
|
||||
/* There's another pagedResults control on the
|
||||
* same connection; reject new pagedResults controls
|
||||
* (allowed by RFC2696) */
|
||||
rs->sr_text = "paged results cookie unavailable; try later";
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
ps->ps_cookie = 0;
|
||||
ps->ps_count = 0;
|
||||
}
|
||||
|
||||
done:;
|
||||
(void)ber_free( ber, 1 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,6 +161,31 @@ glue_op_response ( Operation *op, SlapReply *rs )
|
|||
if (!j) {
|
||||
newctrls = ch_malloc((i+1)*sizeof(LDAPControl *));
|
||||
} else {
|
||||
/* Forget old pagedResults response if we're sending
|
||||
* a new one now
|
||||
*/
|
||||
if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
|
||||
int newpage = 0;
|
||||
for ( k=0; k<i; k++ ) {
|
||||
if ( !strcmp(rs->sr_ctrls[k]->ldctl_oid,
|
||||
LDAP_CONTROL_PAGEDRESULTS )) {
|
||||
newpage = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( newpage ) {
|
||||
for ( k=0; k<j; k++ ) {
|
||||
if ( !strcmp(gs->ctrls[k]->ldctl_oid,
|
||||
LDAP_CONTROL_PAGEDRESULTS )) {
|
||||
gs->ctrls[k]->ldctl_oid = NULL;
|
||||
ldap_control_free( gs->ctrls[k] );
|
||||
gs->ctrls[k] = gs->ctrls[--j];
|
||||
gs->ctrls[j] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newctrls = ch_realloc(gs->ctrls,
|
||||
(j+i+1)*sizeof(LDAPControl *));
|
||||
}
|
||||
|
|
@ -321,7 +346,7 @@ glue_op_search ( Operation *op, SlapReply *rs )
|
|||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
glueinfo *gi = (glueinfo *)on->on_bi.bi_private;
|
||||
BackendDB *b0 = op->o_bd;
|
||||
BackendDB *b1 = NULL, *btmp;
|
||||
BackendDB *btmp;
|
||||
BackendInfo *bi0 = op->o_bd->bd_info;
|
||||
int i;
|
||||
long stoptime = 0, starttime;
|
||||
|
|
@ -360,7 +385,6 @@ glue_op_search ( Operation *op, SlapReply *rs )
|
|||
tlimit0 = op->ors_tlimit;
|
||||
dn = op->o_req_dn;
|
||||
ndn = op->o_req_ndn;
|
||||
b1 = op->o_bd;
|
||||
|
||||
/*
|
||||
* Execute in reverse order, most specific first
|
||||
|
|
@ -375,9 +399,16 @@ glue_op_search ( Operation *op, SlapReply *rs )
|
|||
}
|
||||
if (!btmp || !btmp->be_search)
|
||||
continue;
|
||||
if (!dnIsSuffix(&btmp->be_nsuffix[0], &b1->be_nsuffix[0]))
|
||||
if (!dnIsSuffix(&btmp->be_nsuffix[0], &b0->be_nsuffix[0]))
|
||||
continue;
|
||||
if (get_no_subordinate_glue(op) && btmp != b1)
|
||||
if (get_no_subordinate_glue(op) && btmp != b0)
|
||||
continue;
|
||||
/* If we remembered which backend we were on before,
|
||||
* skip down to it now
|
||||
*/
|
||||
if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED &&
|
||||
op->o_conn->c_pagedresults_state.ps_be &&
|
||||
op->o_conn->c_pagedresults_state.ps_be != btmp )
|
||||
continue;
|
||||
|
||||
if (tlimit0 != SLAP_NO_LIMIT) {
|
||||
|
|
@ -449,7 +480,41 @@ glue_op_search ( Operation *op, SlapReply *rs )
|
|||
case LDAP_X_CANNOT_CHAIN:
|
||||
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|
||||
goto end_of_loop;
|
||||
|
||||
|
||||
case LDAP_SUCCESS:
|
||||
if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
|
||||
PagedResultsState *ps = op->o_pagedresults_state;
|
||||
|
||||
/* Assume this backend can be forgotten now */
|
||||
op->o_conn->c_pagedresults_state.ps_be = NULL;
|
||||
|
||||
/* If we have a full page, exit the loop. We may
|
||||
* need to remember this backend so we can continue
|
||||
* from here on a subsequent request.
|
||||
*/
|
||||
if ( rs->sr_nentries >= ps->ps_size ) {
|
||||
/* Don't bother to remember the first backend.
|
||||
* Only remember the last one if there's more state left.
|
||||
*/
|
||||
if ( op->o_bd != b0 &&
|
||||
( op->o_conn->c_pagedresults_state.ps_cookie ||
|
||||
op->o_bd != gi->gi_n[0].gn_be ))
|
||||
op->o_conn->c_pagedresults_state.ps_be = op->o_bd;
|
||||
goto end_of_loop;
|
||||
}
|
||||
|
||||
/* This backend has run out of entries, but more responses
|
||||
* can fit in the page. Fake a reset of the state so the
|
||||
* next backend will start up properly. Only back-[bh]db
|
||||
* and back-sql look at this state info.
|
||||
*/
|
||||
if ( ps->ps_cookieval.bv_len == sizeof( PagedResultsCookie )) {
|
||||
ps->ps_cookie = 0;
|
||||
memset( ps->ps_cookieval.bv_val, 0,
|
||||
sizeof( PagedResultsCookie ));
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1050,12 +1050,13 @@ static int parsePagedResults (
|
|||
SlapReply *rs,
|
||||
LDAPControl *ctrl )
|
||||
{
|
||||
BerElementBuffer berbuf;
|
||||
BerElement *ber = (BerElement *)&berbuf;
|
||||
struct berval cookie;
|
||||
PagedResultsState *ps;
|
||||
int rc = LDAP_SUCCESS;
|
||||
ber_tag_t tag;
|
||||
ber_int_t size;
|
||||
BerElement *ber;
|
||||
struct berval cookie = BER_BVNULL;
|
||||
PagedResultsState *ps;
|
||||
|
||||
if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
|
||||
rs->sr_text = "paged results control specified multiple times";
|
||||
|
|
@ -1080,11 +1081,7 @@ static int parsePagedResults (
|
|||
* cookie OCTET STRING
|
||||
* }
|
||||
*/
|
||||
ber = ber_init( &ctrl->ldctl_value );
|
||||
if ( ber == NULL ) {
|
||||
rs->sr_text = "internal error";
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
ber_init2( ber, &ctrl->ldctl_value, LBER_USE_DER );
|
||||
|
||||
tag = ber_scanf( ber, "{im}", &size, &cookie );
|
||||
|
||||
|
|
@ -1103,6 +1100,7 @@ static int parsePagedResults (
|
|||
ps = op->o_tmpalloc( sizeof(PagedResultsState), op->o_tmpmemctx );
|
||||
*ps = op->o_conn->c_pagedresults_state;
|
||||
ps->ps_size = size;
|
||||
ps->ps_cookieval = cookie;
|
||||
op->o_pagedresults_state = ps;
|
||||
|
||||
/* NOTE: according to RFC 2696 3.:
|
||||
|
|
@ -1126,7 +1124,6 @@ static int parsePagedResults (
|
|||
}
|
||||
|
||||
done:;
|
||||
(void)ber_free( ber, 1 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2330,8 +2330,9 @@ typedef unsigned long PagedResultsCookie;
|
|||
typedef struct PagedResultsState {
|
||||
Backend *ps_be;
|
||||
ber_int_t ps_size;
|
||||
PagedResultsCookie ps_cookie;
|
||||
int ps_count;
|
||||
PagedResultsCookie ps_cookie;
|
||||
struct berval ps_cookieval;
|
||||
} PagedResultsState;
|
||||
|
||||
struct slap_csn_entry {
|
||||
|
|
|
|||
Loading…
Reference in a new issue