X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fsssvlv.c;h=c6779dd3a7a9129df6024c02f86791a1f4849e1c;hb=59e9ff6243465640956b58ad1756a3ede53eca7c;hp=ec43fb87bdf16b491071ac976f140f835c9e85f8;hpb=b0ad9e76c7aa752b23ccf90a05cca803bf2fbc97;p=openldap diff --git a/servers/slapd/overlays/sssvlv.c b/servers/slapd/overlays/sssvlv.c index ec43fb87bd..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-2012 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,18 +397,35 @@ static int find_next_session( 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 ) @@ -429,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; @@ -582,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; @@ -618,6 +636,8 @@ static void send_page( Operation *op, SlapReply *rs, sort_op *so ) /* Set the first entry to send for the next page */ so->so_tree = next_node; + if ( next_node ) + next_node->avl_left = NULL; op->o_bd = be; } @@ -635,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) || @@ -645,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 ) { @@ -690,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; } } @@ -845,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 ) { @@ -909,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; @@ -932,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; } @@ -1254,7 +1292,7 @@ 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", + { "sssvlv-maxperconn", "num", 2, 2, 0, ARG_INT|ARG_OFFSET, (void *)offsetof(sssvlv_info, svi_max_percon), "( OLcfgOvAt:21.3 NAME 'olcSssVlvMaxPerConn' " @@ -1268,7 +1306,7 @@ static ConfigOCs sssvlv_ocs[] = { "NAME 'olcSssVlvConfig' " "DESC 'SSS VLV configuration' " "SUP olcOverlayConfig " - "MAY ( olcSssVlvMax $ olcSssVlvMaxKeys ) )", + "MAY ( olcSssVlvMax $ olcSssVlvMaxKeys $ olcSssVlvMaxPerConn ) )", Cft_Overlay, sssvlv_cfg, NULL, NULL }, { NULL, 0, NULL } };