mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
Use a single malloc for entry_decode instead of two - partially decode
the entry to get nvals first, so the size can be computed.
This commit is contained in:
parent
cbc238721a
commit
f63f46f0b1
@ -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;
|
||||
|
@ -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,26 +262,40 @@ 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;
|
||||
@ -290,6 +318,8 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
leave:
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ));
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user