/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2009-2013 The OpenLDAP Foundation.
+ * Copyright 2009-2018 The OpenLDAP Foundation.
* Portions copyright 2009 Symas Corporation.
* All rights reserved.
*
typedef struct sort_op
{
- Avlnode *so_tree;
+ TAvlnode *so_tree;
sort_ctrl *so_ctrl;
sssvlv_info *so_info;
int so_paged;
int so_vlv_target;
int so_session;
unsigned long so_vcontext;
+ int so_running;
} sort_op;
/* There is only one conn table for all overlay instances */
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--;
+ if ( sess_id > -1 ) {
+ 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 );
+
+ if ( sess_id > -1 ){
+ if ( so->so_tree ) {
+ if ( so->so_paged > SLAP_CONTROL_IGNORED ) {
+ TAvlnode *cur_node, *next_node;
+ cur_node = so->so_tree;
+ while ( cur_node ) {
+ 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 );
+ }
}
static void free_sort_ops( Connection *conn, sort_op **sos, int svi_max_percon )
SlapReply *rs,
sort_op *so)
{
- Avlnode *cur_node, *tmp_node;
+ TAvlnode *cur_node, *tmp_node;
vlv_ctrl *vc = op->o_controls[vlv_cid];
int i, j, dir, rc;
BackendDB *be;
static void send_page( Operation *op, SlapReply *rs, sort_op *so )
{
- Avlnode *cur_node = so->so_tree;
- Avlnode *next_node = NULL;
+ TAvlnode *cur_node = so->so_tree;
+ TAvlnode *next_node = NULL;
BackendDB *be = op->o_bd;
Entry *e;
int rc;
/* Set the first entry to send for the next page */
so->so_tree = next_node;
- next_node->avl_left = NULL;
+ if ( next_node )
+ next_node->avl_left = NULL;
op->o_bd = be;
}
return;
/* RFC 2891: If critical then send the entries iff they were
- * succesfully sorted. If non-critical send all entries
+ * successfully sorted. If non-critical send all entries
* whether they were sorted or not.
*/
if ( (op->o_ctrlflag[sss_cid] != SLAP_CONTROL_CRITICAL) ||
send_list( op, rs, so );
} else {
/* Get the first node to send */
- Avlnode *start_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
+ TAvlnode *start_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
so->so_tree = start_node;
if ( so->so_paged <= SLAP_CONTROL_IGNORED ) {
if ( so->so_tree == NULL ) {
/* Search finished, so clean up */
free_sort_op( op->o_conn, so );
+ } else {
+ so->so_running = 0;
}
}
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 ) {
- /* Is it a continuation of a paged search? */
- if ( !ps || so->so_paged <= SLAP_CONTROL_IGNORED ||
- op->o_conn->c_pagedresults_state.ps_cookie != ps->ps_cookie ) {
- ok = 0;
- } else if ( !ps->ps_size ) {
- /* Abandoning current request */
- ok = 0;
- so->so_nentries = 0;
- rs->sr_err = LDAP_SUCCESS;
- }
- }
- if (( vc && so->so_paged > SLAP_CONTROL_IGNORED ) ||
- ( ps && so->so_vlv > SLAP_CONTROL_IGNORED )) {
- /* changed from paged to vlv or vice versa, abandon */
- ok = 0;
- so->so_nentries = 0;
- rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+
+ if( so->so_running > 0 ){
+ /* another thread is handling, response busy to client */
+ so = NULL;
+ ok = 0;
+ } else {
+
+ /* Is it a continuation of a VLV search? */
+ if ( !vc || so->so_vlv <= SLAP_CONTROL_IGNORED ||
+ vc->vc_context != so->so_vcontext ) {
+ /* Is it a continuation of a paged search? */
+ if ( !ps || so->so_paged <= SLAP_CONTROL_IGNORED ||
+ op->o_conn->c_pagedresults_state.ps_cookie != ps->ps_cookie ) {
+ ok = 0;
+ } else if ( !ps->ps_size ) {
+ /* Abandoning current request */
+ ok = 0;
+ so->so_nentries = 0;
+ rs->sr_err = LDAP_SUCCESS;
+ }
+ }
+ if (( vc && so->so_paged > SLAP_CONTROL_IGNORED ) ||
+ ( ps && so->so_vlv > SLAP_CONTROL_IGNORED )) {
+ /* changed from paged to vlv or vice versa, abandon */
+ ok = 0;
+ so->so_nentries = 0;
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ }
+
+ if ( ok ) {
+ /* occupy before mutex unlock */
+ so->so_running = 1;
+ }
+
}
/* Are there too many running overall? */
} else if ( si->svi_num >= si->svi_max ) {
cb->sc_response = sssvlv_op_response;
cb->sc_next = op->o_callback;
cb->sc_private = so;
+ cb->sc_writewait = NULL;
so->so_tree = NULL;
so->so_ctrl = sc;
so->so_vlv = op->o_ctrlflag[vlv_cid];
so->so_vcontext = (unsigned long)so;
so->so_nentries = 0;
+ so->so_running = 1;
op->o_callback = cb;
}
"NAME 'olcSssVlvConfig' "
"DESC 'SSS VLV configuration' "
"SUP olcOverlayConfig "
- "MAY ( olcSssVlvMax $ olcSssVlvMaxKeys ) )",
+ "MAY ( olcSssVlvMax $ olcSssVlvMaxKeys $ olcSssVlvMaxPerConn ) )",
Cft_Overlay, sssvlv_cfg, NULL, NULL },
{ NULL, 0, NULL }
};