Back to index

openldap  2.4.31
Classes | Defines | Typedefs | Functions
id2entry.c File Reference
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/errno.h>
#include "back-mdb.h"

Go to the source code of this file.

Classes

struct  Ecount

Defines

#define ADD_FLAGS   (MDB_NOOVERWRITE|MDB_APPEND)
#define HIGH_BIT   (1<<(sizeof(unsigned int)*CHAR_BIT-1))

Typedefs

typedef struct Ecount Ecount

Functions

static int mdb_entry_partsize (struct mdb_info *mdb, MDB_txn *txn, Entry *e, Ecount *eh)
static int mdb_entry_encode (Operation *op, Entry *e, MDB_val *data, Ecount *ec)
static Entrymdb_entry_alloc (Operation *op, int nattrs, int nvals)
static int mdb_id2entry_put (Operation *op, MDB_txn *txn, MDB_cursor *mc, Entry *e, int flag)
int mdb_id2entry_add (Operation *op, MDB_txn *txn, MDB_cursor *mc, Entry *e)
int mdb_id2entry_update (Operation *op, MDB_txn *txn, MDB_cursor *mc, Entry *e)
int mdb_id2entry (Operation *op, MDB_cursor *mc, ID id, Entry **e)
int mdb_id2entry_delete (BackendDB *be, MDB_txn *tid, Entry *e)
int mdb_entry_return (Operation *op, Entry *e)
int mdb_entry_release (Operation *op, Entry *e, int rw)
int mdb_entry_get (Operation *op, struct berval *ndn, ObjectClass *oc, AttributeDescription *at, int rw, Entry **ent)
static void mdb_reader_free (void *key, void *data)
void mdb_reader_flush (MDB_env *env)
int mdb_opinfo_get (Operation *op, struct mdb_info *mdb, int rdonly, mdb_op_info **moip)
int mdb_entry_decode (Operation *op, MDB_val *data, Entry **e)

Class Documentation

struct Ecount

Definition at line 25 of file id2entry.c.

Class Members
ber_len_t len
int nattrs
int nvals
int offset

Define Documentation

Definition at line 38 of file id2entry.c.

#define HIGH_BIT   (1<<(sizeof(unsigned int)*CHAR_BIT-1))

Definition at line 535 of file id2entry.c.


Typedef Documentation

typedef struct Ecount Ecount

Function Documentation

static Entry * mdb_entry_alloc ( Operation op,
int  nattrs,
int  nvals 
) [static]

Definition at line 194 of file id2entry.c.

{
       Entry *e = op->o_tmpalloc( sizeof(Entry) +
              nattrs * sizeof(Attribute) +
              nvals * sizeof(struct berval), op->o_tmpmemctx );
       BER_BVZERO(&e->e_bv);
       e->e_private = e;
       if (nattrs) {
              e->e_attrs = (Attribute *)(e+1);
              e->e_attrs->a_vals = (struct berval *)(e->e_attrs+nattrs);
       } else {
              e->e_attrs = NULL;
       }

       return e;
}

Here is the caller graph for this function:

int mdb_entry_decode ( Operation op,
MDB_val data,
Entry **  e 
)

Definition at line 617 of file id2entry.c.

{
       struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
       int i, j, nattrs, nvals;
       int rc;
       Attribute *a;
       Entry *x;
       const char *text;
       AttributeDescription *ad;
       unsigned int *lp = (unsigned int *)data->mv_data;
       unsigned char *ptr;
       BerVarray bptr;

       Debug( LDAP_DEBUG_TRACE,
              "=> mdb_entry_decode:\n",
              0, 0, 0 );

       nattrs = *lp++;
       nvals = *lp++;
       x = mdb_entry_alloc(op, nattrs, nvals);
       x->e_ocflags = *lp++;
       if (!nvals) {
              goto done;
       }
       a = x->e_attrs;
       bptr = a->a_vals;
       i = *lp++;
       ptr = (unsigned char *)(lp + i);

       for (;nattrs>0; nattrs--) {
              int have_nval = 0;
              a->a_desc = mdb->mi_ads[*lp++];
              a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS;
              a->a_numvals = *lp++;
              if (a->a_numvals & HIGH_BIT) {
                     a->a_numvals ^= HIGH_BIT;
                     have_nval = 1;
              }
              a->a_vals = bptr;
              for (i=0; i<a->a_numvals; i++) {
                     bptr->bv_len = *lp++;;
                     bptr->bv_val = (char *)ptr;
                     ptr += bptr->bv_len+1;
                     bptr++;
              }
              bptr->bv_val = NULL;
              bptr->bv_len = 0;
              bptr++;

              if (have_nval) {
                     a->a_nvals = bptr;
                     for (i=0; i<a->a_numvals; i++) {
                            bptr->bv_len = *lp++;
                            bptr->bv_val = (char *)ptr;
                            ptr += bptr->bv_len+1;
                            bptr++;
                     }
                     bptr->bv_val = NULL;
                     bptr->bv_len = 0;
                     bptr++;
              } 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,
                                   "mdb_entry_decode: attributeType %s value #%d provided more than once\n",
                                   a->a_desc->ad_cname.bv_val, j, 0 );
                            return rc;
                     }
              }
              a->a_next = a+1;
              a = a->a_next;
       }
       a[-1].a_next = NULL;
done:

       Debug(LDAP_DEBUG_TRACE, "<= mdb_entry_decode\n",
              0, 0, 0 );
       *e = x;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int mdb_entry_encode ( Operation op,
Entry e,
MDB_val data,
Ecount ec 
) [static]

Definition at line 553 of file id2entry.c.

{
       struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
       ber_len_t len, i;
       int rc;
       Attribute *a;
       unsigned char *ptr;
       unsigned int *lp, l;

       Debug( LDAP_DEBUG_TRACE, "=> mdb_entry_encode(0x%08lx): %s\n",
              (long) e->e_id, e->e_dn, 0 );

       /* make sure e->e_ocflags is set */
       if (is_entry_referral(e))
              ;      /* empty */

       lp = (unsigned int *)data->mv_data;
       *lp++ = eh->nattrs;
       *lp++ = eh->nvals;
       *lp++ = (unsigned int)e->e_ocflags;
       *lp++ = eh->offset;
       ptr = (unsigned char *)(lp + eh->offset);

       for (a=e->e_attrs; a; a=a->a_next) {
              *lp++ = mdb->mi_adxs[a->a_desc->ad_index];
              l = a->a_numvals;
              if (a->a_nvals != a->a_vals)
                     l |= HIGH_BIT;
              *lp++ = l;
              if (a->a_vals) {
                     for (i=0; a->a_vals[i].bv_val; i++);
                     assert( i == a->a_numvals );
                     for (i=0; i<a->a_numvals; i++) {
                            *lp++ = a->a_vals[i].bv_len;
                            memcpy(ptr, a->a_vals[i].bv_val,
                                   a->a_vals[i].bv_len);
                            ptr += a->a_vals[i].bv_len;
                            *ptr++ = '\0';
                     }
                     if (a->a_nvals != a->a_vals) {
                            for (i=0; i<a->a_numvals; i++) {
                                   *lp++ = a->a_nvals[i].bv_len;
                                   memcpy(ptr, a->a_nvals[i].bv_val,
                                          a->a_nvals[i].bv_len);
                                   ptr += a->a_nvals[i].bv_len;
                                   *ptr++ = '\0';
                            }
                     }
              }
       }

       Debug( LDAP_DEBUG_TRACE, "<= mdb_entry_encode(0x%08lx): %s\n",
              (long) e->e_id, e->e_dn, 0 );

       return 0;
}

Here is the caller graph for this function:

int mdb_entry_get ( Operation op,
struct berval ndn,
ObjectClass oc,
AttributeDescription at,
int  rw,
Entry **  ent 
)

Definition at line 273 of file id2entry.c.

{
       struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
       struct mdb_op_info *moi = NULL;
       MDB_txn *txn = NULL;
       Entry *e = NULL;
       int    rc;
       const char *at_name = at ? at->ad_cname.bv_val : "(null)";

       Debug( LDAP_DEBUG_ARGS,
              "=> mdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); 
       Debug( LDAP_DEBUG_ARGS,
              "=> mdb_entry_get: oc: \"%s\", at: \"%s\"\n",
              oc ? oc->soc_cname.bv_val : "(null)", at_name, 0);

       rc = mdb_opinfo_get( op, mdb, rw == 0, &moi );
       if ( rc )
              return LDAP_OTHER;
       txn = moi->moi_txn;

       /* can we find entry */
       rc = mdb_dn2entry( op, txn, NULL, ndn, &e, 0 );
       switch( rc ) {
       case MDB_NOTFOUND:
       case 0:
              break;
       default:
              return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
       }
       if (e == NULL) {
              Debug( LDAP_DEBUG_ACL,
                     "=> mdb_entry_get: cannot find entry: \"%s\"\n",
                            ndn->bv_val, 0, 0 ); 
              rc = LDAP_NO_SUCH_OBJECT;
              goto return_results;
       }
       
       Debug( LDAP_DEBUG_ACL,
              "=> mdb_entry_get: found entry: \"%s\"\n",
              ndn->bv_val, 0, 0 ); 

       if ( oc && !is_entry_objectclass( e, oc, 0 )) {
              Debug( LDAP_DEBUG_ACL,
                     "<= mdb_entry_get: failed to find objectClass %s\n",
                     oc->soc_cname.bv_val, 0, 0 ); 
              rc = LDAP_NO_SUCH_ATTRIBUTE;
              goto return_results;
       }

       /* NOTE: attr_find() or attrs_find()? */
       if ( at && attr_find( e->e_attrs, at ) == NULL ) {
              Debug( LDAP_DEBUG_ACL,
                     "<= mdb_entry_get: failed to find attribute %s\n",
                     at->ad_cname.bv_val, 0, 0 ); 
              rc = LDAP_NO_SUCH_ATTRIBUTE;
              goto return_results;
       }

return_results:
       if( rc != LDAP_SUCCESS ) {
              /* free entry */
              if ( e )
                     mdb_entry_return( op, e );

              if (moi->moi_ref == 1) {
                     LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
                     mdb_txn_reset( txn );
                     op->o_tmpfree( moi, op->o_tmpmemctx );
              }
       } else {
              *ent = e;
       }

       Debug( LDAP_DEBUG_TRACE,
              "mdb_entry_get: rc=%d\n",
              rc, 0, 0 ); 
       return(rc);
}

Here is the call graph for this function:

static int mdb_entry_partsize ( struct mdb_info mdb,
MDB_txn txn,
Entry e,
Ecount eh 
) [static]

Definition at line 492 of file id2entry.c.

{
       ber_len_t len;
       int i, nat = 0, nval = 0, nnval = 0;
       Attribute *a;

       len = 4*sizeof(int); /* nattrs, nvals, ocflags, offset */
       for (a=e->e_attrs; a; a=a->a_next) {
              /* For AttributeDesc, we only store the attr index */
              nat++;
              if (a->a_desc->ad_index >= MDB_MAXADS) {
                     Debug( LDAP_DEBUG_ANY, "mdb_entry_partsize: too many AttributeDescriptions used\n",
                            0, 0, 0 );
                     return LDAP_OTHER;
              }
              if (!mdb->mi_adxs[a->a_desc->ad_index]) {
                     int rc = mdb_ad_get(mdb, txn, a->a_desc);
                     if (rc)
                            return rc;
              }
              len += 2*sizeof(int);       /* AD index, numvals */
              nval += a->a_numvals + 1;   /* empty berval at end */
              for (i=0; i<a->a_numvals; i++) {
                     len += a->a_vals[i].bv_len + 1 + sizeof(int);    /* len */
              }
              if (a->a_nvals != a->a_vals) {
                     nval += a->a_numvals + 1;
                     nnval++;
                     for (i=0; i<a->a_numvals; i++) {
                            len += a->a_nvals[i].bv_len + 1 + sizeof(int);;
                     }
              }
       }
       /* padding */
       len = (len + sizeof(ID)-1) & ~(sizeof(ID)-1);
       eh->len = len;
       eh->nattrs = nat;
       eh->nvals = nval;
       eh->offset = nat + nval - nnval;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mdb_entry_release ( Operation op,
Entry e,
int  rw 
)

Definition at line 235 of file id2entry.c.

{
       struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
       struct mdb_op_info *moi = NULL;
       int rc;
 
       /* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
                     SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
 
       mdb_entry_return( op, e );
       if ( slapMode == SLAP_SERVER_MODE ) {
              OpExtra *oex;
              LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
                     if ( oex->oe_key == mdb ) {
                            moi = (mdb_op_info *)oex;
                            /* If it was setup by entry_get we should probably free it */
                            if ( moi->moi_flag & MOI_FREEIT ) {
                                   moi->moi_ref--;
                                   if ( moi->moi_ref < 1 ) {
                                          mdb_txn_reset( moi->moi_txn );
                                          moi->moi_ref = 0;
                                          LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
                                          op->o_tmpfree( moi, op->o_tmpmemctx );
                                   }
                            }
                            break;
                     }
              }
       }
 
       return 0;
}

Here is the call graph for this function:

int mdb_entry_return ( Operation op,
Entry e 
)

Definition at line 214 of file id2entry.c.

{
       if ( e->e_private ) {
              if ( op->o_hdr ) {
                     op->o_tmpfree( e->e_nname.bv_val, op->o_tmpmemctx );
                     op->o_tmpfree( e->e_name.bv_val, op->o_tmpmemctx );
                     op->o_tmpfree( e, op->o_tmpmemctx );
              } else {
                     ch_free( e->e_nname.bv_val );
                     ch_free( e->e_name.bv_val );
                     ch_free( e );
              }
       } else {
              entry_free( e );
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mdb_id2entry ( Operation op,
MDB_cursor mc,
ID  id,
Entry **  e 
)

Definition at line 114 of file id2entry.c.

{
       struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
       MDB_val key, data;
       int rc = 0;

       *e = NULL;

       key.mv_data = &id;
       key.mv_size = sizeof(ID);

       /* fetch it */
       rc = mdb_cursor_get( mc, &key, &data, MDB_SET );
       if ( rc == MDB_NOTFOUND ) {
              /* Looking for root entry on an empty-dn suffix? */
              if ( !id && BER_BVISEMPTY( &op->o_bd->be_nsuffix[0] )) {
                     struct berval gluebv = BER_BVC("glue");
                     Entry *r = mdb_entry_alloc(op, 2, 4);
                     Attribute *a = r->e_attrs;
                     struct berval *bptr;

                     r->e_id = 0;
                     r->e_ocflags = SLAP_OC_GLUE|SLAP_OC__END;
                     bptr = a->a_vals;
                     a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS;
                     a->a_desc = slap_schema.si_ad_objectClass;
                     a->a_nvals = a->a_vals;
                     a->a_numvals = 1;
                     *bptr++ = gluebv;
                     BER_BVZERO(bptr);
                     bptr++;
                     a->a_next = a+1;
                     a = a->a_next;
                     a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS;
                     a->a_desc = slap_schema.si_ad_structuralObjectClass;
                     a->a_vals = bptr;
                     a->a_nvals = a->a_vals;
                     a->a_numvals = 1;
                     *bptr++ = gluebv;
                     BER_BVZERO(bptr);
                     a->a_next = NULL;
                     *e = r;
                     return MDB_SUCCESS;
              }
       }
       if ( rc ) return rc;

       rc = mdb_entry_decode( op, &data, e );
       if ( rc ) return rc;

       (*e)->e_id = id;
       (*e)->e_name.bv_val = NULL;
       (*e)->e_nname.bv_val = NULL;

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mdb_id2entry_add ( Operation op,
MDB_txn txn,
MDB_cursor mc,
Entry e 
)

Definition at line 96 of file id2entry.c.

{
       return mdb_id2entry_put(op, txn, mc, e, ADD_FLAGS);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mdb_id2entry_delete ( BackendDB be,
MDB_txn tid,
Entry e 
)

Definition at line 175 of file id2entry.c.

{
       struct mdb_info *mdb = (struct mdb_info *) be->be_private;
       MDB_dbi dbi = mdb->mi_id2entry;
       MDB_val key;
       int rc;

       key.mv_data = &e->e_id;
       key.mv_size = sizeof(ID);

       /* delete from database */
       rc = mdb_del( tid, dbi, &key, NULL );

       return rc;
}

Here is the call graph for this function:

static int mdb_id2entry_put ( Operation op,
MDB_txn txn,
MDB_cursor mc,
Entry e,
int  flag 
) [static]

Definition at line 40 of file id2entry.c.

{
       struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
       Ecount ec;
       MDB_val key, data;
       int rc;

       /* We only store rdns, and they go in the dn2id database. */

       key.mv_data = &e->e_id;
       key.mv_size = sizeof(ID);

       rc = mdb_entry_partsize( mdb, txn, e, &ec );
       if (rc)
              return LDAP_OTHER;

       flag |= MDB_RESERVE;

again:
       data.mv_size = ec.len;
       if ( mc )
              rc = mdb_cursor_put( mc, &key, &data, flag );
       else
              rc = mdb_put( txn, mdb->mi_id2entry, &key, &data, flag );
       if (rc == MDB_SUCCESS) {
              rc = mdb_entry_encode( op, e, &data, &ec );
              if( rc != LDAP_SUCCESS )
                     return LDAP_OTHER;
       }
       if (rc) {
              /* Was there a hole from slapadd? */
              if ( (flag & MDB_NOOVERWRITE) && data.mv_size == 0 ) {
                     flag ^= ADD_FLAGS;
                     goto again;
              }
              Debug( LDAP_DEBUG_ANY,
                     "mdb_id2entry_put: mdb_put failed: %s(%d) \"%s\"\n",
                     mdb_strerror(rc), rc,
                     e->e_nname.bv_val );
              if ( rc != MDB_KEYEXIST )
                     rc = LDAP_OTHER;
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mdb_id2entry_update ( Operation op,
MDB_txn txn,
MDB_cursor mc,
Entry e 
)

Definition at line 105 of file id2entry.c.

{
       return mdb_id2entry_put(op, txn, mc, e, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int mdb_opinfo_get ( Operation op,
struct mdb_info mdb,
int  rdonly,
mdb_op_info **  moip 
)

Definition at line 380 of file id2entry.c.

{
       int rc, renew = 0;
       void *data;
       void *ctx;
       mdb_op_info *moi = NULL;
       OpExtra *oex;

       assert( op != NULL );

       if ( !mdb || !moip ) return -1;

       /* If no op was provided, try to find the ctx anyway... */
       if ( op ) {
              ctx = op->o_threadctx;
       } else {
              ctx = ldap_pvt_thread_pool_context();
       }

       if ( op ) {
              LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
                     if ( oex->oe_key == mdb ) break;
              }
              moi = (mdb_op_info *)oex;
       }

       if ( !moi ) {
              moi = *moip;

              if ( !moi ) {
                     if ( op ) {
                            moi = op->o_tmpalloc(sizeof(struct mdb_op_info),op->o_tmpmemctx);
                     } else {
                            moi = ch_malloc(sizeof(mdb_op_info));
                     }
                     moi->moi_flag = MOI_FREEIT;
                     *moip = moi;
              }
              LDAP_SLIST_INSERT_HEAD( &op->o_extra, &moi->moi_oe, oe_next );
              moi->moi_oe.oe_key = mdb;
              moi->moi_ref = 0;
              moi->moi_txn = NULL;
       }

       if ( !rdonly ) {
              /* This op started as a reader, but now wants to write. */
              if ( moi->moi_flag & MOI_READER ) {
                     moi = *moip;
                     LDAP_SLIST_INSERT_HEAD( &op->o_extra, &moi->moi_oe, oe_next );
              } else {
              /* This op is continuing an existing write txn */
                     *moip = moi;
              }
              moi->moi_ref++;
              if ( !moi->moi_txn ) {
                     rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &moi->moi_txn );
                     if (rc) {
                            Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n",
                                   mdb_strerror(rc), rc, 0 );
                     }
                     return rc;
              }
              return 0;
       }

       /* OK, this is a reader */
       if ( !moi->moi_txn ) {
              if ( !ctx ) {
                     /* Shouldn't happen unless we're single-threaded */
                     rc = mdb_txn_begin( mdb->mi_dbenv, NULL, MDB_RDONLY, &moi->moi_txn );
                     if (rc) {
                            Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n",
                                   mdb_strerror(rc), rc, 0 );
                     }
                     return rc;
              }
              if ( ldap_pvt_thread_pool_getkey( ctx, mdb->mi_dbenv, &data, NULL ) ) {
                     rc = mdb_txn_begin( mdb->mi_dbenv, NULL, MDB_RDONLY, &moi->moi_txn );
                     if (rc) {
                            Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n",
                                   mdb_strerror(rc), rc, 0 );
                            return rc;
                     }
                     data = moi->moi_txn;
                     if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, mdb->mi_dbenv,
                            data, mdb_reader_free, NULL, NULL ) ) ) {
                            mdb_txn_abort( moi->moi_txn );
                            moi->moi_txn = NULL;
                            Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: thread_pool_setkey failed err (%d)\n",
                                   rc, 0, 0 );
                            return rc;
                     }
              } else {
                     moi->moi_txn = data;
                     renew = 1;
              }
              moi->moi_flag |= MOI_READER;
       }
       if ( moi->moi_ref < 1 ) {
              moi->moi_ref = 0;
       }
       if ( renew ) {
              mdb_txn_renew( moi->moi_txn );
       }
       moi->moi_ref++;
       if ( *moip != moi )
              *moip = moi;

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 368 of file id2entry.c.

{
       void *data;
       void *ctx = ldap_pvt_thread_pool_context();

       if ( !ldap_pvt_thread_pool_getkey( ctx, env, &data, NULL ) ) {
              ldap_pvt_thread_pool_setkey( ctx, env, NULL, 0, NULL, NULL );
              mdb_reader_free( env, data );
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void mdb_reader_free ( void key,
void data 
) [static]

Definition at line 359 of file id2entry.c.

{
       MDB_txn *txn = data;

       if ( txn ) mdb_txn_abort( txn );
}

Here is the call graph for this function:

Here is the caller graph for this function: