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
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",
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 */
if ( op->o_abandon ) {
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",
} 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",
} 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 ) {
+ 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 (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",
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",