ID_BLOCK *candidates;
ID id, cursor;
Entry *e;
- BVarray v2refs = NULL;
+ BerVarray v2refs = NULL;
Entry *matched = NULL;
struct berval realbase = { 0, NULL };
int nentries = 0;
struct slap_limits_set *limit = NULL;
int isroot = 0;
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ int filter_hasSubordinates = 0;
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
- "ldbm_back_search: enter\n" ));
+ LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_search: enter\n", 0, 0, 0 );
#else
Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0);
#endif
+ /* grab giant lock for reading */
+ ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock);
if ( nbase->bv_len == 0 ) {
/* DIT root special case */
if ( e == NULL ) {
struct berval matched_dn = { 0, NULL };
- BVarray refs = NULL;
+ BerVarray refs = NULL;
if ( matched != NULL ) {
- BVarray erefs;
+ BerVarray erefs;
ber_dupbv( &matched_dn, &matched->e_name );
erefs = is_entry_referral( matched )
refs = referral_rewrite( erefs, &matched_dn,
base, scope );
- bvarray_free( erefs );
+ ber_bvarray_free( erefs );
}
} else {
NULL, base, scope );
}
+ ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
+
send_ldap_result( conn, op, err, matched_dn.bv_val,
text, refs, NULL );
- bvarray_free( refs );
+ ber_bvarray_free( refs );
ber_memfree( matched_dn.bv_val );
return 1;
}
if (!manageDSAit && is_entry_referral( e ) ) {
/* entry is a referral, don't allow add */
struct berval matched_dn;
- BVarray erefs;
- BVarray refs;
+ BerVarray erefs;
+ BerVarray refs;
ber_dupbv( &matched_dn, &e->e_name );
erefs = get_entry_referrals( be, conn, op, e );
refs = NULL;
cache_return_entry_r( &li->li_cache, e );
+ ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
+ LDAP_LOG( BACK_LDBM, INFO,
"ldbm_search: entry (%s) is a referral.\n",
- e->e_dn ));
+ e->e_dn, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: entry is referral\n",
refs = referral_rewrite( erefs, &matched_dn,
base, scope );
- bvarray_free( erefs );
+ ber_bvarray_free( erefs );
}
if( refs ) {
send_ldap_result( conn, op, LDAP_REFERRAL,
matched_dn.bv_val, NULL, refs, NULL );
- bvarray_free( refs );
+ ber_bvarray_free( refs );
} else {
send_ldap_result( conn, op, LDAP_OTHER,
if ( candidates == NULL ) {
/* no candidates */
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
- "ldbm_search: no candidates\n" ));
+ LDAP_LOG( BACK_LDBM, INFO,
+ "ldbm_search: no candidates\n" , 0, 0, 0);
#else
Debug( LDAP_DEBUG_TRACE, "ldbm_search: no candidates\n",
0, 0, 0 );
/* if candidates exceed to-be-checked entries, abort */
if ( !isroot && limit->lms_s_unchecked != -1 ) {
if ( ID_BLOCK_NIDS( candidates ) > (unsigned) limit->lms_s_unchecked ) {
- send_search_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+ send_search_result( conn, op, LDAP_ADMINLIMIT_EXCEEDED,
NULL, NULL, NULL, NULL, 0 );
rc = 0;
goto done;
/* if requested limit higher than hard limit, abort */
} else if ( tlimit > limit->lms_t_hard ) {
/* no hard limit means use soft instead */
- if ( limit->lms_t_hard == 0 ) {
+ if ( limit->lms_t_hard == 0 && tlimit > limit->lms_t_soft ) {
tlimit = limit->lms_t_soft;
/* positive hard limit means abort */
/* if requested limit higher than hard limit, abort */
} else if ( slimit > limit->lms_s_hard ) {
/* no hard limit means use soft instead */
- if ( limit->lms_s_hard == 0 ) {
+ if ( limit->lms_s_hard == 0 && slimit > limit->lms_s_soft ) {
slimit = limit->lms_s_soft;
/* positive hard limit means abort */
/* compute it anyway; root does not use it */
stoptime = op->o_time + tlimit;
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ /*
+ * is hasSubordinates used in the filter ?
+ * FIXME: we may compute this directly when parsing the filter
+ */
+ filter_hasSubordinates = filter_has_subordinates( filter );
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
for ( id = idl_firstid( candidates, &cursor ); id != NOID;
id = idl_nextid( candidates, &cursor ) )
{
int scopeok = 0;
+ int result = 0;
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ Attribute *hasSubordinates = NULL;
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/* check for abandon */
- ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
-
if ( op->o_abandon ) {
- ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
rc = 0;
goto done;
}
- ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
-
/* check time limit */
if ( tlimit != -1 && slap_get_time() > stoptime ) {
send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
if ( e == NULL ) {
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
- "ldbm_search: candidate %ld not found.\n", id ));
+ LDAP_LOG( BACK_LDBM, INFO,
+ "ldbm_search: candidate %ld not found.\n", id, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: candidate %ld not found\n",
/* need to skip alias which deref into scope */
if( scope & LDAP_SCOPE_ONELEVEL ) {
- char *pdn = dn_parent( NULL, e->e_ndn );
- if ( pdn != NULL ) {
- if( strcmp( pdn, realbase.bv_val ) ) {
- goto loop_continue;
- }
+ struct berval pdn;
+ dnParent( &e->e_nname, &pdn );
+ if ( ber_bvcmp( &pdn, &realbase ) ) {
+ goto loop_continue;
}
} else if ( dnIsSuffix( &e->e_nname, &realbase ) ) {
/* alias is within scope */
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
- "ldbm_search: alias \"%s\" in subtree\n", e->e_dn ));
+ LDAP_LOG( BACK_LDBM, DETAIL1,
+ "ldbm_search: alias \"%s\" in subtree\n", e->e_dn, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: alias \"%s\" in subtree\n",
if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
is_entry_referral( e ) )
{
- char *dn;
+ struct berval dn;
/* check scope */
if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
- if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
- scopeok = (dn == realbase.bv_val)
- ? 1
- : (strcmp( dn, realbase.bv_val ) ? 0 : 1 );
+ if ( !be_issuffix( be, &e->e_nname ) ) {
+ dnParent( &e->e_nname, &dn );
+ scopeok = dn_match( &dn, &realbase );
} else {
scopeok = (realbase.bv_len == 0);
}
}
if( scopeok ) {
- BVarray erefs = get_entry_referrals(
+ BerVarray erefs = get_entry_referrals(
be, conn, op, e );
- BVarray refs = referral_rewrite( erefs,
+ BerVarray refs = referral_rewrite( erefs,
&e->e_name, NULL,
scope == LDAP_SCOPE_SUBTREE
? LDAP_SCOPE_SUBTREE
send_search_reference( be, conn, op,
e, refs, NULL, &v2refs );
- bvarray_free( refs );
+ ber_bvarray_free( refs );
} else {
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL2,
+ LDAP_LOG( BACK_LDBM, DETAIL2,
"ldbm_search: candidate referral %ld scope not okay\n",
- id ));
+ id, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: candidate referral %ld scope not okay\n",
goto loop_continue;
}
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ /*
+ * if hasSubordinates is used in the filter,
+ * append it to the entry's attributes
+ */
+ if ( filter_hasSubordinates ) {
+ int hs;
+
+ hs = has_children( be, e );
+ hasSubordinates = slap_operational_hasSubordinate( hs );
+ if ( hasSubordinates == NULL ) {
+ goto loop_continue;
+ }
+
+ hasSubordinates->a_next = e->e_attrs;
+ e->e_attrs = hasSubordinates;
+ }
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
/* if it matches the filter and scope, send it */
- if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
- char *dn;
+ result = test_filter( be, conn, op, e, filter );
+
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ if ( hasSubordinates ) {
+ /*
+ * FIXME: this is fairly inefficient, because
+ * if hasSubordinates is among the required
+ * attrs, it will be added again later;
+ * maybe we should leave it and check
+ * check later if it's already present,
+ * if required
+ */
+ e->e_attrs = e->e_attrs->a_next;
+ attr_free( hasSubordinates );
+ }
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
+ if ( result == LDAP_COMPARE_TRUE ) {
+ struct berval dn;
/* check scope */
if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
- if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
- scopeok = (dn == realbase.bv_val)
- ? 1
- : (strcmp( dn, realbase.bv_val ) ? 0 : 1 );
+ if ( !be_issuffix( be, &e->e_nname ) ) {
+ dnParent( &e->e_nname, &dn );
+ scopeok = dn_match( &dn, &realbase );
} else {
scopeok = (realbase.bv_len == 0);
}
}
if (e) {
- int result = send_search_entry(be, conn, op,
+ result = send_search_entry(be, conn, op,
e, attrs, attrsonly, NULL);
switch (result) {
}
} else {
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL2,
- "ldbm_search: candidate entry %ld scope not okay\n", id ));
+ LDAP_LOG( BACK_LDBM, DETAIL2,
+ "ldbm_search: candidate entry %ld scope not okay\n",
+ id, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: candidate entry %ld scope not okay\n",
} else {
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL2,
- "ldbm_search: candidate entry %ld does not match filter\n", id ));
+ LDAP_LOG( BACK_LDBM, DETAIL2,
+ "ldbm_search: candidate entry %ld does not match filter\n",
+ id, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: candidate entry %ld does not match filter\n",
rc = 0;
done:
+ ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
+
if( candidates != NULL )
idl_free( candidates );
- if( v2refs ) bvarray_free( v2refs );
+ if( v2refs ) ber_bvarray_free( v2refs );
if( realbase.bv_val ) free( realbase.bv_val );
return rc;
ID_BLOCK *idl;
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
- "base_candidate: base (%s)\n", e->e_dn ));
+ LDAP_LOG( BACK_LDBM, ENTRY, "base_candidate: base (%s)\n", e->e_dn, 0, 0 );
#else
Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
e->e_dn, 0, 0);
struct berval bv_alias = { sizeof("ALIAS")-1, "ALIAS" };
#ifdef NEW_LOGGING
- LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
+ LDAP_LOG( BACK_LDBM, DETAIL1,
"search_candidates: base (%s) scope %d deref %d\n",
- e->e_ndn, scope, deref ));
+ e->e_ndn, scope, deref );
#else
Debug(LDAP_DEBUG_TRACE,
"search_candidates: base=\"%s\" s=%d d=%d\n",