]> git.sur5r.net Git - openldap/commitdiff
Use a single malloc for entry_decode instead of two - partially decode
authorHoward Chu <hyc@openldap.org>
Wed, 20 Sep 2006 02:43:47 +0000 (02:43 +0000)
committerHoward Chu <hyc@openldap.org>
Wed, 20 Sep 2006 02:43:47 +0000 (02:43 +0000)
the entry to get nvals first, so the size can be computed.

servers/slapd/back-bdb/id2entry.c
servers/slapd/back-bdb/tools.c
servers/slapd/entry.c
servers/slapd/proto-slap.h
servers/slapd/slap.h

index 58fafd1cc9ba834a88123dd2eced5c078eded935..3c5580ea9cb62ba08262c04d4ae014490962fe37 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include <ac/string.h>
+#include <ac/errno.h>
 
 #include "back-bdb.h"
 
@@ -100,8 +101,9 @@ int bdb_id2entry(
        DB *db = bdb->bi_id2entry->bdi_db;
        DBT key, data;
        DBC *cursor;
-       struct berval bv;
-       int rc = 0;
+       EntryHeader eh;
+       char buf[16];
+       int rc = 0, off;
        ID nid;
 
        *e = NULL;
@@ -112,7 +114,7 @@ int bdb_id2entry(
        BDB_ID2DISK( id, &nid );
 
        DBTzero( &data );
-       data.flags = DB_DBT_MALLOC;
+       data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
 
        /* fetch it */
        rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
@@ -122,19 +124,47 @@ int bdb_id2entry(
        if ( !tid && locker )
                cursor->locker = locker;
 
+       /* Get the nattrs / nvals counts first */
+       data.ulen = data.dlen = sizeof(buf);
+       data.data = buf;
        rc = cursor->c_get( cursor, &key, &data, DB_SET );
+       if ( rc ) goto leave;
+
+       eh.bv.bv_val = buf;
+       eh.bv.bv_len = data.size;
+       rc = entry_header( &eh );
+       if ( rc ) goto leave;
+
+       /* Get the size */
+       data.flags ^= DB_DBT_PARTIAL;
+       data.ulen = 0;
+       rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
+       if ( rc != ENOMEM ) goto leave;
+
+       /* Allocate a block and retrieve the data */
+       off = eh.data - eh.bv.bv_val;
+       eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
+       eh.bv.bv_val = ch_malloc( eh.bv.bv_len );
+       eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
+       data.data = eh.data;
+       data.ulen = data.size;
+
+       /* skip past already parsed nattr/nvals */
+       eh.data += off;
+
+       rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
+
+leave:
        cursor->c_close( cursor );
 
        if( rc != 0 ) {
                return rc;
        }
 
-       DBT2bv( &data, &bv );
-
 #ifdef SLAP_ZONE_ALLOC
-       rc = entry_decode(&bv, e, bdb->bi_cache.c_zctx);
+       rc = entry_decode(&eh, e, bdb->bi_cache.c_zctx);
 #else
-       rc = entry_decode(&bv, e);
+       rc = entry_decode(&eh, e);
 #endif
 
        if( rc == 0 ) {
@@ -144,11 +174,11 @@ int bdb_id2entry(
                 * decoded in place.
                 */
 #ifndef SLAP_ZONE_ALLOC
-               ch_free(data.data);
+               ch_free(eh.bv.bv_val);
 #endif
        }
 #ifdef SLAP_ZONE_ALLOC
-       ch_free(data.data);
+       ch_free(eh.bv.bv_val);
 #endif
 
        return rc;
index 9c6e23ef7c889ce068fdae516d40297d6d57f162..604471c57aa4bb700a44aa349ed04506b426987d 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include <ac/string.h>
+#include <ac/errno.h>
 
 #define AVL_INTERNAL
 #include "back-bdb.h"
@@ -25,6 +26,8 @@
 
 static DBC *cursor = NULL;
 static DBT key, data;
+static EntryHeader eh;
+static int eoff;
 
 typedef struct dn_id {
        ID id;
@@ -82,7 +85,7 @@ int bdb_tool_entry_open(
        DBTzero( &key );
        DBTzero( &data );
        key.flags = DB_DBT_REALLOC;
-       data.flags = DB_DBT_REALLOC;
+       data.flags = DB_DBT_USERMEM;
 
        if (cursor == NULL) {
                int rc = bdb->bi_id2entry->bdi_db->cursor(
@@ -132,9 +135,9 @@ int bdb_tool_entry_close(
                ch_free( key.data );
                key.data = NULL;
        }
-       if( data.data ) {
-               ch_free( data.data );
-               data.data = NULL;
+       if( eh.bv.bv_val ) {
+               ch_free( eh.bv.bv_val );
+               eh.bv.bv_val = NULL;
        }
 
        if( cursor ) {
@@ -165,14 +168,19 @@ ID bdb_tool_entry_next(
        int rc;
        ID id;
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+       char buf[16], *dptr;
 
        assert( be != NULL );
        assert( slapMode & SLAP_TOOL_MODE );
        assert( bdb != NULL );
        
+       /* Get the header */
+       data.ulen = data.dlen = sizeof( buf );
+       data.data = buf;
+       data.flags |= DB_DBT_PARTIAL;
        rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
 
-       if( rc != 0 ) {
+       if( rc ) {
                /* If we're doing linear indexing and there are more attrs to
                 * index, and we're at the end of the database, start over.
                 */
@@ -190,7 +198,13 @@ ID bdb_tool_entry_next(
                }
        }
 
-       if( data.data == NULL ) {
+       dptr = eh.bv.bv_val;
+       eh.bv.bv_val = buf;
+       eh.bv.bv_len = data.size;
+       rc = entry_header( &eh );
+       eoff = eh.data - eh.bv.bv_val;
+       eh.bv.bv_val = dptr;
+       if( rc ) {
                return NOID;
        }
 
@@ -248,48 +262,64 @@ int bdb_tool_id2entry_get(
 
 Entry* bdb_tool_entry_get( BackendDB *be, ID id )
 {
-       int rc;
+       int rc, off;
        Entry *e = NULL;
-       struct berval bv;
+       char *dptr;
 
        assert( be != NULL );
        assert( slapMode & SLAP_TOOL_MODE );
-       assert( data.data != NULL );
 
-       DBT2bv( &data, &bv );
+       /* Get the size */
+       data.flags ^= DB_DBT_PARTIAL;
+       data.ulen = 0;
+    rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
+       if ( rc != ENOMEM ) goto leave;
+
+       /* Allocate a block and retrieve the data */
+       eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
+       eh.bv.bv_val = ch_realloc( eh.bv.bv_val, eh.bv.bv_len );
+       eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
+       data.data = eh.data;
+       data.ulen = data.size;
+
+       /* Skip past already parsed nattr/nvals */
+       eh.data += eoff;
+
+    rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
 
 #ifdef SLAP_ZONE_ALLOC
        /* FIXME: will add ctx later */
-       rc = entry_decode( &bv, &e, NULL );
+       rc = entry_decode( &eh, &e, NULL );
 #else
-       rc = entry_decode( &bv, &e );
+       rc = entry_decode( &eh, &e );
 #endif
 
        if( rc == LDAP_SUCCESS ) {
                e->e_id = id;
-       }
 #ifdef BDB_HIER
-       if ( slapMode & SLAP_TOOL_READONLY ) {
-               EntryInfo *ei = NULL;
-               Operation op = {0};
-               Opheader ohdr = {0};
-
-               op.o_hdr = &ohdr;
-               op.o_bd = be;
-               op.o_tmpmemctx = NULL;
-               op.o_tmpmfuncs = &ch_mfuncs;
-
-               rc = bdb_cache_find_parent( &op, NULL, cursor->locker, id, &ei );
-               if ( rc == LDAP_SUCCESS ) {
-                       bdb_cache_entryinfo_unlock( ei );
-                       e->e_private = ei;
-                       ei->bei_e = e;
-                       bdb_fix_dn( e, 0 );
-                       ei->bei_e = NULL;
-                       e->e_private = NULL;
+               if ( slapMode & SLAP_TOOL_READONLY ) {
+                       EntryInfo *ei = NULL;
+                       Operation op = {0};
+                       Opheader ohdr = {0};
+
+                       op.o_hdr = &ohdr;
+                       op.o_bd = be;
+                       op.o_tmpmemctx = NULL;
+                       op.o_tmpmfuncs = &ch_mfuncs;
+
+                       rc = bdb_cache_find_parent( &op, NULL, cursor->locker, id, &ei );
+                       if ( rc == LDAP_SUCCESS ) {
+                               bdb_cache_entryinfo_unlock( ei );
+                               e->e_private = ei;
+                               ei->bei_e = e;
+                               bdb_fix_dn( e, 0 );
+                               ei->bei_e = NULL;
+                               e->e_private = NULL;
+                       }
                }
-       }
 #endif
+       }
+leave:
        return e;
 }
 
index f7a1fb7b8d1a320ec153f93cc437c51976f052a6..823d3fbd177ee068e09c6d89a212a4900e73ca19 100644 (file)
@@ -456,10 +456,6 @@ entry_clean( Entry *e )
                free( e->e_bv.bv_val );
        }
 
-       if ( &e->e_abv ) {
-               free( e->e_abv );
-       }
-
        /* free attributes */
        attrs_free( e->e_attrs );
 
@@ -720,20 +716,39 @@ int entry_encode(Entry *e, struct berval *bv)
 }
 
 /* Retrieve an Entry that was stored using entry_encode above.
- * We malloc a single block with the size stored above for the Entry
- * and all of its Attributes. We also must lookup the stored
- * attribute names to get AttributeDescriptions. To detect if the
- * attributes of an Entry are later modified, we note that e->e_attr
- * is always a constant offset from (e).
+ * First entry_header must be called to decode the size of the entry.
+ * Then a single block of memory must be malloc'd to accomodate the
+ * bervals and the bulk data. Next the bulk data is retrieved from
+ * the DB and parsed by entry_decode.
  *
  * Note: everything is stored in a single contiguous block, so
  * you can not free individual attributes or names from this
  * structure. Attempting to do so will likely corrupt memory.
  */
+int entry_header(EntryHeader *eh)
+{
+       unsigned char *ptr = (unsigned char *)eh->bv.bv_val;
+
+       eh->nattrs = entry_getlen(&ptr);
+       if ( !eh->nattrs ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "entry_header: attribute count was zero\n", 0, 0, 0);
+               return LDAP_OTHER;
+       }
+       eh->nvals = entry_getlen(&ptr);
+       if ( !eh->nvals ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "entry_header: value count was zero\n", 0, 0, 0);
+               return LDAP_OTHER;
+       }
+       eh->data = (char *)ptr;
+       return LDAP_SUCCESS;
+}
+
 #ifdef SLAP_ZONE_ALLOC
-int entry_decode(struct berval *bv, Entry **e, void *ctx)
+int entry_decode(EntryHeader *eh, Entry **e, void *ctx)
 #else
-int entry_decode(struct berval *bv, Entry **e)
+int entry_decode(EntryHeader *eh, Entry **e)
 #endif
 {
        int i, j, count, nattrs, nvals;
@@ -742,24 +757,14 @@ int entry_decode(struct berval *bv, Entry **e)
        Entry *x;
        const char *text;
        AttributeDescription *ad;
-       unsigned char *ptr = (unsigned char *)bv->bv_val;
+       unsigned char *ptr = (unsigned char *)eh->bv.bv_val;
        BerVarray bptr;
 
-       nattrs = entry_getlen(&ptr);
-       if (!nattrs) {
-               Debug( LDAP_DEBUG_ANY,
-                       "entry_decode: attribute count was zero\n", 0, 0, 0);
-               return LDAP_OTHER;
-       }
-       nvals = entry_getlen(&ptr);
-       if (!nvals) {
-               Debug( LDAP_DEBUG_ANY,
-                       "entry_decode: value count was zero\n", 0, 0, 0);
-               return LDAP_OTHER;
-       }
+       nattrs = eh->nattrs;
+       nvals = eh->nvals;
        x = entry_alloc();
        x->e_attrs = attrs_alloc( nattrs );
-       x->e_abv = ch_malloc( nvals * sizeof( struct berval ));
+       ptr = (unsigned char *)eh->data;
        i = entry_getlen(&ptr);
        x->e_name.bv_val = (char *) ptr;
        x->e_name.bv_len = i;
@@ -771,10 +776,10 @@ int entry_decode(struct berval *bv, Entry **e)
        Debug( LDAP_DEBUG_TRACE,
                "entry_decode: \"%s\"\n",
                x->e_dn, 0, 0 );
-       x->e_bv = *bv;
+       x->e_bv = eh->bv;
 
        a = x->e_attrs;
-       bptr = x->e_abv;
+       bptr = (BerVarray)eh->bv.bv_val;
 
        while ((i = entry_getlen(&ptr))) {
                struct berval bv;
@@ -853,9 +858,6 @@ Entry *entry_dup( Entry *e )
        ber_dupbv( &ret->e_nname, &e->e_nname );
        ret->e_attrs = attrs_dup( e->e_attrs );
        ret->e_ocflags = e->e_ocflags;
-       ret->e_bv.bv_val = NULL;
-       ret->e_bv.bv_len = 0;
-       ret->e_private = NULL;
 
        return ret;
 }
index 05ea1defb77e01f968928b83fbc369392aa9da16..61b2320e4188d35a21bf0b9e2546d78492db1729 100644 (file)
@@ -853,12 +853,13 @@ LDAP_SLAPD_F (ber_len_t) entry_flatsize LDAP_P(( Entry *e, int norm ));
 LDAP_SLAPD_F (void) entry_partsize LDAP_P(( Entry *e, ber_len_t *len,
        int *nattrs, int *nvals, int norm ));
 
+LDAP_SLAPD_F (int) entry_header LDAP_P(( EntryHeader *eh ));
 #ifdef SLAP_ZONE_ALLOC
 LDAP_SLAPD_F (int) entry_decode LDAP_P((
-                                               struct berval *bv, Entry **e, void *ctx ));
+                                               EntryHeader *eh, Entry **e, void *ctx ));
 #else
 LDAP_SLAPD_F (int) entry_decode LDAP_P((
-                                               struct berval *bv, Entry **e ));
+                                               EntryHeader *eh, Entry **e ));
 #endif
 LDAP_SLAPD_F (int) entry_encode LDAP_P(( Entry *e, struct berval *bv ));
 
index 0f132522d6d2943551be17b29b9d0f678432c366..1d25e3bcfd2e0a4031525e9f3dfc58f116b23384 100644 (file)
@@ -1108,6 +1108,13 @@ typedef struct slap_attr {
 typedef unsigned long  ID;
 #define NOID   ((ID)~0)
 
+typedef struct slap_entry_header {
+       struct berval bv;
+       char *data;
+       int nattrs;
+       int nvals;
+} EntryHeader;
+
 /*
  * represents an entry in core
  */
@@ -1131,7 +1138,6 @@ typedef struct slap_entry {
        slap_mask_t     e_ocflags;
 
        struct berval   e_bv;           /* For entry_encode/entry_decode */
-       struct berval   *e_abv;
 
        /* for use by the backend for any purpose */
        void*   e_private;