From 98d6a4f2bf534bb1de9f8d05397259bd886aa4ea Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 19 Oct 2001 11:53:15 +0000 Subject: [PATCH] Added new bdb_encode/bdb_decode functions, must #define BDB_USE_BINARY_RW to activate. The bdb_decode works in-place on the db data. Add/Search are OK, I think Modify needs to be tweaked. Don't use this yet unless you want to help finish it. --- servers/slapd/back-bdb/id2entry.c | 186 ++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index 51751c230c..688cdc4e9d 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -12,6 +12,190 @@ #include "back-bdb.h" +#ifdef BDB_USE_BINARY_RW + +/* A cache of every AttributeDescription we ever see. We don't want + * to churn thru malloc/free on them all the time since most will be + * encountered repeatedly. + */ +static Avlnode *adcache; + +static int +ad_type_cmp( + char *desc, + AttributeDescription *ad +) +{ + return strcasecmp(desc, ad->ad_cname->bv_val); +} + +static int +ad_info_cmp( + AttributeDescription *a1, + AttributeDescription *a2 +) +{ + return strcasecmp(a1->ad_cname->bv_val, a2->ad_cname->bv_val); +} + +AttributeDescription * +bdb_str2ad(const char *desc) +{ + AttributeDescription *a; + + a = (AttributeDescription *) avl_find(adcache, desc, + (AVL_CMP) ad_type_cmp); + if (!a) { + int rc; + const char *text; + + rc = slap_str2ad(desc, &a, &text); + if (rc != LDAP_SUCCESS) { + return NULL; + } + rc = avl_insert(&adcache, (caddr_t)a, (AVL_CMP) ad_info_cmp, + (AVL_DUP) avl_dup_error); + } + return a; +} + +/* Flatten an Entry into a buffer. The buffer contents become a direct + * copy of the entry, with all pointers converted to offsets from the + * beginning of the buffer. We do this by first walking through all + * the fields of the Entry, adding up their sizes. Then a single chunk + * of memory is malloc'd and the entry is copied. We differentiate between + * fixed size fields and variable-length content when tallying up the + * entry size, so that we can stick all of the variable-length stuff + * into the back half of the buffer. + */ +int bdb_encode(Entry *e, struct berval **bv) +{ + int siz = sizeof(Entry); + int len, dnlen; + int i, j; + Entry *f; + Attribute *a, *b; + struct berval **bvl, *bz; + char *ptr, *base, *data; + + *bv = ch_malloc(sizeof(struct berval)); + /* Compress any white space in the DN */ + dn_validate(e->e_dn); + dnlen = strlen(e->e_dn); + /* The dn and ndn are always the same length */ + len = dnlen + dnlen + 2; /* two trailing NUL bytes */ + for (a=e->e_attrs; a; a=a->a_next) { + /* For AttributeDesc, we only store the attr name */ + siz += sizeof(Attribute); + len += a->a_desc->ad_cname->bv_len+1; + for (i=0; a->a_vals[i]; i++) { + siz += sizeof(struct berval *); + siz += sizeof(struct berval); + len += a->a_vals[i]->bv_len + 1; + } + siz += sizeof(struct berval *); /* NULL pointer at end */ + } + (*bv)->bv_len = siz + len; + (*bv)->bv_val = ch_malloc(siz+len); + base = (*bv)->bv_val; + ptr = base + siz; + f = (Entry *)base; + data = (char *)(f+1); + f->e_id = e->e_id; + f->e_dn = (char *)(ptr-base); + memcpy(ptr, e->e_dn, dnlen); + ptr += dnlen; + *ptr++ = '\0'; + f->e_ndn = (char *)(ptr-base); + memcpy(ptr, e->e_ndn, dnlen); + ptr += dnlen; + *ptr++ = '\0'; + f->e_attrs = e->e_attrs ? (Attribute *)sizeof(Entry) : NULL; + f->e_private = NULL; + for (a=e->e_attrs; a; a=a->a_next) { + b = (Attribute *)data; + data = (char *)(b+1); + b->a_desc = (AttributeDescription *)(ptr-base); + memcpy(ptr, a->a_desc->ad_cname->bv_val, + a->a_desc->ad_cname->bv_len); + ptr += a->a_desc->ad_cname->bv_len; + *ptr++ = '\0'; + if (a->a_vals) { + bvl = (struct berval **)data; + b->a_vals = (struct berval **)(data-base); + for (i=0; a->a_vals[i]; i++); + data = (char *)(bvl+i+1); + bz = (struct berval *)data; + for (j=0; jbv_len = a->a_vals[j]->bv_len; + if (a->a_vals[j]->bv_val) { + bz->bv_val = (char *)(ptr-base); + memcpy(ptr, a->a_vals[j]->bv_val, bz->bv_len); + } else { + bz->bv_val = NULL; + } + ptr += bz->bv_len; + *ptr++ = '\0'; + bvl[j] = (struct berval *)(data-base); + bz++; + data = (char *)bz; + } + bvl[j] = NULL; + } else { + b->a_vals = NULL; + } + + if (a->a_next) + b->a_next = (Attribute *)(data-base); + else + b->a_next = NULL; + } + return 0; +} + +/* Retrieve an Entry that was stored using bdb_encode above. + * All we have to do is add the buffer address to all of the + * stored offsets. We also use the stored attribute names to + * pull AttributeDescriptions from our ad_cache. + */ +int bdb_decode(struct berval *bv, Entry **e) +{ + int i; + long base; + Attribute *a; + Entry *x = (Entry *)bv->bv_val; + + base = (long)bv->bv_val; + x->e_dn += base; + x->e_ndn += base; + x->e_private = bv->bv_val + bv->bv_len; + if (x->e_attrs) + x->e_attrs = (Attribute *)((long)x->e_attrs+base); + for (a=x->e_attrs; a; a=a->a_next) { + if (a->a_next) + a->a_next = (Attribute *)((long)a->a_next+base); + a->a_desc=bdb_str2ad((char *)a->a_desc+base); + if (!a->a_desc) return -1; + if (a->a_vals) { + a->a_vals = (struct berval **)((long)a->a_vals+base); + for (i=0; a->a_vals[i]; i++) { + a->a_vals[i] = (struct berval *) + ((long)a->a_vals[i]+base); + if (a->a_vals[i]->bv_val) + a->a_vals[i]->bv_val += base; + } + } + } + *e = x; + return 0; +} + +#define entry_encode(a, b) bdb_encode(a,b) +#define entry_decode(a, b) bdb_decode(a,b) +#define entry_free(e) ch_free(e) + +#endif /* BDB_USE_BINARY_RW */ + int bdb_id2entry_add( BackendDB *be, DB_TXN *tid, @@ -106,7 +290,9 @@ int bdb_id2entry( (*e)->e_id = id; } +#ifndef BDB_USE_BINARY_RW ch_free( data.data ); +#endif return rc; } -- 2.39.5