]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/sssvlv.c
check for NULL backend (ITS#6490)
[openldap] / servers / slapd / overlays / sssvlv.c
index 555079fa8cf56642a0e79cbd60c6ae9cf0ceaa07..0ee623da4fab9255880b7136eed73f3c592937c1 100644 (file)
@@ -21,8 +21,6 @@
 
 #include "portable.h"
 
-#define SLAPD_OVER_SSSVLV      SLAPD_MOD_DYNAMIC
-
 #ifdef SLAPD_OVER_SSSVLV
 
 #include <stdio.h>
@@ -34,6 +32,9 @@
 
 #include "slap.h"
 #include "lutil.h"
+#include "config.h"
+
+#include "../../../libraries/liblber/lber-int.h"       /* ber_rewind */
 
 /* RFC2891: Server Side Sorting
  * RFC2696: Paged Results
@@ -57,6 +58,8 @@
 
 #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;
@@ -75,7 +78,7 @@ typedef struct sort_key
 
 typedef struct sort_ctrl {
        int sc_nkeys;
-       sort_key sc_keys[0];
+       sort_key sc_keys[1];
 } sort_ctrl;
 
 
@@ -110,6 +113,7 @@ typedef struct sort_op
 /* There is only one conn table for all overlay instances */
 static sort_op **sort_conns;
 static ldap_pvt_thread_mutex_t sort_conns_mutex;
+static int ov_count;
 static const char *debug_header = "sssvlv";
 
 static int sss_cid;
@@ -188,7 +192,6 @@ static int pack_vlv_response_control(
        LDAPControl                     *ctrl;
        BerElementBuffer        berbuf;
        BerElement                      *ber            = (BerElement *)&berbuf;
-       PagedResultsCookie      resp_cookie;
        struct berval           cookie, bv;
        int                                     rc;
 
@@ -339,7 +342,7 @@ static void free_sort_op( Connection *conn, sort_op *so )
        ch_free( so );
 }
 
-static int send_list(
+static void send_list(
        Operation               *op,
        SlapReply               *rs,
        sort_op                 *so)
@@ -427,7 +430,10 @@ range_err:
                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 ) {
@@ -533,6 +539,9 @@ static void send_entry(
                "%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.
@@ -633,23 +642,24 @@ static int sssvlv_op_response(
                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 */
@@ -687,7 +697,7 @@ static int sssvlv_op_search(
        int                                             rc                      = SLAP_CB_CONTINUE;
        int     ok;
        sort_op *so, so2;
-       sort_ctrl *sc = op->o_controls[sss_cid];
+       sort_ctrl *sc;
        PagedResultsState *ps;
        vlv_ctrl *vc;
 
@@ -716,6 +726,7 @@ static int sssvlv_op_search(
                op->o_req_dn.bv_val, op->ors_filterstr.bv_val,
                op->o_ctrlflag[sss_cid]);
 
+       sc = op->o_controls[sss_cid];
        if ( sc->sc_nkeys > si->svi_max_keys ) {
                rs->sr_text = "Too many sort keys";
                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
@@ -807,8 +818,11 @@ static int sssvlv_op_search(
                        } 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;
@@ -990,7 +1004,7 @@ static int sss_parseCtrl(
        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;
 
@@ -1092,12 +1106,46 @@ static int sssvlv_db_open(
        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)
@@ -1108,9 +1156,9 @@ static int sssvlv_db_init(
        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 );
@@ -1118,6 +1166,7 @@ static int sssvlv_db_init(
                sort_conns = ch_calloc( sizeof(sort_op *), dtblsize + 1 );
                sort_conns++;
        }
+       ov_count++;
 
        return LDAP_SUCCESS;
 }
@@ -1129,6 +1178,13 @@ static int sssvlv_db_destroy(
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        sssvlv_info *si = (sssvlv_info *)on->on_bi.bi_private;
        
+       ov_count--;
+       if ( !ov_count && sort_conns) {
+               sort_conns--;
+               ch_free(sort_conns);
+               ldap_pvt_thread_mutex_destroy( &sort_conns_mutex );
+       }
+       
        if ( si ) {
                ch_free( si );
                on->on_bi.bi_private = NULL;
@@ -1149,6 +1205,12 @@ int sssvlv_initialize()
        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,