X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=servers%2Fslapd%2Fback-bdb%2Fsearch.c;h=1f28e9fda2a161c31d8a2cf6d9420dc6094c91cf;hb=65c24bdb1f95d706c25e52f54b78e0be2ebedf36;hp=e47ce1f86b60ced155cf875f6c7ebcc9bfcc7ae6;hpb=273052b57356716b1baa11743ff6b7107e72907b;p=openldap diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index e47ce1f86b..1f28e9fda2 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2004 The OpenLDAP Foundation. + * Copyright 2000-2009 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,11 +28,10 @@ static int base_candidate( ID *ids ); static int search_candidates( - Operation *stackop, /* op with the current threadctx/slab cache */ - Operation *sop, /* search op */ + Operation *op, SlapReply *rs, Entry *e, - u_int32_t locker, + DB_TXN *txn, ID *ids, ID *scopes ); @@ -44,9 +43,6 @@ static void send_paged_response( ID *lastid, int tentries ); -static int bdb_pfid_cmp( const void *v_id1, const void *v_id2 ); -static ID* bdb_id_dup( Operation *op, ID *id ); - /* Dereference aliases for a single alias entry. Return the final * dereferenced entry on success, NULL on any failure. */ @@ -55,7 +51,7 @@ static Entry * deref_base ( SlapReply *rs, Entry *e, Entry **matched, - u_int32_t locker, + DB_TXN *txn, DB_LOCK *lock, ID *tmp, ID *visited ) @@ -68,12 +64,17 @@ static Entry * deref_base ( rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM; rs->sr_text = "maximum deref depth exceeded"; - while (BDB_IDL_N(tmp) < op->o_bd->be_max_deref_depth) { + for (;;) { /* Remember the last entry we looked at, so we can * report broken links */ *matched = e; + if (BDB_IDL_N(tmp) >= op->o_bd->be_max_deref_depth) { + e = NULL; + break; + } + /* If this is part of a subtree or onelevel search, * have we seen this ID before? If so, quit. */ @@ -100,8 +101,10 @@ static Entry * deref_base ( break; } - rs->sr_err = bdb_dn2entry( op, NULL, &ndn, &ei, - 0, locker, &lockr ); + rs->sr_err = bdb_dn2entry( op, txn, &ndn, &ei, + 0, &lockr ); + if ( rs->sr_err == DB_LOCK_DEADLOCK ) + return NULL; if ( ei ) { e = ei->bei_e; @@ -118,8 +121,7 @@ static Entry * deref_base ( /* Free the previous entry, continue to work with the * one we just retrieved. */ - bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, - *matched, lock); + bdb_cache_return_entry_r( bdb, *matched, lock); *lock = lockr; /* We found a regular entry. Return this to the caller. The @@ -143,7 +145,7 @@ static int search_aliases( Operation *op, SlapReply *rs, Entry *e, - u_int32_t locker, + DB_TXN *txn, ID *ids, ID *scopes, ID *stack ) @@ -154,7 +156,7 @@ static int search_aliases( Entry *matched, *a; EntryInfo *ei; struct berval bv_alias = BER_BVC( "alias" ); - AttributeAssertion aa_alias; + AttributeAssertion aa_alias = ATTRIBUTEASSERTION_INIT; Filter af; DB_LOCK locka, lockr; int first = 1; @@ -180,7 +182,7 @@ static int search_aliases( /* Find all aliases in database */ BDB_IDL_ZERO( aliases ); - rs->sr_err = bdb_filter_candidates( op, &af, aliases, + rs->sr_err = bdb_filter_candidates( op, txn, &af, aliases, curscop, visited ); if (rs->sr_err != LDAP_SUCCESS) { return rs->sr_err; @@ -202,13 +204,17 @@ static int search_aliases( * to the cumulative list of candidates. */ BDB_IDL_CPY( curscop, aliases ); - rs->sr_err = bdb_dn2idl( op, e, subscop, + rs->sr_err = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), subscop, subscop2+BDB_IDL_DB_SIZE ); + if (first) { first = 0; } else { - bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &locka); + bdb_cache_return_entry_r (bdb, e, &locka); } + if ( rs->sr_err == DB_LOCK_DEADLOCK ) + return rs->sr_err; + BDB_IDL_CPY(subscop2, subscop); rs->sr_err = bdb_idl_intersection(curscop, subscop); bdb_idl_union( ids, subscop2 ); @@ -220,11 +226,13 @@ static int search_aliases( { ei = NULL; retry1: - rs->sr_err = bdb_cache_find_id(op, NULL, - ida, &ei, 0, locker, &lockr ); + rs->sr_err = bdb_cache_find_id(op, txn, + ida, &ei, 0, &lockr ); if (rs->sr_err != LDAP_SUCCESS) { - if ( rs->sr_err == DB_LOCK_DEADLOCK || - rs->sr_err == DB_LOCK_NOTGRANTED ) goto retry1; + if ( rs->sr_err == DB_LOCK_DEADLOCK ) + return rs->sr_err; + if ( rs->sr_err == DB_LOCK_NOTGRANTED ) + goto retry1; continue; } a = ei->bei_e; @@ -233,14 +241,13 @@ retry1: * turned into a range that spans IDs indiscriminately */ if (!is_entry_alias(a)) { - bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, - a, &lockr); + bdb_cache_return_entry_r (bdb, a, &lockr); continue; } /* Actually dereference the alias */ BDB_IDL_ZERO(tmp); - a = deref_base( op, rs, a, &matched, locker, &lockr, + a = deref_base( op, rs, a, &matched, txn, &lockr, tmp, visited ); if (a) { /* If the target was not already in our current candidates, @@ -252,15 +259,15 @@ retry1: bdb_idl_insert(newsubs, a->e_id); bdb_idl_insert(scopes, a->e_id); } - bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, - a, &lockr); + bdb_cache_return_entry_r( bdb, a, &lockr); + } else if ( rs->sr_err == DB_LOCK_DEADLOCK ) { + return rs->sr_err; } else if (matched) { /* Alias could not be dereferenced, or it deref'd to * an ID we've already seen. Ignore it. */ - bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, - matched, &lockr ); + bdb_cache_return_entry_r( bdb, matched, &lockr ); rs->sr_text = NULL; } } @@ -289,11 +296,12 @@ nextido: */ ei = NULL; sameido: - rs->sr_err = bdb_cache_find_id(op, NULL, ido, &ei, - 0, locker, &locka ); + rs->sr_err = bdb_cache_find_id(op, txn, ido, &ei, + 0, &locka ); if ( rs->sr_err != LDAP_SUCCESS ) { - if ( rs->sr_err == DB_LOCK_DEADLOCK || - rs->sr_err == DB_LOCK_NOTGRANTED ) + if ( rs->sr_err == DB_LOCK_DEADLOCK ) + return rs->sr_err; + if ( rs->sr_err == DB_LOCK_NOTGRANTED ) goto sameido; goto nextido; } @@ -302,505 +310,68 @@ sameido: return rs->sr_err; } -#ifdef BDB_PSEARCH - -#define is_sync_protocol(op) \ - ((op)->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST) - -#define IS_BDB_REPLACE(type) (( type == LDAP_PSEARCH_BY_DELETE ) || \ - ( type == LDAP_PSEARCH_BY_SCOPEOUT )) -#define IS_PSEARCH (op != sop) -#define IS_POST_SEARCH ( op->ors_post_search_id != NOID ) - -static Operation * -bdb_drop_psearch( Operation *op, ber_int_t msgid ) -{ - Operation *ps_list; - struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; - - LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - if ( ps_list->o_connid == op->o_connid ) { - if ( ps_list->o_msgid == msgid ) { - ps_list->o_abandon = 1; - LDAP_LIST_REMOVE( ps_list, o_ps_link ); - ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); - LDAP_STAILQ_REMOVE( &op->o_conn->c_ops, ps_list, - slap_op, o_next ); - LDAP_STAILQ_NEXT( ps_list, o_next ) = NULL; - op->o_conn->c_n_ops_executing--; - op->o_conn->c_n_ops_completed++; - ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); - return ps_list; - } - } - } - - return NULL; -} - -int -bdb_abandon( Operation *op, SlapReply *rs ) -{ - Operation *ps; - void *saved_tmpmemctx; - - ps = bdb_drop_psearch( op, op->oq_abandon.rs_msgid ); - if ( ps ) { - saved_tmpmemctx = ps->o_tmpmemctx; - - if (!BER_BVISNULL(&ps->o_req_dn)) { - slap_sl_free(ps->o_req_dn.bv_val, ps->o_tmpmemctx ); - } - if (!BER_BVISNULL(&ps->o_req_ndn)) { - slap_sl_free(ps->o_req_ndn.bv_val, ps->o_tmpmemctx ); - } - if (!BER_BVISNULL(&ps->ors_filterstr)) { - ps->o_tmpfree(ps->ors_filterstr.bv_val, ps->o_tmpmemctx); - } - if (ps->ors_filter != NULL) { - filter_free_x(ps, ps->ors_filter); - } - if (ps->ors_attrs != NULL) { - ps->o_tmpfree(ps->ors_attrs, ps->o_tmpmemctx); - } - - slap_op_free ( ps ); - - if ( saved_tmpmemctx ) { - slap_sl_mem_destroy( NULL, saved_tmpmemctx ); - } - - return LDAP_SUCCESS; - } - return LDAP_UNAVAILABLE; -} - -int -bdb_cancel( Operation *op, SlapReply *rs ) -{ - Operation *ps; - void *saved_tmpmemctx; - - ps = bdb_drop_psearch( op, op->oq_cancel.rs_msgid ); - if ( ps ) { - saved_tmpmemctx = ps->o_tmpmemctx; - - rs->sr_err = LDAP_CANCELLED; - send_ldap_result( ps, rs ); - - if (!BER_BVISNULL(&ps->o_req_dn)) { - slap_sl_free(ps->o_req_dn.bv_val, ps->o_tmpmemctx ); - } - if (!BER_BVISNULL(&ps->o_req_ndn)) { - slap_sl_free(ps->o_req_ndn.bv_val, ps->o_tmpmemctx ); - } - if (!BER_BVISNULL(&ps->ors_filterstr)) { - ps->o_tmpfree(ps->ors_filterstr.bv_val, ps->o_tmpmemctx); - } - if (ps->ors_filter != NULL) { - filter_free_x(ps, ps->ors_filter); - } - if (ps->ors_attrs != NULL) { - ps->o_tmpfree(ps->ors_attrs, ps->o_tmpmemctx); - } - - slap_op_free ( ps ); - - if ( saved_tmpmemctx ) { - slap_sl_mem_destroy( NULL, saved_tmpmemctx ); - } - - return LDAP_SUCCESS; - } - return LDAP_UNAVAILABLE; -} - -int bdb_search( Operation *op, SlapReply *rs ) -{ - int rc; - struct pc_entry *pce = NULL; - struct pc_entry *tmp_pce = NULL; - Entry ps_e = {0}; - Attribute *a; - - ps_e.e_private = NULL; - ldap_pvt_thread_mutex_init( &op->o_pcmutex ); - LDAP_TAILQ_INIT( &op->o_ps_pre_candidates ); - LDAP_TAILQ_INIT( &op->o_ps_post_candidates ); - - op->ors_post_search_id = NOID; - rc = bdb_do_search( op, rs, op, NULL, 0 ); - - ldap_pvt_thread_mutex_lock( &op->o_pcmutex ); - pce = LDAP_TAILQ_FIRST( &op->o_ps_post_candidates ); - ldap_pvt_thread_mutex_unlock( &op->o_pcmutex ); - - while ( rc == LDAP_SUCCESS && pce && - op->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST ) { - - ps_e.e_id = op->ors_post_search_id = pce->pc_id; - if ( op->o_sync_csn.bv_val ) { - ch_free( op->o_sync_csn.bv_val ); - op->o_sync_csn.bv_val = NULL; - } - ber_dupbv( &op->o_sync_csn, &pce->pc_csn ); - ber_dupbv( &ps_e.e_name, &pce->pc_ename ); - ber_dupbv( &ps_e.e_nname, &pce->pc_enname ); - a = ch_calloc( 1, sizeof( Attribute )); - a->a_desc = slap_schema.si_ad_entryUUID; - a->a_vals = ch_calloc( 2, sizeof( struct berval )); - ber_dupbv( &a->a_vals[0], &pce->pc_entryUUID ); - a->a_nvals = a->a_vals; - a->a_next = NULL; - ps_e.e_attrs = a; - - rc = bdb_do_search( op, rs, op, &ps_e, 0 ); - - tmp_pce = pce; - ldap_pvt_thread_mutex_lock( &op->o_pcmutex ); - pce = LDAP_TAILQ_NEXT( pce, pc_link ); - LDAP_TAILQ_REMOVE( &op->o_ps_post_candidates, tmp_pce, pc_link ); - ldap_pvt_thread_mutex_unlock( &op->o_pcmutex ); - - ch_free( tmp_pce->pc_csn.bv_val ); - ch_free( tmp_pce->pc_entryUUID.bv_val ); - ch_free( tmp_pce->pc_ename.bv_val ); - ch_free( tmp_pce->pc_enname.bv_val ); - ch_free( tmp_pce ); - entry_clean( &ps_e ); - } - return rc; -} - -#define BDB_PSEARCH_MAX_WAIT 3 -int bdb_psearch( Operation *op, SlapReply *rs, Operation *sop, - Entry *ps_e, int ps_type ) -{ - int rc; - struct pc_entry *pce = NULL; - struct pc_entry *p = NULL; - int num_retries = 0; - - op->ors_post_search_id = NOID; - - switch (ps_type) { - case LDAP_PSEARCH_BY_PREMODIFY: - case LDAP_PSEARCH_BY_PREDELETE: - - if ( !op->o_ps_send_wait ) { - if ( sop->o_refresh_in_progress ) { - pce = (struct pc_entry *) ch_calloc( - 1, sizeof( struct pc_entry )); - pce->pc_id = ps_e->e_id; - ldap_pvt_thread_mutex_lock( &sop->o_pcmutex ); - if ( LDAP_TAILQ_EMPTY( &sop->o_ps_pre_candidates )) { - LDAP_TAILQ_INSERT_HEAD( - &sop->o_ps_pre_candidates, pce, pc_link ); - } else { - LDAP_TAILQ_FOREACH( p, - &sop->o_ps_pre_candidates, pc_link ) { - if ( p->pc_id > pce->pc_id ) - break; - } - - if ( p ) { - LDAP_TAILQ_INSERT_BEFORE( p, pce, pc_link ); - } else { - LDAP_TAILQ_INSERT_TAIL( - &sop->o_ps_pre_candidates, - pce, pc_link ); - } - } - ldap_pvt_thread_mutex_unlock( &sop->o_pcmutex ); - } else { - rc = bdb_do_search( op, rs, sop, ps_e, ps_type ); - return rc; - } - } else { - pce = op->o_ps_send_wait; - } - - /* Wait until refresh search send the entry */ - while ( !pce->pc_sent ) { - if ( sop->o_refresh_in_progress ) { - if ( num_retries == BDB_PSEARCH_MAX_WAIT ) { - op->o_ps_send_wait = pce; - return LDAP_BUSY; - } - ldap_pvt_thread_yield(); - bdb_trans_backoff( ++num_retries ); - } else { - break; - } - } - - op->o_ps_send_wait = NULL; - - if ( !sop->o_refresh_in_progress && !pce->pc_sent ) { - /* refresh ended without processing pce */ - /* need to perform psearch for ps_e */ - ldap_pvt_thread_mutex_lock( &sop->o_pcmutex ); - LDAP_TAILQ_REMOVE( &sop->o_ps_pre_candidates, pce, pc_link ); - ldap_pvt_thread_mutex_unlock( &sop->o_pcmutex ); - ch_free( pce ); - rc = bdb_do_search( op, rs, sop, ps_e, ps_type ); - return rc; - } else { - /* the pce entry was sent in the refresh phase */ - if ( ps_type == LDAP_PSEARCH_BY_PREMODIFY ) { - struct psid_entry* psid_e; - psid_e = (struct psid_entry *) ch_calloc(1, - sizeof(struct psid_entry)); - psid_e->ps_op = sop; - LDAP_LIST_INSERT_HEAD( &op->o_pm_list, psid_e, ps_link ); - } - - ldap_pvt_thread_mutex_lock( &sop->o_pcmutex ); - LDAP_TAILQ_REMOVE( &sop->o_ps_pre_candidates, pce, pc_link ); - ldap_pvt_thread_mutex_unlock( &sop->o_pcmutex ); - ch_free( pce ); - return LDAP_SUCCESS; - } - break; - case LDAP_PSEARCH_BY_DELETE: - case LDAP_PSEARCH_BY_SCOPEOUT: - case LDAP_PSEARCH_BY_ADD: - case LDAP_PSEARCH_BY_MODIFY: - ldap_pvt_thread_mutex_lock( &op->o_pcmutex ); - if ( sop->o_refresh_in_progress || - !LDAP_TAILQ_EMPTY( &sop->o_ps_post_candidates )) { - pce = (struct pc_entry *) ch_calloc( 1, sizeof( struct pc_entry )); - pce->pc_id = ps_e->e_id; - ber_dupbv( &pce->pc_csn, &op->o_sync_csn ); - if ( ps_type == LDAP_PSEARCH_BY_DELETE ) { - Attribute *a; - for ( a = ps_e->e_attrs; a != NULL; a = a->a_next ) { - AttributeDescription *desc = a->a_desc; - if ( desc == slap_schema.si_ad_entryUUID ) { - ber_dupbv( &pce->pc_entryUUID, &a->a_nvals[0] ); - } - } - } - ber_dupbv( &pce->pc_ename, &ps_e->e_name ); - ber_dupbv( &pce->pc_enname, &ps_e->e_nname ); - LDAP_TAILQ_INSERT_TAIL( &sop->o_ps_post_candidates, pce, pc_link ); - ldap_pvt_thread_mutex_unlock( &op->o_pcmutex ); - } else { - ldap_pvt_thread_mutex_unlock( &op->o_pcmutex ); - rc = bdb_do_search( op, rs, sop, ps_e, ps_type ); - return rc; - } - break; - default: - Debug( LDAP_DEBUG_TRACE, "do_psearch: invalid psearch type\n", - 0, 0, 0 ); - return LDAP_OTHER; - } -} -#else -int bdb_search( Operation *op, SlapReply *rs ) -{ - return bdb_do_search( op, rs, op, NULL, 0 ); -} -#endif - -/* For persistent searches, op is the currently executing operation, - * sop is the persistent search. For regular searches, sop = op. - */ int -bdb_do_search( Operation *op, SlapReply *rs, Operation *sop, - Entry *ps_e, int ps_type ) +bdb_search( Operation *op, SlapReply *rs ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; - time_t stoptime; ID id, cursor; + ID lastid = NOID; ID candidates[BDB_IDL_UM_SIZE]; ID scopes[BDB_IDL_DB_SIZE]; - Entry *e = NULL, base, e_root = {0}; + Entry *e = NULL, base, *e_root; Entry *matched = NULL; - EntryInfo *ei, ei_root = {0}; + EntryInfo *ei; + AttributeName *attrs; struct berval realbase = BER_BVNULL; + slap_mask_t mask; + time_t stoptime; int manageDSAit; - int tentries = 0; - ID lastid = NOID; - AttributeName *attrs; + int tentries = 0, nentries = 0; + int idflag = 0; - u_int32_t locker = 0; DB_LOCK lock; struct bdb_op_info *opinfo = NULL; DB_TXN *ltid = NULL; - -#ifdef BDB_PSEARCH - Filter contextcsnand, contextcsnle, cookief, csnfnot, - csnfeq, csnfand, csnfge; - AttributeAssertion aa_ge, aa_eq, aa_le; - struct berval *search_context_csn = NULL; - DB_LOCK ctxcsn_lock; - LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; - int num_ctrls = 0; - AttributeName uuid_attr[2]; - int rc_sync = 0; - int entry_sync_state = -1; - AttributeName null_attr; - int no_sync_state_change = 0; - - - Operation *ps_list; - int sync_send_present_mode = 1; - int match; - MatchingRule *mr; - const char *text; - int slog_found = 0; - - struct pc_entry *pce = NULL; - BerVarray syncUUID_set = NULL; - int syncUUID_set_cnt = 0; - -#endif + OpExtra *oex; Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_search) "\n", 0, 0, 0); - attrs = sop->oq_search.rs_attrs; - - opinfo = (struct bdb_op_info *) op->o_private; - -#ifdef BDB_PSEARCH - if ( !IS_POST_SEARCH && !IS_PSEARCH && - sop->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST ) { - struct slap_session_entry *sent; - if ( sop->o_sync_state.sid >= 0 ) { - LDAP_LIST_FOREACH( sent, &bdb->bi_session_list, se_link ) { - if ( sent->se_id == sop->o_sync_state.sid ) { - sop->o_sync_slog_size = sent->se_size; - break; - } - } - } - } - - /* psearch needs to be registered before refresh begins */ - if ( !IS_POST_SEARCH && !IS_PSEARCH && - sop->o_sync_mode & SLAP_SYNC_PERSIST ) { - sop->o_refresh_in_progress = 1; - ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock ); - LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link ); - ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock ); - - } else if ( !IS_POST_SEARCH && !IS_PSEARCH && - sop->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST - && sop->o_sync_slog_size >= 0 ) - { - ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock ); - LDAP_LIST_FOREACH( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - if ( ps_list->o_sync_slog_size >= 0 ) { - if ( ps_list->o_sync_state.sid == sop->o_sync_state.sid ) { - slog_found = 1; - break; - } - } - } + attrs = op->oq_search.rs_attrs; - if ( slog_found ) { - if ( ps_list->o_sync_slog_omitcsn.bv_len != 0 ) { - mr = slap_schema.si_ad_entryCSN->ad_type->sat_ordering; - if ( sop->o_sync_state.ctxcsn && - sop->o_sync_state.ctxcsn->bv_val != NULL ) - { - value_match( &match, slap_schema.si_ad_entryCSN, mr, - SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - sop->o_sync_state.ctxcsn, - &ps_list->o_sync_slog_omitcsn, - &text ); - } else { - match = -1; - } - if ( match >= 0 ) { - sync_send_present_mode = 0; - } - } else { - sync_send_present_mode = 0; - } - } else if ( sop->o_sync_slog_size >= 0 ) { - LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link ); - } else { - sop->o_sync_state.sid = -1; - } - ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock ); + LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) { + if ( oex->oe_key == bdb ) + break; } + opinfo = (struct bdb_op_info *) oex; - null_attr.an_desc = NULL; - null_attr.an_oc = NULL; - null_attr.an_oc_exclude = 0; - BER_BVZERO( &null_attr.an_name ); - - for( num_ctrls = 0; num_ctrls < SLAP_MAX_RESPONSE_CONTROLS; num_ctrls++ ) { - ctrls[num_ctrls] = NULL; - } - num_ctrls = 0; - - if ( IS_PSEARCH && IS_BDB_REPLACE(ps_type)) { - attrs = uuid_attr; - attrs[0].an_desc = NULL; - attrs[0].an_oc = NULL; - attrs[0].an_oc_exclude = 0; - BER_BVZERO( &attrs[0].an_name ); - } -#endif - - manageDSAit = get_manageDSAit( sop ); - -#ifdef BDB_PSEARCH - /* Sync control overrides manageDSAit */ - if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_REFRESH ) { - if ( manageDSAit == SLAP_CONTROL_NONE ) { - manageDSAit = SLAP_CONTROL_CRITICAL; - } - } else if ( IS_PSEARCH ) { - if ( manageDSAit == SLAP_CONTROL_NONE ) { - manageDSAit = SLAP_CONTROL_CRITICAL; - } - } -#endif + manageDSAit = get_manageDSAit( op ); if ( opinfo && opinfo->boi_txn ) { ltid = opinfo->boi_txn; - locker = TXN_ID( ltid ); } else { - rs->sr_err = LOCK_ID( bdb->bi_dbenv, &locker ); + rs->sr_err = bdb_reader_get( op, bdb->bi_dbenv, <id ); switch(rs->sr_err) { case 0: break; default: - send_ldap_error( sop, rs, LDAP_OTHER, "internal error" ); + send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return rs->sr_err; } } -#ifdef BDB_PSEARCH - if ( IS_POST_SEARCH ) { - cursor = 0; - candidates[0] = 1; - candidates[1] = op->ors_post_search_id; - search_context_csn = ber_dupbv( NULL, &op->o_sync_csn ); - goto loop_start; - } -#endif - - if ( sop->o_req_ndn.bv_len == 0 ) { + e_root = bdb->bi_cache.c_dntree.bei_e; + if ( op->o_req_ndn.bv_len == 0 ) { /* DIT root special case */ - ei_root.bei_e = &e_root; - ei_root.bei_parent = &ei_root; - e_root.e_private = &ei_root; - e_root.e_id = 0; - BER_BVSTR( &e_root.e_nname, "" ); - BER_BVSTR( &e_root.e_name, "" ); - ei = &ei_root; + ei = e_root->e_private; rs->sr_err = LDAP_SUCCESS; } else { + if ( op->ors_deref & LDAP_DEREF_FINDING ) { + BDB_IDL_ZERO(candidates); + } dn2entry_retry: /* get entry with reader lock */ - rs->sr_err = bdb_dn2entry( op, ltid, &sop->o_req_ndn, &ei, - 1, locker, &lock ); + rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, + 1, &lock ); } switch(rs->sr_err) { @@ -810,48 +381,78 @@ dn2entry_retry: case 0: e = ei->bei_e; break; + case DB_LOCK_DEADLOCK: + if ( !opinfo ) { + ltid->flags &= ~TXN_DEADLOCK; + goto dn2entry_retry; + } + opinfo->boi_err = rs->sr_err; + /* FALLTHRU */ case LDAP_BUSY: - send_ldap_error( sop, rs, LDAP_BUSY, "ldap server busy" ); - if ( !opinfo ) - LOCK_ID_FREE (bdb->bi_dbenv, locker ); + send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" ); return LDAP_BUSY; - case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto dn2entry_retry; default: - send_ldap_error( sop, rs, LDAP_OTHER, "internal error" ); - if ( !opinfo ) - LOCK_ID_FREE (bdb->bi_dbenv, locker ); + send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return rs->sr_err; } - if ( e && (op->ors_deref & LDAP_DEREF_FINDING) && is_entry_alias(e) ) { - BDB_IDL_ZERO(candidates); - e = deref_base( op, rs, e, &matched, locker, &lock, - candidates, NULL ); + if ( op->ors_deref & LDAP_DEREF_FINDING ) { + if ( matched && is_entry_alias( matched )) { + struct berval stub; + + stub.bv_val = op->o_req_ndn.bv_val; + stub.bv_len = op->o_req_ndn.bv_len - matched->e_nname.bv_len - 1; + e = deref_base( op, rs, matched, &matched, ltid, &lock, + candidates, NULL ); + if ( e ) { + build_new_dn( &op->o_req_ndn, &e->e_nname, &stub, + op->o_tmpmemctx ); + bdb_cache_return_entry_r (bdb, e, &lock); + matched = NULL; + goto dn2entry_retry; + } + } else if ( e && is_entry_alias( e )) { + e = deref_base( op, rs, e, &matched, ltid, &lock, + candidates, NULL ); + } } if ( e == NULL ) { struct berval matched_dn = BER_BVNULL; if ( matched != NULL ) { - BerVarray erefs; - ber_dupbv( &matched_dn, &matched->e_name ); + BerVarray erefs = NULL; - erefs = is_entry_referral( matched ) - ? get_entry_referrals( op, matched ) - : NULL; + /* return referral only if "disclose" + * is granted on the object */ + if ( ! access_allowed( op, matched, + slap_schema.si_ad_entry, + NULL, ACL_DISCLOSE, NULL ) ) + { + rs->sr_err = LDAP_NO_SUCH_OBJECT; + + } else { + ber_dupbv( &matched_dn, &matched->e_name ); + + erefs = is_entry_referral( matched ) + ? get_entry_referrals( op, matched ) + : NULL; + if ( rs->sr_err == DB_NOTFOUND ) + rs->sr_err = LDAP_REFERRAL; + rs->sr_matched = matched_dn.bv_val; + } #ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, matched); #endif - bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, - matched, &lock); + bdb_cache_return_entry_r (bdb, matched, &lock); matched = NULL; - if( erefs ) { + if ( erefs ) { rs->sr_ref = referral_rewrite( erefs, &matched_dn, - &sop->o_req_dn, sop->oq_search.rs_scope ); + &op->o_req_dn, op->oq_search.rs_scope ); ber_bvarray_free( erefs ); } @@ -860,57 +461,77 @@ dn2entry_retry: slap_zn_runlock(bdb->bi_cache.c_zctx, matched); #endif rs->sr_ref = referral_rewrite( default_referral, - NULL, &sop->o_req_dn, sop->oq_search.rs_scope ); + NULL, &op->o_req_dn, op->oq_search.rs_scope ); + rs->sr_err = rs->sr_ref != NULL ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT; } - rs->sr_err = LDAP_REFERRAL; - rs->sr_matched = matched_dn.bv_val; - send_ldap_result( sop, rs ); + send_ldap_result( op, rs ); - if ( !opinfo ) - LOCK_ID_FREE (bdb->bi_dbenv, locker ); if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } - if ( matched_dn.bv_val ) { + if ( !BER_BVISNULL( &matched_dn ) ) { ber_memfree( matched_dn.bv_val ); rs->sr_matched = NULL; } return rs->sr_err; } - if ( !manageDSAit && e != &e_root && is_entry_referral( e ) ) { + /* NOTE: __NEW__ "search" access is required + * on searchBase object */ + if ( ! access_allowed_mask( op, e, slap_schema.si_ad_entry, + NULL, ACL_SEARCH, NULL, &mask ) ) + { + if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) { + rs->sr_err = LDAP_NO_SUCH_OBJECT; + } else { + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; + } + +#ifdef SLAP_ZONE_ALLOC + slap_zn_runlock(bdb->bi_cache.c_zctx, e); +#endif + if ( e != e_root ) { + bdb_cache_return_entry_r(bdb, e, &lock); + } + send_ldap_result( op, rs ); + return rs->sr_err; + } + + if ( !manageDSAit && e != e_root && is_entry_referral( e ) ) { /* entry is a referral, don't allow add */ - struct berval matched_dn; - BerVarray erefs; + struct berval matched_dn = BER_BVNULL; + BerVarray erefs = NULL; ber_dupbv( &matched_dn, &e->e_name ); erefs = get_entry_referrals( op, e ); + rs->sr_err = LDAP_REFERRAL; + #ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e); #endif - bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock ); + bdb_cache_return_entry_r( bdb, e, &lock ); e = NULL; - if( erefs ) { + if ( erefs ) { rs->sr_ref = referral_rewrite( erefs, &matched_dn, - &sop->o_req_dn, sop->oq_search.rs_scope ); + &op->o_req_dn, op->oq_search.rs_scope ); ber_bvarray_free( erefs ); + + if ( !rs->sr_ref ) { + rs->sr_text = "bad_referral object"; + } } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_search) ": entry is referral\n", 0, 0, 0 ); - if (!rs->sr_ref) rs->sr_text = "bad_referral object"; - rs->sr_err = LDAP_REFERRAL; rs->sr_matched = matched_dn.bv_val; - send_ldap_result( sop, rs ); + send_ldap_result( op, rs ); - if ( !opinfo ) - LOCK_ID_FREE (bdb->bi_dbenv, locker ); ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; ber_memfree( matched_dn.bv_val ); @@ -925,12 +546,15 @@ dn2entry_retry: #ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e); #endif - send_ldap_result( sop, rs ); + if ( e != e_root ) { + bdb_cache_return_entry_r(bdb, e, &lock); + } + send_ldap_result( op, rs ); return 1; } /* compute it anyway; root does not use it */ - stoptime = op->o_time + sop->ors_tlimit; + stoptime = op->o_time + op->ors_tlimit; /* need normalized dn below */ ber_dupbv( &realbase, &e->e_nname ); @@ -945,73 +569,35 @@ dn2entry_retry: #ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e); #endif - if ( e != &e_root ) { - bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock); + if ( e != e_root ) { + bdb_cache_return_entry_r(bdb, e, &lock); } e = NULL; -#ifdef BDB_PSEARCH - if ( !IS_PSEARCH ) { - rs->sr_err = bdb_get_commit_csn( sop, rs, &search_context_csn, - locker, &ctxcsn_lock ); - - if ( rs->sr_err != LDAP_SUCCESS ) { - send_ldap_error( sop, rs, rs->sr_err, - "error in csn management in search" ); - goto done; - } - - if ( sop->o_sync_mode != SLAP_SYNC_NONE && - sop->o_sync_state.ctxcsn && - sop->o_sync_state.ctxcsn->bv_val && - ber_bvcmp( &sop->o_sync_state.ctxcsn[0], search_context_csn ) == 0 ) - { - bdb_cache_entry_db_unlock( bdb->bi_dbenv, &ctxcsn_lock ); - goto nochange; - } - } else { - search_context_csn = ber_dupbv( NULL, &op->o_sync_csn ); - } -#endif - /* select candidates */ - if ( sop->oq_search.rs_scope == LDAP_SCOPE_BASE ) { + if ( op->oq_search.rs_scope == LDAP_SCOPE_BASE ) { rs->sr_err = base_candidate( op->o_bd, &base, candidates ); } else { +cand_retry: BDB_IDL_ZERO( candidates ); BDB_IDL_ZERO( scopes ); - rs->sr_err = search_candidates( op, sop, rs, &base, - locker, candidates, scopes ); + rs->sr_err = search_candidates( op, rs, &base, + ltid, candidates, scopes ); + if ( rs->sr_err == DB_LOCK_DEADLOCK ) { + if ( !opinfo ) { + ltid->flags &= ~TXN_DEADLOCK; + goto cand_retry; + } + opinfo->boi_err = rs->sr_err; + send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" ); + return LDAP_BUSY; + } } -#ifdef BDB_PSEARCH - if ( !IS_PSEARCH && sop->o_sync_mode != SLAP_SYNC_NONE ) { - bdb_cache_entry_db_unlock( bdb->bi_dbenv, &ctxcsn_lock ); - } -#endif - /* start cursor at beginning of candidates. */ cursor = 0; -#ifdef BDB_PSEARCH - if (IS_PSEARCH) { - if ( !BDB_IDL_IS_RANGE( candidates ) ) { - cursor = bdb_idl_search( candidates, ps_e->e_id ); - if ( candidates[cursor] != ps_e->e_id ) { - rs->sr_err = LDAP_SUCCESS; - goto done; - } - } else if ( ps_e->e_id < BDB_IDL_RANGE_FIRST( candidates ) || - ps_e->e_id > BDB_IDL_RANGE_LAST( candidates )) - { - rs->sr_err = LDAP_SUCCESS; - goto done; - } - candidates[0] = 1; - candidates[1] = ps_e->e_id; - } -#endif if ( candidates[0] == 0 ) { Debug( LDAP_DEBUG_TRACE, @@ -1022,304 +608,164 @@ dn2entry_retry: } /* if not root and candidates exceed to-be-checked entries, abort */ - if ( sop->ors_limit /* isroot == FALSE */ && - sop->ors_limit->lms_s_unchecked != -1 && - BDB_IDL_N(candidates) > (unsigned) sop->ors_limit->lms_s_unchecked ) + if ( op->ors_limit /* isroot == FALSE */ && + op->ors_limit->lms_s_unchecked != -1 && + BDB_IDL_N(candidates) > (unsigned) op->ors_limit->lms_s_unchecked ) { rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; - send_ldap_result( sop, rs ); + send_ldap_result( op, rs ); rs->sr_err = LDAP_SUCCESS; goto done; } - if ( sop->ors_limit == NULL /* isroot == TRUE */ || - !sop->ors_limit->lms_s_pr_hide ) + if ( op->ors_limit == NULL /* isroot == TRUE */ || + !op->ors_limit->lms_s_pr_hide ) { tentries = BDB_IDL_N(candidates); } - if ( get_pagedresults( sop ) > SLAP_CONTROL_IGNORED ) { - PagedResultsState *ps = sop->o_pagedresults_state; + if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) { + PagedResultsState *ps = op->o_pagedresults_state; /* deferred cookie parsing */ - rs->sr_err = parse_paged_cookie( sop, rs ); + rs->sr_err = parse_paged_cookie( op, rs ); if ( rs->sr_err != LDAP_SUCCESS ) { - send_ldap_result( sop, rs ); + send_ldap_result( op, rs ); goto done; } - if ( (ID)( ps->ps_cookie ) == 0 ) { - id = bdb_idl_first( candidates, &cursor ); - - } else { - if ( ps->ps_size == 0 ) { - rs->sr_err = LDAP_SUCCESS; - rs->sr_text = "search abandoned by pagedResult size=0"; - send_ldap_result( sop, rs ); - goto done; - } - for ( id = bdb_idl_first( candidates, &cursor ); - id != NOID && - id <= (ID)( ps->ps_cookie ); - id = bdb_idl_next( candidates, &cursor ) ) - { - /* empty */; - } + cursor = (ID) ps->ps_cookie; + if ( cursor && ps->ps_size == 0 ) { + rs->sr_err = LDAP_SUCCESS; + rs->sr_text = "search abandoned by pagedResult size=0"; + send_ldap_result( op, rs ); + goto done; } - - if ( cursor == NOID ) { + id = bdb_idl_first( candidates, &cursor ); + if ( id == NOID ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_search) ": no paged results candidates\n", 0, 0, 0 ); - send_paged_response( sop, rs, &lastid, 0 ); + send_paged_response( op, rs, &lastid, 0 ); rs->sr_err = LDAP_OTHER; goto done; } + nentries = ps->ps_count; + if ( id == (ID)ps->ps_cookie ) + id = bdb_idl_next( candidates, &cursor ); goto loop_begin; } -#ifdef BDB_PSEARCH - if (( sop->o_sync_mode & SLAP_SYNC_REFRESH ) || IS_PSEARCH ) { - int match; - - cookief.f_choice = LDAP_FILTER_AND; - cookief.f_and = &csnfnot; - cookief.f_next = NULL; - - csnfnot.f_choice = LDAP_FILTER_NOT; - csnfnot.f_not = &csnfeq; - csnfnot.f_next = &csnfand; - - csnfeq.f_choice = LDAP_FILTER_EQUALITY; - csnfeq.f_ava = &aa_eq; - csnfeq.f_av_desc = slap_schema.si_ad_entryCSN; - if ( sop->o_sync_state.ctxcsn != NULL ) { - csnfeq.f_av_value = *sop->o_sync_state.ctxcsn; - } else { - csnfeq.f_av_value = slap_empty_bv; - } - - csnfand.f_choice = LDAP_FILTER_AND; - csnfand.f_and = &csnfge; - csnfand.f_next = NULL; - - csnfge.f_choice = LDAP_FILTER_GE; - csnfge.f_ava = &aa_ge; - csnfge.f_av_desc = slap_schema.si_ad_entryCSN; - if ( sop->o_sync_state.ctxcsn != NULL ) { - csnfge.f_av_value = *sop->o_sync_state.ctxcsn; - } else { - csnfge.f_av_value = slap_empty_bv; - } - - if ( search_context_csn && !IS_PSEARCH ) { - csnfge.f_next = &contextcsnand; - - contextcsnand.f_choice = LDAP_FILTER_AND; - contextcsnand.f_and = &contextcsnle; - contextcsnand.f_next = NULL; - - contextcsnle.f_choice = LDAP_FILTER_LE; - contextcsnle.f_ava = &aa_le; - contextcsnle.f_av_desc = slap_schema.si_ad_entryCSN; - contextcsnle.f_av_value = *search_context_csn; - contextcsnle.f_next = sop->oq_search.rs_filter; - - mr = slap_schema.si_ad_entryCSN->ad_type->sat_ordering; - if ( sop->o_sync_state.ctxcsn && - sop->o_sync_state.ctxcsn->bv_val != NULL ) - { - value_match( &match, slap_schema.si_ad_entryCSN, mr, - SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - &sop->o_sync_state.ctxcsn[0], search_context_csn, - &text ); - } else { - match = -1; - } - no_sync_state_change = ( match >= 0 ); - } else { - csnfge.f_next = sop->oq_search.rs_filter; - } - } -#endif - -loop_start: - for ( id = bdb_idl_first( candidates, &cursor ); - id != NOID -#ifdef BDB_PSEARCH - && !no_sync_state_change -#endif - ; id = bdb_idl_next( candidates, &cursor ) ) + id != NOID ; id = bdb_idl_next( candidates, &cursor ) ) { - int scopeok = 0; - ID* idhole = NULL; + int scopeok; loop_begin: -#ifdef BDB_PSEARCH - if ( !IS_POST_SEARCH ) { - idhole = (ID*) avl_find( sop->o_psearch_finished, - (caddr_t)&id, bdb_pfid_cmp ); - if ( idhole ) { - avl_delete( &sop->o_psearch_finished, - (caddr_t)idhole, bdb_pfid_cmp ); - sop->o_tmpfree( idhole, sop->o_tmpmemctx ); - goto loop_continue; - } - - if ( sop->o_refresh_in_progress ) { - ldap_pvt_thread_mutex_lock( &sop->o_pcmutex ); - pce = LDAP_TAILQ_FIRST( &sop->o_ps_pre_candidates ); - while ( pce && pce->pc_sent ) { - pce = LDAP_TAILQ_NEXT( pce, pc_link ); - } - ldap_pvt_thread_mutex_unlock( &sop->o_pcmutex ); - if ( pce ) { - ID pos; - if ( BDB_IDL_IS_RANGE( candidates ) ) { - if ( pce->pc_id >= candidates[1] && - pce->pc_id <= candidates[2] && - pce->pc_id > cursor-1 ) { - id = pce->pc_id; - cursor--; - avl_insert( &sop->o_psearch_finished, - (caddr_t)bdb_id_dup( sop, &pce->pc_id ), - bdb_pfid_cmp, avl_dup_error ); - } else { - pce->pc_sent = 1; - } - } else { - pos = bdb_idl_search(candidates, pce->pc_id); - if ( pos > cursor-1 && pos <= candidates[0] ) { - id = pce->pc_id; - cursor--; - avl_insert( &sop->o_psearch_finished, - (caddr_t)bdb_id_dup( sop, &pce->pc_id ), - bdb_pfid_cmp, avl_dup_error ); - } else { - pce->pc_sent = 1; - } - } - } - } - } - /* check for abandon */ - if ( sop->o_abandon ) { - if ( sop != op ) { - bdb_drop_psearch( sop, sop->o_msgid ); - } - rs->sr_err = LDAP_SUCCESS; + if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; goto done; } - if ( sop->o_cancel ) { - assert( sop->o_cancel == SLAP_CANCEL_REQ ); - rs->sr_err = LDAP_CANCELLED; - send_ldap_result( sop, rs ); - sop->o_cancel = SLAP_CANCEL_ACK; - rs->sr_err = LDAP_SUCCESS; + /* mostly needed by internal searches, + * e.g. related to syncrepl, for whom + * abandon does not get set... */ + if ( slapd_shutdown ) { + rs->sr_err = LDAP_UNAVAILABLE; + send_ldap_disconnect( op, rs ); goto done; } -#else - /* check for abandon */ - if ( sop->o_abandon ) { - rs->sr_err = LDAP_SUCCESS; - goto done; - } -#endif /* check time limit */ - if ( sop->ors_tlimit != SLAP_NO_LIMIT + if ( op->ors_tlimit != SLAP_NO_LIMIT && slap_get_time() > stoptime ) { rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; rs->sr_ref = rs->sr_v2ref; - send_ldap_result( sop, rs ); + send_ldap_result( op, rs ); rs->sr_err = LDAP_SUCCESS; goto done; } -#ifdef BDB_PSEARCH - if (!IS_PSEARCH) { -#endif + /* If we inspect more entries than will + * fit into the entry cache, stop caching + * any subsequent entries + */ + nentries++; + if ( nentries > bdb->bi_cache.c_maxsize && !idflag ) { + idflag = ID_NOCACHE; + } + fetch_entry_retry: - /* get the entry with reader lock */ - ei = NULL; - rs->sr_err = bdb_cache_find_id( op, ltid, - id, &ei, 0, locker, &lock ); + /* get the entry with reader lock */ + ei = NULL; + rs->sr_err = bdb_cache_find_id( op, ltid, + id, &ei, idflag, &lock ); - if (rs->sr_err == LDAP_BUSY) { - rs->sr_text = "ldap server busy"; - send_ldap_result( sop, rs ); - goto done; + if (rs->sr_err == LDAP_BUSY) { + rs->sr_text = "ldap server busy"; + send_ldap_result( op, rs ); + goto done; - } else if ( rs->sr_err == DB_LOCK_DEADLOCK - || rs->sr_err == DB_LOCK_NOTGRANTED ) - { + } else if ( rs->sr_err == DB_LOCK_DEADLOCK ) { + if ( !opinfo ) { + ltid->flags &= ~TXN_DEADLOCK; goto fetch_entry_retry; } + opinfo->boi_err = rs->sr_err; + send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" ); + goto done; - if ( ei && rs->sr_err == LDAP_SUCCESS ) { - e = ei->bei_e; - } else { - e = NULL; - } + } else if ( rs->sr_err == DB_LOCK_NOTGRANTED ) + { + goto fetch_entry_retry; + } else if ( rs->sr_err == LDAP_OTHER ) { + rs->sr_text = "internal error"; + send_ldap_result( op, rs ); + goto done; + } - if ( e == NULL ) { -#ifdef BDB_PSEARCH - if ( IS_POST_SEARCH ) { - /* send LDAP_SYNC_DELETE */ - rs->sr_entry = e = ps_e; - goto post_search_no_entry; - } else -#endif - if( !BDB_IDL_IS_RANGE(candidates) ) { - /* only complain for non-range IDLs */ - Debug( LDAP_DEBUG_TRACE, - LDAP_XSTRING(bdb_search) - ": candidate %ld not found\n", - (long) id, 0, 0 ); - } + if ( ei && rs->sr_err == LDAP_SUCCESS ) { + e = ei->bei_e; + } else { + e = NULL; + } - goto loop_continue; + if ( e == NULL ) { + if( !BDB_IDL_IS_RANGE(candidates) ) { + /* only complain for non-range IDLs */ + Debug( LDAP_DEBUG_TRACE, + LDAP_XSTRING(bdb_search) + ": candidate %ld not found\n", + (long) id, 0, 0 ); } -#ifdef BDB_PSEARCH - } else { - e = ps_e; + + goto loop_continue; } -#endif rs->sr_entry = e; -#ifdef BDB_SUBENTRIES - /* FIXME: send all but syncrepl */ -#if 0 - if ( !is_sync_protocol( sop ) ) -#endif - { - if ( is_entry_subentry( e ) ) { - if( sop->oq_search.rs_scope != LDAP_SCOPE_BASE ) { - if(!get_subentries_visibility( sop )) { - /* only subentries are visible */ - goto loop_continue; - } - - } else if ( get_subentries( sop ) && - !get_subentries_visibility( sop )) - { + if ( is_entry_subentry( e ) ) { + if( op->oq_search.rs_scope != LDAP_SCOPE_BASE ) { + if(!get_subentries_visibility( op )) { /* only subentries are visible */ goto loop_continue; } - } else if ( get_subentries_visibility( sop )) { + } else if ( get_subentries( op ) && + !get_subentries_visibility( op )) + { /* only subentries are visible */ goto loop_continue; } + + } else if ( get_subentries_visibility( op )) { + /* only subentries are visible */ + goto loop_continue; } -#endif /* BDB_SUBENTRIES */ /* Does this candidate actually satisfy the search scope? * @@ -1330,7 +776,8 @@ fetch_entry_retry: * scope while we are looking at it, and unless we're using * BDB_HIER, its parents cannot be moved either. */ - switch( sop->ors_scope ) { + scopeok = 0; + switch( op->ors_scope ) { case LDAP_SCOPE_BASE: /* This is always true, yes? */ if ( id == base.e_id ) scopeok = 1; @@ -1357,12 +804,12 @@ fetch_entry_retry: } /* aliases were already dereferenced in candidate list */ - if ( sop->ors_deref & LDAP_DEREF_SEARCHING ) { + if ( op->ors_deref & LDAP_DEREF_SEARCHING ) { /* but if the search base is an alias, and we didn't * deref it when finding, return it. */ if ( is_entry_alias(e) && - ((sop->ors_deref & LDAP_DEREF_FINDING) || + ((op->ors_deref & LDAP_DEREF_FINDING) || !bvmatch(&e->e_nname, &op->o_req_ndn))) { goto loop_continue; @@ -1371,7 +818,7 @@ fetch_entry_retry: /* scopes is only non-empty for onelevel or subtree */ if ( !scopeok && BDB_IDL_N(scopes) ) { unsigned x; - if ( sop->ors_scope == LDAP_SCOPE_ONELEVEL ) { + if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) { x = bdb_idl_search( scopes, e->e_id ); if ( scopes[x] == e->e_id ) scopeok = 1; } else { @@ -1389,11 +836,7 @@ fetch_entry_retry: } /* Not in scope, ignore it */ -#ifdef BDB_PSEARCH - if ( !IS_POST_SEARCH && !scopeok ) -#else if ( !scopeok ) -#endif { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_search) @@ -1407,15 +850,53 @@ fetch_entry_retry: * this for non-base searches, and don't check the filter * explicitly here since it's only a candidate anyway. */ - if ( !manageDSAit && sop->oq_search.rs_scope != LDAP_SCOPE_BASE + if ( !manageDSAit && op->oq_search.rs_scope != LDAP_SCOPE_BASE && is_entry_referral( e ) ) { - BerVarray erefs = get_entry_referrals( sop, e ); + struct bdb_op_info bois; + struct bdb_lock_info blis; + BerVarray erefs = get_entry_referrals( op, e ); rs->sr_ref = referral_rewrite( erefs, &e->e_name, NULL, - sop->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL + op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE ); - send_search_reference( sop, rs ); + /* Must set lockinfo so that entry_release will work */ + if (!opinfo) { + bois.boi_oe.oe_key = bdb; + bois.boi_txn = NULL; + bois.boi_err = 0; + bois.boi_acl_cache = op->o_do_not_cache; + bois.boi_flag = BOI_DONTFREE; + bois.boi_locks = &blis; + blis.bli_next = NULL; + LDAP_SLIST_INSERT_HEAD( &op->o_extra, &bois.boi_oe, + oe_next ); + } else { + blis.bli_next = opinfo->boi_locks; + opinfo->boi_locks = &blis; + } + blis.bli_id = e->e_id; + blis.bli_lock = lock; + blis.bli_flag = BLI_DONTFREE; + + rs->sr_flags = REP_ENTRY_MUSTRELEASE; + + send_search_reference( op, rs ); + + if ( blis.bli_flag ) { +#ifdef SLAP_ZONE_ALLOC + slap_zn_runlock(bdb->bi_cache.c_zctx, e); +#endif + bdb_cache_return_entry_r(bdb, e, &lock); + if ( opinfo ) { + opinfo->boi_locks = blis.bli_next; + } else { + LDAP_SLIST_REMOVE( &op->o_extra, &bois.boi_oe, + OpExtra, oe_next ); + } + } + rs->sr_entry = NULL; + e = NULL; ber_bvarray_free( rs->sr_ref ); ber_bvarray_free( erefs ); @@ -1429,277 +910,88 @@ fetch_entry_retry: } /* if it matches the filter and scope, send it */ -#ifndef BDB_PSEARCH - rs->sr_err = test_filter( sop, rs->sr_entry, sop->oq_search.rs_filter ); -#else - if (IS_PSEARCH) { - if (ps_type != LDAP_PSEARCH_BY_SCOPEOUT) { - rs->sr_err = test_filter( sop, rs->sr_entry, &cookief ); - } else { - rs->sr_err = LDAP_COMPARE_TRUE; - } - - } else { - if ( !IS_POST_SEARCH ) { - if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) { - rc_sync = test_filter( sop, rs->sr_entry, &cookief ); - rs->sr_err = test_filter( sop, rs->sr_entry, - &contextcsnand ); - if ( rs->sr_err == LDAP_COMPARE_TRUE ) { - if ( rc_sync == LDAP_COMPARE_TRUE ) { - if ( no_sync_state_change ) { - Debug( LDAP_DEBUG_TRACE, - LDAP_XSTRING(bdb_search) ": " - "error in context csn management\n", - 0, 0, 0 ); - } - entry_sync_state = LDAP_SYNC_ADD; - - } else { - if ( no_sync_state_change ) { - goto loop_continue; - } - entry_sync_state = LDAP_SYNC_PRESENT; - } - } - } else { - rs->sr_err = test_filter( sop, - rs->sr_entry, sop->oq_search.rs_filter ); - } - } else { - if ( scopeok ) { - rs->sr_err = test_filter( sop, - rs->sr_entry, sop->oq_search.rs_filter ); - } else { - rs->sr_err = LDAP_COMPARE_TRUE; - } - } - } -#endif + rs->sr_err = test_filter( op, rs->sr_entry, op->oq_search.rs_filter ); if ( rs->sr_err == LDAP_COMPARE_TRUE ) { /* check size limit */ - if ( --sop->ors_slimit == -1 -#ifdef BDB_PSEARCH - && sop->o_sync_slog_size == -1 -#endif - ) { -#ifdef BDB_PSEARCH - if (!IS_PSEARCH) { -#endif + if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) { + if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) { #ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e); #endif - bdb_cache_return_entry_r( bdb->bi_dbenv, - &bdb->bi_cache, e, &lock ); -#ifdef BDB_PSEARCH - } -#endif - e = NULL; - rs->sr_entry = NULL; - rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; - rs->sr_ref = rs->sr_v2ref; - send_ldap_result( sop, rs ); - rs->sr_err = LDAP_SUCCESS; - goto done; - } - - if ( get_pagedresults(sop) > SLAP_CONTROL_IGNORED ) { - if ( rs->sr_nentries >= ((PagedResultsState *)sop->o_pagedresults_state)->ps_size ) { - send_paged_response( sop, rs, &lastid, tentries ); + bdb_cache_return_entry_r( bdb, e, &lock ); + e = NULL; + send_paged_response( op, rs, &lastid, tentries ); goto done; } lastid = id; } if (e) { - /* safe default */ - int result = -1; -#ifdef BDB_PSEARCH - if (IS_PSEARCH || IS_POST_SEARCH) { - int premodify_found = 0; - - if ( IS_POST_SEARCH || - ps_type == LDAP_PSEARCH_BY_ADD || - ps_type == LDAP_PSEARCH_BY_DELETE || - ps_type == LDAP_PSEARCH_BY_MODIFY || - ps_type == LDAP_PSEARCH_BY_SCOPEOUT ) - { - if ( !IS_POST_SEARCH && - ps_type == LDAP_PSEARCH_BY_MODIFY ) { - struct psid_entry* psid_e; - LDAP_LIST_FOREACH( psid_e, - &op->o_pm_list, ps_link) - { - if( psid_e->ps_op == sop ) { - premodify_found = 1; - LDAP_LIST_REMOVE(psid_e, ps_link); - break; - } - } - if (psid_e != NULL) free (psid_e); - } - - if ( IS_POST_SEARCH ) { - if ( scopeok ) { - entry_sync_state = LDAP_SYNC_ADD; - } else { -post_search_no_entry: - entry_sync_state = LDAP_SYNC_DELETE; - } - } else if ( ps_type == LDAP_PSEARCH_BY_ADD ) { - entry_sync_state = LDAP_SYNC_ADD; - } else if ( ps_type == LDAP_PSEARCH_BY_DELETE ) { - entry_sync_state = LDAP_SYNC_DELETE; - } else if ( ps_type == LDAP_PSEARCH_BY_MODIFY ) { - if ( premodify_found ) { - entry_sync_state = LDAP_SYNC_MODIFY; - } else { - entry_sync_state = LDAP_SYNC_ADD; - } - } else if ( ps_type == LDAP_PSEARCH_BY_SCOPEOUT ) { - entry_sync_state = LDAP_SYNC_DELETE; - } else { - rs->sr_err = LDAP_OTHER; - goto done; - } - - if ( sop->o_sync_slog_size != -1 ) { - if ( entry_sync_state == LDAP_SYNC_DELETE ) { - result = slap_add_session_log( op, sop, e ); - } else { - result = 1; - } - } else { - struct berval cookie; - slap_compose_sync_cookie( sop, &cookie, - search_context_csn, - sop->o_sync_state.sid, - sop->o_sync_state.rid ); - rs->sr_err = slap_build_sync_state_ctrl( - sop, rs, e, entry_sync_state, ctrls, - num_ctrls++, 1, &cookie ); - if ( rs->sr_err != LDAP_SUCCESS ) goto done; - if (!(IS_POST_SEARCH && - entry_sync_state == LDAP_SYNC_DELETE)) { - rs->sr_attrs = attrs; - } else { - rs->sr_attrs = NULL; - } - rs->sr_operational_attrs = NULL; - rs->sr_ctrls = ctrls; - rs->sr_flags = 0; - result = send_search_entry( sop, rs ); - if ( cookie.bv_val ) ch_free( cookie.bv_val ); - slap_sl_free( - ctrls[num_ctrls-1]->ldctl_value.bv_val, - sop->o_tmpmemctx ); - slap_sl_free( ctrls[--num_ctrls], - sop->o_tmpmemctx ); - ctrls[num_ctrls] = NULL; - rs->sr_ctrls = NULL; - } - - } else if ( ps_type == LDAP_PSEARCH_BY_PREMODIFY ) { - struct psid_entry* psid_e; - psid_e = (struct psid_entry *) ch_calloc(1, - sizeof(struct psid_entry)); - psid_e->ps_op = sop; - LDAP_LIST_INSERT_HEAD( &op->o_pm_list, - psid_e, ps_link ); - - } else { - Debug( LDAP_DEBUG_TRACE, - LDAP_XSTRING(bdb_search) - ": invalid ps_type (%d) \n", - ps_type, 0, 0); - } - + struct bdb_op_info bois; + struct bdb_lock_info blis; + + /* Must set lockinfo so that entry_release will work */ + if (!opinfo) { + bois.boi_oe.oe_key = bdb; + bois.boi_txn = NULL; + bois.boi_err = 0; + bois.boi_acl_cache = op->o_do_not_cache; + bois.boi_flag = BOI_DONTFREE; + bois.boi_locks = &blis; + blis.bli_next = NULL; + LDAP_SLIST_INSERT_HEAD( &op->o_extra, &bois.boi_oe, + oe_next ); } else { - if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) { - if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */ - rs->sr_err = slap_build_sync_state_ctrl( - sop, rs, e, entry_sync_state, ctrls, - num_ctrls++, 0, NULL ); - if ( rs->sr_err != LDAP_SUCCESS ) goto done; - rs->sr_ctrls = ctrls; - rs->sr_attrs = sop->oq_search.rs_attrs; - rs->sr_operational_attrs = NULL; - rs->sr_flags = 0; - result = send_search_entry( sop, rs ); - slap_sl_free( - ctrls[num_ctrls-1]->ldctl_value.bv_val, - sop->o_tmpmemctx ); - slap_sl_free( ctrls[--num_ctrls], - sop->o_tmpmemctx ); - ctrls[num_ctrls] = NULL; - rs->sr_ctrls = NULL; - - } else { /* PRESENT */ - if ( sync_send_present_mode ) { - result = slap_build_syncUUID_set( sop, - &syncUUID_set, e ); - if ( result <= 0 ) { - result = -1; - } else { - syncUUID_set_cnt++; - if ( syncUUID_set_cnt == - SLAP_SYNCUUID_SET_SIZE ) - { - rs->sr_err = LDAP_SUCCESS; - rs->sr_rspoid = LDAP_SYNC_INFO; - rs->sr_ctrls = NULL; - result = slap_send_syncinfo( sop, rs, - LDAP_TAG_SYNC_ID_SET, - NULL, 0, syncUUID_set, 0 ); - if ( result != LDAP_SUCCESS ) { - result = -1; - } - ber_bvarray_free_x( syncUUID_set, - sop->o_tmpmemctx ); - syncUUID_set = NULL; - syncUUID_set_cnt = 0; - } - } - - } else { - result = 1; - } - } + blis.bli_next = opinfo->boi_locks; + opinfo->boi_locks = &blis; + } + blis.bli_id = e->e_id; + blis.bli_lock = lock; + blis.bli_flag = BLI_DONTFREE; - } else { + /* safe default */ + rs->sr_attrs = op->oq_search.rs_attrs; + rs->sr_operational_attrs = NULL; + rs->sr_ctrls = NULL; + rs->sr_flags = REP_ENTRY_MUSTRELEASE; + rs->sr_err = LDAP_SUCCESS; + rs->sr_err = send_search_entry( op, rs ); + + /* send_search_entry will usually free it. + * an overlay might leave its own copy here; + * bli_flag will be 0 if lock was already released. + */ + if ( blis.bli_flag ) { +#ifdef SLAP_ZONE_ALLOC + slap_zn_runlock(bdb->bi_cache.c_zctx, e); #endif - rs->sr_attrs = sop->oq_search.rs_attrs; - rs->sr_operational_attrs = NULL; - rs->sr_ctrls = NULL; - rs->sr_flags = 0; - rs->sr_err = LDAP_SUCCESS; - result = send_search_entry( sop, rs ); -#ifdef BDB_PSEARCH + bdb_cache_return_entry_r(bdb, e, &lock); + if ( opinfo ) { + opinfo->boi_locks = blis.bli_next; + } else { + LDAP_SLIST_REMOVE( &op->o_extra, &bois.boi_oe, + OpExtra, oe_next ); } } -#endif + rs->sr_entry = NULL; + e = NULL; - switch (result) { - case 0: /* entry sent ok */ + switch ( rs->sr_err ) { + case LDAP_SUCCESS: /* entry sent ok */ break; - case 1: /* entry not sent */ + default: /* entry not sent */ break; - case -1: /* connection closed */ -#ifdef BDB_PSEARCH - if (!IS_PSEARCH) { -#endif -#ifdef SLAP_ZONE_ALLOC - slap_zn_runlock(bdb->bi_cache.c_zctx, e); -#endif - bdb_cache_return_entry_r(bdb->bi_dbenv, - &bdb->bi_cache, e, &lock); -#ifdef BDB_PSEARCH + case LDAP_UNAVAILABLE: + case LDAP_SIZELIMIT_EXCEEDED: + if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) { + rs->sr_ref = rs->sr_v2ref; + send_ldap_result( op, rs ); + rs->sr_err = LDAP_SUCCESS; + + } else { + rs->sr_err = LDAP_OTHER; } -#endif - e = NULL; - rs->sr_entry = NULL; - rs->sr_err = LDAP_OTHER; goto done; } } @@ -1714,197 +1006,29 @@ post_search_no_entry: loop_continue: if( e != NULL ) { /* free reader lock */ -#ifdef BDB_PSEARCH - if (!IS_PSEARCH) { - if (!(IS_POST_SEARCH && - entry_sync_state == LDAP_SYNC_DELETE)) { -#ifdef SLAP_ZONE_ALLOC - slap_zn_runlock(bdb->bi_cache.c_zctx, e); -#endif - bdb_cache_return_entry_r( bdb->bi_dbenv, - &bdb->bi_cache, e , &lock ); - if ( sop->o_nocaching ) { - bdb_cache_delete_entry( bdb, ei, locker, &lock ); - } - } - } -#else #ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e); #endif - bdb_cache_return_entry_r( bdb->bi_dbenv, - &bdb->bi_cache, e , &lock ); -#endif + bdb_cache_return_entry_r( bdb, e , &lock ); e = NULL; rs->sr_entry = NULL; } - -#ifdef BDB_PSEARCH - if ( sop->o_refresh_in_progress ) { - if ( pce ) { - pce->pc_sent = 1; - } - } -#endif - - ldap_pvt_thread_yield(); - } - -#ifdef BDB_PSEARCH - if ( syncUUID_set_cnt > 0 ) { - rs->sr_err = LDAP_SUCCESS; - rs->sr_rspoid = LDAP_SYNC_INFO; - rs->sr_ctrls = NULL; - slap_send_syncinfo( sop, rs, LDAP_TAG_SYNC_ID_SET, - NULL, 0, syncUUID_set, 0 ); - ber_bvarray_free_x( syncUUID_set, sop->o_tmpmemctx ); - syncUUID_set_cnt = 0; } -#endif nochange: -#ifdef BDB_PSEARCH - if (!IS_PSEARCH && !IS_POST_SEARCH) { - if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) { - if ( sop->o_sync_mode & SLAP_SYNC_PERSIST ) { - struct berval cookie; - slap_compose_sync_cookie( sop, &cookie, search_context_csn, - sop->o_sync_state.sid, sop->o_sync_state.rid ); - - if ( sync_send_present_mode ) { - rs->sr_err = LDAP_SUCCESS; - rs->sr_rspoid = LDAP_SYNC_INFO; - rs->sr_ctrls = NULL; - slap_send_syncinfo( sop, rs, - LDAP_TAG_SYNC_REFRESH_PRESENT, &cookie, 1, NULL, 0 ); - - } else { - if ( !no_sync_state_change ) { - int slog_found = 0; - ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); - LDAP_LIST_FOREACH( ps_list, &bdb->bi_psearch_list, - o_ps_link ) - { - if ( ps_list->o_sync_slog_size > 0 ) { - if ( ps_list->o_sync_state.sid == - sop->o_sync_state.sid ) - { - slog_found = 1; - break; - } - } - } - - if ( slog_found ) { - rs->sr_err = LDAP_SUCCESS; - rs->sr_rspoid = NULL; - rs->sr_ctrls = NULL; - slap_send_session_log( op, ps_list, rs ); - } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); - } - - rs->sr_err = LDAP_SUCCESS; - rs->sr_rspoid = LDAP_SYNC_INFO; - rs->sr_ctrls = NULL; - slap_send_syncinfo( sop, rs, - LDAP_TAG_SYNC_REFRESH_DELETE, &cookie, 1, NULL, 0 ); - } - - if ( cookie.bv_val ) ch_free( cookie.bv_val ); - - } else { - /* refreshOnly mode */ - struct berval cookie; - slap_compose_sync_cookie( sop, &cookie, search_context_csn, - sop->o_sync_state.sid, sop->o_sync_state.rid ); - - if ( sync_send_present_mode ) { - slap_build_sync_done_ctrl( sop, rs, ctrls, - num_ctrls++, 1, &cookie, LDAP_SYNC_REFRESH_PRESENTS ); - - } else { - if ( !no_sync_state_change ) { - int slog_found = 0; - ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); - LDAP_LIST_FOREACH( ps_list, &bdb->bi_psearch_list, - o_ps_link ) - { - if ( ps_list->o_sync_slog_size > 0 ) { - if ( ps_list->o_sync_state.sid == - sop->o_sync_state.sid ) { - slog_found = 1; - break; - } - } - } - - if ( slog_found ) { - slap_send_session_log( op, ps_list, rs ); - } - ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); - } - - slap_build_sync_done_ctrl( sop, rs, ctrls, - num_ctrls++, 1, &cookie, LDAP_SYNC_REFRESH_DELETES ); - } - - rs->sr_ctrls = ctrls; - rs->sr_ref = rs->sr_v2ref; - rs->sr_err = (rs->sr_v2ref == NULL) - ? LDAP_SUCCESS : LDAP_REFERRAL; - rs->sr_rspoid = NULL; - send_ldap_result( sop, rs ); - if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) { - slap_sl_free( ctrls[num_ctrls-1]->ldctl_value.bv_val, - sop->o_tmpmemctx ); - } - slap_sl_free( ctrls[--num_ctrls], sop->o_tmpmemctx ); - ctrls[num_ctrls] = NULL; - if ( cookie.bv_val ) ch_free( cookie.bv_val ); - } - - } else { -#endif - rs->sr_ctrls = NULL; - rs->sr_ref = rs->sr_v2ref; - rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL; - rs->sr_rspoid = NULL; - if ( get_pagedresults(sop) > SLAP_CONTROL_IGNORED ) { - send_paged_response( sop, rs, NULL, 0 ); - } else { - send_ldap_result( sop, rs ); - } -#ifdef BDB_PSEARCH - } - } - - if ( sop->o_refresh_in_progress ) { - sop->o_refresh_in_progress = 0; + rs->sr_ctrls = NULL; + rs->sr_ref = rs->sr_v2ref; + rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL; + rs->sr_rspoid = NULL; + if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) { + send_paged_response( op, rs, NULL, 0 ); + } else { + send_ldap_result( op, rs ); } -#endif rs->sr_err = LDAP_SUCCESS; done: -#ifdef BDB_PSEARCH - if ( sop->o_psearch_finished ) { - avl_free( sop->o_psearch_finished, ch_free ); - } - - if( !IS_PSEARCH && e != NULL ) { - /* free reader lock */ -#ifdef SLAP_ZONE_ALLOC - slap_zn_runlock(bdb->bi_cache.c_zctx, e); -#endif - bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock ); - } - ber_bvfree( search_context_csn ); -#endif - - if ( !opinfo ) - LOCK_ID_FREE( bdb->bi_dbenv, locker ); - if( rs->sr_v2ref ) { ber_bvarray_free( rs->sr_v2ref ); rs->sr_v2ref = NULL; @@ -1938,7 +1062,7 @@ static int oc_filter( { int rc = 0; - assert( f ); + assert( f != NULL ); if( cur > *max ) *max = cur; @@ -1974,7 +1098,7 @@ static void *search_stack( Operation *op ) void *ret = NULL; if ( op->o_threadctx ) { - ldap_pvt_thread_pool_getkey( op->o_threadctx, search_stack, + ldap_pvt_thread_pool_getkey( op->o_threadctx, (void *)search_stack, &ret, NULL ); } else { ret = bdb->bi_search_stack; @@ -1984,8 +1108,8 @@ static void *search_stack( Operation *op ) ret = ch_malloc( bdb->bi_search_stack_depth * BDB_IDL_UM_SIZE * sizeof( ID ) ); if ( op->o_threadctx ) { - ldap_pvt_thread_pool_setkey( op->o_threadctx, search_stack, - ret, search_stack_free ); + ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)search_stack, + ret, search_stack_free, NULL, NULL ); } else { bdb->bi_search_stack = ret; } @@ -1994,11 +1118,10 @@ static void *search_stack( Operation *op ) } static int search_candidates( - Operation *stackop, Operation *op, SlapReply *rs, Entry *e, - u_int32_t locker, + DB_TXN *txn, ID *ids, ID *scopes ) { @@ -2006,11 +1129,9 @@ static int search_candidates( int rc, depth = 1; Filter f, rf, xf, nf; ID *stack; - AttributeAssertion aa_ref; -#ifdef BDB_SUBENTRIES + AttributeAssertion aa_ref = ATTRIBUTEASSERTION_INIT; Filter sf; - AttributeAssertion aa_subentry; -#endif + AttributeAssertion aa_subentry = ATTRIBUTEASSERTION_INIT; /* * This routine takes as input a filter (user-filter) @@ -2031,11 +1152,7 @@ static int search_candidates( * these clauses are redundant. */ if (!oc_filter(op->oq_search.rs_filter, 1, &depth) - && !get_subentries_visibility(op) -#ifdef BDB_PSEARCH - && !is_sync_protocol(op) -#endif - ) { + && !get_subentries_visibility(op)) { if( !get_manageDSAit(op) && !get_domainScope(op) ) { /* match referral objects */ struct berval bv_ref = BER_BVC( "referral" ); @@ -2060,7 +1177,6 @@ static int search_candidates( /* Filter depth increased again, adding dummy clause */ depth++; -#ifdef BDB_SUBENTRIES if( get_subentries_visibility( op ) ) { struct berval bv_subentry = BER_BVC( "subentry" ); sf.f_choice = LDAP_FILTER_EQUALITY; @@ -2070,23 +1186,22 @@ static int search_candidates( sf.f_next = nf.f_next; nf.f_next = &sf; } -#endif /* Allocate IDL stack, plus 1 more for former tmp */ if ( depth+1 > bdb->bi_search_stack_depth ) { stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) ); } else { - stack = search_stack( stackop ); + stack = search_stack( op ); } if( op->ors_deref & LDAP_DEREF_SEARCHING ) { - rc = search_aliases( op, rs, e, locker, ids, scopes, stack ); + rc = search_aliases( op, rs, e, txn, ids, scopes, stack ); } else { - rc = bdb_dn2idl( op, e, ids, stack ); + rc = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), ids, stack ); } if ( rc == LDAP_SUCCESS ) { - rc = bdb_filter_candidates( op, &f, ids, + rc = bdb_filter_candidates( op, txn, &f, ids, stack, stack+BDB_IDL_UM_SIZE ); } @@ -2113,12 +1228,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 @@ -2126,53 +1236,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 */ @@ -2186,24 +1260,9 @@ parse_paged_cookie( Operation *op, SlapReply *rs ) goto done; } - } 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; } @@ -2243,7 +1302,8 @@ send_paged_response( op->o_conn->c_pagedresults_state.ps_cookie = respcookie; op->o_conn->c_pagedresults_state.ps_count = - ((PagedResultsState *)op->o_pagedresults_state)->ps_count + rs->sr_nentries; + ((PagedResultsState *)op->o_pagedresults_state)->ps_count + + rs->sr_nentries; /* return size of 0 -- no estimate */ ber_printf( ber, "{iO}", 0, &cookie ); @@ -2264,18 +1324,3 @@ done: (void) ber_free_buf( ber ); } -static int -bdb_pfid_cmp( const void *v_id1, const void *v_id2 ) -{ - const ID *p1 = v_id1, *p2 = v_id2; - return *p1 - *p2; -} - -static ID* -bdb_id_dup( Operation *op, ID *id ) -{ - ID *new; - new = ch_malloc( sizeof(ID) ); - *new = *id; - return new; -}