#include "slap.h"
#include "lutil.h"
+#include "config.h"
+
+#include "../../../libraries/liblber/lber-int.h" /* ber_rewind */
/* RFC2891: Server Side Sorting
* RFC2696: Paged Results
#define SAFESTR(macro_str, macro_def) ((macro_str) ? (macro_str) : (macro_def))
+#define SSSVLV_DEFAULT_MAX_KEYS 5
+
typedef struct vlv_ctrl {
int vc_before;
int vc_after;
typedef struct sort_ctrl {
int sc_nkeys;
- sort_key sc_keys[0];
+ sort_key sc_keys[1];
} sort_ctrl;
LDAPControl *ctrl;
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
- PagedResultsCookie resp_cookie;
struct berval cookie, bv;
int rc;
ch_free( so );
}
-static int send_list(
+static void send_list(
Operation *op,
SlapReply *rs,
sort_op *so)
for (i=1; i<sc->sc_nkeys; i++) {
BER_BVZERO( &sn->sn_vals[i] );
}
- cur_node = tavl_find2( so->so_tree, sn, node_cmp );
+ cur_node = tavl_find3( so->so_tree, sn, node_cmp, &j );
+ /* didn't find >= match */
+ if ( j > 0 )
+ cur_node = NULL;
op->o_tmpfree( sn, op->o_tmpmemctx );
if ( !cur_node ) {
"%s: response control: status=%d, text=%s\n",
debug_header, rs->sr_err, SAFESTR(rs->sr_text, "<None>"));
+ if ( !so->so_tree )
+ return;
+
/* RFC 2891: If critical then send the entries iff they were
* succesfully sorted. If non-critical send all entries
* whether they were sorted or not.
sn2->sn_vals = (struct berval *)(sn2+1);
AC_MEMCPY( sn2->sn_vals, sn->sn_vals,
sc->sc_nkeys * sizeof(struct berval));
- sn = sn2;
- ptr = (char *)(sn->sn_vals + sc->sc_nkeys);
- sn->sn_dn.bv_val = ptr;
- sn->sn_dn.bv_len = rs->sr_entry->e_nname.bv_len;
+ 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;
AC_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( &sn->sn_vals[i] )) {
- AC_MEMCPY( ptr, sn->sn_vals[i].bv_val, sn->sn_vals[i].bv_len );
- sn->sn_vals[i].bv_val = ptr;
- ptr += sn->sn_vals[i].bv_len;
+ if ( !BER_BVISNULL( &sn2->sn_vals[i] )) {
+ AC_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;
/* Insert into the AVL tree */
} else {
so->so_paged = 0;
so->so_page_size = 0;
- if ( vc )
+ if ( vc ) {
so->so_vlv = op->o_ctrlflag[vlv_cid];
+ so->so_vlv_target = 0;
+ so->so_vlv_rc = 0;
+ }
}
so->so_vcontext = (unsigned long)so;
so->so_nentries = 0;
i = count_key( ber );
sc = op->o_tmpalloc( sizeof(sort_ctrl) +
- i * sizeof(sort_key), op->o_tmpmemctx );
+ (i-1) * sizeof(sort_key), op->o_tmpmemctx );
sc->sc_nkeys = i;
op->o_controls[sss_cid] = sc;
BackendDB *be,
ConfigReply *cr )
{
- int rc = overlay_register_control( be, LDAP_CONTROL_SORTREQUEST );
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+ sssvlv_info *si = on->on_bi.bi_private;
+ int rc;
+
+ /* If not set, default to 1/2 of available threads */
+ if ( !si->svi_max )
+ si->svi_max = connection_pool_max / 2;
+
+ rc = overlay_register_control( be, LDAP_CONTROL_SORTREQUEST );
if ( rc == LDAP_SUCCESS )
rc = overlay_register_control( be, LDAP_CONTROL_VLVREQUEST );
return rc;
}
+static ConfigTable sssvlv_cfg[] = {
+ { "sssvlv-max", "num",
+ 2, 2, 0, ARG_INT|ARG_OFFSET,
+ (void *)offsetof(sssvlv_info, svi_max),
+ "( OLcfgOvAt:21.1 NAME 'olcSssVlvMax' "
+ "DESC 'Maximum number of concurrent Sort requests' "
+ "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+ { "sssvlv-maxkeys", "num",
+ 2, 2, 0, ARG_INT|ARG_OFFSET,
+ (void *)offsetof(sssvlv_info, svi_max_keys),
+ "( OLcfgOvAt:21.2 NAME 'olcSssVlvMaxKeys' "
+ "DESC 'Maximum number of Keys in a Sort request' "
+ "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs sssvlv_ocs[] = {
+ { "( OLcfgOvOc:21.1 "
+ "NAME 'olcSssVlvConfig' "
+ "DESC 'SSS VLV configuration' "
+ "SUP olcOverlayConfig "
+ "MAY ( olcSssVlvMax $ olcSssVlvMaxKeys ) )",
+ Cft_Overlay, sssvlv_cfg, NULL, NULL },
+ { NULL, 0, NULL }
+};
+
static int sssvlv_db_init(
BackendDB *be,
ConfigReply *cr)
si = (sssvlv_info *)ch_malloc(sizeof(sssvlv_info));
on->on_bi.bi_private = si;
- si->svi_max = 5;
+ si->svi_max = 0;
si->svi_num = 0;
- si->svi_max_keys = 5;
+ si->svi_max_keys = SSSVLV_DEFAULT_MAX_KEYS;
if ( dtblsize && !sort_conns ) {
ldap_pvt_thread_mutex_init( &sort_conns_mutex );
sssvlv.on_bi.bi_connection_destroy = sssvlv_connection_destroy;
sssvlv.on_bi.bi_op_search = sssvlv_op_search;
+ sssvlv.on_bi.bi_cf_ocs = sssvlv_ocs;
+
+ rc = config_register_schema( sssvlv_cfg, sssvlv_ocs );
+ if ( rc )
+ return rc;
+
rc = register_supported_control2( LDAP_CONTROL_SORTREQUEST,
SLAP_CTRL_SEARCH,
NULL,