Example #1
0
static void free_sort_op( Connection *conn, sort_op *so )
{
	ldap_pvt_thread_mutex_lock( &sort_conns_mutex );
	int sess_id = find_session_by_so( so->so_info->svi_max_percon, conn->c_conn_idx, so );

	if (sess_id < 0 || ! so) {
		ldap_pvt_thread_mutex_unlock( &sort_conns_mutex );
		return;
	}

	assert(sort_conns[conn->c_conn_idx][sess_id] == so);
	assert(so->so_info->svi_num > 0);
	sort_conns[conn->c_conn_idx][sess_id] = NULL;
	so->so_info->svi_num--;
	ldap_pvt_thread_mutex_unlock( &sort_conns_mutex );

	if ( so->so_tree ) {
		if ( so->so_paged > SLAP_CONTROL_IGNORED ) {
			TAvlnode *cur_node = so->so_tree;
			while ( cur_node ) {
				TAvlnode *next_node = tavl_next( cur_node, TAVL_DIR_RIGHT );
				ch_free( cur_node->avl_data );
				ber_memfree( cur_node );

				cur_node = next_node;
			}
		} else {
			tavl_free( so->so_tree, ch_free );
		}
		so->so_tree = NULL;
	}

	ch_free( so );
}
Example #2
0
static void free_sort_op( Connection *conn, sort_op *so )
{
    int sess_id;
    if ( so->so_tree ) {
        tavl_free( so->so_tree, ch_free );
        so->so_tree = NULL;
    }

    ldap_pvt_thread_mutex_lock( &sort_conns_mutex );
    sess_id = find_session_by_so( so->so_info->svi_max_percon, conn->c_conn_idx, so );
    sort_conns[conn->c_conn_idx][sess_id] = NULL;
    so->so_info->svi_num--;
    ldap_pvt_thread_mutex_unlock( &sort_conns_mutex );

    ch_free( so );
}
Example #3
0
static int sssvlv_op_response(
	Operation	*op,
	SlapReply	*rs )
{
	sort_ctrl *sc = op->o_controls[sss_cid];
	sort_op *so = op->o_callback->sc_private;

	if ( rs->sr_type == REP_SEARCH ) {
		int i;
		size_t len;
		sort_node *sn, *sn2;
		struct berval *bv;
		char *ptr;

		len = sizeof(sort_node) + sc->sc_nkeys * sizeof(struct berval) +
			rs->sr_entry->e_nname.bv_len + 1;
		sn = op->o_tmpalloc( len, op->o_tmpmemctx );
		sn->sn_vals = (struct berval *)(sn+1);

		/* Build tmp list of key values */
		for ( i=0; i<sc->sc_nkeys; i++ ) {
			Attribute *a = attr_find( rs->sr_entry->e_attrs,
				sc->sc_keys[i].sk_ad );
			if ( a ) {
				if ( a->a_numvals > 1 ) {
					bv = select_value( a, &sc->sc_keys[i] );
				} else {
					bv = a->a_nvals;
				}
				sn->sn_vals[i] = *bv;
				len += bv->bv_len + 1;
			} else {
				BER_BVZERO( &sn->sn_vals[i] );
			}
		}

		/* Now dup into regular memory */
		sn2 = ch_malloc( len );
		sn2->sn_vals = (struct berval *)(sn2+1);
		memcpy( sn2->sn_vals, sn->sn_vals,
				sc->sc_nkeys * sizeof(struct berval));

		ptr = (char *)(sn2->sn_vals + sc->sc_nkeys);
		sn2->sn_dn.bv_val = ptr;
		sn2->sn_dn.bv_len = rs->sr_entry->e_nname.bv_len;
		memcpy( ptr, rs->sr_entry->e_nname.bv_val,
			rs->sr_entry->e_nname.bv_len );
		ptr += rs->sr_entry->e_nname.bv_len;
		*ptr++ = '\0';
		for ( i=0; i<sc->sc_nkeys; i++ ) {
			if ( !BER_BVISNULL( &sn2->sn_vals[i] )) {
				memcpy(ptr, sn2->sn_vals[i].bv_val, sn2->sn_vals[i].bv_len);
				sn2->sn_vals[i].bv_val = ptr;
				ptr += sn2->sn_vals[i].bv_len;
				*ptr++ = '\0';
			}
		}
		op->o_tmpfree( sn, op->o_tmpmemctx );
		sn = sn2;
		sn->sn_conn = op->o_conn->c_conn_idx;
		sn->sn_session = find_session_by_so( so->so_info->svi_max_percon, op->o_conn->c_conn_idx, so );

		/* Insert into the AVL tree */
		tavl_insert(&(so->so_tree), sn, node_insert, avl_dup_error);

		so->so_nentries++;

		/* Collected the keys so that they can be sorted.  Thus, stop
		 * the entry from propagating.
		 */
		rs->sr_err = LDAP_SUCCESS;
	}
	else if ( rs->sr_type == REP_RESULT ) {
		/* Remove serversort response callback.
		 * We don't want the entries that we are about to send to be
		 * processed by serversort response again. */
		slap_callback **scp = &op->o_callback;
		while ( *scp ) {
			if ( (*scp)->sc_response == sssvlv_op_response ) {
				*scp = (*scp)->sc_next;
				break;
			}
			scp = &(*scp)->sc_next;
		}

		send_entry( op, rs, so );
		send_result( op, rs, so );
	}

	return rs->sr_err;
}
Example #4
0
static void send_list(
	Operation		*op,
	SlapReply		*rs,
	sort_op			*so)
{
	TAvlnode *cur_node, *tmp_node;
	vlv_ctrl *vc = op->o_controls[vlv_cid];
	int i, j, dir, rc;
	BackendDB *be;
	Entry *e;
	LDAPControl *ctrls[2];

	rs->sr_attrs = op->ors_attrs;

	/* FIXME: it may be better to just flatten the tree into
	 * an array before doing all of this...
	 */

	/* Are we just counting an offset? */
	if ( BER_BVISNULL( &vc->vc_value )) {
		if ( vc->vc_offset == vc->vc_count ) {
			/* wants the last entry in the list */
			cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
			so->so_vlv_target = so->so_nentries;
		} else if ( vc->vc_offset == 1 ) {
			/* wants the first entry in the list */
			cur_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
			so->so_vlv_target = 1;
		} else {
			int target;
			/* Just iterate to the right spot */
			if ( vc->vc_count && vc->vc_count != so->so_nentries ) {
				if ( vc->vc_offset > vc->vc_count )
					goto range_err;
				target = so->so_nentries * vc->vc_offset / vc->vc_count;
			} else {
				if ( vc->vc_offset > so->so_nentries ) {
range_err:
					so->so_vlv_rc = LDAP_VLV_RANGE_ERROR;
					pack_vlv_response_control( op, rs, so, ctrls );
					ctrls[1] = NULL;
					slap_add_ctrls( op, rs, ctrls );
					rs->sr_err = LDAP_VLV_ERROR;
					return;
				}
				target = vc->vc_offset;
			}
			so->so_vlv_target = target;
			/* Start at left and go right, or start at right and go left? */
			if ( target < so->so_nentries / 2 ) {
				cur_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
				dir = TAVL_DIR_RIGHT;
			} else {
				cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
				dir = TAVL_DIR_LEFT;
				target = so->so_nentries - target + 1;
			}
			for ( i=1; i<target; i++ )
				cur_node = tavl_next( cur_node, dir );
		}
	} else {
	/* we're looking for a specific value */
		sort_ctrl *sc = so->so_ctrl;
		MatchingRule *mr = sc->sc_keys[0].sk_ordering;
		sort_node *sn;
		struct berval bv;

		if ( mr->smr_normalize ) {
			rc = mr->smr_normalize( SLAP_MR_VALUE_OF_SYNTAX,
				mr->smr_syntax, mr, &vc->vc_value, &bv, op->o_tmpmemctx );
			if ( rc ) {
				so->so_vlv_rc = LDAP_INAPPROPRIATE_MATCHING;
				pack_vlv_response_control( op, rs, so, ctrls );
				ctrls[1] = NULL;
				slap_add_ctrls( op, rs, ctrls );
				rs->sr_err = LDAP_VLV_ERROR;
				return;
			}
		} else {
			bv = vc->vc_value;
		}

		sn = op->o_tmpalloc( sizeof(sort_node) +
			sc->sc_nkeys * sizeof(struct berval), op->o_tmpmemctx );
		sn->sn_vals = (struct berval *)(sn+1);
		sn->sn_conn = op->o_conn->c_conn_idx;
		sn->sn_session = find_session_by_so( so->so_info->svi_max_percon, op->o_conn->c_conn_idx, so );
		sn->sn_vals[0] = bv;
		for (i=1; i<sc->sc_nkeys; i++) {
			BER_BVZERO( &sn->sn_vals[i] );
		}
		cur_node = tavl_find3( so->so_tree, sn, node_cmp, &j );
		/* didn't find >= match */
		if ( j > 0 ) {
			if ( cur_node )
				cur_node = tavl_next( cur_node, TAVL_DIR_RIGHT );
		}
		op->o_tmpfree( sn, op->o_tmpmemctx );

		if ( !cur_node ) {
			so->so_vlv_target = so->so_nentries + 1;
		} else {
			sort_node *sn = so->so_tree->avl_data;
			/* start from the left or the right side? */
			mr->smr_match( &i, 0, mr->smr_syntax, mr, &bv, &sn->sn_vals[0] );
			if ( i > 0 ) {
				tmp_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
				dir = TAVL_DIR_LEFT;
			} else {
				tmp_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
				dir = TAVL_DIR_RIGHT;
			}
			for (i=0; tmp_node != cur_node;
				tmp_node = tavl_next( tmp_node, dir ), i++);
			so->so_vlv_target = (dir == TAVL_DIR_RIGHT) ? i+1 : so->so_nentries - i;
		}
		if ( bv.bv_val != vc->vc_value.bv_val )
			op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
	}
	if ( !cur_node ) {
		i = 1;
		cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
	} else {
		i = 0;
	}
	for ( ; i<vc->vc_before; i++ ) {
		tmp_node = tavl_next( cur_node, TAVL_DIR_LEFT );
		if ( !tmp_node ) break;
		cur_node = tmp_node;
	}
	j = i + vc->vc_after + 1;
	be = op->o_bd;
	for ( i=0; i<j; i++ ) {
		sort_node *sn = cur_node->avl_data;

		if ( slapd_shutdown ) break;

		op->o_bd = select_backend( &sn->sn_dn, 0 );
		e = NULL;
		rc = be_entry_get_rw( op, &sn->sn_dn, NULL, NULL, 0, &e );

		if ( e && rc == LDAP_SUCCESS ) {
			rs->sr_entry = e;
			rs->sr_flags = REP_ENTRY_MUSTRELEASE;
			rs->sr_err = send_search_entry( op, rs );
			if ( rs->sr_err == LDAP_UNAVAILABLE )
				break;
		}
		cur_node = tavl_next( cur_node, TAVL_DIR_RIGHT );
		if ( !cur_node ) break;
	}
	so->so_vlv_rc = LDAP_SUCCESS;

	op->o_bd = be;
}