mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-04-12 15:10:31 +08:00
ITS#9929: more performance tweaks
For simple (non-nested) member compares, avoid unnecessary fetches of dyngroups that can't match the filter. cache filter/entry instance info across multiple dyn entries to avoid refetching each filter entry for each dyngruop test.
This commit is contained in:
parent
ebb4e03cc6
commit
d7cd8d80fc
@ -99,6 +99,47 @@ ad_infilter( AttributeDescription *ad, Filter *f )
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct dynlist_filterinst_t {
|
||||
AttributeAssertion *df_a;
|
||||
Entry *df_e;
|
||||
} dynlist_filterinst_t;
|
||||
|
||||
/* Record occurrences of ad in filter. Ignore in negated filters. */
|
||||
static void
|
||||
dynlist_filter_instances( Operation *op, AttributeDescription *ad, Filter *f, int not, int *dfn, dynlist_filterinst_t **dfp )
|
||||
{
|
||||
if ( !f )
|
||||
return;
|
||||
|
||||
switch( f->f_choice & SLAPD_FILTER_MASK ) {
|
||||
case LDAP_FILTER_EQUALITY:
|
||||
if ( !not && f->f_av_desc == ad ) {
|
||||
dynlist_filterinst_t *df = *dfp;
|
||||
int n = *dfn;
|
||||
df = op->o_tmprealloc( df, (n + 1) * sizeof(dynlist_filterinst_t), op->o_tmpmemctx );
|
||||
df[n].df_a = f->f_ava;
|
||||
df[n++].df_e = NULL;
|
||||
*dfp = df;
|
||||
*dfn = n;
|
||||
}
|
||||
break;
|
||||
case SLAPD_FILTER_COMPUTED:
|
||||
case LDAP_FILTER_PRESENT:
|
||||
case LDAP_FILTER_GE:
|
||||
case LDAP_FILTER_LE:
|
||||
case LDAP_FILTER_APPROX:
|
||||
case LDAP_FILTER_SUBSTRINGS:
|
||||
case LDAP_FILTER_EXT:
|
||||
break;
|
||||
case LDAP_FILTER_NOT: not ^= 1;
|
||||
/* FALLTHRU */
|
||||
case LDAP_FILTER_AND:
|
||||
case LDAP_FILTER_OR:
|
||||
for ( f = f->f_list; f; f = f->f_next )
|
||||
dynlist_filter_instances( op, ad, f, not, dfn, dfp );
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dynlist_make_filter( Operation *op, Entry *e, dynlist_info_t *dli, const char *url, struct berval *oldf, struct berval *newf )
|
||||
{
|
||||
@ -330,6 +371,7 @@ done:;
|
||||
typedef struct dynlist_name_t {
|
||||
struct berval dy_name;
|
||||
dynlist_info_t *dy_dli;
|
||||
dynlist_map_t *dy_dlm;
|
||||
AttributeDescription *dy_staticmember;
|
||||
int dy_seen;
|
||||
int dy_numuris;
|
||||
@ -949,8 +991,8 @@ done:;
|
||||
|
||||
/* check for dynlist objectClass; done if not found */
|
||||
dli = (dynlist_info_t *)dlg->dlg_dli;
|
||||
while ( dli != NULL && !is_entry_objectclass_or_sub( e, dli->dli_oc ) &&
|
||||
!dynlist_check_scope( op, e, dli )) {
|
||||
while ( dli != NULL && ( !is_entry_objectclass_or_sub( e, dli->dli_oc ) ||
|
||||
!dynlist_check_scope( op, e, dli ))) {
|
||||
dli = dli->dli_next;
|
||||
}
|
||||
if ( dli == NULL ) {
|
||||
@ -1091,6 +1133,7 @@ dynlist_search1resp( Operation *op, SlapReply *rs )
|
||||
dyn = ch_calloc(1, sizeof(dynlist_name_t)+rs->sr_entry->e_nname.bv_len + 1 + len);
|
||||
dyn->dy_name.bv_val = ((char *)(dyn+1)) + len;
|
||||
dyn->dy_dli = ds->ds_dli;
|
||||
dyn->dy_dlm = ds->ds_dlm;
|
||||
dyn->dy_name.bv_len = rs->sr_entry->e_nname.bv_len;
|
||||
if ( a ) {
|
||||
Filter *f;
|
||||
@ -1450,23 +1493,12 @@ dynlist_search_cleanup( Operation *op, SlapReply *rs )
|
||||
}
|
||||
|
||||
static int
|
||||
dynlist_test_membership(Operation *op, dynlist_name_t *dyn, Entry *e)
|
||||
dynlist_test_dynmember(Operation *op, dynlist_name_t *dyn, Entry *e)
|
||||
{
|
||||
LDAPURLDesc *ludp;
|
||||
struct berval nbase, bv;
|
||||
int i, rc = LDAP_COMPARE_FALSE;
|
||||
if ( dyn->dy_staticmember ) {
|
||||
Entry *grp;
|
||||
if ( overlay_entry_get_ov( op, &dyn->dy_name, NULL, NULL, 0, &grp, (slap_overinst *)op->o_bd->bd_info ) == LDAP_SUCCESS && grp ) {
|
||||
Attribute *a = attr_find( grp->e_attrs, dyn->dy_staticmember );
|
||||
if ( a ) {
|
||||
i = value_find_ex( dyn->dy_staticmember, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
|
||||
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, a->a_nvals, &e->e_nname, op->o_tmpmemctx );
|
||||
}
|
||||
overlay_entry_release_ov( op, grp, 0, (slap_overinst *)op->o_bd->bd_info );
|
||||
return i == LDAP_SUCCESS ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<dyn->dy_numuris; i++) {
|
||||
ludp = dyn->dy_uris[i];
|
||||
nbase.bv_val = ludp->lud_dn;
|
||||
@ -1503,6 +1535,28 @@ dynlist_test_membership(Operation *op, dynlist_name_t *dyn, Entry *e)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
dynlist_test_membership(Operation *op, dynlist_name_t *dyn, Entry *e)
|
||||
{
|
||||
if ( dyn->dy_staticmember ) {
|
||||
Entry *grp;
|
||||
if ( overlay_entry_get_ov( op, &dyn->dy_name, NULL, NULL, 0, &grp, (slap_overinst *)op->o_bd->bd_info ) == LDAP_SUCCESS && grp ) {
|
||||
Attribute *a = attr_find( grp->e_attrs, dyn->dy_staticmember );
|
||||
int rc;
|
||||
if ( a ) {
|
||||
rc = value_find_ex( dyn->dy_staticmember, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
|
||||
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, a->a_nvals, &e->e_nname, op->o_tmpmemctx );
|
||||
rc = ( rc == LDAP_SUCCESS ) ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
|
||||
} else {
|
||||
rc = LDAP_COMPARE_FALSE;
|
||||
}
|
||||
overlay_entry_release_ov( op, grp, 0, (slap_overinst *)op->o_bd->bd_info );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return dynlist_test_dynmember( op, dyn, e );
|
||||
}
|
||||
|
||||
static void
|
||||
dynlist_add_memberOf(Operation *op, SlapReply *rs, dynlist_search_t *ds)
|
||||
{
|
||||
@ -1549,6 +1603,22 @@ dynlist_add_memberOf(Operation *op, SlapReply *rs, dynlist_search_t *ds)
|
||||
}
|
||||
}
|
||||
|
||||
/* See if a DN-valued filter attribute belongs to a dyngroup */
|
||||
static int
|
||||
dynmember( dynlist_name_t *dyn, Filter *f, int ndf, dynlist_filterinst_t *df )
|
||||
{
|
||||
int i;
|
||||
int ret = 1; /* default to accepting everything */
|
||||
|
||||
for ( i = 0; i < ndf; i++ ) {
|
||||
if ( df[i].df_e ) {
|
||||
ret = dynlist_test_dynmember( NULL, dyn, df[i].df_e ) == LDAP_COMPARE_TRUE;
|
||||
if ( ret )
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* process the search responses */
|
||||
static int
|
||||
@ -1588,9 +1658,13 @@ dynlist_search2resp( Operation *op, SlapReply *rs )
|
||||
}
|
||||
return rc;
|
||||
} else if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS ) {
|
||||
TAvlnode *ptr;
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
TAvlnode *ptr, *skip = NULL;
|
||||
SlapReply r = *rs;
|
||||
dynlist_map_t *dlm = NULL;
|
||||
Filter *f = ds->ds_origfilter ? ds->ds_origfilter : op->ors_filter;
|
||||
dynlist_filterinst_t *df = NULL;
|
||||
int ndf = 0;
|
||||
|
||||
if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED )
|
||||
return SLAP_CB_CONTINUE;
|
||||
@ -1598,29 +1672,79 @@ dynlist_search2resp( Operation *op, SlapReply *rs )
|
||||
/* Check for any unexpanded dynamic group entries that weren't picked up
|
||||
* by the original search filter.
|
||||
*/
|
||||
for ( ptr = ldap_tavl_end( ds->ds_names, TAVL_DIR_LEFT ); ptr;
|
||||
ptr = ldap_tavl_next( ptr, TAVL_DIR_RIGHT )) {
|
||||
ptr = ldap_tavl_end( ds->ds_names, TAVL_DIR_LEFT );
|
||||
while ( ptr ) {
|
||||
dyn = ptr->avl_data;
|
||||
if ( dyn->dy_seen )
|
||||
continue;
|
||||
goto next;
|
||||
dyn->dy_seen = 1;
|
||||
if ( !dnIsSuffixScope( &dyn->dy_name, &op->o_req_ndn, op->ors_scope ))
|
||||
continue;
|
||||
if ( overlay_entry_get_ov( op, &dyn->dy_name, NULL, NULL, 0, &r.sr_entry, (slap_overinst *)op->o_bd->bd_info ) != LDAP_SUCCESS ||
|
||||
r.sr_entry == NULL )
|
||||
continue;
|
||||
r.sr_flags = REP_ENTRY_MUSTRELEASE;
|
||||
if ( dynlist_check_scope( op, r.sr_entry, dyn->dy_dli )) {
|
||||
dynlist_prepare_entry( op, &r, dyn->dy_dli, dyn );
|
||||
if ( test_filter( op, r.sr_entry, f ) == LDAP_COMPARE_TRUE ) {
|
||||
r.sr_attrs = op->ors_attrs;
|
||||
rs->sr_err = send_search_entry( op, &r );
|
||||
if ( rs->sr_err != LDAP_SUCCESS )
|
||||
break;
|
||||
r.sr_entry = NULL;
|
||||
goto next;
|
||||
/* can only pre-check if this is a dyngroup, otherwise just build the entry */
|
||||
if ( dyn->dy_dli->dli_dlm && !dyn->dy_dli->dli_dlm->dlm_next &&
|
||||
!dyn->dy_dlm->dlm_mapped_ad ) {
|
||||
if ( !dlm ) {
|
||||
AttributeDescription *ad;
|
||||
int i;
|
||||
dlm = dyn->dy_dlm;
|
||||
ad = dlm->dlm_member_ad;
|
||||
/* can only pre-check DN-valued attrs */
|
||||
if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) {
|
||||
/* find any instances of this ad in the filter */
|
||||
dynlist_filter_instances( op, ad, f, 0, &ndf, &df );
|
||||
for ( i = 0; i < ndf; i++ ) {
|
||||
overlay_entry_get_ov( op, &df[i].df_a->aa_value, NULL, NULL, 0, &df[i].df_e, on );
|
||||
}
|
||||
}
|
||||
} else if ( dlm != dyn->dy_dlm ) { /* if a different map, do it later */
|
||||
if ( !skip )
|
||||
skip = ptr;
|
||||
dyn->dy_seen = 0; /* we'll want to process it next time thru */
|
||||
goto next;
|
||||
}
|
||||
/* only pre-check for non-nested */
|
||||
if ( !dyn->dy_sups && !dyn->dy_subs && ndf && !dynmember( dyn, f, ndf, df ))
|
||||
goto next;
|
||||
}
|
||||
if ( overlay_entry_get_ov( op, &dyn->dy_name, NULL, NULL, 0, &r.sr_entry, on ) != LDAP_SUCCESS ||
|
||||
r.sr_entry == NULL )
|
||||
goto next;
|
||||
r.sr_flags = REP_ENTRY_MUSTRELEASE;
|
||||
dynlist_prepare_entry( op, &r, dyn->dy_dli, dyn );
|
||||
if ( test_filter( op, r.sr_entry, f ) == LDAP_COMPARE_TRUE ) {
|
||||
r.sr_attrs = op->ors_attrs;
|
||||
rs->sr_err = send_search_entry( op, &r );
|
||||
if ( rs->sr_err != LDAP_SUCCESS )
|
||||
break;
|
||||
r.sr_entry = NULL;
|
||||
}
|
||||
if ( r.sr_entry )
|
||||
rs_flush_entry( op, &r, NULL );
|
||||
next:
|
||||
ptr = ldap_tavl_next( ptr, TAVL_DIR_RIGHT );
|
||||
if ( !ptr ) {
|
||||
int i;
|
||||
for ( i = 0; i<ndf; i++ ) {
|
||||
if ( df[i].df_e )
|
||||
overlay_entry_release_ov( op, df[i].df_e, 0, on );
|
||||
}
|
||||
op->o_tmpfree( df, op->o_tmpmemctx );
|
||||
ndf = 0;
|
||||
if ( skip ) { /* go back for dyns we skipped */
|
||||
ptr = skip;
|
||||
skip = NULL;
|
||||
dlm = NULL;
|
||||
df = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ndf ) {
|
||||
int i;
|
||||
for ( i = 0; i<ndf; i++ ) {
|
||||
if ( df[i].df_e )
|
||||
overlay_entry_release_ov( op, df[i].df_e, 0, on );
|
||||
}
|
||||
op->o_tmpfree( df, op->o_tmpmemctx );
|
||||
}
|
||||
rs->sr_nentries = r.sr_nentries;
|
||||
}
|
||||
@ -1828,10 +1952,13 @@ dynlist_search( Operation *op, SlapReply *rs )
|
||||
ds->ds_dlm = dlm;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
{
|
||||
AttributeDescription *ad = dlm->dlm_mapped_ad ? dlm->dlm_mapped_ad : dlm->dlm_member_ad;
|
||||
if ( ad_infilter( ad, op->ors_filter )) {
|
||||
ds->ds_want = tmpwant = WANT_MEMBER;
|
||||
tmpwant |= WANT_MEMBER;
|
||||
ds->ds_want = tmpwant;
|
||||
ds->ds_dlm = dlm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -365,6 +365,65 @@ facsimileTelephoneNumber: +1 313 555 7762
|
||||
telephoneNumber: +1 313 555 4177
|
||||
memberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
|
||||
|
||||
# Testing filtered member functionality...
|
||||
dn: cn=All Staff,ou=Groups,dc=example,dc=com
|
||||
member: cn=Manager,dc=example,dc=com
|
||||
member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
|
||||
ple,dc=com
|
||||
member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
|
||||
=com
|
||||
member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
|
||||
mple,dc=com
|
||||
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
|
||||
e,dc=com
|
||||
owner: cn=Manager,dc=example,dc=com
|
||||
cn: All Staff
|
||||
description: Everyone in the sample data
|
||||
objectClass: groupofnames
|
||||
|
||||
dn: cn=Alumni Assoc Staff,ou=Groups,dc=example,dc=com
|
||||
member: cn=Manager,dc=example,dc=com
|
||||
member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
owner: cn=Manager,dc=example,dc=com
|
||||
description: All Alumni Assoc Staff
|
||||
cn: Alumni Assoc Staff
|
||||
objectClass: groupofnames
|
||||
|
||||
dn: cn=Dynamic List of Members,ou=Dynamic Lists,dc=example,dc=com
|
||||
objectClass: groupOfURLs
|
||||
objectClass: dgIdentityAux
|
||||
cn: Dynamic List of Members
|
||||
memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
|
||||
dgIdentity: cn=Bjorn Jensen,ou=Information Technology DivisioN,ou=People,dc=ex
|
||||
ample,dc=com
|
||||
dgAuthz: {0}dn:cn=Barbara Jensen,ou=Information Technology DivisioN,ou=People,
|
||||
dc=example,dc=com
|
||||
member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
|
||||
ple,dc=com
|
||||
member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
|
||||
e,dc=com
|
||||
member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
|
||||
mple,dc=com
|
||||
member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
|
||||
=com
|
||||
member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
|
||||
# Testing static group memberOf functionality...
|
||||
dn: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
objectClass: OpenLDAPperson
|
||||
|
@ -763,7 +763,20 @@ echo "Testing filtered memberOf functionality..."
|
||||
echo "# Testing filtered memberOf functionality..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -b "ou=People,$BASEDN" -H $URI1 \
|
||||
-D "$BABSDN" -w bjensen \
|
||||
'(&(memberOf=cn=Dynamic List of Members,ou=Dynamic Lists,dc=example,dc=com)(cn=Mark Elliot))' '*' 'memberOf' \
|
||||
"(&(memberOf=cn=Dynamic List of Members,ou=Dynamic Lists,$BASEDN)(cn=Mark Elliot))" '*' 'memberOf' \
|
||||
>> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Testing filtered member functionality..."
|
||||
echo "# Testing filtered member functionality..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
|
||||
-D "$BABSDN" -w bjensen \
|
||||
"(member=cn=Jane Doe,ou=Alumni Association,ou=People,$BASEDN)" \
|
||||
>> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
|
Loading…
x
Reference in New Issue
Block a user