1 /* id2entry.c - routines to deal with the id2entry database */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2000-2011 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/string.h>
25 static int mdb_id2entry_put(
31 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
32 MDB_dbi dbi = mdb->mi_id2entry;
36 struct berval odn, ondn;
38 /* We only store rdns, and they go in the dn2id database. */
40 odn = e->e_name; ondn = e->e_nname;
42 e->e_name = slap_empty_bv;
43 e->e_nname = slap_empty_bv;
45 key.mv_data = &e->e_id;
46 key.mv_size = sizeof(ID);
48 rc = entry_encode( e, &bv );
49 e->e_name = odn; e->e_nname = ondn;
50 if( rc != LDAP_SUCCESS ) {
54 data.mv_size = bv.bv_len;
55 data.mv_data = bv.bv_val;
57 rc = mdb_put( tid, dbi, &key, &data, flag );
59 op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
64 * This routine adds (or updates) an entry on disk.
65 * The cache should be already be updated.
74 return mdb_id2entry_put(op, tid, e, MDB_NOOVERWRITE);
77 int mdb_id2entry_update(
82 return mdb_id2entry_put(op, tid, e, 0);
91 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
92 MDB_dbi dbi = mdb->mi_id2entry;
100 key.mv_size = sizeof(ID);
103 rc = mdb_get( tid, dbi, &key, &data );
106 eh.bv.bv_val = data.mv_data;
107 eh.bv.bv_len = data.mv_size;
108 rc = entry_header( &eh );
111 eh.bv.bv_len = eh.nvals * sizeof( struct berval );
112 eh.bv.bv_val = ch_malloc( eh.bv.bv_len );
113 rc = entry_decode(&eh, e);
118 (*e)->e_name.bv_val = NULL;
119 (*e)->e_nname.bv_val = NULL;
121 ch_free( eh.bv.bv_val );
127 int mdb_id2entry_delete(
132 struct mdb_info *mdb = (struct mdb_info *) be->be_private;
133 MDB_dbi dbi = mdb->mi_id2entry;
137 key.mv_data = &e->e_id;
138 key.mv_size = sizeof(ID);
140 /* delete from database */
141 rc = mdb_del( tid, dbi, &key, NULL, 0 );
146 int mdb_entry_return(
154 int mdb_entry_release(
159 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
160 struct mdb_op_info *moi = NULL;
163 /* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
164 SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
166 mdb_entry_return ( e );
167 if ( slapMode == SLAP_SERVER_MODE ) {
169 LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
170 if ( oex->oe_key == mdb ) {
171 moi = (mdb_op_info *)oex;
172 /* If it was setup by entry_get we should probably free it */
173 if ( moi->moi_flag & MOI_FREEIT ) {
175 if ( moi->moi_ref < 1 ) {
176 mdb_txn_reset( moi->moi_txn );
178 LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
179 op->o_tmpfree( moi, op->o_tmpmemctx );
190 /* return LDAP_SUCCESS IFF we can retrieve the specified entry.
196 AttributeDescription *at,
200 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
201 struct mdb_op_info *moi = NULL;
205 const char *at_name = at ? at->ad_cname.bv_val : "(null)";
207 Debug( LDAP_DEBUG_ARGS,
208 "=> mdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 );
209 Debug( LDAP_DEBUG_ARGS,
210 "=> mdb_entry_get: oc: \"%s\", at: \"%s\"\n",
211 oc ? oc->soc_cname.bv_val : "(null)", at_name, 0);
213 rc = mdb_opinfo_get( op, mdb, rw == 0, &moi );
218 /* can we find entry */
219 rc = mdb_dn2entry( op, txn, ndn, &e, 0 );
225 return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
228 Debug( LDAP_DEBUG_ACL,
229 "=> mdb_entry_get: cannot find entry: \"%s\"\n",
231 return LDAP_NO_SUCH_OBJECT;
234 Debug( LDAP_DEBUG_ACL,
235 "=> mdb_entry_get: found entry: \"%s\"\n",
238 if ( oc && !is_entry_objectclass( e, oc, 0 )) {
239 Debug( LDAP_DEBUG_ACL,
240 "<= mdb_entry_get: failed to find objectClass %s\n",
241 oc->soc_cname.bv_val, 0, 0 );
242 rc = LDAP_NO_SUCH_ATTRIBUTE;
246 /* NOTE: attr_find() or attrs_find()? */
247 if ( at && attr_find( e->e_attrs, at ) == NULL ) {
248 Debug( LDAP_DEBUG_ACL,
249 "<= mdb_entry_get: failed to find attribute %s\n",
250 at->ad_cname.bv_val, 0, 0 );
251 rc = LDAP_NO_SUCH_ATTRIBUTE;
256 if( rc != LDAP_SUCCESS ) {
258 mdb_entry_return( e );
261 *ent = entry_dup( e );
264 Debug( LDAP_DEBUG_TRACE,
265 "mdb_entry_get: rc=%d\n",
271 mdb_reader_free( void *key, void *data )
275 if ( txn ) mdb_txn_abort( txn );
278 /* free up any keys used by the main thread */
280 mdb_reader_flush( MDB_env *env )
283 void *ctx = ldap_pvt_thread_pool_context();
285 if ( !ldap_pvt_thread_pool_getkey( ctx, env, &data, NULL ) ) {
286 ldap_pvt_thread_pool_setkey( ctx, env, NULL, 0, NULL, NULL );
287 mdb_reader_free( env, data );
292 mdb_opinfo_get( Operation *op, struct mdb_info *mdb, int rdonly, mdb_op_info **moip )
297 mdb_op_info *moi = NULL;
300 assert( op != NULL );
302 if ( !mdb || !moip ) return -1;
304 /* If no op was provided, try to find the ctx anyway... */
306 ctx = op->o_threadctx;
308 ctx = ldap_pvt_thread_pool_context();
312 LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
313 if ( oex->oe_key == mdb ) break;
315 moi = (mdb_op_info *)oex;
323 moi = op->o_tmpalloc(sizeof(struct mdb_op_info),op->o_tmpmemctx);
325 moi = ch_malloc(sizeof(mdb_op_info));
327 moi->moi_flag = MOI_FREEIT;
330 LDAP_SLIST_INSERT_HEAD( &op->o_extra, &moi->moi_oe, oe_next );
331 moi->moi_oe.oe_key = mdb;
337 /* This op started as a reader, but now wants to write. */
338 if ( moi->moi_flag & MOI_READER ) {
340 LDAP_SLIST_INSERT_HEAD( &op->o_extra, &moi->moi_oe, oe_next );
342 /* This op is continuing an existing write txn */
346 if ( !moi->moi_txn ) {
347 rc = mdb_txn_begin( mdb->mi_dbenv, 0, &moi->moi_txn );
349 Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n",
350 mdb_strerror(rc), rc, 0 );
357 /* OK, this is a reader */
358 if ( !moi->moi_txn ) {
360 /* Shouldn't happen unless we're single-threaded */
361 rc = mdb_txn_begin( mdb->mi_dbenv, 1, &moi->moi_txn );
363 Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n",
364 mdb_strerror(rc), rc, 0 );
368 if ( ldap_pvt_thread_pool_getkey( ctx, mdb->mi_dbenv, &data, NULL ) ) {
369 rc = mdb_txn_begin( mdb->mi_dbenv, 1, &moi->moi_txn );
371 Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n",
372 mdb_strerror(rc), rc, 0 );
376 if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, mdb->mi_dbenv,
377 data, mdb_reader_free, NULL, NULL ) ) ) {
378 mdb_txn_abort( moi->moi_txn );
380 Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: thread_pool_setkey failed err (%d)\n",
387 moi->moi_flag |= MOI_READER;
389 if ( moi->moi_ref < 1 ) {
391 mdb_txn_renew( moi->moi_txn );