]> git.sur5r.net Git - openldap/commitdiff
ITS#5153 from HEAD - sorted values
authorHoward Chu <hyc@openldap.org>
Sat, 29 Sep 2007 11:55:21 +0000 (11:55 +0000)
committerHoward Chu <hyc@openldap.org>
Sat, 29 Sep 2007 11:55:21 +0000 (11:55 +0000)
42 files changed:
doc/man/man5/slapd-config.5
doc/man/man5/slapd.conf.5
servers/slapd/aci.c
servers/slapd/acl.c
servers/slapd/add.c
servers/slapd/attr.c
servers/slapd/back-bdb/compare.c
servers/slapd/back-bdb/monitor.c
servers/slapd/back-ldap/search.c
servers/slapd/back-meta/search.c
servers/slapd/back-monitor/compare.c
servers/slapd/back-sql/compare.c
servers/slapd/back-sql/entry-id.c
servers/slapd/back-sql/operational.c
servers/slapd/backend.c
servers/slapd/bconfig.c
servers/slapd/compare.c
servers/slapd/entry.c
servers/slapd/filterentry.c
servers/slapd/modify.c
servers/slapd/modrdn.c
servers/slapd/mods.c
servers/slapd/operational.c
servers/slapd/overlays/accesslog.c
servers/slapd/overlays/dds.c
servers/slapd/overlays/dynlist.c
servers/slapd/overlays/memberof.c
servers/slapd/overlays/pcache.c
servers/slapd/overlays/ppolicy.c
servers/slapd/overlays/refint.c
servers/slapd/overlays/rwm.c
servers/slapd/overlays/syncprov.c
servers/slapd/overlays/translucent.c
servers/slapd/overlays/valsort.c
servers/slapd/passwd.c
servers/slapd/proto-slap.h
servers/slapd/sasl.c
servers/slapd/schema_check.c
servers/slapd/slap.h
servers/slapd/slapi/slapi_utils.c
servers/slapd/syncrepl.c
servers/slapd/value.c

index 146dc30131198b2565f43f34cf7a0af4f4a6ebe8..0d88236129d66b0f42f2aacd43b04a5fd76b26bf 100644 (file)
@@ -479,6 +479,8 @@ lookup. The default is 2. For example, with the default values, a search
 using this filter "cn=*abcdefgh*" would generate index lookups for
 "abcd", "cdef", and "efgh".
 
+Note: Indexing support depends on the particular backend in use.
+
 .TP
 .B olcLocalSSF: <SSF>
 Specifies the Security Strength Factor (SSF) to be given local LDAP sessions,
@@ -616,42 +618,6 @@ versions of crypt(3) to use an MD5 algorithm and provides
 8 random characters of salt.  The default is "%s", which
 provides 31 characters of salt.
 .TP
-.B olcPasswordHash: <hash> [<hash>...]
-This option configures one or more hashes to be used in generation of user
-passwords stored in the userPassword attribute during processing of
-LDAP Password Modify Extended Operations (RFC 3062).
-The <hash> must be one of
-.BR {SSHA} ,
-.BR {SHA} ,
-.BR {SMD5} ,
-.BR {MD5} ,
-.BR {CRYPT} ,
-and
-.BR {CLEARTEXT} .
-The default is
-.BR {SSHA} .
-
-.B {SHA}
-and
-.B {SSHA}
-use the SHA-1 algorithm (FIPS 160-1), the latter with a seed.
-
-.B {MD5}
-and
-.B {SMD5}
-use the MD5 algorithm (RFC 1321), the latter with a seed.
-
-.B {CRYPT}
-uses the
-.BR crypt (3).
-
-.B {CLEARTEXT}
-indicates that the new password should be
-added to userPassword as clear text.
-
-Note that this option does not alter the normal user applications
-handling of userPassword during LDAP Add, Modify, or other LDAP operations.
-.TP
 .B olcPidFile: <filename>
 The ( absolute ) name of a file that will hold the 
 .B slapd
@@ -1079,6 +1045,43 @@ non-base search request with an empty base DN.
 Base scoped search requests with an empty base DN are not affected.
 This setting is only allowed in the frontend entry.
 .TP
+.B olcPasswordHash: <hash> [<hash>...]
+This option configures one or more hashes to be used in generation of user
+passwords stored in the userPassword attribute during processing of
+LDAP Password Modify Extended Operations (RFC 3062).
+The <hash> must be one of
+.BR {SSHA} ,
+.BR {SHA} ,
+.BR {SMD5} ,
+.BR {MD5} ,
+.BR {CRYPT} ,
+and
+.BR {CLEARTEXT} .
+The default is
+.BR {SSHA} .
+
+.B {SHA}
+and
+.B {SSHA}
+use the SHA-1 algorithm (FIPS 160-1), the latter with a seed.
+
+.B {MD5}
+and
+.B {SMD5}
+use the MD5 algorithm (RFC 1321), the latter with a seed.
+
+.B {CRYPT}
+uses the
+.BR crypt (3).
+
+.B {CLEARTEXT}
+indicates that the new password should be
+added to userPassword as clear text.
+
+Note that this option does not alter the normal user applications
+handling of userPassword during LDAP Add, Modify, or other LDAP operations.
+This setting is only allowed in the frontend entry.
+.TP
 .B olcReadOnly: TRUE | FALSE
 This option puts the database into "read-only" mode.  Any attempts to 
 modify the database will return an "unwilling to perform" error.  By
@@ -1189,6 +1192,15 @@ See
 .BR olcLimits
 for an explanation of the different flags.
 .TP
+.B olcSortVals <attr> [...]
+Specify a list of multi-valued attributes whose values will always
+be maintained in sorted order. Using this option will allow Modify,
+Compare, and filter evaluations on these attributes to be performed
+more efficiently. The resulting sort order depends on the
+attributes' syntax and matching rules and may not correspond to
+lexical order or any other recognizable order.
+This setting is only allowed in the frontend entry.
+.TP
 .B olcTimeLimit: {<integer>|unlimited}
 .TP
 .B olcTimeLimit: time[.{soft|hard}]=<integer> [...]
index e5c5a1cc2e4415454312e4e8cb977478b8533428..5d9fc030e16b2f8c02924a83d31b782707469aa4 100644 (file)
@@ -495,6 +495,9 @@ for the segments of a filter string that are processed for a subany index
 lookup. The default is 2. For example, with the default values, a search
 using this filter "cn=*abcdefgh*" would generate index lookups for
 "abcd", "cdef", and "efgh".
+
+Note: Indexing support depends on the particular backend in use.
+
 .TP
 .B localSSF <SSF>
 Specifies the Security Strength Factor (SSF) to be given local LDAP sessions,
@@ -891,6 +894,14 @@ The default is 262143.
 Specify the maximum incoming LDAP PDU size for authenticated sessions.
 The default is 4194303.
 .TP
+.B sortvals <attr> [...]
+Specify a list of multi-valued attributes whose values will always
+be maintained in sorted order. Using this option will allow Modify,
+Compare, and filter evaluations on these attributes to be performed
+more efficiently. The resulting sort order depends on the
+attributes' syntax and matching rules and may not correspond to
+lexical order or any other recognizable order.
+.TP
 .B threads <integer>
 Specify the maximum size of the primary thread pool.
 The default is 16; the minimum value is 2.
index ac786ace756f4faad96051293d1125abf3ebd89d..0acf6c108ff38848a953c28454866a33390b613c 100644 (file)
@@ -592,11 +592,10 @@ aci_mask(
                                at != NULL;
                                at = attrs_find( at->a_next, ad ) )
                {
-                       if ( value_find_ex( ad,
+                       if ( attr_valfind( at, 
                                SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                        SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                               at->a_nvals,
-                               &op->o_ndn, op->o_tmpmemctx ) == 0 )
+                               &op->o_ndn, NULL, op->o_tmpmemctx ) == 0 )
                        {
                                rc = 1;
                                break;
index 5647ce57fda2ed7ffe170206db330da0386ac6bb..adcfc1508484949509e67f11ec97fd8128021007 100644 (file)
@@ -974,11 +974,10 @@ acl_mask_dnattr(
                at != NULL;
                at = attrs_find( at->a_next, bdn->a_at ) )
        {
-               if ( value_find_ex( bdn->a_at,
+               if ( attr_valfind( at,
                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                       at->a_nvals,
-                       &bv, op->o_tmpmemctx ) == 0 )
+                       &bv, NULL, op->o_tmpmemctx ) == 0 )
                {
                        /* found it */
                        match = 1;
@@ -2043,11 +2042,6 @@ acl_set_cb_gather( Operation *op, SlapReply *rs )
 
                                a = attr_find( rs->sr_entry->e_attrs, desc );
                                if ( a != NULL ) {
-                                       int     i;
-
-                                       for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ )
-                                               ;
-
                                        bvalsp = a->a_nvals;
                                }
                        }
index 280fb4f20f5c083b564285330ebe7fa6c993f885..9c6ca2e6eedd06e66cc47378a482eeab49e54188 100644 (file)
@@ -380,6 +380,7 @@ slap_mods2entry(
        char *textbuf, size_t textlen )
 {
        Attribute **tail;
+       int i;
 
        if ( initial ) {
                assert( (*e)->e_attrs == NULL );
@@ -400,7 +401,7 @@ slap_mods2entry(
                if( attr != NULL ) {
 #define SLURPD_FRIENDLY
 #ifdef SLURPD_FRIENDLY
-                       ber_len_t i,j;
+                       int j;
 
                        if ( !initial ) {
                                /*      
@@ -413,12 +414,9 @@ slap_mods2entry(
                                return LDAP_SUCCESS;
                        }
 
-                       for( i=0; attr->a_vals[i].bv_val; i++ ) {
-                               /* count them */
-                       }
-                       for( j=0; mods->sml_values[j].bv_val; j++ ) {
-                               /* count them */
-                       }
+                       i = attr->a_numvals;
+                       j = mods->sml_numvals;
+                       attr->a_numvals += j;
                        j++;    /* NULL */
                        
                        attr->a_vals = ch_realloc( attr->a_vals,
@@ -466,9 +464,9 @@ slap_mods2entry(
                attr = attr_alloc( mods->sml_desc );
 
                /* move values to attr structure */
+               i = mods->sml_numvals;
+               attr->a_numvals = mods->sml_numvals;
                if ( dup ) { 
-                       int i;
-                       for ( i = 0; mods->sml_values[i].bv_val; i++ ) /* EMPTY */;
                        attr->a_vals = (BerVarray) ch_calloc( i+1, sizeof( BerValue ));
                        for ( i = 0; mods->sml_values[i].bv_val; i++ ) {
                                ber_dupbv( &attr->a_vals[i], &mods->sml_values[i] );
@@ -480,8 +478,7 @@ slap_mods2entry(
 
                if ( mods->sml_nvalues ) {
                        if ( dup ) {
-                               int i;
-                               for ( i = 0; mods->sml_nvalues[i].bv_val; i++ ) /* EMPTY */;
+                               i = mods->sml_numvals;
                                attr->a_nvals = (BerVarray) ch_calloc( i+1, sizeof( BerValue ));
                                for ( i = 0; mods->sml_nvalues[i].bv_val; i++ ) {
                                        ber_dupbv( &attr->a_nvals[i], &mods->sml_nvalues[i] );
@@ -493,6 +490,9 @@ slap_mods2entry(
                } else {
                        attr->a_nvals = attr->a_vals;
                }
+               /* slap_mods_check() gives us sorted results */
+               if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL )
+                       attr->a_flags |= SLAP_ATTR_SORTED_VALS;
 
                *tail = attr;
                tail = &attr->a_next;
@@ -528,7 +528,8 @@ slap_entry2mods(
 
                mod->sml_type = a_new_desc->ad_cname;
 
-               for ( count = 0; a_new->a_vals[count].bv_val; count++ ) /* EMPTY */;
+               count = a_new->a_numvals;
+               mod->sml_numvals = a_new->a_numvals;
 
                mod->sml_values = (struct berval*) malloc(
                        (count+1) * sizeof( struct berval) );
index 315442466f4403587a8ba80ed6fb722294c40814..e66b65a84120d0f296016f1f65e52b869651e2a3 100644 (file)
@@ -153,6 +153,7 @@ attr_clean( Attribute *a )
        a->a_comp_data = NULL;
 #endif
        a->a_flags = 0;
+       a->a_numvals = 0;
 }
 
 void
@@ -210,15 +211,13 @@ attrs_free( Attribute *a )
 static void
 attr_dup2( Attribute *tmp, Attribute *a )
 {
+       tmp->a_flags = a->a_flags & SLAP_ATTR_PERSISTENT_FLAGS;
        if ( a->a_vals != NULL ) {
                int     i;
 
-               for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
-                       /* EMPTY */ ;
-               }
-
-               tmp->a_vals = ch_malloc( (i + 1) * sizeof(struct berval) );
-               for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
+               tmp->a_numvals = a->a_numvals;
+               tmp->a_vals = ch_malloc( (tmp->a_numvals + 1) * sizeof(struct berval) );
+               for ( i = 0; i < tmp->a_numvals; i++ ) {
                        ber_dupbv( &tmp->a_vals[i], &a->a_vals[i] );
                        if ( BER_BVISNULL( &tmp->a_vals[i] ) ) break;
                        /* FIXME: error? */
@@ -231,7 +230,7 @@ attr_dup2( Attribute *tmp, Attribute *a )
                if ( a->a_nvals != a->a_vals ) {
                        int     j;
 
-                       tmp->a_nvals = ch_malloc( (i + 1) * sizeof(struct berval) );
+                       tmp->a_nvals = ch_malloc( (tmp->a_numvals + 1) * sizeof(struct berval) );
                        for ( j = 0; !BER_BVISNULL( &a->a_nvals[j] ); j++ ) {
                                assert( j < i );
                                ber_dupbv( &tmp->a_nvals[j], &a->a_nvals[j] );
@@ -283,6 +282,163 @@ attrs_dup( Attribute *a )
        return anew;
 }
 
+int
+attr_valfind(
+       Attribute *a,
+       unsigned flags,
+       struct berval *val,
+       unsigned *slot,
+       void *ctx )
+{
+       struct berval nval = BER_BVNULL, *cval;
+       MatchingRule *mr;
+       const char *text;
+       int match = -1, rc;
+       unsigned i;
+
+       if ( flags & SLAP_MR_ORDERING )
+               mr = a->a_desc->ad_type->sat_ordering;
+       else
+               mr = a->a_desc->ad_type->sat_equality;
+
+       if( !SLAP_IS_MR_ASSERTED_VALUE_NORMALIZED_MATCH( flags ) &&
+               mr->smr_normalize )
+       {
+               rc = (mr->smr_normalize)(
+                       flags & (SLAP_MR_TYPE_MASK|SLAP_MR_SUBTYPE_MASK|SLAP_MR_VALUE_OF_SYNTAX),
+                       a->a_desc->ad_type->sat_syntax,
+                       mr, val, &nval, ctx );
+
+               if( rc != LDAP_SUCCESS ) {
+                       return LDAP_INVALID_SYNTAX;
+               }
+               cval = &nval;
+       } else {
+               cval = val;
+       }
+
+       if ( a->a_flags & SLAP_ATTR_SORTED_VALS ) {
+       /* Binary search */
+               unsigned base = 0, n = a->a_numvals;
+               int val = 0;
+
+               while ( 0 < n ) {
+                       unsigned pivot = n >> 1;
+                       i = base + pivot;
+                       if ( i >= a->a_numvals ) {
+                               i = a->a_numvals - 1;
+                               break;
+                       }
+                       rc = value_match( &match, a->a_desc, mr, flags,
+                               &a->a_nvals[i], cval, &text );
+                       if ( rc == LDAP_SUCCESS && match == 0 )
+                               break;
+                       n = pivot;
+                       if ( match < 0 )
+                               base = i+1;
+               }
+               if ( match < 0 )
+                       i++;
+       } else {
+       /* Linear search */
+               for ( i = 0; i < a->a_numvals; i++ ) {
+                       const char *text;
+
+                       rc = ordered_value_match( &match, a->a_desc, mr, flags,
+                               &a->a_nvals[i], cval, &text );
+                       if ( rc == LDAP_SUCCESS && match == 0 )
+                               break;
+               }
+       }
+       if ( slot )
+               *slot = i;
+       if ( match )
+               rc = LDAP_NO_SUCH_ATTRIBUTE;
+       if ( nval.bv_val )
+               slap_sl_free( nval.bv_val, ctx );
+
+       return rc;
+}
+
+int
+attr_valadd(
+       Attribute *a,
+       BerVarray vals,
+       BerVarray nvals,
+       int nn )
+{
+       int             i;
+       BerVarray       v2;
+
+       v2 = (BerVarray) SLAP_REALLOC( (char *) a->a_vals,
+                   (a->a_numvals + nn + 1) * sizeof(struct berval) );
+       if( v2 == NULL ) {
+               Debug(LDAP_DEBUG_TRACE,
+                 "attr_valadd: SLAP_REALLOC failed.\n", 0, 0, 0 );
+               return LBER_ERROR_MEMORY;
+       }
+       a->a_vals = v2;
+       if ( nvals ) {
+               v2 = (BerVarray) SLAP_REALLOC( (char *) a->a_nvals,
+                               (a->a_numvals + nn + 1) * sizeof(struct berval) );
+               if( v2 == NULL ) {
+                       Debug(LDAP_DEBUG_TRACE,
+                         "attr_valadd: SLAP_REALLOC failed.\n", 0, 0, 0 );
+                       return LBER_ERROR_MEMORY;
+               }
+               a->a_nvals = v2;
+       } else {
+               a->a_nvals = a->a_vals;
+       }
+
+       /* If sorted and old vals exist, must insert */
+       if (( a->a_flags & SLAP_ATTR_SORTED_VALS ) && a->a_numvals ) {
+               unsigned slot;
+               int j, rc;
+               v2 = nvals ? nvals : vals;
+               for ( i = 0; i < nn; i++ ) {
+                       rc = attr_valfind( a, SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX |
+                               SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
+                               &v2[i], &slot, NULL );
+                       if ( rc != LDAP_NO_SUCH_ATTRIBUTE ) {
+                               /* should never happen */
+                               if ( rc == LDAP_SUCCESS )
+                                       rc = LDAP_TYPE_OR_VALUE_EXISTS;
+                               return rc;
+                       }
+                       for ( j = a->a_numvals; j >= slot; j-- ) {
+                               a->a_vals[j+1] = a->a_vals[j];
+                               if ( nvals )
+                                       a->a_nvals[j+1] = a->a_nvals[j];
+                       }
+                       ber_dupbv( &a->a_nvals[slot], &v2[i] );
+                       if ( nvals )
+                               ber_dupbv( &a->a_vals[slot], &vals[i] );
+                       a->a_numvals++;
+               }
+               BER_BVZERO( &a->a_vals[a->a_numvals] );
+               if ( a->a_vals != a->a_nvals )
+                       BER_BVZERO( &a->a_nvals[a->a_numvals] );
+       } else {
+               v2 = &a->a_vals[a->a_numvals];
+               for ( i = 0 ; i < nn; i++ ) {
+                       ber_dupbv( &v2[i], &vals[i] );
+                       if ( BER_BVISNULL( &v2[i] ) ) break;
+               }
+               BER_BVZERO( &v2[i] );
+
+               if ( nvals ) {
+                       v2 = &a->a_nvals[a->a_numvals];
+                       for ( i = 0 ; i < nn; i++ ) {
+                               ber_dupbv( &v2[i], &nvals[i] );
+                               if ( BER_BVISNULL( &v2[i] ) ) break;
+                       }
+                       BER_BVZERO( &v2[i] );
+               }
+               a->a_numvals += i;
+       }
+       return 0;
+}
 
 /*
  * attr_merge - merge the given type and value with the list of
@@ -302,7 +458,7 @@ attr_merge(
        BerVarray       vals,
        BerVarray       nvals )
 {
-       int rc;
+       int i = 0;
 
        Attribute       **a;
 
@@ -325,18 +481,10 @@ attr_merge(
                                        || ( (*a)->a_nvals != (*a)->a_vals ) ) ) );
        }
 
-       rc = value_add( &(*a)->a_vals, vals );
-
-       if ( rc == LDAP_SUCCESS ) {
-               if ( nvals ) {
-                       rc = value_add( &(*a)->a_nvals, nvals );
-                       /* FIXME: what if rc != LDAP_SUCCESS ? */
-               } else {
-                       (*a)->a_nvals = (*a)->a_vals;
-               }
+       if ( vals != NULL ) {
+               for ( ; !BER_BVISNULL( &vals[i] ); i++ ) ;
        }
-
-       return rc;
+       return attr_valadd( *a, vals, nvals, i );
 }
 
 /*
@@ -415,7 +563,6 @@ attr_merge_one(
        struct berval   *val,
        struct berval   *nval )
 {
-       int rc;
        Attribute       **a;
 
        for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
@@ -428,17 +575,7 @@ attr_merge_one(
                *a = attr_alloc( desc );
        }
 
-       rc = value_add_one( &(*a)->a_vals, val );
-
-       if ( rc == LDAP_SUCCESS ) {
-               if ( nval ) {
-                       rc = value_add_one( &(*a)->a_nvals, nval );
-                       /* FIXME: what if rc != LDAP_SUCCESS ? */
-               } else {
-                       (*a)->a_nvals = (*a)->a_vals;
-               }
-       }
-       return rc;
+       return attr_valadd( *a, val, nval, 1 );
 }
 
 /*
index 972071314c1df14ad87c8f4f56f8e94f3727212a..538d1da61a32d3b7da8719c58db1fffa25840c0f 100644 (file)
@@ -158,10 +158,10 @@ dn2entry_retry:
        {
                rs->sr_err = LDAP_COMPARE_FALSE;
 
-               if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
+               if ( attr_valfind( a,
                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                       a->a_nvals, &op->oq_compare.rs_ava->aa_value,
+                       &op->oq_compare.rs_ava->aa_value, NULL,
                        op->o_tmpmemctx ) == 0 )
                {
                        rs->sr_err = LDAP_COMPARE_TRUE;
index f30469702cda7bf85d632ba5204b7013c7f8a013..2271940de1eb18680a3f2c7a558061a584459194 100644 (file)
@@ -210,6 +210,7 @@ bdb_monitor_free(
        mod.sm_op = LDAP_MOD_DELETE;
        mod.sm_desc = slap_schema.si_ad_objectClass;
        mod.sm_values = values;
+       mod.sm_numvals = 1;
        values[ 0 ] = oc_olmBDBDatabase->soc_cname;
        BER_BVZERO( &values[ 1 ] );
 
@@ -218,9 +219,10 @@ bdb_monitor_free(
        /* don't care too much about return code... */
 
        /* remove attrs */
+       mod.sm_values = NULL;
+       mod.sm_numvals = 0;
        for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
                mod.sm_desc = *s_at[ i ].ad;
-               mod.sm_values = NULL;
                rc = modify_delete_values( e, &mod, 1, &text,
                        textbuf, sizeof( textbuf ) );
                /* don't care too much about return code... */
@@ -371,26 +373,22 @@ bdb_monitor_db_open( BackendDB *be )
        }
 
        a->a_desc = slap_schema.si_ad_objectClass;
-       value_add_one( &a->a_vals, &oc_olmBDBDatabase->soc_cname );
-       a->a_nvals = a->a_vals;
+       attr_valadd( a, &oc_olmBDBDatabase->soc_cname, NULL, 1 );
        next = a->a_next;
 
        {
                struct berval   bv = BER_BVC( "0" );
 
                next->a_desc = ad_olmBDBEntryCache;
-               value_add_one( &next->a_vals, &bv );
-               next->a_nvals = next->a_vals;
+               attr_valadd( next, &bv, NULL, 1 );
                next = next->a_next;
 
                next->a_desc = ad_olmBDBDNCache;
-               value_add_one( &next->a_vals, &bv );
-               next->a_nvals = next->a_vals;
+               attr_valadd( next, &bv, NULL, 1 );
                next = next->a_next;
 
                next->a_desc = ad_olmBDBIDLCache;
-               value_add_one( &next->a_vals, &bv );
-               next->a_nvals = next->a_vals;
+               attr_valadd( next, &bv, NULL, 1 );
                next = next->a_next;
        }
 
@@ -432,6 +430,7 @@ bdb_monitor_db_open( BackendDB *be )
                next->a_desc = ad_olmDbDirectory;
                next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
                next->a_vals[ 0 ] = bv;
+               next->a_numvals = 1;
 
                if ( BER_BVISNULL( &nbv ) ) {
                        next->a_nvals = next->a_vals;
index 13a9fb3960f6b1c877635df192983780058a55f7..3d23276bf1d1f48a7f8edad17a5b9d4207283a68 100644 (file)
@@ -676,11 +676,6 @@ ldap_build_entry(
                         * values result filter
                         */
                        attr->a_vals = (struct berval *)&slap_dummy_bv;
-                       last = 0;
-
-               } else {
-                       for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); last++ )
-                               /* just count vals */ ;
                }
 
                validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
@@ -692,7 +687,7 @@ ldap_build_entry(
                        goto next_attr;
                }
 
-               for ( i = 0; i < last; i++ ) {
+               for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) {
                        struct berval   pval;
                        int             rc;
 
@@ -724,6 +719,7 @@ ldap_build_entry(
                                attr->a_vals[i] = pval;
                        }
                }
+               attr->a_numvals = last = i;
 
                if ( last && attr->a_desc->ad_type->sat_equality &&
                                attr->a_desc->ad_type->sat_equality->smr_normalize )
index c9e435b41d08cdf48f0e7605ca3a5ec021357e5b..571d10a663a2e393893066c0b53aa98a0a22fc67 100644 (file)
@@ -1885,6 +1885,7 @@ meta_send_entry(
                        for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last )
                                ;
                }
+               attr->a_numvals = last;
 
                validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
                pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;
index 3a8df66624c29f16ea9093b82eaa169708566282..9cac645bc92daaf0fbd377d83d3b3f72e2b952b4 100644 (file)
@@ -71,10 +71,10 @@ monitor_back_compare( Operation *op, SlapReply *rs )
                        a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc )) {
                rs->sr_err = LDAP_COMPARE_FALSE;
 
-               if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
+               if ( attr_valfind( a,
                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                       a->a_nvals, &op->oq_compare.rs_ava->aa_value,
+                       &op->oq_compare.rs_ava->aa_value, NULL,
                        op->o_tmpmemctx ) == 0 )
                {
                        rs->sr_err = LDAP_COMPARE_TRUE;
index 24fe2e9fb126ffcef5ec54bff196ba34d957e0ef..403e82c3e578ba6d04dd31b3db4f64e4ce7f582e 100644 (file)
@@ -131,11 +131,10 @@ backsql_compare( Operation *op, SlapReply *rs )
                        a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ) )
        {
                rs->sr_err = LDAP_COMPARE_FALSE;
-               if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
+               if ( attr_valfind( a,
                                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                        SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                                       a->a_nvals,
-                                       &op->oq_compare.rs_ava->aa_value,
+                                       &op->oq_compare.rs_ava->aa_value, NULL,
                                        op->o_tmpmemctx ) == 0 )
                {
                        rs->sr_err = LDAP_COMPARE_TRUE;
index 78f1da14459b6ece37edc0d7eb604450871ab09f..f61fc5c8640f03cadb32e7450c7dee7af504ad9d 100644 (file)
@@ -617,8 +617,7 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
                BerVarray       tmp;
 
                if ( attr->a_vals != NULL ) {
-                       for ( ; !BER_BVISNULL( &attr->a_vals[ oldcount ] ); oldcount++ )
-                               /* just count */ ;
+                       oldcount = attr->a_numvals;
                }
 
                tmp = ch_realloc( attr->a_vals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
@@ -639,19 +638,20 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
                } else {
                        attr->a_nvals = attr->a_vals;
                }
+               attr->a_numvals += count;
 
        } else {
                append = 1;
 
                /* Make space for the array of values */
                attr = attr_alloc( at->bam_true_ad );
+               attr->a_numvals = count;
                attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) );
                if ( attr->a_vals == NULL ) {
                        Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 );
                        ch_free( attr );
                        return 1;
                }
-               memset( attr->a_vals, 0, ( count + 1 ) * sizeof( struct berval ) );
                if ( normfunc ) {
                        attr->a_nvals = ch_calloc( count + 1, sizeof( struct berval ) );
                        if ( attr->a_nvals == NULL ) {
@@ -659,8 +659,6 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
                                ch_free( attr );
                                return 1;
 
-                       } else {
-                               memset( attr->a_nvals, 0, ( count + 1 ) * sizeof( struct berval ) );
                        }
 
                } else {
index f6fe6aea4ff06f768f96c3286e6c6dd06ccc9cdd..6909d7b31a4e720f0d9a8a26248079ee27639e2d 100644 (file)
@@ -55,6 +55,7 @@ backsql_operational_entryUUID( backsql_info *bi, backsql_entryID *id )
 
        a = attr_alloc( desc );
 
+       a->a_numvals = 1;
        a->a_vals = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
        a->a_vals[ 0 ] = val;
        BER_BVZERO( &a->a_vals[ 1 ] );
@@ -74,6 +75,7 @@ backsql_operational_entryCSN( Operation *op )
        Attribute       *a;
 
        a = attr_alloc( slap_schema.si_ad_entryCSN );
+       a->a_numvals = 1;
        a->a_vals = ch_malloc( 2 * sizeof( struct berval ) );
        BER_BVZERO( &a->a_vals[ 1 ] );
 
index 3d83060f557712d26bca64b69ec5a54457a18994..3eb2a679d4bfeefa6dc3a3371d9dcef9968b8be1 100644 (file)
@@ -1501,10 +1501,10 @@ loopit:
                                op->o_bd = b2;
 
                        } else {
-                               rc = value_find_ex( group_at,
+                               rc = attr_valfind( a,
                                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                        SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                                       a->a_nvals, op_ndn, op->o_tmpmemctx );
+                                       op_ndn, NULL, op->o_tmpmemctx );
                                if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
                                        rc = LDAP_COMPARE_FALSE;
                                }
@@ -1648,9 +1648,7 @@ fe_acl_attribute(
                                goto freeit;
                        }
 
-                       for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ )
-                               ;
-                       
+                       i = a->a_numvals;
                        v = op->o_tmpalloc( sizeof(struct berval) * ( i + 1 ),
                                op->o_tmpmemctx );
                        for ( i = 0, j = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ )
index 40d7a90585d31b980d43cbd8d0b2b3c8ab8d3d5a..7576a2c2f75e3bccbefd1f13cfafeb86c14ca823 100644 (file)
@@ -177,6 +177,7 @@ enum {
        CFG_HIDDEN,
        CFG_MONITORING,
        CFG_SERVERID,
+       CFG_SORTVALS,
 
        CFG_LAST
 };
@@ -552,6 +553,11 @@ static ConfigTable config_back_cf_table[] = {
        { "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T,
                &sockbuf_max_incoming_auth, "( OLcfgGlAt:62 NAME 'olcSockbufMaxIncomingAuth' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+       { "sortvals", "attr", 2, 0, 0, ARG_MAGIC|CFG_SORTVALS,
+               &config_generic, "( OLcfgGlAt:83 NAME 'olcSortVals' "
+                       "DESC 'Attributes whose values will always be sorted' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "subordinate", "[advertise]", 1, 2, 0, ARG_DB|ARG_MAGIC,
                &config_subordinate, "( OLcfgDbAt:0.15 NAME 'olcSubordinate' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
@@ -765,7 +771,7 @@ static ConfigOCs cf_ocs[] = {
                "NAME 'olcFrontendConfig' "
                "DESC 'OpenLDAP frontend configuration' "
                "AUXILIARY "
-               "MAY ( olcDefaultSearchBase $ olcPasswordHash ) )",
+               "MAY ( olcDefaultSearchBase $ olcPasswordHash $ olcSortVals ) )",
                Cft_Database, NULL, NULL },
 #ifdef SLAPD_MODULES
        { "( OLcfgGlOc:8 "
@@ -786,6 +792,13 @@ typedef struct ServerID {
 
 static ServerID *sid_list;
 
+typedef struct ADlist {
+       struct ADlist *al_next;
+       AttributeDescription *al_desc;
+} ADlist;
+
+static ADlist *sortVals;
+
 static int
 config_generic(ConfigArgs *c) {
        int i;
@@ -1000,6 +1013,14 @@ config_generic(ConfigArgs *c) {
                case CFG_SSTR_IF_MIN:
                        c->value_int = index_substr_if_minlen;
                        break;
+               case CFG_SORTVALS: {
+                       ADlist *sv;
+                       rc = 1;
+                       for ( sv = sortVals; sv; sv = sv->al_next ) {
+                               value_add_one( &c->rvalue_vals, &sv->al_desc->ad_cname );
+                               rc = 0;
+                       }
+                       } break;
 #ifdef SLAPD_MODULES
                case CFG_MODLOAD: {
                        ModPaths *mp = c->private;
@@ -1224,6 +1245,27 @@ config_generic(ConfigArgs *c) {
                                }
                        }
                        break;
+               case CFG_SORTVALS:
+                       if ( c->valx < 0 ) {
+                               ADlist *sv;
+                               for ( sv = sortVals; sv; sv = sortVals ) {
+                                       sortVals = sv->al_next;
+                                       sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL;
+                                       ch_free( sv );
+                               }
+                       } else {
+                               ADlist *sv, **prev;
+                               int i = 0;
+
+                               for ( prev = &sortVals, sv = sortVals; i < c->valx; i++ ) {
+                                       prev = &sv->al_next;
+                                       sv = sv->al_next;
+                               }
+                               sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL;
+                               *prev = sv->al_next;
+                               ch_free( sv );
+                       }
+                       break;
 
                case CFG_LIMITS:
                        /* FIXME: there is no limits_free function */
@@ -1447,6 +1489,53 @@ config_generic(ConfigArgs *c) {
                                        return(1);
                        break;
 
+               case CFG_SORTVALS: {
+                       ADlist *svnew = NULL, *svtail, *sv;
+
+                       for ( i = 1; i < c->argc; i++ ) {
+                               AttributeDescription *ad = NULL;
+                               const char *text;
+                               int rc;
+
+                               rc = slap_str2ad( c->argv[i], &ad, &text );
+                               if ( rc ) {
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown attribute type #%d",
+                                               c->argv[0], i );
+sortval_reject:
+                                       Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+                                               c->log, c->cr_msg, c->argv[i] );
+                                       for ( sv = svnew; sv; sv = svnew ) {
+                                               svnew = sv->al_next;
+                                               ch_free( sv );
+                                       }
+                                       return 1;
+                               }
+                               if (( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) ||
+                                       ad->ad_type->sat_single_value ) {
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> inappropriate attribute type #%d",
+                                               c->argv[0], i );
+                                       goto sortval_reject;
+                               }
+                               sv = ch_malloc( sizeof( ADlist ));
+                               sv->al_desc = ad;
+                               if ( !svnew ) {
+                                       svnew = sv;
+                               } else {
+                                       svtail->al_next = sv;
+                               }
+                               svtail = sv;
+                       }
+                       sv->al_next = NULL;
+                       for ( sv = svnew; sv; sv = sv->al_next )
+                               sv->al_desc->ad_type->sat_flags |= SLAP_AT_SORTED_VAL;
+                       for ( sv = sortVals; sv && sv->al_next; sv = sv->al_next );
+                       if ( sv )
+                               sv->al_next = svnew;
+                       else
+                               sortVals = svnew;
+                       }
+                       break;
+
                case CFG_ACL:
                        /* Don't append to the global ACL if we're on a specific DB */
                        i = c->valx;
@@ -4544,7 +4633,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                         */
                        if ( ct && ml->sml_values ) {
                                delrec *d;
-                               for (i=0; ml->sml_values[i].bv_val; i++);
+                               i = ml->sml_numvals;
                                d = ch_malloc( sizeof(delrec) + (i - 1)* sizeof(int));
                                d->nidx = i;
                                d->next = NULL;
@@ -4577,8 +4666,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                                if ( ct->arg_type & ARG_NO_INSERT ) {
                                        Attribute *a = attr_find( e->e_attrs, ml->sml_desc );
                                        if ( a ) {
-                                               for (i = 0; a->a_vals[i].bv_val; i++ );
-                                               navals = i;
+                                               navals = a->a_numvals;
                                        }
                                }
                                for ( i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++ ) {
@@ -5384,6 +5472,7 @@ config_check_schema(Operation *op, CfBackInfo *cfb)
                                ber_bvarray_free( a->a_vals );
                                a->a_vals = NULL;
                                a->a_nvals = NULL;
+                               a->a_numvals = 0;
                        }
                        oidm_unparse( &bv, NULL, NULL, 1 );
                        attr_merge_normalize( e, cfAd_om, bv, NULL );
@@ -5398,6 +5487,7 @@ config_check_schema(Operation *op, CfBackInfo *cfb)
                                ber_bvarray_free( a->a_vals );
                                a->a_vals = NULL;
                                a->a_nvals = NULL;
+                               a->a_numvals = 0;
                        }
                        at_unparse( &bv, NULL, NULL, 1 );
                        attr_merge_normalize( e, cfAd_attr, bv, NULL );
@@ -5412,6 +5502,7 @@ config_check_schema(Operation *op, CfBackInfo *cfb)
                                ber_bvarray_free( a->a_vals );
                                a->a_vals = NULL;
                                a->a_nvals = NULL;
+                               a->a_numvals = 0;
                        }
                        oc_unparse( &bv, NULL, NULL, 1 );
                        attr_merge_normalize( e, cfAd_oc, bv, NULL );
index eaee0c0e9bd3ceecc9f2e2cda2e8f1bd84b6a0a4..1af6ba0b6aa8905fcdb88a428af12e158eeaf964 100644 (file)
@@ -384,10 +384,10 @@ static int compare_entry(
                        break;
                }
 
-               if ( value_find_ex( ava->aa_desc,
+               if ( attr_valfind( a, 
                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                       a->a_nvals, &ava->aa_value, op->o_tmpmemctx ) == 0 )
+                       &ava->aa_value, NULL, op->o_tmpmemctx ) == 0 )
                {
                        rc = LDAP_COMPARE_TRUE;
                        break;
index 660bcb676b7ba680b3b2aa6f7cb28b2a1e63f914..b83c550defe664064e6fee2875d5d75b74ed650c 100644 (file)
@@ -277,9 +277,22 @@ str2entry2( char *s, int checkvals )
 
                if (( ad_prev && ad != ad_prev ) || ( i == lines )) {
                        int j, k;
+                       /* FIXME: we only need this when migrating from an unsorted DB */
+                       if ( atail != &ahead && atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
+                               rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL );
+                               if ( rc == LDAP_SUCCESS ) {
+                                       atail->a_flags |= SLAP_ATTR_SORTED_VALS;
+                               } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "str2entry: attributeType %s value #%d provided more than once\n",
+                                               atail->a_desc->ad_cname.bv_val, j, 0 );
+                                       goto fail;
+                               }
+                       }
                        atail->a_next = attr_alloc( NULL );
                        atail = atail->a_next;
                        atail->a_flags = 0;
+                       atail->a_numvals = attr_cnt;
                        atail->a_desc = ad_prev;
                        atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval));
                        if( ad_prev->ad_type->sat_equality &&
@@ -371,7 +384,7 @@ str2entry2( char *s, int checkvals )
 
                        if ( rc ) {
                                Debug( LDAP_DEBUG_ANY,
-                                       "<= str2entry NULL (smr_normalize %d)\n", rc, 0, 0 );
+                                       "<= str2entry NULL (smr_normalize %s %d)\n", ad->ad_cname.bv_val, rc, 0 );
                                goto fail;
                        }
                }
@@ -744,6 +757,7 @@ int entry_encode(Entry *e, struct berval *bv)
                *ptr++ = '\0';
                if (a->a_vals) {
                        for (i=0; a->a_vals[i].bv_val; i++);
+                       assert( i == a->a_numvals );
                        entry_putlen(&ptr, i);
                        for (i=0; a->a_vals[i].bv_val; i++) {
                                entry_putlen(&ptr, a->a_vals[i].bv_len);
@@ -805,7 +819,7 @@ int entry_decode(EntryHeader *eh, Entry **e, void *ctx)
 int entry_decode(EntryHeader *eh, Entry **e)
 #endif
 {
-       int i, j, count, nattrs, nvals;
+       int i, j, nattrs, nvals;
        int rc;
        Attribute *a;
        Entry *x;
@@ -857,7 +871,8 @@ int entry_decode(EntryHeader *eh, Entry **e)
                ptr += i + 1;
                a->a_desc = ad;
                a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS;
-               count = j = entry_getlen(&ptr);
+               j = entry_getlen(&ptr);
+               a->a_numvals = j;
                a->a_vals = bptr;
 
                while (j) {
@@ -889,6 +904,19 @@ int entry_decode(EntryHeader *eh, Entry **e)
                } else {
                        a->a_nvals = a->a_vals;
                }
+               /* FIXME: This is redundant once a sorted entry is saved into the DB */
+               if ( a->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
+                       rc = slap_sort_vals( (Modifications *)a, &text, &j, NULL );
+                       if ( rc == LDAP_SUCCESS ) {
+                               a->a_flags |= SLAP_ATTR_SORTED_VALS;
+                       } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
+                               /* should never happen */
+                               Debug( LDAP_DEBUG_ANY,
+                                       "entry_decode: attributeType %s value #%d provided more than once\n",
+                                       a->a_desc->ad_cname.bv_val, j, 0 );
+                               return rc;
+                       }
+               }
                a = a->a_next;
                nattrs--;
                if ( !nattrs )
@@ -962,6 +990,7 @@ Entry *entry_dup_bv( Entry *e )
                dst->a_desc = src->a_desc;
                dst->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS;
                dst->a_vals = bvl;
+               dst->a_numvals = src->a_numvals;
                for ( i=0; src->a_vals[i].bv_val; i++ ) {
                        bvl->bv_len = src->a_vals[i].bv_len;
                        bvl->bv_val = ptr;
index d1fb4856e30cf5bb8162656713bebaa912e3a9dc..911b72e5a0a863eadd1fac50c89386950b1614e9 100644 (file)
@@ -212,12 +212,7 @@ static int test_mra_filter(
                        if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
                                num_attr_vals = 0;
                                if ( !a->a_comp_data ) {
-                                       for ( ;
-                                               !BER_BVISNULL( &a->a_vals[num_attr_vals] );
-                                               num_attr_vals++ )
-                                       {
-                                               /* empty */;
-                                       }
+                                       num_attr_vals = a->a_numvals;
                                        if ( num_attr_vals <= 0 ) {
                                                /* no attribute value */
                                                return LDAP_INAPPROPRIATE_MATCHING;
@@ -662,6 +657,56 @@ test_ava_filter(
                        continue;
                }
 
+               /* We have no Sort optimization for Approx matches */
+               if (( a->a_flags & SLAP_ATTR_SORTED_VALS ) && type != LDAP_FILTER_APPROX ) {
+                       unsigned slot;
+                       int ret;
+
+                       /* For Ordering matches, we just need to do one comparison with
+                        * either the first (least) or last (greatest) value.
+                        */
+                       if ( use == SLAP_MR_ORDERING ) {
+                               const char *text;
+                               int match, which;
+                               which = (type == LDAP_FILTER_LE) ? 0 : a->a_numvals-1;
+                               ret = value_match( &match, a->a_desc, mr, use,
+                                       &a->a_nvals[which], &ava->aa_value, &text );
+                               if ( ret != LDAP_SUCCESS ) return ret;
+                               if (( type == LDAP_FILTER_LE && match <= 0 ) ||
+                                       ( type == LDAP_FILTER_GE && match >= 0 ))
+                                       return LDAP_COMPARE_TRUE;
+                               continue;
+                       }
+                       /* Only Equality will get here */
+                       ret = attr_valfind( a, use | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
+                               SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, 
+                               &ava->aa_value, &slot, NULL );
+                       if ( ret == LDAP_SUCCESS )
+                               return LDAP_COMPARE_TRUE;
+                       else if ( ret != LDAP_NO_SUCH_ATTRIBUTE )
+                               return ret;
+#if 0
+                       /* The following is useful if we want to know which values
+                        * matched an ordering test. But here we don't care, we just
+                        * want to know if any value did, and that is checked above.
+                        */
+                       if ( ret == LDAP_NO_SUCH_ATTRIBUTE ) {
+                               /* If insertion point is not the end of the list, there was
+                                * at least one value greater than the assertion.
+                                */
+                               if ( type == LDAP_FILTER_GE && slot < a->a_numvals )
+                                       return LDAP_COMPARE_TRUE;
+                               /* Likewise, if insertion point is not the head of the list,
+                                * there was at least one value less than the assertion.
+                                */
+                               if ( type == LDAP_FILTER_LE && slot > 0 )
+                                       return LDAP_COMPARE_TRUE;
+                               return LDAP_COMPARE_FALSE;
+                       }
+#endif
+                       continue;
+               }
+
 #ifdef LDAP_COMP_MATCH
                if ( nibble_mem_allocator && ava->aa_cf && !a->a_comp_data ) {
                        /* Component Matching */
index e6ba1dfe4b2aedcf1813af0ca8e777c8e798fbee..d0282b16e6039ca45b70e5303eab6cd78aaf2624 100644 (file)
@@ -585,6 +585,7 @@ int slap_mods_check(
                                        ml->sml_values[nvals] = pval;
                                }
                        }
+                       ml->sml_numvals = nvals;
 
                        /*
                         * a rough single value check... an additional check is needed
@@ -639,200 +640,200 @@ int slap_mods_check(
                        /* check for duplicates, but ignore Deletes.
                         */
                        if( nvals > 1 && ml->sml_op != LDAP_MOD_DELETE ) {
-#define        SLAP_MODS_CHECK_QUICKSORT
-#ifndef SLAP_MODS_CHECK_QUICKSORT
-                               int             i, j, rc, match;
-                               MatchingRule *mr = ad->ad_type->sat_equality;
-
-                               for ( i = 1; i < nvals ; i++ ) {
-                                       /* test asserted values against themselves */
-                                       for( j = 0; j < i; j++ ) {
-                                               rc = ordered_value_match( &match, ml->sml_desc, mr,
-                                                       SLAP_MR_EQUALITY
-                                                               | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
-                                                               | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
-                                                               | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
-                                                       ml->sml_nvalues
-                                                               ? &ml->sml_nvalues[i]
-                                                               : &ml->sml_values[i],
-                                                       ml->sml_nvalues
-                                                               ? &ml->sml_nvalues[j]
-                                                               : &ml->sml_values[j],
-                                                       text );
-                                               if ( rc == LDAP_SUCCESS && match == 0 ) {
-                                                       /* value exists already */
-                                                       snprintf( textbuf, textlen,
-                                                               "%s: value #%d provided more than once",
-                                                               ml->sml_desc->ad_cname.bv_val, j );
-                                                       *text = textbuf;
-                                                       return LDAP_TYPE_OR_VALUE_EXISTS;
-
-                                               } else if ( rc != LDAP_SUCCESS ) {
-                                                       return rc;
-                                               }
-                                       }
+                               int i;
+                               rc = slap_sort_vals( ml, text, &i, ctx );
+                               if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
+                                       /* value exists already */
+                                       snprintf( textbuf, textlen,
+                                               "%s: value #%d provided more than once",
+                                               ml->sml_desc->ad_cname.bv_val, i );
+                                       *text = textbuf;
                                }
-#else  /* SLAP_MODS_CHECK_QUICKSORT */
+                               if ( rc )
+                                       return rc;
+                       }
+               } else {
+                       ml->sml_numvals = 0;
+               }
+       }
+
+       return LDAP_SUCCESS;
+}
+
+/* Sort a set of values. An (Attribute *) may be used interchangeably here
+ * instead of a (Modifications *) structure.
+ *
+ * Uses Quicksort + Insertion sort for small arrays
+ */
 
-/* Quicksort + Insertion sort for small arrays */
+int
+slap_sort_vals(
+       Modifications *ml,
+       const char **text,
+       int *dup,
+       void *ctx )
+{
+       AttributeDescription *ad;
+       MatchingRule *mr;
+       int istack[sizeof(int)*16];
+       int i, j, k, l, ir, jstack, match, *ix, itmp, nvals, rc;
+       int is_norm;
+       struct berval a, *cv;
 
 #define SMALL  8
 #define        SWAP(a,b,tmp)   tmp=(a);(a)=(b);(b)=tmp
 #define        COMP(a,b)       match=0; rc = ordered_value_match( &match, \
-                                               ml->sml_desc, mr, SLAP_MR_EQUALITY \
+                                               ad, mr, SLAP_MR_EQUALITY \
                                                                | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX \
                                                                | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH \
                                                                | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, \
                                                                &(a), &(b), text );
 
-                                       MatchingRule *mr = ad->ad_type->sat_equality;
-                                       int istack[sizeof(int)*16];
-                                       int i, j, k, l, ir, jstack, match, *ix, itmp;
-                                       struct berval a, *cv;
-
-/* If PRESERVE_ORDER is defined only the index array is sorted; the
- * actual values are left in their incoming order. Otherwise, the
- * only reason to keep the index array is to identify the offending
- * value when duplicates are found.
- */
-#define        PRESERVE_ORDER
-#ifndef PRESERVE_ORDER
-                                       struct berval va, *v, *nv, bvtmp;
-
-#define        IX(x)   x
-#define        EXCH(x,y)       SWAP(ix[x],ix[y],itmp); SWAP(cv[x],cv[y],bvtmp); \
-       if (nv) {SWAP(v[x],v[y],bvtmp);}
-#define        SETA(x) itmp = ix[x]; a = cv[x]; if (nv) va=v[x]
-#define        GETA(x) ix[x] = itmp; cv[x] = a; if (nv) v[x]=va
-#define        SET(x,y)        ix[x] = ix[y]; cv[x] = cv[y]; if (nv) v[x]=v[y]
-
-                                       v = ml->sml_values;
-                                       nv = ml->sml_nvalues;
-
-#else  /* PRESERVE_ORDER */
-
 #define        IX(x)   ix[x]
 #define        EXCH(x,y)       SWAP(ix[x],ix[y],itmp)
 #define        SETA(x) itmp = ix[x]; a = cv[itmp]
 #define        GETA(x) ix[x] = itmp;
 #define        SET(x,y)        ix[x] = ix[y]
 
-#endif /* PRESERVE_ORDER */
-
-                                       cv = ml->sml_nvalues ? ml->sml_nvalues : ml->sml_values;
-                                       if ( ad == slap_schema.si_ad_objectClass )
-                                               mr = NULL;      /* shortcut matching */
-
-                                       /* record indices to preserve input ordering */
-                                       ix = slap_sl_malloc( nvals * sizeof(int), ctx );
-                                       for (i=0; i<nvals; i++) ix[i] = i;
-
-                                       ir = nvals-1;
-                                       l = 0;
-                                       jstack = 0;
-
-                                       for(;;) {
-                                               if (ir - l < SMALL) {   /* Insertion sort */
-                                                       match=1;
-                                                       for (j=l+1;j<=ir;j++) {
-                                                               SETA(j);
-                                                               for (i=j-1;i>=0;i--) {
-                                                                       COMP(cv[IX(i)], a);
-                                                                       if ( match <= 0 )
-                                                                               break;
-                                                                       SET(i+1,i);
-                                                               }
-                                                               GETA(i+1);
-                                                               if ( match == 0 ) goto done;
-                                                       }
-                                                       if ( jstack == 0 ) break;
-                                                       if ( match == 0 ) break;
-                                                       ir = istack[jstack--];
-                                                       l = istack[jstack--];
-                                               } else {
-                                                       k = (l + ir) >> 1;      /* Choose median of left, center, right */
-                                                       EXCH(k, l+1);
-                                                       COMP( cv[IX(l)], cv[IX(ir)] );
-                                                       if ( match > 0 ) {
-                                                               EXCH(l, ir);
-                                                       } else if ( match == 0 ) {
-                                                               i = ir;
-                                                               break;
-                                                       }
-                                                       COMP( cv[IX(l+1)], cv[IX(ir)] );
-                                                       if ( match > 0 ) {
-                                                               EXCH(l+1, ir);
-                                                       } else if ( match == 0 ) {
-                                                               i = ir;
-                                                               break;
-                                                       }
-                                                       COMP( cv[IX(l)], cv[IX(l+1)] );
-                                                       if ( match > 0 ) {
-                                                               EXCH(l, l+1);
-                                                       } else if ( match == 0 ) {
-                                                               i = l;
-                                                               break;
-                                                       }
-                                                       i = l+1;
-                                                       j = ir;
-                                                       a = cv[IX(i)];
-                                                       for(;;) {
-                                                               do {
-                                                                       i++;
-                                                                       COMP( cv[IX(i)], a );
-                                                               } while( match < 0 );
-                                                               while( match > 0 ) {
-                                                                       j--;
-                                                                       COMP( cv[IX(j)], a );
-                                                               }
-                                                               if (j < i) {
-                                                                       match = 1;
-                                                                       break;
-                                                               }
-                                                               if ( match == 0 ) {
-                                                                       i = l+1;
-                                                                       break;
-                                                               }
-                                                               EXCH(i,j);
-                                                       }
-                                                       if ( match == 0 )
-                                                               break;
-                                                       EXCH(l+1,j);
-                                                       jstack += 2;
-                                                       if (ir-i+1 >= j) {
-                                                               istack[jstack] = ir;
-                                                               istack[jstack-1] = i;
-                                                               ir = j;
-                                                       } else {
-                                                               istack[jstack] = j;
-                                                               istack[jstack-1] = l;
-                                                               l = i;
-                                               }
-                                       }
-                               }
-done:
-                               if ( i >= 0 )
-                                       j = ix[i];
+       ad = ml->sml_desc;
+       nvals = ml->sml_numvals;
 
-                               slap_sl_free( ix, ctx );
+       /* For Modifications, sml_nvalues is NULL if normalization wasn't needed.
+        * For Attributes, sml_nvalues == sml_values when normalization isn't needed.
+        */
+       if ( ml->sml_nvalues && ml->sml_nvalues != ml->sml_values ) {
+               cv = ml->sml_nvalues;
+               is_norm = 1;
+       } else {
+               cv = ml->sml_values;
+               is_norm = 0;
+       }
 
-                               if ( rc != LDAP_SUCCESS ) {
-                                       return rc;
-                               } else if ( match == 0 ) {
-                                       /* value exists already */
-                                       assert( i >= 0 );
-                                       assert( i < nvals );
-                                       snprintf( textbuf, textlen,
-                                               "%s: value #%d provided more than once",
-                                               ml->sml_desc->ad_cname.bv_val, j );
-                                       *text = textbuf;
-                                       return LDAP_TYPE_OR_VALUE_EXISTS;
+       if ( ad == slap_schema.si_ad_objectClass )
+               mr = NULL;      /* shortcut matching */
+       else
+               mr = ad->ad_type->sat_equality;
+
+       /* record indices to preserve input ordering */
+       ix = slap_sl_malloc( nvals * sizeof(int), ctx );
+       for (i=0; i<nvals; i++) ix[i] = i;
+
+       ir = nvals-1;
+       l = 0;
+       jstack = 0;
+
+       for(;;) {
+               if (ir - l < SMALL) {   /* Insertion sort */
+                       match=1;
+                       for (j=l+1;j<=ir;j++) {
+                               SETA(j);
+                               for (i=j-1;i>=0;i--) {
+                                       COMP(cv[IX(i)], a);
+                                       if ( match <= 0 )
+                                               break;
+                                       SET(i+1,i);
+                               }
+                               GETA(i+1);
+                               if ( match == 0 ) goto done;
+                       }
+                       if ( jstack == 0 ) break;
+                       if ( match == 0 ) break;
+                       ir = istack[jstack--];
+                       l = istack[jstack--];
+               } else {
+                       k = (l + ir) >> 1;      /* Choose median of left, center, right */
+                       EXCH(k, l+1);
+                       COMP( cv[IX(l)], cv[IX(ir)] );
+                       if ( match > 0 ) {
+                               EXCH(l, ir);
+                       } else if ( match == 0 ) {
+                               i = ir;
+                               break;
+                       }
+                       COMP( cv[IX(l+1)], cv[IX(ir)] );
+                       if ( match > 0 ) {
+                               EXCH(l+1, ir);
+                       } else if ( match == 0 ) {
+                               i = ir;
+                               break;
+                       }
+                       COMP( cv[IX(l)], cv[IX(l+1)] );
+                       if ( match > 0 ) {
+                               EXCH(l, l+1);
+                       } else if ( match == 0 ) {
+                               i = l;
+                               break;
+                       }
+                       i = l+1;
+                       j = ir;
+                       a = cv[IX(i)];
+                       for(;;) {
+                               do {
+                                       i++;
+                                       COMP( cv[IX(i)], a );
+                               } while( match < 0 );
+                               while( match > 0 ) {
+                                       j--;
+                                       COMP( cv[IX(j)], a );
+                               }
+                               if (j < i) {
+                                       match = 1;
+                                       break;
+                               }
+                               if ( match == 0 ) {
+                                       i = l+1;
+                                       break;
                                }
-#endif /* SLAP_MODS_CHECK_QUICKSORT */
+                               EXCH(i,j);
+                       }
+                       if ( match == 0 )
+                               break;
+                       EXCH(l+1,j);
+                       jstack += 2;
+                       if (ir-i+1 >= j) {
+                               istack[jstack] = ir;
+                               istack[jstack-1] = i;
+                               ir = j;
+                       } else {
+                               istack[jstack] = j;
+                               istack[jstack-1] = l;
+                               l = i;
                        }
                }
        }
+       done:
+       if ( i >= 0 )
+               *dup = ix[i];
+
+       /* For sorted attributes, put the values in index order */
+       if ( rc == LDAP_SUCCESS && match &&
+               ( ad->ad_type->sat_flags & SLAP_AT_SORTED_VAL )) {
+               BerVarray tmpv = slap_sl_malloc( sizeof( struct berval ) * nvals, ctx );
+               for ( i = 0; i<nvals; i++ )
+                       tmpv[i] = cv[ix[i]];
+               for ( i = 0; i<nvals; i++ )
+                       cv[i] = tmpv[i];
+               /* Check if the non-normalized array needs to move too */
+               if ( is_norm ) {
+                       cv = ml->sml_values;
+                       for ( i = 0; i<nvals; i++ )
+                               tmpv[i] = cv[ix[i]];
+                       for ( i = 0; i<nvals; i++ )
+                               cv[i] = tmpv[i];
+               }
+               slap_sl_free( tmpv, ctx );
+       }
+
+       slap_sl_free( ix, ctx );
 
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
+       } else if ( match == 0 ) {
+               /* value exists already */
+               assert( i >= 0 );
+               assert( i < nvals );
+               return LDAP_TYPE_OR_VALUE_EXISTS;
+       }
        return LDAP_SUCCESS;
 }
 
@@ -946,6 +947,7 @@ void slap_mods_opattrs(
                        mod->sml_next = NULL;
                        BER_BVZERO( &mod->sml_type );
                        mod->sml_desc = slap_schema.si_ad_entryCSN;
+                       mod->sml_numvals = 1;
                        mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                        ber_dupbv( &mod->sml_values[0], &csn );
                        BER_BVZERO( &mod->sml_values[1] );
@@ -963,6 +965,7 @@ void slap_mods_opattrs(
                        mod->sml_next = NULL;
                        BER_BVZERO( &mod->sml_type );
                        mod->sml_desc = slap_schema.si_ad_modifiersName;
+                       mod->sml_numvals = 1;
                        mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                        ber_dupbv( &mod->sml_values[0], &name );
                        BER_BVZERO( &mod->sml_values[1] );
@@ -983,6 +986,7 @@ void slap_mods_opattrs(
                        mod->sml_next = NULL;
                        BER_BVZERO( &mod->sml_type );
                        mod->sml_desc = slap_schema.si_ad_modifyTimestamp;
+                       mod->sml_numvals = 1;
                        mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                        ber_dupbv( &mod->sml_values[0], &timestamp );
                        BER_BVZERO( &mod->sml_values[1] );
index 3aae6ac4448c7733197577d195e6069ab2d196e9..e0f1725efef6f43a3e9e19dd01d1327247cebb84 100644 (file)
@@ -428,6 +428,7 @@ slap_modrdn2mods(
                mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications ) );
                mod_tmp->sml_desc = desc;
                BER_BVZERO( &mod_tmp->sml_type );
+               mod_tmp->sml_numvals = 1;
                mod_tmp->sml_values = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) );
                ber_dupbv( &mod_tmp->sml_values[0], &new_rdn[a_cnt]->la_value );
                mod_tmp->sml_values[1].bv_val = NULL;
@@ -469,6 +470,7 @@ slap_modrdn2mods(
                        mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications ) );
                        mod_tmp->sml_desc = desc;
                        BER_BVZERO( &mod_tmp->sml_type );
+                       mod_tmp->sml_numvals = 1;
                        mod_tmp->sml_values = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) );
                        ber_dupbv( &mod_tmp->sml_values[0], &old_rdn[d_cnt]->la_value );
                        mod_tmp->sml_values[1].bv_val = NULL;
index 31b79274c8a0fddf04ac21bcd35bf2c58516b6f8..2d0d01fc8bda05b56838857e97b57d6065483bd2 100644 (file)
@@ -56,11 +56,21 @@ modify_add_values(
                assert( 0 );
        }
 
+       /* FIXME: Catch old code that doesn't set sm_numvals.
+        */
+       if ( !BER_BVISNULL( &mod->sm_values[mod->sm_numvals] )) {
+               int i;
+               for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ );
+               assert( mod->sm_numvals == i );
+       }
+
        /* check if values to add exist in attribute */
        a = attr_find( e->e_attrs, mod->sm_desc );
        if ( a != NULL ) {
-               int             rc, i, j, p;
                MatchingRule    *mr;
+               struct berval *cvals;
+               int             rc, i, j, p;
+               unsigned flags;
 
                mr = mod->sm_desc->ad_type->sat_equality;
                if( mr == NULL || !mr->smr_match ) {
@@ -74,10 +84,7 @@ modify_add_values(
                }
 
                if ( permissive ) {
-                       for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
-                               /* EMPTY -- just counting 'em */;
-                       }
-
+                       i = mod->sm_numvals;
                        pmod.sm_values = (BerVarray)ch_malloc(
                                (i + 1) * sizeof( struct berval ));
                        if ( pmod.sm_nvalues != NULL ) {
@@ -92,39 +99,32 @@ modify_add_values(
                 * server (whether from LDAP or from the underlying
                 * database).
                 */
-               for ( p = i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
-                       int     match;
-
-                       assert( a->a_vals[0].bv_val != NULL );
-                       for ( j = 0; !BER_BVISNULL( &a->a_vals[j] ); j++ ) {
-                               if ( mod->sm_nvalues ) {
-                                       rc = ordered_value_match( &match, mod->sm_desc, mr,
-                                               SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
-                                                       | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
-                                                       | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
-                                               &a->a_nvals[j], &mod->sm_nvalues[i], text );
-                               } else {
-                                       rc = ordered_value_match( &match, mod->sm_desc, mr,
-                                               SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
-                                               &a->a_vals[j], &mod->sm_values[i], text );
-                               }
+               flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX;
+               if ( mod->sm_nvalues ) {
+                       flags |= SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
+                               SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
+                       cvals = mod->sm_nvalues;
+               } else {
+                       cvals = mod->sm_values;
+               }
+               for ( p = i = 0; i < mod->sm_numvals; i++ ) {
+                       unsigned        slot;
 
-                               if ( rc == LDAP_SUCCESS && match == 0 ) {
+                       rc = attr_valfind( a, flags, &cvals[i], &slot, NULL );
+                       if ( rc == LDAP_SUCCESS ) {
+                               if ( !permissive ) {
                                        /* value already exists */
-                                       if ( permissive ) break;
-
                                        *text = textbuf;
                                        snprintf( textbuf, textlen,
                                                "modify/%s: %s: value #%d already exists",
                                                op, mod->sm_desc->ad_cname.bv_val, i );
                                        return LDAP_TYPE_OR_VALUE_EXISTS;
-
-                               } else if ( rc != LDAP_SUCCESS ) {
-                                       return rc;
                                }
+                       } else if ( rc != LDAP_NO_SUCH_ATTRIBUTE ) {
+                               return rc;
                        }
 
-                       if ( permissive && match != 0 ) {
+                       if ( permissive && rc ) {
                                if ( pmod.sm_nvalues ) {
                                        pmod.sm_nvalues[p] = mod->sm_nvalues[i];
                                }
@@ -164,8 +164,8 @@ modify_add_values(
                /* this should return result of attr_merge */
                *text = textbuf;
                snprintf( textbuf, textlen,
-                       "modify/%s: %s: merge error",
-                       op, mod->sm_desc->ad_cname.bv_val );
+                       "modify/%s: %s: merge error (%d)",
+                       op, mod->sm_desc->ad_cname.bv_val, rc );
                return LDAP_OTHER;
        }
 
@@ -192,11 +192,13 @@ modify_delete_vindex(
        char *textbuf, size_t textlen,
        int *idx )
 {
-       int             i, j, k, rc = LDAP_SUCCESS;
        Attribute       *a;
        MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
+       struct berval *cvals;
+       int             *id2 = NULL;
+       int             i, j, rc = 0;
+       unsigned flags;
        char            dummy = '\0';
-       int             match = 0;
 
        /*
         * If permissive is set, then the non-existence of an 
@@ -219,6 +221,17 @@ modify_delete_vindex(
                return rc;
        }
 
+       /* FIXME: Catch old code that doesn't set sm_numvals.
+        */
+       if ( !BER_BVISNULL( &mod->sm_values[mod->sm_numvals] )) {
+               for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ );
+               assert( mod->sm_numvals == i );
+       }
+       if ( !idx ) {
+               id2 = ch_malloc( mod->sm_numvals * sizeof( int ));
+               idx = id2;
+       }
+
        if( mr == NULL || !mr->smr_match ) {
                /* disallow specific attributes from being deleted if
                        no equality rule */
@@ -226,101 +239,90 @@ modify_delete_vindex(
                snprintf( textbuf, textlen,
                        "modify/delete: %s: no equality matching rule",
                        mod->sm_desc->ad_cname.bv_val );
-               return LDAP_INAPPROPRIATE_MATCHING;
+               rc = LDAP_INAPPROPRIATE_MATCHING;
+               goto return_result;
        }
 
        /* delete specific values - find the attribute first */
        if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
                if( permissive ) {
-                       return LDAP_SUCCESS;
+                       rc = LDAP_SUCCESS;
+                       goto return_result;
                }
                *text = textbuf;
                snprintf( textbuf, textlen,
                        "modify/delete: %s: no such attribute",
                        mod->sm_desc->ad_cname.bv_val );
-               return LDAP_NO_SUCH_ATTRIBUTE;
+               rc = LDAP_NO_SUCH_ATTRIBUTE;
+               goto return_result;
        }
 
-       for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
-               int     found = 0;
-               for ( j = 0; !BER_BVISNULL( &a->a_vals[j] ); j++ ) {
-                       /* skip already deleted values */
-                       if ( a->a_vals[j].bv_val == &dummy ) {
-                               continue;
-                       }
-
-                       if( mod->sm_nvalues ) {
-                               assert( a->a_nvals != NULL );
-                               rc = ordered_value_match( &match, a->a_desc, mr,
-                                       SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
-                                               | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
-                                               | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
-                                       &a->a_nvals[j], &mod->sm_nvalues[i], text );
-                       } else {
-#if 0
-                               assert( a->a_nvals == NULL );
-#endif
-                               rc = ordered_value_match( &match, a->a_desc, mr,
-                                       SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
-                                       &a->a_vals[j], &mod->sm_values[i], text );
-                       }
-
-                       if ( rc != LDAP_SUCCESS ) {
-                               *text = textbuf;
-                               snprintf( textbuf, textlen,
-                                       "%s: matching rule failed",
-                                       mod->sm_desc->ad_cname.bv_val );
-                               break;
-                       }
+       if ( mod->sm_nvalues ) {
+               flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
+                       | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
+                       | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
+               cvals = mod->sm_nvalues;
+       } else {
+               flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX;
+               cvals = mod->sm_values;
+       }
 
-                       if ( match != 0 ) {
+       /* Locate values to delete */
+       for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
+               unsigned sort;
+               rc = attr_valfind( a, flags, &cvals[i], &sort, NULL );
+               if ( rc == LDAP_SUCCESS ) {
+                       idx[i] = sort;
+               } else if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
+                       if ( permissive ) {
+                               idx[i] = -1;
                                continue;
                        }
-
-                       found = 1;
-
-                       if ( idx )
-                               idx[i] = j;
-
-                       /* delete value and mark it as dummy */
-                       free( a->a_vals[j].bv_val );
-                       a->a_vals[j].bv_val = &dummy;
-                       if( a->a_nvals != a->a_vals ) {
-                               free( a->a_nvals[j].bv_val );
-                               a->a_nvals[j].bv_val = &dummy;
-                       }
-
-                       break;
-               }
-
-               if ( found == 0 ) {
                        *text = textbuf;
                        snprintf( textbuf, textlen,
                                "modify/delete: %s: no such value",
                                mod->sm_desc->ad_cname.bv_val );
-                       rc = LDAP_NO_SUCH_ATTRIBUTE;
-                       if ( i > 0 ) {
-                               break;
-                       } else {
-                               goto return_results;
-                       }
+                       goto return_result;
+               } else {
+                       *text = textbuf;
+                       snprintf( textbuf, textlen,
+                               "modify/delete: %s: matching rule failed",
+                               mod->sm_desc->ad_cname.bv_val );
+                       goto return_result;
+               }
+       }
+
+       /* Delete the values */
+       for ( i = 0; i < mod->sm_numvals; i++ ) {
+               /* Skip permissive values that weren't found */
+               if ( idx[i] < 0 )
+                       continue;
+               /* Skip duplicate delete specs */
+               if ( a->a_vals[idx[i]].bv_val == &dummy )
+                       continue;
+               /* delete value and mark it as gone */
+               free( a->a_vals[idx[i]].bv_val );
+               a->a_vals[idx[i]].bv_val = &dummy;
+               if( a->a_nvals != a->a_vals ) {
+                       free( a->a_nvals[idx[i]].bv_val );
+                       a->a_nvals[idx[i]].bv_val = &dummy;
                }
+               a->a_numvals--;
        }
 
        /* compact array skipping dummies */
-       for ( k = 0, j = 0; !BER_BVISNULL( &a->a_vals[k] ); k++ ) {
+       for ( i = 0, j = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
                /* skip dummies */
-               if( a->a_vals[k].bv_val == &dummy ) {
-                       assert( a->a_nvals[k].bv_val == &dummy );
+               if( a->a_vals[i].bv_val == &dummy ) {
+                       assert( a->a_nvals[i].bv_val == &dummy );
                        continue;
                }
-               if ( j != k ) {
-                       a->a_vals[ j ] = a->a_vals[ k ];
+               if ( j != i ) {
+                       a->a_vals[ j ] = a->a_vals[ i ];
                        if (a->a_nvals != a->a_vals) {
-                               a->a_nvals[ j ] = a->a_nvals[ k ];
+                               a->a_nvals[ j ] = a->a_nvals[ i ];
                        }
                }
-
                j++;
        }
 
@@ -330,8 +332,9 @@ modify_delete_vindex(
        }
 
        /* if no values remain, delete the entire attribute */
-       if ( BER_BVISNULL( &a->a_vals[0] ) ) {
+       if ( !a->a_numvals ) {
                if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
+                       /* Can never happen */
                        *text = textbuf;
                        snprintf( textbuf, textlen,
                                "modify/delete: %s: no such attribute",
@@ -342,9 +345,9 @@ modify_delete_vindex(
                /* For an ordered attribute, renumber the value indices */
                ordered_value_sort( a, 1 );
        }
-
-return_results:;
-
+return_result:
+       if ( id2 )
+               ch_free( id2 );
        return rc;
 }
 
index fd12d0aff6e38f89c691edfe763b8b015e05aedb..f55cfd98f8491b2df94ff7795c3094aae9c30c5d 100644 (file)
@@ -31,6 +31,7 @@ slap_operational_subschemaSubentry( Backend *be )
 
        a = attr_alloc( slap_schema.si_ad_subschemaSubentry );
 
+       a->a_numvals = 1;
        a->a_vals = ch_malloc( 2 * sizeof( struct berval ) );
        ber_dupbv( a->a_vals, &frontendDB->be_schemadn );
        a->a_vals[1].bv_len = 0;
@@ -55,6 +56,7 @@ slap_operational_entryDN( Entry *e )
 
        a = attr_alloc( slap_schema.si_ad_entryDN );
 
+       a->a_numvals = 1;
        a->a_vals = ch_malloc( 2 * sizeof( struct berval ) );
        ber_dupbv( &a->a_vals[ 0 ], &e->e_name );
        BER_BVZERO( &a->a_vals[ 1 ] );
@@ -75,6 +77,7 @@ slap_operational_hasSubordinate( int hs )
        val = hs ? slap_true_bv : slap_false_bv;
 
        a = attr_alloc( slap_schema.si_ad_hasSubordinates );
+       a->a_numvals = 1;
        a->a_vals = ch_malloc( 2 * sizeof( struct berval ) );
 
        ber_dupbv( &a->a_vals[0], &val );
index b034d061cb7ce3ceb5766f5811031b9fe3beb9d4..e0b0e8bb024dd01c5181d9f98b5bddee7803da7a 100644 (file)
@@ -1365,11 +1365,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                /* count all the vals */
                i = 0;
                for ( a=e2->e_attrs; a; a=a->a_next ) {
-                       if ( a->a_vals ) {
-                               for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
-                                       i++;
-                               }
-                       }
+                       i += a->a_numvals;
                }
                vals = ch_malloc( (i+1) * sizeof( struct berval ));
                i = 0;
@@ -1383,6 +1379,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                vals[i].bv_val = NULL;
                vals[i].bv_len = 0;
                a = attr_alloc( logop == LOG_EN_ADD ? ad_reqMod : ad_reqOld );
+               a->a_numvals = i;
                a->a_vals = vals;
                a->a_nvals = vals;
                last_attr->a_next = a;
@@ -1395,9 +1392,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                i = 0;
                for ( m = op->orm_modlist; m; m = m->sml_next ) {
                        if ( m->sml_values ) {
-                               for ( b = m->sml_values; !BER_BVISNULL( b ); b++ ) {
-                                       i++;
-                               }
+                               i += m->sml_numvals;
                        } else if ( m->sml_op == LDAP_MOD_DELETE ||
                                m->sml_op == LDAP_MOD_REPLACE )
                        {
@@ -1478,6 +1473,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                if ( i > 0 ) {
                        BER_BVZERO( &vals[i] );
                        a = attr_alloc( ad_reqMod );
+                       a->a_numvals = i;
                        a->a_vals = vals;
                        a->a_nvals = vals;
                        last_attr->a_next = a;
@@ -1492,9 +1488,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                        i = 0;
                        for ( a = old->e_attrs; a != NULL; a = a->a_next ) {
                                if ( a->a_vals && a->a_flags ) {
-                                       for ( b = a->a_vals; !BER_BVISNULL( b ); b++ ) {
-                                               i++;
-                                       }
+                                       i += a->a_numvals;
                                }
                        }
                        vals = ch_malloc( (i + 1) * sizeof( struct berval ) );
@@ -1509,6 +1503,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                        vals[i].bv_val = NULL;
                        vals[i].bv_len = 0;
                        a = attr_alloc( ad_reqOld );
+                       a->a_numvals = i;
                        a->a_vals = vals;
                        a->a_nvals = vals;
                        last_attr->a_next = a;
@@ -1788,10 +1783,9 @@ accesslog_operational( Operation *op, SlapReply *rs )
                                ad_inlist( ad_auditContext, rs->sr_attrs ) )
                {
                        *ap = attr_alloc( ad_auditContext );
-                       value_add_one( &(*ap)->a_vals,
-                               &li->li_db->be_suffix[0] );
-                       value_add_one( &(*ap)->a_nvals,
-                               &li->li_db->be_nsuffix[0] );
+                       attr_valadd( *ap,
+                               &li->li_db->be_suffix[0],
+                               &li->li_db->be_nsuffix[0], 1 );
                }
        }
 
index 1df2ccd7bbbc061464daa80e7f2ac90a9328ccb2..ebf70ec878b8fde65af3d5032a01f13a42fbc799 100644 (file)
@@ -788,6 +788,7 @@ done:;
                        tmpmod->sml_op = LDAP_MOD_REPLACE;
                        value_add_one( &tmpmod->sml_values, &bv );
                        value_add_one( &tmpmod->sml_nvalues, &bv );
+                       tmpmod->sml_numvals = 1;
                }
        }
 
@@ -1087,6 +1088,7 @@ dds_op_extended( Operation *op, SlapReply *rs )
                ttlmod.sml_flags = SLAP_MOD_MANAGING;
                ttlmod.sml_desc = slap_schema.si_ad_entryTtl;
                ttlmod.sml_values = ttlvalues;
+               ttlmod.sml_numvals = 1;
                ttlvalues[ 0 ].bv_val = ttlbuf;
                ttlvalues[ 0 ].bv_len = snprintf( ttlbuf, sizeof( ttlbuf ), "%ld", ttl );
                BER_BVZERO( &ttlvalues[ 1 ] );
index 1446df1fbe9ff363cefc445ec18357249be25cf4..4fcd0794ac1b2addbc3e06b2d9566053c3629f57 100644 (file)
@@ -92,10 +92,10 @@ dynlist_is_dynlist_next( Operation *op, SlapReply *rs, dynlist_info_t *old_dli )
        }
 
        for ( ; dli; dli = dli->dli_next ) {
-               if ( value_find_ex( slap_schema.si_ad_objectClass, 
+               if ( attr_valfind( a,
                                SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                               a->a_nvals, &dli->dli_oc->soc_cname,
+                               &dli->dli_oc->soc_cname, NULL,
                                op->o_tmpmemctx ) == 0 )
                {
                        return dli;
@@ -189,6 +189,7 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
                        mod.sm_type = dlc->dlc_dli->dli_member_ad->ad_cname;
                        mod.sm_values = vals;
                        mod.sm_nvalues = nvals;
+                       mod.sm_numvals = 1;
 
                        (void)modify_add_values( e, &mod, /* permissive */ 1,
                                        &text, textbuf, sizeof( textbuf ) );
@@ -248,8 +249,7 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
                }
 
                /* test access to attribute */
-               for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ )
-                       /* just count */ ;
+               i = a->a_numvals;
 
                vals = op->o_tmpalloc( ( i + 1 ) * sizeof( struct berval ), op->o_tmpmemctx );
                if ( a->a_nvals != a->a_vals ) {
@@ -293,6 +293,7 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
                        mod.sm_type = a->a_desc->ad_cname;
                        mod.sm_values = vals;
                        mod.sm_nvalues = nvals;
+                       mod.sm_numvals = j;
 
                        (void)modify_add_values( e, &mod, /* permissive */ 1,
                                        &text, textbuf, sizeof( textbuf ) );
@@ -635,7 +636,7 @@ dynlist_compare( Operation *op, SlapReply *rs )
                }
 
                o.ors_filterstr = *slap_filterstr_objectClass_pres;
-               o.ors_filter = slap_filter_objectClass_pres;
+               o.ors_filter = (Filter *) slap_filter_objectClass_pres;
 
                o.ors_scope = LDAP_SCOPE_BASE;
                o.ors_deref = LDAP_DEREF_NEVER;
@@ -673,10 +674,10 @@ dynlist_compare( Operation *op, SlapReply *rs )
                        /* if we're here, we got a match... */
                        rs->sr_err = LDAP_COMPARE_FALSE;
 
-                       if ( value_find_ex( op->orc_ava->aa_desc,
+                       if ( attr_valfind( a,
                                SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                        SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                               a->a_nvals, &op->orc_ava->aa_value, op->o_tmpmemctx ) == 0 )
+                               &op->orc_ava->aa_value, NULL, op->o_tmpmemctx ) == 0 )
                        {
                                rs->sr_err = LDAP_COMPARE_TRUE;
                                break;
index 5bbe2a2dbf7961435c865aa2ec1ebc20012223f0..40cf08b93026a3bd6e26c46360a409737ff0fcc9 100644 (file)
@@ -195,7 +195,7 @@ memberof_saved_member_get( Operation *op, void *keyp )
        BerVarray       vals;
        BerVarray       *key = (BerVarray *)keyp;
 
-       assert( op );
+       assert( op != NULL );
 
        if ( op->o_threadctx == NULL ) {
                vals = *key;
@@ -217,7 +217,7 @@ memberof_saved_member_set( Operation *op, void *keyp, BerVarray vals )
        BerVarray       saved_vals = NULL;
        BerVarray       *key = (BerVarray*)keyp;
 
-       assert( op );
+       assert( op != NULL );
 
        if ( vals ) {
                ber_bvarray_dup_x( &saved_vals, vals, NULL );
@@ -268,8 +268,8 @@ memberof_saveMember_cb( Operation *op, SlapReply *rs )
                mc = (memberof_cookie_t *)op->o_callback->sc_private;
                mc->foundit = 1;
 
-               assert( rs->sr_entry );
-               assert( rs->sr_entry->e_attrs );
+               assert( rs->sr_entry != NULL );
+               assert( rs->sr_entry->e_attrs != NULL );
 
                a = attr_find( rs->sr_entry->e_attrs, mc->ad );
 
@@ -416,6 +416,7 @@ memberof_value_modify(
        op2.o_ndn = op->o_bd->be_rootndn;
 
        ml = &mod[ 0 ];
+       ml->sml_numvals = 1;
        ml->sml_values = &values[ 0 ];
        ml->sml_values[ 0 ] = mo->mo_dn;
        BER_BVZERO( &ml->sml_values[ 1 ] );
@@ -430,6 +431,7 @@ memberof_value_modify(
        op2.orm_modlist = ml;
 
        ml = &mod[ 1 ];
+       ml->sml_numvals = 1;
        ml->sml_values = &values[ 2 ];
        BER_BVZERO( &ml->sml_values[ 1 ] );
        ml->sml_nvalues = &nvalues[ 2 ];
@@ -778,7 +780,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
                        case LDAP_MOD_ADD:
                                /* NOTE: right now, the attributeType we use
                                 * for member must have a normalized value */
-                               assert( ml->sml_nvalues );
+                               assert( ml->sml_nvalues != NULL );
        
                                for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) {
                                        int             rc;
@@ -812,6 +814,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
                                                BER_BVZERO( &ml->sml_values[ i ] );
                                                ber_memfree( ml->sml_nvalues[ i ].bv_val );
                                                BER_BVZERO( &ml->sml_nvalues[ i ] );
+                                               ml->sml_numvals--;
                                                if ( j - i == 1 ) {
                                                        break;
                                                }
@@ -909,6 +912,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
                                                                ber_memfree( ml->sml_nvalues[ i ].bv_val );
                                                                BER_BVZERO( &ml->sml_nvalues[ i ] );
                                                        }
+                                                       ml->sml_numvals--;
                                                        if ( j - i == 1 ) {
                                                                break;
                                                        }
@@ -1019,6 +1023,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
                                                        ber_memfree( ml->sml_nvalues[ i ].bv_val );
                                                        BER_BVZERO( &ml->sml_nvalues[ i ] );
                                                }
+                                               ml->sml_numvals--;
                                                if ( j - i == 1 ) {
                                                        break;
                                                }
index 71e04db825d56d34303df1d6b5aaf11bc6d9d9eb..70ef66ac5580ae1216e39db0ccfb35d90f3a82b7 100644 (file)
@@ -1367,8 +1367,7 @@ remove_func (
        attr = attr_find( rs->sr_entry->e_attrs,  ad_queryId );
        if ( attr == NULL ) return 0;
 
-       for ( count = 0; !BER_BVISNULL( &attr->a_vals[count] ); count++ )
-               ;
+       count = attr->a_numvals;
        assert( count > 0 );
        qi = op->o_tmpalloc( sizeof( struct query_info ), op->o_tmpmemctx );
        qi->next = op->o_callback->sc_private;
@@ -1450,6 +1449,7 @@ remove_query_data(
                        mod.sml_type = ad_queryId->ad_cname;
                        mod.sml_values = vals;
                        mod.sml_nvalues = NULL;
+                        mod.sml_numvals = 1;
                        mod.sml_next = NULL;
                        Debug( pcache_debug,
                                "REMOVING TEMP ATTR : TEMPLATE=%s\n",
@@ -3354,6 +3354,7 @@ pcache_db_close(
                mod.sml_type = ad_cachedQueryURL->ad_cname;
                mod.sml_values = vals;
                mod.sml_nvalues = NULL;
+                mod.sml_numvals = 1;
                mod.sml_next = NULL;
                Debug( pcache_debug,
                        "%sSETTING CACHED QUERY URLS\n",
index 2900c64c31cd0ff17301e976080d1ca26c4df9b8..e126598055cc1fd3e186c8091899474709639bce 100644 (file)
@@ -921,6 +921,7 @@ ppolicy_bind_response( Operation *op, SlapReply *rs )
                m->sml_flags = 0;
                m->sml_type = ad_pwdFailureTime->ad_cname;
                m->sml_desc = ad_pwdFailureTime;
+               m->sml_numvals = 1;
                m->sml_values = ch_calloc( sizeof(struct berval), 2 );
                m->sml_nvalues = ch_calloc( sizeof(struct berval), 2 );
 
@@ -970,6 +971,7 @@ ppolicy_bind_response( Operation *op, SlapReply *rs )
                        m->sml_flags = 0;
                        m->sml_type = ad_pwdAccountLockedTime->ad_cname;
                        m->sml_desc = ad_pwdAccountLockedTime;
+                       m->sml_numvals = 1;
                        m->sml_values = ch_calloc( sizeof(struct berval), 2 );
                        m->sml_nvalues = ch_calloc( sizeof(struct berval), 2 );
                        ber_dupbv( &m->sml_values[0], &timestamp );
@@ -1062,6 +1064,7 @@ grace:
                m->sml_flags = 0;
                m->sml_type = ad_pwdGraceUseTime->ad_cname;
                m->sml_desc = ad_pwdGraceUseTime;
+               m->sml_numvals = 1;
                m->sml_values = ch_calloc( sizeof(struct berval), 2 );
                m->sml_nvalues = ch_calloc( sizeof(struct berval), 2 );
                ber_dupbv( &m->sml_values[0], &timestamp );
@@ -1469,6 +1472,7 @@ ppolicy_modify( Operation *op, SlapReply *rs )
                                ml->sml_flags = SLAP_MOD_INTERNAL;
                                ml->sml_type.bv_val = NULL;
                                ml->sml_desc = ad_pwdGraceUseTime;
+                               ml->sml_numvals = 0;
                                ml->sml_values = NULL;
                                ml->sml_nvalues = NULL;
                                ml->sml_next = NULL;
@@ -1481,6 +1485,7 @@ ppolicy_modify( Operation *op, SlapReply *rs )
                                ml->sml_flags = SLAP_MOD_INTERNAL;
                                ml->sml_type.bv_val = NULL;
                                ml->sml_desc = ad_pwdAccountLockedTime;
+                               ml->sml_numvals = 0;
                                ml->sml_values = NULL;
                                ml->sml_nvalues = NULL;
                                ml->sml_next = NULL;
@@ -1492,6 +1497,7 @@ ppolicy_modify( Operation *op, SlapReply *rs )
                                ml->sml_flags = SLAP_MOD_INTERNAL;
                                ml->sml_type.bv_val = NULL;
                                ml->sml_desc = ad_pwdFailureTime;
+                               ml->sml_numvals = 0;
                                ml->sml_values = NULL;
                                ml->sml_nvalues = NULL;
                                ml->sml_next = NULL;
@@ -1671,6 +1677,7 @@ ppolicy_modify( Operation *op, SlapReply *rs )
                ml->sml_flags = SLAP_MOD_INTERNAL;
                ml->sml_desc = pp.ad;
                ml->sml_type = pp.ad->ad_cname;
+               ml->sml_numvals = 1;
                ml->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                ber_dupbv( &ml->sml_values[0], &oldpw );
                BER_BVZERO( &ml->sml_values[1] );
@@ -1838,6 +1845,7 @@ do_modify:
                mods->sml_desc = ad_pwdChangedTime;
                if (pwmop != LDAP_MOD_DELETE) {
                        mods->sml_op = LDAP_MOD_REPLACE;
+                       mods->sml_numvals = 1;
                        mods->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                        ber_dupbv( &mods->sml_values[0], &timestamp );
                        BER_BVZERO( &mods->sml_values[1] );
@@ -1914,6 +1922,7 @@ do_modify:
                                mods->sml_op = LDAP_MOD_DELETE;
                                mods->sml_flags = SLAP_MOD_INTERNAL;
                                mods->sml_desc = ad_pwdHistory;
+                               mods->sml_numvals = hsize - pp.pwdInHistory + 1;
                                mods->sml_values = ch_calloc( sizeof( struct berval ),
                                        hsize - pp.pwdInHistory + 2 );
                                BER_BVZERO( &mods->sml_values[ hsize - pp.pwdInHistory + 1 ] );
@@ -1945,6 +1954,7 @@ do_modify:
                                mods->sml_type.bv_val = NULL;
                                mods->sml_desc = ad_pwdHistory;
                                mods->sml_nvalues = NULL;
+                               mods->sml_numvals = 1;
                                mods->sml_values = ch_calloc( sizeof( struct berval ), 2 );
                                mods->sml_values[ 1 ].bv_val = NULL;
                                mods->sml_values[ 1 ].bv_len = 0;
index 4afc7204e17ac64a878cf3797c86e25a75d2ddd8..55fae2d0e63a9e985e45c0808b372b2c19e90014 100644 (file)
@@ -54,6 +54,7 @@ typedef struct refint_attrs_s {
        BerVarray               old_nvals;
        BerVarray               new_vals;
        BerVarray               new_nvals;
+       int                             ra_numvals;
 } refint_attrs;
 
 typedef struct dependents_s {
@@ -423,6 +424,7 @@ refint_search_cb(
                                                        ber_bvarray_add_x( &na->old_vals, &olddn, op->o_tmpmemctx );
                                                        ber_dupbv_x( &oldndn, &a->a_nvals[first], op->o_tmpmemctx );
                                                        ber_bvarray_add_x( &na->old_nvals, &oldndn, op->o_tmpmemctx );
+                                                       na->ra_numvals++;
 
                                                        newsub = a->a_vals[first];
                                                        newsub.bv_len -= rq->olddn.bv_len + 1;
@@ -445,6 +447,7 @@ refint_search_cb(
                                                ber_bvarray_add_x( &na->old_vals, &olddn, op->o_tmpmemctx );
                                                ber_dupbv_x( &oldndn, &a->a_nvals[i], op->o_tmpmemctx );
                                                ber_bvarray_add_x( &na->old_nvals, &oldndn, op->o_tmpmemctx );
+                                               na->ra_numvals++;
 
                                                newsub = a->a_vals[i];
                                                newsub.bv_len -= rq->olddn.bv_len + 1;
@@ -461,7 +464,7 @@ refint_search_cb(
                                                ber_bvarray_add_x( &na->new_nvals, &newdn, op->o_tmpmemctx );
                                        }
 
-                                       /* count deteles */
+                                       /* count deletes */
                                        if ( BER_BVISEMPTY( &rq->newdn ) ) {
                                                deleted++;
                                        }
@@ -642,6 +645,7 @@ refint_qtask( void *ctx, void *arg )
                                        m->sml_flags = SLAP_MOD_INTERNAL;
                                        m->sml_desc = slap_schema.si_ad_modifiersName;
                                        m->sml_type = m->sml_desc->ad_cname;
+                                       m->sml_numvals = 1;
                                        m->sml_values = (BerVarray)(m+1);
                                        m->sml_nvalues = m->sml_values+2;
                                        BER_BVZERO( &m->sml_values[1] );
@@ -672,6 +676,7 @@ refint_qtask( void *ctx, void *arg )
                                                m->sml_nvalues = m->sml_values+2;
                                                BER_BVZERO( &m->sml_values[1] );
                                                BER_BVZERO( &m->sml_nvalues[1] );
+                                               m->sml_numvals = 1;
                                                if ( BER_BVISEMPTY( &rq->newdn )) {
                                                        op->o_tmpfree( ra, op->o_tmpmemctx );
                                                        ra = dp->attrs;
@@ -685,6 +690,7 @@ refint_qtask( void *ctx, void *arg )
                                        } else {
                                                m->sml_values = ra->new_vals;
                                                m->sml_nvalues = ra->new_nvals;
+                                               m->sml_numvals = ra->ra_numvals;
                                        }
                                }
 
@@ -703,6 +709,7 @@ refint_qtask( void *ctx, void *arg )
                                m->sml_desc = ra->attr;
                                m->sml_type = ra->attr->ad_cname;
                                if ( ra->old_vals == NULL ) {
+                                       m->sml_numvals = 1;
                                        m->sml_values = (BerVarray)(m+1);
                                        m->sml_nvalues = m->sml_values+2;
                                        m->sml_values[0] = rq->olddn;
@@ -712,6 +719,7 @@ refint_qtask( void *ctx, void *arg )
                                } else {
                                        m->sml_values = ra->old_vals;
                                        m->sml_nvalues = ra->old_nvals;
+                                       m->sml_numvals = ra->ra_numvals;
                                }
                                op->o_tmpfree( ra, op->o_tmpmemctx );
                        }
index a6df7904578028f9e673cdbdbb4ec3dc7dc88a4d..ed9fbfa9bb20377093a0a18dfda2fcd3403357d1 100644 (file)
@@ -226,9 +226,7 @@ rwm_op_add( Operation *op, SlapReply *rs )
                {
                        int             j, last;
 
-                       for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[ last ] ); last++ )
-                                       /* count values */ ;
-                       last--;
+                       last = (*ap)->a_numvals - 1;
                        for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
                                struct ldapmapping      *mapping = NULL;
 
@@ -245,6 +243,7 @@ rwm_op_add( Operation *op, SlapReply *rs )
                                                        (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
                                                }
                                                BER_BVZERO( &(*ap)->a_vals[ last ] );
+                                               (*ap)->a_numvals--;
                                                last--;
                                                j--;
                                        }
@@ -1057,9 +1056,8 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                                        mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
                                {
                                        int i = 0;
-                                       for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
-                                               /* just count */ ;
 
+                                       last = (*ap)->a_numvals;
                                        if ( last )
                                        {
                                                (*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
@@ -1108,8 +1106,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                }
 
                if ( last == -1 ) { /* not yet counted */ 
-                       for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
-                               /* just count */ ;
+                       last = (*ap)->a_numvals;
                }
 
                if ( last == 0 ) {
@@ -1228,6 +1225,7 @@ cleanup_attr:;
                                        mod.sm_op = LDAP_MOD_ADD;
                                        mod.sm_desc = (*ap)->a_desc;
                                        mod.sm_type = mod.sm_desc->ad_cname;
+                                       mod.sm_numvals = (*tap)->a_numvals;
                                        mod.sm_values = (*tap)->a_vals;
                                        mod.sm_nvalues = (*tap)->a_nvals;
 
index bbdbf30085b373932baa4986e91d4534f44b262b..9cae2c53dc3212cf2ba6ddad9d467be00bf67b58 100644 (file)
@@ -1287,6 +1287,7 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
        SlapReply rsm = { 0 };
        slap_callback cb = {0};
 
+       mod.sml_numvals = si->si_numcsns;
        mod.sml_values = si->si_ctxcsn;
        mod.sml_nvalues = NULL;
        mod.sml_desc = slap_schema.si_ad_contextCSN;
@@ -1679,10 +1680,10 @@ syncprov_op_compare( Operation *op, SlapReply *rs )
 
                rs->sr_err = LDAP_COMPARE_FALSE;
 
-               if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
+               if ( attr_valfind( &a,
                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                               a.a_nvals, &op->oq_compare.rs_ava->aa_value, op->o_tmpmemctx ) == 0 )
+                               &op->oq_compare.rs_ava->aa_value, NULL, op->o_tmpmemctx ) == 0 )
                {
                        rs->sr_err = LDAP_COMPARE_TRUE;
                }
@@ -2306,9 +2307,9 @@ syncprov_operational(
                                        a->a_nvals = NULL;
                                        ber_bvarray_free( a->a_vals );
                                        a->a_vals = NULL;
+                                       a->a_numvals = 0;
                                }
-                               ber_bvarray_dup_x( &a->a_vals, si->si_ctxcsn, NULL );
-                               ber_bvarray_dup_x( &a->a_nvals, si->si_ctxcsn, NULL );
+                               attr_valadd( a, si->si_ctxcsn, si->si_ctxcsn, si->si_numcsns );
                        }
                        ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock );
                }
@@ -2554,11 +2555,9 @@ syncprov_db_open(
 
                a = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
                if ( a ) {
-                       int i;
                        ber_bvarray_dup_x( &si->si_ctxcsn, a->a_vals, NULL );
-                       for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ );
-                       si->si_numcsns = i;
-                       si->si_sids = slap_parse_csn_sids( si->si_ctxcsn, i, NULL );
+                       si->si_numcsns = a->a_numvals;
+                       si->si_sids = slap_parse_csn_sids( si->si_ctxcsn, a->a_numvals, NULL );
                }
                overlay_entry_release_ov( op, e, 0, on );
                if ( si->si_ctxcsn ) {
index dce035531d1d1610d374d1bad2292ec2e9263a33..db9079692f43fe09b21a1c796b98a66a0eb09c9f 100644 (file)
@@ -147,6 +147,7 @@ void glue_parent(Operation *op) {
        ber_dupbv(&e->e_nname, &ndn);
 
        a = attr_alloc( slap_schema.si_ad_objectClass );
+       a->a_numvals = 2;
        a->a_vals = ch_malloc(sizeof(struct berval) * 3);
        ber_dupbv(&a->a_vals[0], &glue[0]);
        ber_dupbv(&a->a_vals[1], &glue[1]);
@@ -156,6 +157,7 @@ void glue_parent(Operation *op) {
        e->e_attrs = a;
 
        a = attr_alloc( slap_schema.si_ad_structuralObjectClass );
+       a->a_numvals = 1;
        a->a_vals = ch_malloc(sizeof(struct berval) * 2);
        ber_dupbv(&a->a_vals[0], &glue[1]);
        ber_dupbv(&a->a_vals[1], &glue[2]);
@@ -428,6 +430,8 @@ release:
                atmp.a_desc = m->sml_desc;
                atmp.a_vals = m->sml_values;
                atmp.a_nvals = m->sml_nvalues ? m->sml_nvalues : atmp.a_vals;
+               atmp.a_numvals = m->sml_numvals;
+               atmp.a_flags = 0;
                a = attr_dup( &atmp );
                a->a_next  = ax;
                ax = a;
index 5950a208c40b4e09a960901f360fcddbf3ddc2ee..5cc06cfaf0acdbe7d4300c826e438f9f82cbe722 100644 (file)
@@ -304,9 +304,7 @@ valsort_response( Operation *op, SlapReply *rs )
                        a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad );
                }
 
-               /* count values */
-               for ( n = 0; !BER_BVISNULL( &a->a_vals[n] ); n++ );
-
+               n = a->a_numvals;
                if ( vi->vi_sort & VALSORT_WEIGHTED ) {
                        int j, gotnvals;
                        long *index = op->o_tmpalloc( n * sizeof(long), op->o_tmpmemctx );
index a287bf0356899213b43324950e23143326d71492..7444b179c2697970684791e1a29d5385ccf8c407 100644 (file)
@@ -252,6 +252,7 @@ old_good:
                nhash = 1;
                hashes = (char **)defhash;
        }
+       ml->sml_numvals = nhash;
        ml->sml_values = ch_malloc( (nhash+1)*sizeof(struct berval) );
        for ( i=0; hashes[i]; i++ ) {
                slap_passwd_hash_type( &qpw->rs_new, &hash, hashes[i], &rs->sr_text );
index ec130c416012d2c7e864ee791f063ff2b932d42e..fbbc9ae67535995552860bb2163c3f83d278082b 100644 (file)
@@ -268,6 +268,15 @@ LDAP_SLAPD_F (void) comp_tree_free LDAP_P(( Attribute *a ));
 LDAP_SLAPD_F (Attribute *) attr_alloc LDAP_P(( AttributeDescription *ad ));
 LDAP_SLAPD_F (Attribute *) attrs_alloc LDAP_P(( int num ));
 LDAP_SLAPD_F (int) attr_prealloc LDAP_P(( int num ));
+LDAP_SLAPD_F (int) attr_valfind LDAP_P(( Attribute *a,
+       unsigned flags,
+       struct berval *val,
+       unsigned *slot,
+       void *ctx ));
+LDAP_SLAPD_F (int) attr_valadd LDAP_P(( Attribute *a,
+       BerVarray vals,
+       BerVarray nvals,
+       int num ));
 LDAP_SLAPD_F (int) attr_merge LDAP_P(( Entry *e,
        AttributeDescription *desc,
        BerVarray vals,
@@ -1162,6 +1171,12 @@ LDAP_SLAPD_F( int ) slap_mods_check(
        const char **text,
        char *textbuf, size_t textlen, void *ctx );
 
+LDAP_SLAPD_F( int ) slap_sort_vals(
+       Modifications *ml,
+       const char **text,
+       int *dup,
+       void *ctx );
+
 LDAP_SLAPD_F( void ) slap_timestamp(
        time_t *tm,
        struct berval *bv );
@@ -1803,8 +1818,7 @@ LDAP_SLAPD_F (int) ordered_value_match LDAP_P((
        const char ** text ));
 
 LDAP_SLAPD_F (void) ordered_value_renumber LDAP_P((
-       Attribute *a,
-       int vals ));
+       Attribute *a ));
 
 LDAP_SLAPD_F (int) ordered_value_sort LDAP_P((
        Attribute *a,
index 9e019fdec0bc91a64c34d6d965b8f12528c6c02a..d9a604efc1e08a2f9740e28505fc3b72ed7eba76 100644 (file)
@@ -455,6 +455,7 @@ slap_auxprop_store(
                mod->sml_op = LDAP_MOD_REPLACE;
                mod->sml_flags = 0;
                ber_str2bv( pr[i].name, 0, 0, &mod->sml_type );
+               mod->sml_numvals = pr[i].nvalues;
                mod->sml_values = (struct berval *)ch_malloc( (pr[i].nvalues + 1) *
                        sizeof(struct berval));
                for (j=0; j<pr[i].nvalues; j++) {
index a5860d7dc9fd9b0128fc562f2484962e665b4df8..4c0d376249473159d7083f03e99014b8b13b36ff 100644 (file)
@@ -856,9 +856,9 @@ entry_naming_check(
                        break;
                }
 
-               rc = value_find_ex( desc, SLAP_MR_VALUE_OF_ASSERTION_SYNTAX|
+               rc = attr_valfind( attr, SLAP_MR_VALUE_OF_ASSERTION_SYNTAX|
                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
-                       attr->a_nvals, &ava->la_value, NULL );
+                       &ava->la_value, NULL, NULL );
 
                if( rc != 0 ) {
                        switch( rc ) {
index b04ccd3f7a52a8b7690503505767c0e72c432b4e..65319e1a6ef0955e7115a77c4950eef92c9469b9 100644 (file)
@@ -690,10 +690,19 @@ struct AttributeType {
 
 #define SLAP_AT_MANAGEABLE             0x0800U /* no-user-mod can be by-passed */
 
+/* Note: ORDERED values have an ordering specifically set by the
+ * user, denoted by the {x} ordering prefix on the values.
+ *
+ * SORTED values are simply sorted by memcmp. SORTED values can
+ * be efficiently located by binary search. ORDERED values have no
+ * such advantage. An attribute cannot have both properties.
+ */
 #define        SLAP_AT_ORDERED_VAL             0x0001U /* values are ordered */
 #define        SLAP_AT_ORDERED_SIB             0x0002U /* siblings are ordered */
 #define        SLAP_AT_ORDERED                 0x0003U /* value has order index */
 
+#define        SLAP_AT_SORTED_VAL              0x0010U /* values should be sorted */
+
 #define        SLAP_AT_HARDCODE                0x10000U        /* hardcoded schema */
 #define        SLAP_AT_DELETED                 0x20000U
 
@@ -1109,20 +1118,28 @@ struct ValuesReturnFilter {
 
 /*
  * represents an attribute (description + values)
+ * desc, vals, nvals, numvals fields must align with Modification
  */
 struct Attribute {
        AttributeDescription    *a_desc;
        BerVarray               a_vals;         /* preserved values */
        BerVarray               a_nvals;        /* normalized values */
-#ifdef LDAP_COMP_MATCH
-       ComponentData           *a_comp_data;   /* component values */
-#endif
-       Attribute               *a_next;
+       unsigned                a_numvals;      /* number of vals */
        unsigned                a_flags;
 #define SLAP_ATTR_IXADD                        0x1U
 #define SLAP_ATTR_IXDEL                        0x2U
 #define SLAP_ATTR_DONT_FREE_DATA       0x4U
 #define SLAP_ATTR_DONT_FREE_VALS       0x8U
+#define        SLAP_ATTR_SORTED_VALS           0x10U   /* values are sorted */
+
+/* These flags persist across an attr_dup() */
+#define        SLAP_ATTR_PERSISTENT_FLAGS \
+       SLAP_ATTR_SORTED_VALS
+
+       Attribute               *a_next;
+#ifdef LDAP_COMP_MATCH
+       ComponentData           *a_comp_data;   /* component values */
+#endif
 };
 
 
@@ -1169,8 +1186,13 @@ struct Entry {
 
 /*
  * A list of LDAPMods
+ * desc, values, nvalues, numvals must align with Attribute
  */
 struct Modification {
+       AttributeDescription *sm_desc;
+       BerVarray sm_values;
+       BerVarray sm_nvalues;
+       unsigned sm_numvals;
        short sm_op;
        short sm_flags;
 /* Set for internal mods, will bypass ACL checks. Only needed when
@@ -1178,11 +1200,7 @@ struct Modification {
  */
 #define        SLAP_MOD_INTERNAL       0x01
 #define        SLAP_MOD_MANAGING       0x02
-
-       AttributeDescription *sm_desc;
        struct berval sm_type;
-       BerVarray sm_values;
-       BerVarray sm_nvalues;
 };
 
 struct Modifications {
@@ -1193,17 +1211,10 @@ struct Modifications {
 #define        sml_type        sml_mod.sm_type
 #define sml_values     sml_mod.sm_values
 #define sml_nvalues    sml_mod.sm_nvalues
+#define sml_numvals    sml_mod.sm_numvals
        Modifications   *sml_next;
 };
 
-struct LDAPModList {
-       LDAPMod         ml_mod;
-       LDAPModList     *ml_next;
-#define ml_op          ml_mod.mod_op
-#define ml_type                ml_mod.mod_type
-#define ml_values      ml_mod.mod_values
-};
-
 /*
  * represents an access control list
  */
index 99d5ccbc33840033df433532ba70d57f2dc75d83..6c37e3b7f45be8d67baee5523e818ee0e97367a8 100644 (file)
@@ -72,7 +72,8 @@ static int checkBVString(const struct berval *bv)
 int
 bvptr2obj(
        struct berval   **bvptr, 
-       BerVarray       *bvobj )
+       BerVarray       *bvobj,
+       unsigned *num )
 {
        int             rc = LDAP_SUCCESS;
        int             i;
@@ -85,6 +86,8 @@ bvptr2obj(
        for ( i = 0; bvptr != NULL && bvptr[i] != NULL; i++ ) {
                ; /* EMPTY */
        }
+       if ( num )
+               *num = i;
 
        tmpberval = (BerVarray)slapi_ch_malloc( (i + 1)*sizeof(struct berval));
        if ( tmpberval == NULL ) {
@@ -231,12 +234,12 @@ slapi_entry_attr_merge(
                return -1;
        }
        
-       rc = bvptr2obj( vals, &bv );
+       rc = bvptr2obj( vals, &bv, NULL );
        if ( rc != LDAP_SUCCESS ) {
                return -1;
        }
        
-       rc = attr_merge_normalize_one( e, ad, bv, NULL );
+       rc = attr_merge_normalize( e, ad, bv, NULL );
        ch_free( bv );
 
        return rc;
@@ -545,9 +548,10 @@ slapi_entry_add_values( Slapi_Entry *e, const char *type, struct berval **vals )
                 * FIXME: sm_values = NULL ? */
                mod.sm_values = (BerVarray)ch_malloc( sizeof(struct berval) );
                mod.sm_values->bv_val = NULL;
+               mod.sm_numvals = 0;
 
        } else {
-               rc = bvptr2obj( vals, &mod.sm_values );
+               rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
                if ( rc != LDAP_SUCCESS ) {
                        return LDAP_CONSTRAINT_VIOLATION;
                }
@@ -611,7 +615,7 @@ slapi_entry_delete_values( Slapi_Entry *e, const char *type, struct berval **val
                return attr_delete( &e->e_attrs, mod.sm_desc ) ? LDAP_OTHER : LDAP_SUCCESS;
        }
 
-       rc = bvptr2obj( vals, &mod.sm_values );
+       rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
        if ( rc != LDAP_SUCCESS ) {
                return LDAP_CONSTRAINT_VIOLATION;
        }
@@ -730,7 +734,7 @@ slapi_entry_attr_replace_sv( Slapi_Entry *e, const char *type, Slapi_Value **val
 
        attr_delete( &e->e_attrs, ad );
 
-       rc = bvptr2obj( vals, &bv );
+       rc = bvptr2obj( vals, &bv, NULL );
        if ( rc != LDAP_SUCCESS ) {
                return -1;
        }
@@ -1350,7 +1354,7 @@ slapi_send_ldap_result(
                if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
                        rs->sr_nentries = nentries;
                if ( urls != NULL )
-                       bvptr2obj( urls, &rs->sr_ref );
+                       bvptr2obj( urls, &rs->sr_ref, NULL );
 
                send_ldap_result( pb->pb_op, rs );
 
@@ -1429,7 +1433,7 @@ slapi_send_ldap_search_reference(
        rs.sr_matched = NULL;
        rs.sr_text = NULL;
 
-       rc = bvptr2obj( references, &rs.sr_ref );
+       rc = bvptr2obj( references, &rs.sr_ref, NULL );
        if ( rc != LDAP_SUCCESS ) {
                return rc;
        }
@@ -1440,7 +1444,7 @@ slapi_send_ldap_search_reference(
        rs.sr_entry = e;
 
        if ( v2refs != NULL ) {
-               rc = bvptr2obj( v2refs, &rs.sr_v2ref );
+               rc = bvptr2obj( v2refs, &rs.sr_v2ref, NULL );
                if ( rc != LDAP_SUCCESS ) {
                        slapi_ch_free( (void **)&rs.sr_ref );
                        return rc;
@@ -2148,28 +2152,15 @@ int slapi_attr_value_cmp( const Slapi_Attr *a, const struct berval *v1, const st
 
 int slapi_attr_value_find( const Slapi_Attr *a, struct berval *v )
 {
-       MatchingRule *mr;
-       struct berval *bv;
-       int j;
-       const char *text;
        int rc;
        int ret;
 
        if ( a ->a_vals == NULL ) {
                return -1;
        }
-       mr = a->a_desc->ad_type->sat_equality;
-       for ( bv = a->a_vals, j = 0; bv->bv_val != NULL; bv++, j++ ) {
-               rc = value_match( &ret, a->a_desc, mr,
-                       SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, bv, v, &text );
-               if ( rc != LDAP_SUCCESS ) {
-                       return -1;
-               }
-               if ( ret == 0 ) {
-                       return 0;
-               }
-       }
-       return -1;
+       rc = attr_valfind( (Attribute *)a, SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, v,
+               NULL, NULL );
+       return rc == 0 ? 0 : -1;
 }
 
 int slapi_attr_type_cmp( const char *t1, const char *t2, int opt )
@@ -2720,6 +2711,7 @@ Modifications *slapi_int_ldapmods2modifications ( Operation *op, LDAPMod **mods
                                        i++;
                        }
                }
+               mod->sml_numvals = i;
 
                if ( i == 0 ) {
                        mod->sml_values = NULL;
index af6de8893d89d25a0432a6441ae9ad73d1ebf042..a657088bed3fec522844fc5fc38ecde27c922a88 100644 (file)
@@ -562,9 +562,7 @@ do_syncrep1(
                ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
                rc = backend_operational( op, &rs );
                if ( rc == LDAP_SUCCESS && a.a_vals ) {
-                       int num;
-                       for (i=0; !BER_BVISNULL( &a.a_vals[i] ); i++) ;
-                       num = i;
+                       int num = a.a_numvals;
                        /* check for differences */
                        if ( num != si->si_cookieState->cs_num ) {
                                changed = 1;
@@ -1383,6 +1381,7 @@ syncrepl_accesslog_mods(
                        mod->sml_type = ad->ad_cname;
                        mod->sml_values = NULL;
                        mod->sml_nvalues = NULL;
+                       mod->sml_numvals = 0;
 
                        *modtail = mod;
                        modtail = &mod->sml_next;
@@ -1392,6 +1391,7 @@ syncrepl_accesslog_mods(
                        bv.bv_len = vals[i].bv_len - ( bv.bv_val - vals[i].bv_val );
                        ber_dupbv( &bv2, &bv );
                        ber_bvarray_add( &mod->sml_values, &bv2 );
+                       mod->sml_numvals++;
                }
        }
        return modlist;
@@ -1724,6 +1724,7 @@ syncrepl_message_to_entry(
                mod->sml_type = tmp.sml_type;
                mod->sml_values = tmp.sml_values;
                mod->sml_nvalues = NULL;
+               mod->sml_numvals = 0;   /* slap_mods_check will set this */
 
                *modtail = mod;
                modtail = &mod->sml_next;
@@ -2337,6 +2338,7 @@ syncrepl_del_nonpresent(
                                mod1.sml_flags = 0;
                                mod1.sml_desc = slap_schema.si_ad_objectClass;
                                mod1.sml_type = mod1.sml_desc->ad_cname;
+                               mod1.sml_numvals = 2;
                                mod1.sml_values = &gcbva[0];
                                mod1.sml_nvalues = NULL;
                                mod1.sml_next = &mod2;
@@ -2345,6 +2347,7 @@ syncrepl_del_nonpresent(
                                mod2.sml_flags = 0;
                                mod2.sml_desc = slap_schema.si_ad_structuralObjectClass;
                                mod2.sml_type = mod2.sml_desc->ad_cname;
+                               mod1.sml_numvals = 1;
                                mod2.sml_values = &gcbva[1];
                                mod2.sml_nvalues = NULL;
                                mod2.sml_next = NULL;
@@ -2472,6 +2475,7 @@ syncrepl_add_glue(
 
                a = attr_alloc( slap_schema.si_ad_objectClass );
 
+               a->a_numvals = 2;
                a->a_vals = ch_calloc( 3, sizeof( struct berval ) );
                ber_dupbv( &a->a_vals[0], &gcbva[0] );
                ber_dupbv( &a->a_vals[1], &gcbva[1] );
@@ -2484,6 +2488,7 @@ syncrepl_add_glue(
 
                a = attr_alloc( slap_schema.si_ad_structuralObjectClass );
 
+               a->a_numvals = 1;
                a->a_vals = ch_calloc( 2, sizeof( struct berval ) );
                ber_dupbv( &a->a_vals[0], &gcbva[1] );
                ber_dupbv( &a->a_vals[1], &gcbva[2] );
@@ -2562,6 +2567,7 @@ syncrepl_updateCookie(
        mod[0].sml_type = mod[0].sml_desc->ad_cname;
        mod[0].sml_values = NULL;
        mod[0].sml_nvalues = NULL;
+       mod[0].sml_numvals = 0;
        mod[0].sml_next = &mod[1];
 
        mod[1].sml_op = LDAP_MOD_ADD;
@@ -2569,6 +2575,7 @@ syncrepl_updateCookie(
        mod[1].sml_type = mod[0].sml_desc->ad_cname;
        mod[1].sml_values = NULL;
        mod[1].sml_nvalues = NULL;
+       mod[1].sml_numvals = 0;
        mod[1].sml_next = NULL;
 
        ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
@@ -2584,8 +2591,10 @@ syncrepl_updateCookie(
                                si->si_cookieState->cs_vals[j].bv_val, len ) > 0 ) {
                                ber_bvarray_add_x( &mod[0].sml_values,
                                        &si->si_cookieState->cs_vals[j], op->o_tmpmemctx );
+                               mod[0].sml_numvals++;
                                ber_bvarray_add_x( &mod[1].sml_values,
                                        &syncCookie->ctxcsn[i], op->o_tmpmemctx );
+                               mod[1].sml_numvals++;
                                if ( BER_BVISNULL( &first ))
                                        first = syncCookie->ctxcsn[i];
                        }
@@ -2595,6 +2604,7 @@ syncrepl_updateCookie(
                if ( j == si->si_cookieState->cs_num ) {
                        ber_bvarray_add_x( &mod[1].sml_values,
                                &syncCookie->ctxcsn[i], op->o_tmpmemctx );
+                       mod[1].sml_numvals++;
                        if ( BER_BVISNULL( &first ))
                                first = syncCookie->ctxcsn[i];
                }
@@ -2727,6 +2737,7 @@ attr_cmp( Operation *op, Attribute *old, Attribute *new,
                        mod->sml_flags = 0;
                        mod->sml_desc = old->a_desc;
                        mod->sml_type = mod->sml_desc->ad_cname;
+                       mod->sml_numvals = no;
                        mod->sml_values = ch_malloc( ( no + 1 ) * sizeof(struct berval) );
                        if ( old->a_vals != old->a_nvals ) {
                                mod->sml_nvalues = ch_malloc( ( no + 1 ) * sizeof(struct berval) );
@@ -2758,6 +2769,7 @@ attr_cmp( Operation *op, Attribute *old, Attribute *new,
                        mod->sml_flags = 0;
                        mod->sml_desc = old->a_desc;
                        mod->sml_type = mod->sml_desc->ad_cname;
+                       mod->sml_numvals = nn;
                        mod->sml_values = ch_malloc( ( nn + 1 ) * sizeof(struct berval) );
                        if ( old->a_vals != old->a_nvals ) {
                                mod->sml_nvalues = ch_malloc( ( nn + 1 ) * sizeof(struct berval) );
@@ -2846,11 +2858,11 @@ dn_callback(
                                        oldRDN.bv_len -= oldVal.bv_len + 2;
                                        slap_bv2ad( &oldRDN, &ad, &rs->sr_text );
                                        a = attr_find( dni->new_entry->e_attrs, ad );
-                                       if ( !a || value_find_ex( ad,
+                                       if ( !a || attr_valfind( a,
                                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
                                                SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
-                                               SLAP_MR_VALUE_OF_SYNTAX, a->a_nvals,
-                                               &oldVal, op->o_tmpmemctx ) != LDAP_SUCCESS )
+                                               SLAP_MR_VALUE_OF_SYNTAX,
+                                               &oldVal, NULL, op->o_tmpmemctx ) != LDAP_SUCCESS )
                                        {
                                                dni->delOldRDN = 1;
                                        }
@@ -2937,6 +2949,7 @@ dn_callback(
                                                        mod->sml_flags = 0;
                                                        mod->sml_desc = old->a_desc;
                                                        mod->sml_type = mod->sml_desc->ad_cname;
+                                                       mod->sml_numvals = 0;
                                                        mod->sml_values = NULL;
                                                        mod->sml_nvalues = NULL;
                                                        *modtail = mod;
index ac6ddd3c5372f0d0bd2aef269ac34a48a8cb9d87..0aecdb3293f0b2d54a318807d2804321995cc6ba 100644 (file)
@@ -263,7 +263,7 @@ int value_find_ex(
 
 /* assign new indexes to an attribute's ordered values */
 void
-ordered_value_renumber( Attribute *a, int vals )
+ordered_value_renumber( Attribute *a )
 {
        char *ptr, ibuf[64];    /* many digits */
        struct berval ibv, tmp, vtmp;
@@ -271,7 +271,7 @@ ordered_value_renumber( Attribute *a, int vals )
 
        ibv.bv_val = ibuf;
 
-       for (i=0; i<vals; i++) {
+       for (i=0; i<a->a_numvals; i++) {
                ibv.bv_len = sprintf(ibv.bv_val, "{%d}", i);
                vtmp = a->a_vals[i];
                if ( vtmp.bv_val[0] == '{' ) {
@@ -405,7 +405,7 @@ ordered_value_sort( Attribute *a, int do_renumber )
        }
 
        if ( do_renumber && renumber )
-               ordered_value_renumber( a, vals );
+               ordered_value_renumber( a );
 
        return 0;
 }
@@ -706,16 +706,14 @@ ordered_value_add(
        vnum = i;
 
        if ( a ) {
-               for (i=0; !BER_BVISNULL( a->a_vals+i ); i++) ;
-               anum = i;
                ordered_value_sort( a, 0 );
        } else {
                Attribute **ap;
-               anum = 0;
                for ( ap=&e->e_attrs; *ap; ap = &(*ap)->a_next ) ;
                a = attr_alloc( ad );
                *ap = a;
        }
+       anum = a->a_numvals;
 
        new = ch_malloc( (anum+vnum+1) * sizeof(struct berval));
 
@@ -739,7 +737,7 @@ ordered_value_add(
        }
        if ( anum ) {
                AC_MEMCPY( new, a->a_vals, anum * sizeof(struct berval));
-               if ( nnew )
+               if ( nnew && a->a_nvals )
                        AC_MEMCPY( nnew, a->a_nvals, anum * sizeof(struct berval));
        }
 
@@ -789,7 +787,8 @@ ordered_value_add(
                a->a_nvals = a->a_vals;
        }
 
-       ordered_value_renumber( a, anum );
+       a->a_numvals = anum;
+       ordered_value_renumber( a );
 
        return 0;
 }