Ejemplo n.º 1
0
static int node_cmp( const void* val1, const void* val2 )
{
	sort_node *sn1 = (sort_node *)val1;
	sort_node *sn2 = (sort_node *)val2;
	sort_ctrl *sc;
	MatchingRule *mr;
	int i, cmp = 0;
	assert( sort_conns[sn1->sn_conn]
		&& sort_conns[sn1->sn_conn][sn1->sn_session]
		&& sort_conns[sn1->sn_conn][sn1->sn_session]->so_ctrl );
	sc = sort_conns[sn1->sn_conn][sn1->sn_session]->so_ctrl;

	for ( i=0; cmp == 0 && i<sc->sc_nkeys; i++ ) {
		if ( BER_BVISNULL( &sn1->sn_vals[i] )) {
			if ( BER_BVISNULL( &sn2->sn_vals[i] ))
				cmp = 0;
			else
				cmp = sc->sc_keys[i].sk_direction;
		} else if ( BER_BVISNULL( &sn2->sn_vals[i] )) {
			cmp = sc->sc_keys[i].sk_direction * -1;
		} else {
			mr = sc->sc_keys[i].sk_ordering;
			mr->smr_match( &cmp, 0, mr->smr_syntax, mr,
				&sn1->sn_vals[i], &sn2->sn_vals[i] );
			if ( cmp )
				cmp *= sc->sc_keys[i].sk_direction;
		}
	}
	return cmp;
}
Ejemplo n.º 2
0
/* RFC 2981 Section 2.2
 * If a sort key is a multi-valued attribute, and an entry happens to
 * have multiple values for that attribute and no other controls are
 * present that affect the sorting order, then the server SHOULD use the
 * least value (according to the ORDERING rule for that attribute).
 */
static struct berval* select_value(
	Attribute		*attr,
	sort_key			*key )
{
	struct berval* ber1, *ber2;
	MatchingRule *mr = key->sk_ordering;
	unsigned i;
	int cmp;

	ber1 = &(attr->a_nvals[0]);
	ber2 = ber1+1;
	for ( i = 1; i < attr->a_numvals; i++,ber2++ ) {
		mr->smr_match( &cmp, 0, mr->smr_syntax, mr, ber1, ber2 );
		if ( cmp > 0 ) {
			ber1 = ber2;
		}
	}

	Debug(LDAP_DEBUG_TRACE, "%s: value selected for compare: %s\n",
		debug_header,
		SAFESTR(ber1->bv_val, "<Empty>"),
		0);

	return ber1;
}
Ejemplo n.º 3
0
string DebugPrint(MatchingRule const & rule) { return rule.ToString(); }
Ejemplo n.º 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;
}