]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
Rewrite attrs_dup with attrs_alloc.
authorHoward Chu <hyc@openldap.org>
Thu, 30 Nov 2006 06:03:56 +0000 (06:03 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 30 Nov 2006 06:03:56 +0000 (06:03 +0000)
Add new entry_dup_bv that dups an entry in a single malloc. Leave it
unused for now; faster but consumes more heap.

servers/slapd/attr.c
servers/slapd/entry.c
servers/slapd/proto-slap.h

index 4c21b9bfc0332f9d171deac124d2ca337d2cff40..82c94abaa01b7674056c51f31c27105b0740adcc 100644 (file)
@@ -181,15 +181,10 @@ attrs_free( Attribute *a )
        }
 }
 
-Attribute *
-attr_dup( Attribute *a )
-{
-       Attribute *tmp;
-
-       if ( a == NULL) return NULL;
-
-       tmp = attr_alloc( a->a_desc );
 
+static void
+attr_dup2( Attribute *tmp, Attribute *a )
+{
        if ( a->a_vals != NULL ) {
                int     i;
 
@@ -224,31 +219,42 @@ attr_dup( Attribute *a )
                } else {
                        tmp->a_nvals = tmp->a_vals;
                }
-
-       } else {
-               tmp->a_vals = NULL;
-               tmp->a_nvals = NULL;
        }
+}
+
+Attribute *
+attr_dup( Attribute *a )
+{
+       Attribute *tmp;
+
+       if ( a == NULL) return NULL;
+
+       tmp = attr_alloc( a->a_desc );
+       attr_dup2( tmp, a );
        return tmp;
 }
 
 Attribute *
 attrs_dup( Attribute *a )
 {
-       Attribute *tmp, **next;
+       int i;
+       Attribute *tmp, *anew;
 
        if( a == NULL ) return NULL;
 
-       tmp = NULL;
-       next = &tmp;
+       /* count them */
+       for( tmp=a,i=0; tmp; tmp=tmp->a_next ) {
+               i++;
+       }
+
+       anew = attrs_alloc( i );
 
-       for( ; a != NULL ; a = a->a_next ) {
-               *next = attr_dup( a );
-               next = &((*next)->a_next);
+       for( tmp=anew; a; a=a->a_next ) {
+               attr_dup2( tmp, a );
+               tmp=tmp->a_next;
        }
-       *next = NULL;
 
-       return tmp;
+       return anew;
 }
 
 
index e7c4222b7d8f3980f3cfd83b57e90c194183752d..f074fb654964d1e699336fbd0a31e604f53e5f75 100644 (file)
@@ -862,3 +862,76 @@ Entry *entry_dup( Entry *e )
        return ret;
 }
 
+#if 1
+/* Duplicates an entry using a single malloc. Saves CPU time, increases
+ * heap usage because a single large malloc is harder to satisfy than
+ * lots of small ones, and the freed space isn't as easily reusable.
+ *
+ * Probably not worth using this function.
+ */
+Entry *entry_dup_bv( Entry *e )
+{
+       ber_len_t len;
+       int nattrs, nvals;
+       Entry *ret;
+       struct berval *bvl;
+       char *ptr;
+       Attribute *src, *dst;
+
+       ret = entry_alloc();
+
+       entry_partsize(e, &len, &nattrs, &nvals, 1);
+       ret->e_id = e->e_id;
+       ret->e_attrs = attrs_alloc( nattrs );
+       ret->e_ocflags = e->e_ocflags;
+       ret->e_bv.bv_len = len + nvals * sizeof(struct berval);
+       ret->e_bv.bv_val = ch_malloc( ret->e_bv.bv_len );
+
+       bvl = (struct berval *)ret->e_bv.bv_val;
+       ptr = (char *)(bvl + nvals);
+
+       ret->e_name.bv_len = e->e_name.bv_len;
+       ret->e_name.bv_val = ptr;
+       AC_MEMCPY( ptr, e->e_name.bv_val, e->e_name.bv_len );
+       ptr += e->e_name.bv_len;
+       *ptr++ = '\0';
+
+       ret->e_nname.bv_len = e->e_nname.bv_len;
+       ret->e_nname.bv_val = ptr;
+       AC_MEMCPY( ptr, e->e_nname.bv_val, e->e_nname.bv_len );
+       ptr += e->e_name.bv_len;
+       *ptr++ = '\0';
+
+       dst = ret->e_attrs;
+       for (src = e->e_attrs; src; src=src->a_next,dst=dst->a_next ) {
+               int i;
+               dst->a_desc = src->a_desc;
+               dst->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS;
+               dst->a_vals = bvl;
+               for ( i=0; src->a_vals[i].bv_val; i++ ) {
+                       bvl->bv_len = src->a_vals[i].bv_len;
+                       bvl->bv_val = ptr;
+                       AC_MEMCPY( ptr, src->a_vals[i].bv_val, bvl->bv_len );
+                       ptr += bvl->bv_len;
+                       *ptr++ = '\0';
+                       bvl++;
+               }
+               BER_BVZERO(bvl);
+               bvl++;
+               if ( src->a_vals != src->a_nvals ) {
+                       dst->a_nvals = bvl;
+                       for ( i=0; src->a_nvals[i].bv_val; i++ ) {
+                               bvl->bv_len = src->a_nvals[i].bv_len;
+                               bvl->bv_val = ptr;
+                               AC_MEMCPY( ptr, src->a_nvals[i].bv_val, bvl->bv_len );
+                               ptr += bvl->bv_len;
+                               *ptr++ = '\0';
+                               bvl++;
+                       }
+                       BER_BVZERO(bvl);
+                       bvl++;
+               }
+       }
+       return ret;
+}
+#endif
index 5a8e0dc2d9728cb106810d9da3f87dcf914e2f45..5f8b8743adcb1d0721ee27c46d5dffbfe0729b10 100644 (file)
@@ -872,6 +872,7 @@ LDAP_SLAPD_F (int) entry_cmp LDAP_P(( Entry *a, Entry *b ));
 LDAP_SLAPD_F (int) entry_dn_cmp LDAP_P(( const void *v_a, const void *v_b ));
 LDAP_SLAPD_F (int) entry_id_cmp LDAP_P(( const void *v_a, const void *v_b ));
 LDAP_SLAPD_F (Entry *) entry_dup LDAP_P(( Entry *e ));
+LDAP_SLAPD_F (Entry *) entry_dup_bv LDAP_P(( Entry *e ));
 LDAP_SLAPD_F (Entry *) entry_alloc LDAP_P((void));
 LDAP_SLAPD_F (int) entry_prealloc LDAP_P((int num));