mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-30 13:30:57 +08:00
ITS#6686 add multiple sorts per connection, from Raphael Ouazana @ Linagora
This commit is contained in:
parent
38d9e22b00
commit
e907ba219b
@ -34,6 +34,10 @@ connections. The default is one half of the number of server threads.
|
||||
.TP
|
||||
.B sssvlv\-maxkeys <num>
|
||||
Set the maximum number of keys allowed in a sort request. The default is 5.
|
||||
.TP
|
||||
.B sssvlv\-maxperconn <num>
|
||||
Set the maximum number of concurrent paged search requests per connection. The default is 5. The number of concurrent requests remains limited by
|
||||
.B sssvlv-max.
|
||||
.SH FILES
|
||||
.TP
|
||||
ETCDIR/slapd.conf
|
||||
|
@ -16,7 +16,8 @@
|
||||
*/
|
||||
/* ACKNOWLEDGEMENTS:
|
||||
* This work was initially developed by Howard Chu for inclusion in
|
||||
* OpenLDAP Software.
|
||||
* OpenLDAP Software. Support for multiple sorts per connection added
|
||||
* by Raphael Ouazana.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
@ -59,6 +60,10 @@
|
||||
#define SAFESTR(macro_str, macro_def) ((macro_str) ? (macro_str) : (macro_def))
|
||||
|
||||
#define SSSVLV_DEFAULT_MAX_KEYS 5
|
||||
#define SSSVLV_DEFAULT_MAX_REQUEST_PER_CONN 5
|
||||
|
||||
#define NO_PS_COOKIE (PagedResultsCookie) -1
|
||||
#define NO_VC_CONTEXT (unsigned long) -1
|
||||
|
||||
typedef struct vlv_ctrl {
|
||||
int vc_before;
|
||||
@ -85,6 +90,7 @@ typedef struct sort_ctrl {
|
||||
typedef struct sort_node
|
||||
{
|
||||
int sn_conn;
|
||||
int sn_session;
|
||||
struct berval sn_dn;
|
||||
struct berval *sn_vals;
|
||||
} sort_node;
|
||||
@ -94,6 +100,7 @@ typedef struct sssvlv_info
|
||||
int svi_max; /* max concurrent sorts */
|
||||
int svi_num; /* current # sorts */
|
||||
int svi_max_keys; /* max sort keys per request */
|
||||
int svi_max_percon; /* max concurrent sorts per con */
|
||||
} sssvlv_info;
|
||||
|
||||
typedef struct sort_op
|
||||
@ -107,11 +114,13 @@ typedef struct sort_op
|
||||
int so_vlv;
|
||||
int so_vlv_rc;
|
||||
int so_vlv_target;
|
||||
int so_session;
|
||||
unsigned long so_vcontext;
|
||||
} sort_op;
|
||||
|
||||
/* There is only one conn table for all overlay instances */
|
||||
static sort_op **sort_conns;
|
||||
/* Each conn can handle one session by context */
|
||||
static sort_op ***sort_conns;
|
||||
static ldap_pvt_thread_mutex_t sort_conns_mutex;
|
||||
static int ov_count;
|
||||
static const char *debug_header = "sssvlv";
|
||||
@ -155,7 +164,9 @@ 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 = sort_conns[sn1->sn_conn]->so_ctrl;
|
||||
assert( sort_conns[sn1->sn_conn] && sort_conns[sn1->sn_conn][sn1->sn_session]
|
||||
&& sort_conns[sn1->sn_conn][sn1->sn_session]->so_ctrl );
|
||||
sort_ctrl *sc = sort_conns[sn1->sn_conn][sn1->sn_session]->so_ctrl;
|
||||
MatchingRule *mr;
|
||||
int i, cmp = 0;
|
||||
|
||||
@ -328,21 +339,73 @@ static int pack_sss_response_control(
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/* Return the session id or -1 if unknown */
|
||||
static int find_session_by_context(
|
||||
int svi_max_percon,
|
||||
int conn_id,
|
||||
unsigned long vc_context,
|
||||
PagedResultsCookie ps_cookie )
|
||||
{
|
||||
int sess_id;
|
||||
for(sess_id = 0; sess_id < svi_max_percon; sess_id++) {
|
||||
if( sort_conns[conn_id] && sort_conns[conn_id][sess_id] &&
|
||||
( sort_conns[conn_id][sess_id]->so_vcontext == vc_context ||
|
||||
(PagedResultsCookie) sort_conns[conn_id][sess_id]->so_tree == ps_cookie ) )
|
||||
return sess_id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_next_session(
|
||||
int svi_max_percon,
|
||||
int conn_id )
|
||||
{
|
||||
int sess_id;
|
||||
assert(sort_conns[conn_id] != NULL);
|
||||
for(sess_id = 0; sess_id < svi_max_percon; sess_id++) {
|
||||
if(!sort_conns[conn_id][sess_id]) {
|
||||
return sess_id;
|
||||
}
|
||||
}
|
||||
if (sess_id >= svi_max_percon) {
|
||||
return -1;
|
||||
} else {
|
||||
return sess_id;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_sort_op( Connection *conn, sort_op *so )
|
||||
{
|
||||
int sess_id;
|
||||
PagedResultsCookie ps_cookie = (PagedResultsCookie) so->so_tree;
|
||||
if ( so->so_tree ) {
|
||||
tavl_free( so->so_tree, ch_free );
|
||||
so->so_tree = NULL;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &sort_conns_mutex );
|
||||
sort_conns[conn->c_conn_idx] = NULL;
|
||||
sess_id = find_session_by_context( so->so_info->svi_max_percon, conn->c_conn_idx, so->so_vcontext, ps_cookie );
|
||||
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 );
|
||||
}
|
||||
|
||||
static void free_sort_ops( Connection *conn, sort_op **sos, int svi_max_percon )
|
||||
{
|
||||
int sess_id;
|
||||
sort_op *so;
|
||||
|
||||
for( sess_id = 0; sess_id < svi_max_percon ; sess_id++ ) {
|
||||
so = sort_conns[conn->c_conn_idx][sess_id];
|
||||
if ( so ) {
|
||||
free_sort_op( conn, so );
|
||||
sort_conns[conn->c_conn_idx][sess_id] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void send_list(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
@ -427,6 +490,7 @@ range_err:
|
||||
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_context( so->so_info->svi_max_percon, op->o_conn->c_conn_idx, vc->vc_context, NO_PS_COOKIE );
|
||||
sn->sn_vals[0] = bv;
|
||||
for (i=1; i<sc->sc_nkeys; i++) {
|
||||
BER_BVZERO( &sn->sn_vals[i] );
|
||||
@ -665,6 +729,7 @@ static int sssvlv_op_response(
|
||||
op->o_tmpfree( sn, op->o_tmpmemctx );
|
||||
sn = sn2;
|
||||
sn->sn_conn = op->o_conn->c_conn_idx;
|
||||
sn->sn_session = find_session_by_context( so->so_info->svi_max_percon, op->o_conn->c_conn_idx, so->so_vcontext, (PagedResultsCookie) so->so_tree );
|
||||
|
||||
/* Insert into the AVL tree */
|
||||
tavl_insert(&(so->so_tree), sn, node_insert, avl_dup_error);
|
||||
@ -700,10 +765,11 @@ static int sssvlv_op_search(
|
||||
sssvlv_info *si = on->on_bi.bi_private;
|
||||
int rc = SLAP_CB_CONTINUE;
|
||||
int ok;
|
||||
sort_op *so, so2;
|
||||
sort_op *so = NULL, so2;
|
||||
sort_ctrl *sc;
|
||||
PagedResultsState *ps;
|
||||
vlv_ctrl *vc;
|
||||
int sess_id;
|
||||
|
||||
if ( op->o_ctrlflag[sss_cid] <= SLAP_CONTROL_IGNORED ) {
|
||||
if ( op->o_ctrlflag[vlv_cid] > SLAP_CONTROL_IGNORED ) {
|
||||
@ -712,6 +778,7 @@ static int sssvlv_op_search(
|
||||
so2.so_vlv_target = 0;
|
||||
so2.so_nentries = 0;
|
||||
so2.so_vlv_rc = LDAP_VLV_SSS_MISSING;
|
||||
so2.so_vlv = op->o_ctrlflag[vlv_cid];
|
||||
rc = pack_vlv_response_control( op, rs, &so2, ctrls );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
ctrls[1] = NULL;
|
||||
@ -750,9 +817,10 @@ static int sssvlv_op_search(
|
||||
|
||||
ok = 1;
|
||||
ldap_pvt_thread_mutex_lock( &sort_conns_mutex );
|
||||
so = sort_conns[op->o_conn->c_conn_idx];
|
||||
/* Is there already a sort running on this conn? */
|
||||
if ( so ) {
|
||||
sess_id = find_session_by_context( si->svi_max_percon, op->o_conn->c_conn_idx, vc ? vc->vc_context : NO_VC_CONTEXT, ps ? ps->ps_cookie : NO_PS_COOKIE );
|
||||
if ( sess_id >= 0 ) {
|
||||
so = sort_conns[op->o_conn->c_conn_idx][sess_id];
|
||||
/* Is it a continuation of a VLV search? */
|
||||
if ( !vc || so->so_vlv <= SLAP_CONTROL_IGNORED ||
|
||||
vc->vc_context != so->so_vcontext ) {
|
||||
@ -777,21 +845,24 @@ static int sssvlv_op_search(
|
||||
/* Are there too many running overall? */
|
||||
} else if ( si->svi_num >= si->svi_max ) {
|
||||
ok = 0;
|
||||
} else if ( ( sess_id = find_next_session(si->svi_max_percon, op->o_conn->c_conn_idx ) ) < 0 ) {
|
||||
ok = 0;
|
||||
} else {
|
||||
/* OK, this connection now has a sort running */
|
||||
si->svi_num++;
|
||||
sort_conns[op->o_conn->c_conn_idx] = &so2;
|
||||
sort_conns[op->o_conn->c_conn_idx][sess_id] = &so2;
|
||||
sort_conns[op->o_conn->c_conn_idx][sess_id]->so_session = sess_id;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &sort_conns_mutex );
|
||||
if ( ok ) {
|
||||
/* are we continuing a VLV search? */
|
||||
if ( vc && vc->vc_context ) {
|
||||
if ( so && vc && vc->vc_context ) {
|
||||
so->so_ctrl = sc;
|
||||
send_list( op, rs, so );
|
||||
send_result( op, rs, so );
|
||||
rc = LDAP_SUCCESS;
|
||||
/* are we continuing a paged search? */
|
||||
} else if ( ps && ps->ps_cookie ) {
|
||||
} else if ( so && ps && ps->ps_cookie ) {
|
||||
so->so_ctrl = sc;
|
||||
send_page( op, rs, so );
|
||||
send_result( op, rs, so );
|
||||
@ -805,7 +876,7 @@ static int sssvlv_op_search(
|
||||
} else {
|
||||
so = op->o_tmpcalloc( 1, sizeof(sort_op), op->o_tmpmemctx );
|
||||
}
|
||||
sort_conns[op->o_conn->c_conn_idx] = so;
|
||||
sort_conns[op->o_conn->c_conn_idx][sess_id] = so;
|
||||
|
||||
cb->sc_cleanup = NULL;
|
||||
cb->sc_response = sssvlv_op_response;
|
||||
@ -830,6 +901,8 @@ static int sssvlv_op_search(
|
||||
so->so_vlv = SLAP_CONTROL_NONE;
|
||||
}
|
||||
}
|
||||
so->so_session = sess_id;
|
||||
so->so_vlv = op->o_ctrlflag[vlv_cid];
|
||||
so->so_vcontext = (unsigned long)so;
|
||||
so->so_nentries = 0;
|
||||
|
||||
@ -1099,8 +1172,12 @@ static int vlv_parseCtrl(
|
||||
|
||||
static int sssvlv_connection_destroy( BackendDB *be, Connection *conn )
|
||||
{
|
||||
if ( sort_conns[conn->c_conn_idx] )
|
||||
free_sort_op( conn, sort_conns[conn->c_conn_idx] );
|
||||
slap_overinst *on = (slap_overinst *)be->bd_info;
|
||||
sssvlv_info *si = on->on_bi.bi_private;
|
||||
|
||||
if ( sort_conns[conn->c_conn_idx] ) {
|
||||
free_sort_ops( conn, sort_conns[conn->c_conn_idx], si->svi_max_percon );
|
||||
}
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
@ -1112,11 +1189,22 @@ static int sssvlv_db_open(
|
||||
slap_overinst *on = (slap_overinst *)be->bd_info;
|
||||
sssvlv_info *si = on->on_bi.bi_private;
|
||||
int rc;
|
||||
int conn_index;
|
||||
|
||||
/* If not set, default to 1/2 of available threads */
|
||||
if ( !si->svi_max )
|
||||
si->svi_max = connection_pool_max / 2;
|
||||
|
||||
if ( dtblsize && !sort_conns ) {
|
||||
ldap_pvt_thread_mutex_init( &sort_conns_mutex );
|
||||
/* accommodate for c_conn_idx == -1 */
|
||||
sort_conns = ch_calloc( dtblsize + 1, sizeof(sort_op **) );
|
||||
for ( conn_index = 0 ; conn_index < dtblsize + 1 ; conn_index++ ) {
|
||||
sort_conns[conn_index] = ch_calloc( si->svi_max_percon, sizeof(sort_op *) );
|
||||
}
|
||||
sort_conns++;
|
||||
}
|
||||
|
||||
rc = overlay_register_control( be, LDAP_CONTROL_SORTREQUEST );
|
||||
if ( rc == LDAP_SUCCESS )
|
||||
rc = overlay_register_control( be, LDAP_CONTROL_VLVREQUEST );
|
||||
@ -1136,6 +1224,12 @@ static ConfigTable sssvlv_cfg[] = {
|
||||
"( OLcfgOvAt:21.2 NAME 'olcSssVlvMaxKeys' "
|
||||
"DESC 'Maximum number of Keys in a Sort request' "
|
||||
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
||||
{ "sssvlv-maxpercon", "num",
|
||||
2, 2, 0, ARG_INT|ARG_OFFSET,
|
||||
(void *)offsetof(sssvlv_info, svi_max_percon),
|
||||
"( OLcfgOvAt:21.3 NAME 'olcSssVlvMaxPerConn' "
|
||||
"DESC 'Maximum number of concurrent paged search requests per connection' "
|
||||
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
||||
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
|
||||
};
|
||||
|
||||
@ -1194,13 +1288,8 @@ static int sssvlv_db_init(
|
||||
si->svi_max = 0;
|
||||
si->svi_num = 0;
|
||||
si->svi_max_keys = SSSVLV_DEFAULT_MAX_KEYS;
|
||||
si->svi_max_percon = SSSVLV_DEFAULT_MAX_REQUEST_PER_CONN;
|
||||
|
||||
if ( dtblsize && !sort_conns ) {
|
||||
ldap_pvt_thread_mutex_init( &sort_conns_mutex );
|
||||
/* accommodate for c_conn_idx == -1 */
|
||||
sort_conns = ch_calloc( sizeof(sort_op *), dtblsize + 1 );
|
||||
sort_conns++;
|
||||
}
|
||||
ov_count++;
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
@ -1212,10 +1301,14 @@ static int sssvlv_db_destroy(
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)be->bd_info;
|
||||
sssvlv_info *si = (sssvlv_info *)on->on_bi.bi_private;
|
||||
int conn_index;
|
||||
|
||||
ov_count--;
|
||||
if ( !ov_count && sort_conns) {
|
||||
sort_conns--;
|
||||
for ( conn_index = 0 ; conn_index < dtblsize + 1 ; conn_index++ ) {
|
||||
ch_free(sort_conns[conn_index]);
|
||||
}
|
||||
ch_free(sort_conns);
|
||||
ldap_pvt_thread_mutex_destroy( &sort_conns_mutex );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user