X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fsssvlv.c;h=e650840530bbad6a8635da848bc192da9ec9eac8;hb=59e9ff6243465640956b58ad1756a3ede53eca7c;hp=50e0710d1fa6bc6b853c9e5f2491da846b741f74;hpb=9328a41f49b22089e85084e6676a764c2573ede1;p=openldap diff --git a/servers/slapd/overlays/sssvlv.c b/servers/slapd/overlays/sssvlv.c index 50e0710d1f..e650840530 100644 --- a/servers/slapd/overlays/sssvlv.c +++ b/servers/slapd/overlays/sssvlv.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2009-2014 The OpenLDAP Foundation. + * Copyright 2009-2018 The OpenLDAP Foundation. * Portions copyright 2009 Symas Corporation. * All rights reserved. * @@ -105,7 +105,7 @@ typedef struct sssvlv_info typedef struct sort_op { - Avlnode *so_tree; + TAvlnode *so_tree; sort_ctrl *so_ctrl; sssvlv_info *so_info; int so_paged; @@ -116,6 +116,7 @@ typedef struct sort_op 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 */ @@ -396,30 +397,35 @@ static int find_next_session( static void free_sort_op( Connection *conn, sort_op *so ) { int sess_id; - if ( so->so_tree ) { - if ( so->so_paged > SLAP_CONTROL_IGNORED ) { - Avlnode *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; - } - + 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 ) @@ -441,7 +447,7 @@ static void send_list( 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; @@ -594,8 +600,8 @@ range_err: 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; @@ -649,7 +655,7 @@ static void send_entry( 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) || @@ -659,7 +665,7 @@ static void send_entry( 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 ) { @@ -704,6 +710,8 @@ static void send_result( if ( so->so_tree == NULL ) { /* Search finished, so clean up */ free_sort_op( op->o_conn, so ); + } else { + so->so_running = 0; } } @@ -859,26 +867,40 @@ static int sssvlv_op_search( 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 ) { @@ -923,6 +945,7 @@ static int sssvlv_op_search( 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; @@ -946,6 +969,7 @@ static int sssvlv_op_search( 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; }