Fixed back-bdb ctxcsn locking bug
Fixed back-ldap validate/pretty values (ITS#3218)
Fixed back-ldap shared connections failover (ITS#3217)
+ Fixed slapi slapi_int_compute_output_ber attrs bug
Fixed slapd oidValidate 0 bug (ITS#3211)
Fixed slapd uniqueMember/nameUID bugs (ITS#3210)
Fixed slapd operational attribute log message bug (ITS#3205)
Fixed slapd invalid cookie in pagedResults control (ITS#3089)
Fixed slapd group ACL locking bug (ITS#3173)
- Fixed slapi slapi_int_compute_output_ber attrs bug
+ Fixed slapd abandon/cancel pending bug
+ Fixed slapd attribute description syntax bug
+ Fixed libldap SASL re-encode bug
Fixed libldap sasl_encode 64-bit bug (ITS#3054,3212)
Fixed libldap matchedValues parsing bug (ITS#3208,3216)
+ Fixed libldap DN '=' handling
Fixed libldap_r runqueue bug
+ Updated libldap_r read/writer locks
Build environments
Added additional res_query detection for MacOS X
Added default ldapi:// SSF build setting
/* Are there anything left in the buffer? */
if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
- if ( ret < 0 )
- return ret;
+ if ( ret < 0 ) return ret;
+
/* Still have something left?? */
if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
errno = EAGAIN;
- return 0;
+ return -1;
}
}
ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
"sb_sasl_write: failed to encode packet: %s\n",
sasl_errstring( ret, NULL, NULL ) );
+ errno = EIO;
return -1;
}
p->buf_out.buf_end = p->buf_out.buf_size;
ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
- if ( ret <= 0 ) {
- /* caller will retry, so clear this buffer out */
- p->buf_out.buf_ptr = p->buf_out.buf_end;
- return ret;
- }
+
+ /* return number of bytes encoded, not written, to ensure
+ * no byte is encoded twice (even if only sent once).
+ */
return len;
}
p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
if ( opt == LBER_SB_OPT_DATA_READY ) {
- if ( p->buf_in.buf_ptr != p->buf_in.buf_end )
- return 1;
+ if ( p->buf_in.buf_ptr != p->buf_in.buf_end ) return 1;
}
return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
#define LDAP_DN_ESCAPE(c) ( (c) == '\\' )
#define LDAP_DN_VALUE_END(c) \
( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) )
+
+/* NOTE: according to draft-ietf-ldapbis-dn, '=' can be escaped
+ * and treated as special, i.e. escaped both as "\<hexpair>" and
+ * as "\=", but it is treated as a regular char, i.e. it can also
+ * appear as '='.
+ *
+ * As such, we currently choose to allow reading unescaped '=',
+ * but we always produce escaped '\3D'; this may change in the
+ * future, if compatibility issues do not arise */
+#ifdef LDAP_DEVEL
+#define LDAP_DN_NE(c) \
+ ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \
+ || LDAP_DN_QUOTES(c) \
+ || (c) == '<' || (c) == '>' )
+#define LDAP_DN_MAYESCAPE(c) \
+ ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \
+ || LDAP_DN_AVA_EQUALS(c) \
+ || LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) )
+#define LDAP_DN_SHOULDESCAPE(c) ( LDAP_DN_AVA_EQUALS(c) )
+#else /* ! LDAP_DEVEL */
#define LDAP_DN_NE(c) \
( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \
|| LDAP_DN_AVA_EQUALS(c) || LDAP_DN_QUOTES(c) \
#define LDAP_DN_MAYESCAPE(c) \
( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \
|| LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) )
+#define LDAP_DN_SHOULDESCAPE(c) ( 0 )
+#endif /* ! LDAP_DEVEL */
+
#define LDAP_DN_NEEDESCAPE(c) \
( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) )
#define LDAP_DN_NEEDESCAPE_LEAD(c) LDAP_DN_MAYESCAPE(c)
assert( dn );
#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ARGS, "ldap_bv2dn(%s,%u)\n%s", str, flags, "" );
+ LDAP_LOG ( OPERATION, ARGS, "ldap_bv2dn(%s,%u)\n", str, flags, 0 );
#else
- Debug( LDAP_DEBUG_TRACE, "=> ldap_bv2dn(%s,%u)\n%s", str, flags, "" );
+ Debug( LDAP_DEBUG_TRACE, "=> ldap_bv2dn(%s,%u)\n", str, flags, 0 );
#endif
*dn = NULL;
}
#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS, "<= ldap_bv2dn(%s,%u)=%d\n",
- str, flags, rc );
+ LDAP_LOG ( OPERATION, RESULTS, "<= ldap_bv2dn(%s)=%d %s\n",
+ str, rc, ldap_err2string( rc ) );
#else
- Debug( LDAP_DEBUG_TRACE, "<= ldap_bv2dn(%s,%u)=%d\n", str, flags, rc );
+ Debug( LDAP_DEBUG_TRACE, "<= ldap_bv2dn(%s)=%d %s\n", str, rc,
+ ldap_err2string( rc ) );
#endif
*dn = newDN;
*/
return( 1 );
- } else if (!LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) {
+ } else if ( !LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) {
if ( p[ 0 ] == '\0' ) {
return( 1 );
}
l += escaped_byte_len * cl;
} else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] )
+ || LDAP_DN_SHOULDESCAPE( p[ 0 ] )
|| ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
|| ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
#ifdef PRETTY_ESCAPE
#endif
#else /* ! PRETTY_ESCAPE */
|| LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
+ || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
|| ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) )
} else {
#ifdef PRETTY_ESCAPE
if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
+ || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
|| ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) {
str[ d++ ] = '\\';
} else {
for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
if ( LDAP_DN_NEEDESCAPE( p[ 0 ] )
+ || LDAP_DN_SHOULDESCAPE( p[ 0 ] )
|| ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
|| ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
l += 2;
for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
+ || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
|| ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) {
str[ d++ ] = '\\';
bv->bv_val = NULL;
#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ARGS, "=> ldap_dn2bv(%u)\n%s%s",
- flags, "", "" );
+ LDAP_LOG ( OPERATION, ARGS, "=> ldap_dn2bv(%u)\n", flags, 0, 0 );
#else
- Debug( LDAP_DEBUG_TRACE, "=> ldap_dn2bv(%u)\n%s%s", flags, "", "" );
+ Debug( LDAP_DEBUG_TRACE, "=> ldap_dn2bv(%u)\n", flags, 0, 0 );
#endif
/*
}
#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS, "<= ldap_dn2bv(%s,%u)=%d\n",
- bv->bv_val, flags, rc );
+ LDAP_LOG ( OPERATION, RESULTS, "<= ldap_dn2bv(%s)=%d %s\n",
+ bv->bv_val, rc, ldap_err2string( rc ) );
#else
- Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2bv(%s,%u)=%d\n",
- bv->bv_val, flags, rc );
+ Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2bv(%s)=%d %s\n",
+ bv->bv_val, rc, ldap_err2string( rc ) );
#endif
return_results:;
if(urls != NULL) {
rc = ldap_url_parselist(&ludlist, urls);
-
} else if(ld == NULL) {
/*
* must want global default returned
rc = LDAP_NO_MEMORY;
}
+ switch (rc) {
+ case LDAP_URL_SUCCESS: /* Success */
+ rc = LDAP_SUCCESS;
+ break;
+
+ case LDAP_URL_ERR_MEM: /* can't allocate memory space */
+ rc = LDAP_NO_MEMORY;
+ break;
+
+ case LDAP_URL_ERR_PARAM: /* parameter is bad */
+ case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */
+ case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */
+ case LDAP_URL_ERR_BADURL: /* URL is bad */
+ case LDAP_URL_ERR_BADHOST: /* host port is bad */
+ case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */
+ case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */
+ case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */
+ case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */
+ rc = LDAP_PARAM_ERROR;
+ break;
+ }
+
if (rc == LDAP_OPT_SUCCESS) {
if (lo->ldo_defludp != NULL)
ldap_free_urllist(lo->ldo_defludp);
int ltrw_w_active;
int ltrw_r_wait;
int ltrw_w_wait;
+#ifdef LDAP_RDWR_DEBUG
+ /* keep track of who has these locks */
+#define MAX_READERS 32
+ ldap_pvt_thread_t ltrw_readers[MAX_READERS];
+ ldap_pvt_thread_t ltrw_writer;
+#endif
};
int
assert( rw->ltrw_r_wait >= 0 );
}
+#ifdef LDAP_RDWR_DEBUG
+ rw->ltrw_readers[rw->ltrw_r_active] = ldap_pvt_thread_self();
+#endif
rw->ltrw_r_active++;
+
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
return 0;
return LDAP_PVT_THREAD_EBUSY;
}
+#ifdef LDAP_RDWR_DEBUG
+ rw->ltrw_readers[rw->ltrw_r_active] = ldap_pvt_thread_self();
+#endif
rw->ltrw_r_active++;
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex );
+#ifdef LDAP_RDWR_DEBUG
+ /* Remove us from the list of readers */
+ { int i, j;
+ ldap_pvt_thread_t self = ldap_pvt_thread_self();
+
+ for (i=0; i<rw->ltrw_r_active;i++)
+ {
+ if (rw->ltrw_readers[i] == self) {
+ for (j=i; j<rw->ltrw_r_active-1; j++)
+ rw->ltrw_readers[j] = rw->ltrw_readers[j+1];
+ rw->ltrw_readers[j] = 0;
+ break;
+ }
+ }
+ }
+#endif
rw->ltrw_r_active--;
assert( rw->ltrw_w_active >= 0 );
assert( rw->ltrw_w_wait >= 0 );
}
+#ifdef LDAP_RDWR_DEBUG
+ rw->ltrw_writer = ldap_pvt_thread_self();
+#endif
rw->ltrw_w_active++;
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
return LDAP_PVT_THREAD_EBUSY;
}
+#ifdef LDAP_RDWR_DEBUG
+ rw->ltrw_writer = ldap_pvt_thread_self();
+#endif
rw->ltrw_w_active++;
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
ldap_pvt_thread_cond_signal( &rw->ltrw_write );
}
+#ifdef LDAP_RDWR_DEBUG
+ rw->ltrw_writer = 0;
+#endif
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
return 0;
assert( rw->ltrw_r_active >= 0 );
assert( rw->ltrw_r_wait >= 0 );
- return(ldap_pvt_thread_rdwr_readers(rw) +
- ldap_pvt_thread_rdwr_writers(rw));
+ return(ldap_pvt_thread_rdwr_readers(rwlock) +
+ ldap_pvt_thread_rdwr_writers(rwlock));
}
#endif /* LDAP_DEBUG */
/* The minimum we can function with */
#define MINIMUM_SEARCH_STACK_DEPTH 8
-/* for the IDL cache */
-#define SLAP_IDL_CACHE 1
-
-#ifdef SLAP_IDL_CACHE
typedef struct bdb_idl_cache_entry_s {
struct berval kstr;
ldap_pvt_thread_rdwr_t idl_entry_rwlock;
struct bdb_idl_cache_entry_s* idl_lru_prev;
struct bdb_idl_cache_entry_s* idl_lru_next;
} bdb_idl_cache_entry_t;
-#endif
/* BDB backend specific entry info */
typedef struct bdb_entry_info {
#define CACHE_ENTRY_NO_KIDS 2
#define CACHE_ENTRY_NOT_LINKED 4
#define CACHE_ENTRY_NO_GRANDKIDS 8
+#define CACHE_ENTRY_LOADING 0x10
/*
* remaining fields require backend cache lock to access
LDAP_LIST_HEAD(pl, slap_op) bi_psearch_list;
ldap_pvt_thread_rdwr_t bi_pslist_rwlock;
LDAP_LIST_HEAD(se, slap_session_entry) bi_session_list;
-#ifdef SLAP_IDL_CACHE
int bi_idl_cache_max_size;
int bi_idl_cache_size;
Avlnode *bi_idl_tree;
bdb_idl_cache_entry_t *bi_idl_lru_tail;
ldap_pvt_thread_rdwr_t bi_idl_tree_rwlock;
ldap_pvt_thread_mutex_t bi_idl_tree_lrulock;
-#endif
};
#define bi_id2entry bi_databases[BDB_ID2ENTRY]
static void bdb_lru_print(Cache *cache);
#endif
+static int bdb_txn_get( Operation *op, DB_ENV *env, DB_TXN **txn );
+
static EntryInfo *
bdb_cache_entryinfo_new( Cache *cache )
{
rc = env->lock_vec(env, locker, tryOnly ? DB_LOCK_NOWAIT : 0,
list, 2, NULL );
- if (rc) {
+ if (rc && !tryOnly) {
#ifdef NEW_LOGGING
LDAP_LOG( CACHE, DETAIL1,
"bdb_cache_entry_db_relock: entry %ld, rw %d, rc %d\n",
rc = LOCK_GET(env, locker, tryOnly ? DB_LOCK_NOWAIT : 0,
&lockobj, db_rw, lock);
- if (rc) {
+ if (rc && !tryOnly) {
#ifdef NEW_LOGGING
LDAP_LOG( CACHE, DETAIL1,
"bdb_cache_entry_db_lock: entry %ld, rw %d, rc %d\n",
} else { \
(cache)->c_lrutail = (ei)->bei_lruprev; \
} \
+ (ei)->bei_lrunext = (ei)->bei_lruprev = NULL; \
} while(0)
#define LRU_ADD( cache, ei ) do { \
Entry *ep = NULL;
int rc = 0;
EntryInfo ei;
- int lru_del = 0;
ei.bei_id = id;
if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
rc = DB_NOTFOUND;
} else {
- rc = bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, *eip, 0, 0, lock );
- /* entry is protected now, we don't need to hold the entryinfo */
+ int load = 0;
+ /* Make sure only one thread tries to load the entry */
+load1: if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) {
+ load = 1;
+ (*eip)->bei_state |= CACHE_ENTRY_LOADING;
+ }
if ( islocked ) {
bdb_cache_entryinfo_unlock( *eip );
islocked = 0;
}
- if ( rc == 0 ) {
- if ( !(*eip)->bei_e ) {
- if (!ep) {
- rc = bdb_id2entry( op->o_bd, tid, id, &ep );
+ rc = bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, *eip, 0, 0, lock );
+ if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
+ rc = DB_NOTFOUND;
+ bdb_cache_entry_db_unlock( bdb->bi_dbenv, lock );
+ } else if ( rc == 0 ) {
+ if ( load ) {
+ DB_TXN *ltid;
+ u_int32_t locker2 = locker;
+
+ /* We don't wrap entire read operations in txn's, but
+ * we need our cache entry lock and any DB page locks
+ * to be associated, in order for deadlock detection
+ * to work properly. So if we need to read from the DB,
+ * we use a long-lived per-thread txn for this step.
+ */
+ if ( !ep && !tid ) {
+ rc = bdb_txn_get( op, bdb->bi_dbenv, <id );
+ if ( ltid )
+ locker2 = TXN_ID( ltid );
+ } else {
+ ltid = tid;
}
- if ( rc == 0 ) {
- bdb_cache_entry_db_relock( bdb->bi_dbenv, locker,
+ /* Give up original read lock, obtain write lock with
+ * (possibly) new locker ID.
+ */
+ if ( rc == 0 ) {
+ rc = bdb_cache_entry_db_relock( bdb->bi_dbenv, locker2,
*eip, 1, 0, lock );
- /* Make sure no other modifier beat us to it */
- if ( (*eip)->bei_e ) {
- bdb_entry_return( ep );
- ep = NULL;
- } else {
- ep->e_private = *eip;
+ }
+ if ( rc == 0 && !ep) {
+ rc = bdb_id2entry( op->o_bd, ltid, id, &ep );
+ }
+ if ( rc == 0 ) {
+ ep->e_private = *eip;
#ifdef BDB_HIER
- bdb_fix_dn( ep, 0 );
+ bdb_fix_dn( ep, 0 );
#endif
- (*eip)->bei_e = ep;
- }
- bdb_cache_entry_db_relock( bdb->bi_dbenv, locker,
+ (*eip)->bei_e = ep;
+ ep = NULL;
+ }
+ (*eip)->bei_state ^= CACHE_ENTRY_LOADING;
+ if ( rc == 0 ) {
+ /* If we succeeded, downgrade back to a readlock. */
+ rc = bdb_cache_entry_db_relock( bdb->bi_dbenv, locker,
*eip, 0, 0, lock );
+ } else {
+ /* Otherwise, release the lock. */
+ bdb_cache_entry_db_unlock( bdb->bi_dbenv, lock );
}
- } else {
- /* If we had the entry already, this item
- * is on the LRU list.
+ if ( locker2 != locker ) {
+ /* If we're using the per-thread txn, release all
+ * of its page locks now.
+ */
+ DB_LOCKREQ list;
+ list.op = DB_LOCK_PUT_ALL;
+ list.obj = NULL;
+ bdb->bi_dbenv->lock_vec( bdb->bi_dbenv, locker2,
+ 0, &list, 1, NULL );
+ }
+ } else if ( !(*eip)->bei_e ) {
+ /* Some other thread is trying to load the entry,
+ * give it a chance to finish.
*/
- lru_del = 1;
+ bdb_cache_entry_db_unlock( bdb->bi_dbenv, lock );
+ ldap_pvt_thread_yield();
+ bdb_cache_entryinfo_lock( *eip );
+ islocked = 1;
+ goto load1;
#ifdef BDB_HIER
+ } else {
+ /* Check for subtree renames
+ */
rc = bdb_fix_dn( (*eip)->bei_e, 1 );
if ( rc ) {
bdb_cache_entry_db_relock( bdb->bi_dbenv,
}
}
}
+ if ( islocked ) {
+ bdb_cache_entryinfo_unlock( *eip );
+ }
+ if ( ep ) {
+ bdb_entry_return( ep );
+ }
if ( rc == 0 ) {
/* set lru mutex */
ldap_pvt_thread_mutex_lock( &bdb->bi_cache.lru_mutex );
- /* if entry is old, remove from old spot on LRU list */
- if ( lru_del ) {
+ /* if entry is on LRU list, remove from old spot */
+ if ( (*eip)->bei_lrunext || (*eip)->bei_lruprev ) {
LRU_DELETE( &bdb->bi_cache, *eip );
} else {
/* if entry is new, bump cache size */
bdb_cache_lru_add( bdb, locker, *eip );
}
- if ( islocked ) {
- bdb_cache_entryinfo_unlock( *eip );
- }
return rc;
}
rc = bdb_entryinfo_add_internal( bdb, &ei, &new );
/* bdb_csn_commit can cause this when adding the database root entry */
- if ( new->bei_e ) bdb_entry_return( new->bei_e );
+ if ( new->bei_e ) {
+ new->bei_e->e_private = NULL;
+ bdb_entry_return( new->bei_e );
+ }
new->bei_e = e;
e->e_private = new;
new->bei_state = CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
avl_free( cache->c_dntree.bei_kids, NULL );
avl_free( cache->c_idtree, bdb_entryinfo_release );
+ for (;cache->c_eifree;cache->c_eifree = cache->c_lruhead) {
+ cache->c_lruhead = cache->c_eifree->bei_lrunext;
+ bdb_cache_entryinfo_destroy(cache->c_eifree);
+ }
cache->c_lruhead = NULL;
cache->c_lrutail = NULL;
}
#endif
+static void
+bdb_txn_free( void *key, void *data )
+{
+ DB_TXN *txn = data;
+ TXN_ABORT( txn );
+}
+
+/* Obtain a long-lived transaction for the current thread */
+static int
+bdb_txn_get( Operation *op, DB_ENV *env, DB_TXN **txn )
+{
+ int i, rc, lockid;
+ void *ctx, *data;
+
+ /* If no op was provided, try to find the ctx anyway... */
+ if ( op ) {
+ ctx = op->o_threadctx;
+ } else {
+ ctx = ldap_pvt_thread_pool_context();
+ }
+
+ /* Shouldn't happen unless we're single-threaded */
+ if ( !ctx ) {
+ *txn = NULL;
+ return 0;
+ }
+
+ if ( ldap_pvt_thread_pool_getkey( ctx, ((char *)env)+1, &data, NULL ) ) {
+ for ( i=0, rc=1; rc != 0 && i<4; i++ ) {
+ rc = TXN_BEGIN( env, NULL, txn, 0 );
+ if (rc) ldap_pvt_thread_yield();
+ }
+ if ( rc != 0) {
+ return rc;
+ }
+ if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, ((char *)env)+1,
+ *txn, bdb_txn_free ) ) ) {
+ TXN_ABORT( *txn );
+#ifdef NEW_LOGGING
+ LDAP_LOG( BACK_BDB, ERR, "bdb_txn_get: err %s(%d)\n",
+ db_strerror(rc), rc, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY, "bdb_txn_get: err %s(%d)\n",
+ db_strerror(rc), rc, 0 );
+#endif
+
+ return rc;
+ }
+ } else {
+ *txn = data;
+ }
+ return 0;
+}
+
#ifdef BDB_REUSE_LOCKERS
static void
bdb_locker_id_free( void *key, void *data )
"bdb_locker_id_free: %d err %s(%d)\n",
lockid, db_strerror(rc), rc );
#endif
- memset( &lr, 0, sizeof(lr) );
-
/* release all locks held by this locker. */
lr.op = DB_LOCK_PUT_ALL;
+ lr.obj = NULL;
env->lock_vec( env, lockid, 0, &lr, 1, NULL );
XLOCK_ID_FREE( env, lockid );
}
bdb->bi_search_stack_depth = MINIMUM_SEARCH_STACK_DEPTH;
}
-#ifdef SLAP_IDL_CACHE
/* size of the IDL cache in entries */
} else if ( strcasecmp( argv[0], "idlcachesize" ) == 0 ) {
if ( argc < 2 ) {
}
if ( !( slapMode & SLAP_TOOL_MODE ) )
bdb->bi_idl_cache_max_size = atoi( argv[1] );
-#endif
-
} else if ( strcasecmp( argv[0], "sessionlog" ) == 0 ) {
int se_id = 0, se_size = 0;
struct slap_session_entry *sent;
)
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- struct berval ctxcsn_ndn = BER_BVNULL;
EntryInfo *ctxcsn_ei = NULL;
DB_LOCK ctxcsn_lock;
struct berval max_committed_csn;
size_t textlen = sizeof textbuf;
EntryInfo *eip = NULL;
+ assert( !BER_BVISNULL( &op->o_bd->be_context_csn ) );
+
if ( ei ) {
e = ei->bei_e;
}
- build_new_dn( &ctxcsn_ndn, &op->o_bd->be_nsuffix[0],
- (struct berval *)&slap_ldapsync_cn_bv, op->o_tmpmemctx );
-
- rc = bdb_dn2entry( op, tid, &ctxcsn_ndn, &ctxcsn_ei,
+ rc = bdb_dn2entry( op, tid, &op->o_bd->be_context_csn, &ctxcsn_ei,
1, locker, &ctxcsn_lock );
*ctxcsn_e = ctxcsn_ei->bei_e;
- op->o_tmpfree( ctxcsn_ndn.bv_val, op->o_tmpmemctx );
-
slap_get_commit_csn( op, &max_committed_csn );
if ( max_committed_csn.bv_val == NULL ) {
if ( !*ctxcsn_e ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "context csn not present";
- ch_free( max_committed_csn.bv_val );
+ op->o_tmpfree( max_committed_csn.bv_val, op->o_tmpmemctx );
return BDB_CSN_ABORT;
} else {
Modifications mod;
dummy = **ctxcsn_e;
ret = bdb_modify_internal( op, tid, &mod, &dummy,
&rs->sr_text, textbuf, textlen );
- ch_free( max_committed_csn.bv_val );
+ op->o_tmpfree( max_committed_csn.bv_val, op->o_tmpmemctx );
if ( ret != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
}
*ctxcsn_e = slap_create_context_csn_entry( op->o_bd, &max_committed_csn );
- ch_free( max_committed_csn.bv_val );
+ op->o_tmpfree( max_committed_csn.bv_val, op->o_tmpmemctx );
(*ctxcsn_e)->e_id = ctxcsn_id;
*ctxcsn_added = 1;
)
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- struct berval ctxcsn_ndn = BER_BVNULL;
struct berval csn = BER_BVNULL;
EntryInfo *ctxcsn_ei = NULL;
EntryInfo *suffix_ei = NULL;
if ( op->o_sync_mode != SLAP_SYNC_NONE &&
!LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) {
char substr[67];
+ struct berval ctxcsn_ndn = BER_BVNULL;
struct berval bv;
LDAP_STAILQ_FOREACH( si, &op->o_bd->be_syncinfo, si_next ) {
sprintf( substr, "cn=syncrepl%ld", si->si_rid );
ber_str2bv( substr, 0, 0, &bv );
- build_new_dn( &ctxcsn_ndn, &op->o_bd->be_nsuffix[0], &bv, NULL );
+ build_new_dn( &ctxcsn_ndn, &op->o_bd->be_nsuffix[0], &bv, op->o_tmpmemctx );
consumer_ctxcsn_retry :
rs->sr_err = bdb_dn2entry( op, NULL, &ctxcsn_ndn, &ctxcsn_ei,
0, locker, ctxcsn_lock );
switch(rs->sr_err) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto consumer_ctxcsn_retry;
case 0:
- ch_free( ctxcsn_ndn.bv_val );
+ op->o_tmpfree( ctxcsn_ndn.bv_val, op->o_tmpmemctx );
ctxcsn_ndn.bv_val = NULL;
if ( ctxcsn_ei ) {
ctxcsn_e = ctxcsn_ei->bei_e;
}
break;
- case LDAP_BUSY:
- goto done;
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto consumer_ctxcsn_retry;
case DB_NOTFOUND:
- rs->sr_err = LDAP_OTHER;
- goto done;
default:
rs->sr_err = LDAP_OTHER;
+ case LDAP_BUSY:
+ op->o_tmpfree( ctxcsn_ndn.bv_val, op->o_tmpmemctx );
+ ctxcsn_ndn.bv_val = NULL;
goto done;
}
}
} else if ( op->o_sync_mode != SLAP_SYNC_NONE &&
LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) {
- build_new_dn( &ctxcsn_ndn, &op->o_bd->be_nsuffix[0],
- (struct berval *)&slap_ldapsync_cn_bv, NULL );
provider_ctxcsn_retry :
- rs->sr_err = bdb_dn2entry( op, NULL, &ctxcsn_ndn, &ctxcsn_ei,
+ rs->sr_err = bdb_dn2entry( op, NULL, &op->o_bd->be_context_csn, &ctxcsn_ei,
0, locker, ctxcsn_lock );
switch(rs->sr_err) {
case 0:
goto done;
}
- rs->sr_err = bdb_dn2entry( op, NULL, &ctxcsn_ndn, &ctxcsn_ei,
+ rs->sr_err = bdb_dn2entry( op, NULL, &op->o_bd->be_context_csn, &ctxcsn_ei,
0, ctxcsn_locker, ctxcsn_lock );
- ch_free( ctxcsn_ndn.bv_val );
- ctxcsn_ndn.bv_val = NULL;
if ( ctxcsn_ei ) {
ctxcsn_e = ctxcsn_ei->bei_e;
TXN_ABORT( ltid );
}
- if ( ctxcsn_ndn.bv_val != NULL )
- ch_free( ctxcsn_ndn.bv_val );
-
return rs->sr_err;
}
((char *)key.data)[0] = DN_ONE_PREFIX;
AC_MEMCPY( &((char *)key.data)[1], e->e_nname.bv_val, key.size - 1 );
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
rc = bdb_idl_cache_get( bdb, db, &key, NULL );
if ( rc != LDAP_NO_SUCH_OBJECT ) {
return rc;
}
}
-#endif
/* we actually could do a empty get... */
DBTzero( &data );
data.data = &id;
db->put( db, txn, &key, &data, DB_NODUPDATA );
}
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
bdb_idl_cache_del( bdb, db, &key );
}
-#endif
data.data = d;
data.size = sizeof(diskNode) + rlen + nrlen;
data.flags = DB_DBT_USERMEM;
data.dlen = data.size;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
bdb_idl_cache_del( bdb, db, &key );
}
-#endif
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
key.data = &e->e_id;
key.flags = DB_DBT_USERMEM;
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
rc = bdb_idl_cache_get( bdb, db, &key, NULL );
if ( rc != LDAP_NO_SUCH_OBJECT ) {
return rc;
}
}
-#endif
DBTzero(&data);
data.data = &d;
data.ulen = sizeof(d);
struct dn2id_cookie *cx
)
{
-#ifdef SLAP_IDL_CACHE
if ( cx->bdb->bi_idl_cache_size ) {
cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);
if ( cx->rc == DB_NOTFOUND ) {
goto gotit;
}
}
-#endif
BDB_IDL_ZERO( cx->tmp );
if ( !cx->ei ) {
}
saveit:
-#ifdef SLAP_IDL_CACHE
if ( cx->bdb->bi_idl_cache_max_size ) {
bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );
}
-#endif
;
gotit:
if ( !BDB_IDL_IS_ZERO( cx->tmp )) {
SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
if ( slapMode == SLAP_SERVER_MODE ) {
+ /* If not in our cache, just free it */
+ if ( !e->e_private ) {
+ return bdb_entry_return( e );
+ }
/* free entry and reader or writer lock */
if ( o ) {
boi = (struct bdb_op_info *)o->o_private;
#define IDL_CMP(x,y) ( x < y ? -1 : ( x > y ? 1 : 0 ) )
-#ifdef SLAP_IDL_CACHE
#define IDL_LRU_DELETE( bdb, e ) do { \
if ( e->idl_lru_prev != NULL ) { \
e->idl_lru_prev->idl_lru_next = e->idl_lru_next; \
if ((rc = idl1->kstr.bv_len - idl2->kstr.bv_len )) return rc;
return ( memcmp ( idl1->kstr.bv_val, idl2->kstr.bv_val , idl1->kstr.bv_len ) );
}
-#endif
#if IDL_DEBUG > 0
static void idl_check( ID *ids )
}
}
-#ifdef SLAP_IDL_CACHE
-
/* Find a db/key pair in the IDL cache. If ids is non-NULL,
* copy the cached IDL into it, otherwise just return the status.
*/
}
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
}
-#endif
int
bdb_idl_fetch_key(
assert( ids != NULL );
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
rc = bdb_idl_cache_get( bdb, db, key, ids );
if ( rc != LDAP_NO_SUCH_OBJECT ) return rc;
}
-#endif
DBTzero( &data );
}
if( rc == DB_NOTFOUND ) {
-#ifndef SLAP_IDL_CACHE
return rc;
-#endif
} else if( rc != 0 ) {
#ifdef NEW_LOGGING
return -1;
}
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_max_size ) {
bdb_idl_cache_put( bdb, db, key, ids, rc );
}
-#endif
return rc;
}
assert( id != NOID );
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
bdb_idl_cache_del( bdb, db, key );
}
-#endif
DBTzero( &data );
data.size = sizeof( ID );
}
assert( id != NOID );
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_max_size ) {
bdb_idl_cache_del( bdb, db, key );
}
-#endif
DBTzero( &data );
data.data = &tmp;
LDAP_LOG( BACK_BDB, ENTRY, "bdb_db_init", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "bdb_db_init: Initializing BDB database\n",
- 0, 0, 0 );
+ "bdb_db_init: Initializing %s database\n",
+ be->bd_info->bi_type, 0, 0 );
#endif
/* allocate backend-database-specific stuff */
bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall );
bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect );
-#ifdef SLAP_IDL_CACHE
+ /* One long-lived TXN per thread, two TXNs per write op */
+ bdb->bi_dbenv->set_tx_max( bdb->bi_dbenv, connection_pool_max * 3 );
+
if ( bdb->bi_idl_cache_max_size ) {
bdb->bi_idl_tree = NULL;
ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
bdb->bi_idl_cache_size = 0;
}
-#endif
#ifdef BDB_SUBDIRS
{
return rc;
}
- bdb->bi_dbenv->lock_id(bdb->bi_dbenv, &bdb->bi_cache.c_locker);
+ XLOCK_ID(bdb->bi_dbenv, &bdb->bi_cache.c_locker);
/* <insert> open (and create) index databases */
return 0;
int rc;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
struct bdb_db_info *db;
-#ifdef SLAP_IDL_CACHE
bdb_idl_cache_entry_t *entry, *next_entry;
-#endif
while( bdb->bi_ndatabases-- ) {
db = bdb->bi_databases[bdb->bi_ndatabases];
bdb_cache_release_all (&bdb->bi_cache);
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_max_size ) {
ldap_pvt_thread_rdwr_wlock ( &bdb->bi_idl_tree_rwlock );
avl_free( bdb->bi_idl_tree, NULL );
}
ldap_pvt_thread_rdwr_wunlock ( &bdb->bi_idl_tree_rwlock );
}
-#endif
+
+ XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker);
return 0;
}
ldap_pvt_thread_rdwr_destroy ( &bdb->bi_pslist_rwlock );
ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
ldap_pvt_thread_mutex_destroy( &bdb->bi_database_mutex );
-#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_max_size ) {
ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
}
-#endif
ch_free( bdb );
be->be_private = NULL;
rc = entry_schema_check( op->o_bd, e, save_attrs, text, textbuf, textlen );
if ( rc != LDAP_SUCCESS || op->o_noop ) {
attrs_free( e->e_attrs );
+ /* clear the indexing flags */
+ for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
+ ap->a_flags = 0;
+ }
e->e_attrs = save_attrs;
if ( rc != LDAP_SUCCESS ) {
size_t textlen = sizeof textbuf;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo;
- Entry dummy;
+ Entry dummy = {0};
u_int32_t locker = 0;
DB_LOCK lock;
if( 0 ) {
retry: /* transaction retry */
+ if ( dummy.e_attrs ) {
+ attrs_free( dummy.e_attrs );
+ dummy.e_attrs = NULL;
+ }
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
e = NULL;
if ( (rs->sr_err == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
rs->sr_err = opinfo.boi_err;
}
+ /* Only free attrs if they were dup'd. */
+ if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
- attrs_free( dummy.e_attrs );
- dummy.e_attrs = NULL;
goto retry;
}
goto return_results;
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
- attrs_free( dummy.e_attrs );
- dummy.e_attrs = NULL;
goto retry;
}
rs->sr_text = "entry update failed";
case BDB_CSN_ABORT :
goto return_results;
case BDB_CSN_RETRY :
- attrs_free( dummy.e_attrs );
- dummy.e_attrs = NULL;
goto retry;
}
}
postread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
- if( slap_read_controls( op, rs, e,
+ if( slap_read_controls( op, rs, &dummy,
&slap_post_read_bv, postread_ctrl ) )
{
#ifdef NEW_LOGGING
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
- attrs_free( dummy.e_attrs );
- dummy.e_attrs = NULL;
goto retry;
}
+ dummy.e_attrs = NULL;
if ( LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) {
if ( ctxcsn_added ) {
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
+ if( dummy.e_attrs ) {
+ attrs_free( dummy.e_attrs );
+ }
send_ldap_result( op, rs );
if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) {
size_t textlen = sizeof textbuf;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo;
- Entry dummy, *save;
+ Entry dummy = {0};
ID id;
if( 0 ) {
retry: /* transaction retry */
+ if ( dummy.e_attrs ) {
+ attrs_free( dummy.e_attrs );
+ dummy.e_attrs = NULL;
+ }
if (e != NULL) {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
e = NULL;
goto return_results;
}
- dummy = *e;
- save = e;
- e = &dummy;
-
- /* delete old one */
+ /* delete old DN */
rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
if ( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
goto return_results;
}
- /* Binary format uses a single contiguous block, cannot
- * free individual fields. But if a previous modrdn has
- * already happened, must free the names. The frees are
- * done in bdb_cache_modrdn().
- */
- if( e->e_nname.bv_val < e->e_bv.bv_val ||
- e->e_nname.bv_val > e->e_bv.bv_val + e->e_bv.bv_len )
- {
- e->e_name.bv_val = NULL;
- e->e_nname.bv_val = NULL;
- }
- e->e_name = new_dn;
- e->e_nname = new_ndn;
- new_dn.bv_val = NULL;
- new_ndn.bv_val = NULL;
+ /* copy the entry, then override some fields */
+ dummy = *e;
+ dummy.e_name = new_dn;
+ dummy.e_nname = new_ndn;
+ dummy.e_attrs = NULL;
- /* add new one */
- rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, e );
+ /* add new DN */
+ rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, &dummy );
if ( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
goto return_results;
}
+ dummy.e_attrs = e->e_attrs;
+
if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop && !op->o_no_psearch ) {
ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock );
LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
- rc = bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
+ rc = bdb_psearch( op, rs, ps_list, &dummy, LDAP_PSEARCH_BY_PREMODIFY );
if ( rc ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock );
}
+
/* modify entry */
- rs->sr_err = bdb_modify_internal( op, lt2, &mod[0], e,
+ rs->sr_err = bdb_modify_internal( op, lt2, &mod[0], &dummy,
&rs->sr_text, textbuf, textlen );
if( rs->sr_err != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
rs->sr_err = opinfo.boi_err;
}
+ if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
}
/* id2entry index */
- rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, e );
+ rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
if ( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
postread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
- if( slap_read_controls( op, rs, e,
+ if( slap_read_controls( op, rs, &dummy,
&slap_post_read_bv, postread_ctrl ) )
{
#ifdef NEW_LOGGING
}
} else {
- rc = bdb_cache_modrdn( save, &op->orr_nnewrdn, e, neip,
+ rc = bdb_cache_modrdn( e, &op->orr_nnewrdn, &dummy, neip,
bdb->bi_dbenv, locker, &lock );
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
+ dummy.e_attrs = NULL;
+ new_dn.bv_val = NULL;
+ new_ndn.bv_val = NULL;
if ( LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) {
if ( ctxcsn_added ) {
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
+ if ( dummy.e_attrs ) {
+ attrs_free( dummy.e_attrs );
+ }
send_ldap_result( op, rs );
if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) {
assert( e );
+ /* NOTE: this should never happen, but it actually happens
+ * when using back-relay; until we find a better way to
+ * preserve entry's private information while rewriting it,
+ * let's disable the hasSubordinate feature for back-relay.
+ */
+ if ( BEI( e ) == NULL ) {
+ return LDAP_OTHER;
+ }
+
retry:
+ /* FIXME: we can no longer assume the entry's e_private
+ * field is correctly populated; so we need to reacquire
+ * it with reader lock */
rc = bdb_cache_children( op, NULL, e );
switch( rc ) {
/*
* idl.c
*/
-#ifdef SLAP_IDL_CACHE
#define bdb_idl_cache_get BDB_SYMBOL(idl_cache_get)
#define bdb_idl_cache_put BDB_SYMBOL(idl_cache_put)
struct bdb_info *bdb,
DB *db,
DBT *key );
-#endif
#define bdb_idl_first BDB_SYMBOL(idl_first)
#define bdb_idl_next BDB_SYMBOL(idl_next)
ID cursora, ida, cursoro, ido, *subscop2;
Entry *matched, *a;
EntryInfo *ei;
- struct berval bv_alias = { sizeof("alias")-1, "alias" };
+ struct berval bv_alias = BER_BVC( "alias" );
AttributeAssertion aa_alias;
Filter af;
DB_LOCK locka, lockr;
ida = bdb_idl_next(curscop, &cursora))
{
ei = NULL;
+retry1:
rs->sr_err = bdb_cache_find_id(op, NULL,
ida, &ei, 0, locker, &lockr );
if (rs->sr_err != LDAP_SUCCESS) {
+ if ( rs->sr_err == DB_LOCK_DEADLOCK ||
+ rs->sr_err == DB_LOCK_NOTGRANTED ) goto retry1;
continue;
}
a = ei->bei_e;
* Set the name so that the scope's IDL can be retrieved.
*/
ei = NULL;
+sameido:
rs->sr_err = bdb_cache_find_id(op, NULL, ido, &ei,
0, locker, &locka );
- if ( rs->sr_err != LDAP_SUCCESS ) goto nextido;
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ if ( rs->sr_err == DB_LOCK_DEADLOCK ||
+ rs->sr_err == DB_LOCK_NOTGRANTED )
+ goto sameido;
+ goto nextido;
+ }
e = ei->bei_e;
}
return rs->sr_err;
null_attr.an_desc = NULL;
null_attr.an_oc = NULL;
null_attr.an_oc_exclude = 0;
- null_attr.an_name.bv_len = 0;
- null_attr.an_name.bv_val = NULL;
+ BER_BVZERO( &null_attr.an_name );
for( num_ctrls = 0; num_ctrls < SLAP_MAX_RESPONSE_CONTROLS; num_ctrls++ ) {
ctrls[num_ctrls] = NULL;
attrs[0].an_desc = NULL;
attrs[0].an_oc = NULL;
attrs[0].an_oc_exclude = 0;
- attrs[0].an_name.bv_len = 0;
- attrs[0].an_name.bv_val = NULL;
+ BER_BVZERO( &attrs[0].an_name );
}
manageDSAit = get_manageDSAit( sop );
ei_root.bei_parent = &ei_root;
e_root.e_private = &ei_root;
e_root.e_id = 0;
- e_root.e_nname.bv_val="";
- e_root.e_name.bv_val="";
+ BER_BVSTR( &e_root.e_nname, "" );
+ BER_BVSTR( &e_root.e_name, "" );
ei = &ei_root;
rs->sr_err = LDAP_SUCCESS;
} else {
{
if( !get_manageDSAit(op) && !get_domainScope(op) ) {
/* match referral objects */
- struct berval bv_ref = { sizeof("referral")-1, "referral" };
+ struct berval bv_ref = BER_BVC( "referral" );
rf.f_choice = LDAP_FILTER_EQUALITY;
rf.f_ava = &aa_ref;
rf.f_av_desc = slap_schema.si_ad_objectClass;
#ifdef BDB_SUBENTRIES
if( get_subentries_visibility( op ) ) {
- struct berval bv_subentry = { sizeof("SUBENTRY")-1, "SUBENTRY" };
+ struct berval bv_subentry = BER_BVC( "SUBENTRY" );
sf.f_choice = LDAP_FILTER_EQUALITY;
sf.f_ava = &aa_subentry;
sf.f_av_desc = slap_schema.si_ad_objectClass;
lastid ? *lastid : 0, rs->sr_nentries, NULL );
#endif
- ctrl.ldctl_value.bv_val = NULL;
+ BER_BVZERO( &ctrl.ldctl_value );
ctrls[0] = &ctrl;
ctrls[1] = NULL;
} else {
respcookie = ( PagedResultsCookie )0;
- cookie.bv_val = "";
- cookie.bv_len = 0;
+ BER_BVSTR( &cookie, "" );
}
op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
if ( csne->ce_state == SLAP_CSN_PENDING ) break;
}
- if ( committed_csne ) ber_dupbv( csn, committed_csne->ce_csn );
+ if ( committed_csne ) ber_dupbv_x( csn, committed_csne->ce_csn, op->o_tmpmemctx );
ldap_pvt_thread_mutex_unlock( &op->o_bd->be_pcl_mutex );
}
int i, j;
for ( i=0; a != NULL; a = a->a_next, i++ ) {
- struct berval *bv, value;
+ struct berval *bv, assertedValue;
if ( mra->ma_desc ) {
if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
continue;
}
- value = mra->ma_value;
+ assertedValue = mra->ma_value;
} else {
int rc;
const char *text = NULL;
/* check if matching is appropriate */
- if ( strcmp( mra->ma_rule->smr_syntax->ssyn_oid,
- a->a_desc->ad_type->sat_syntax->ssyn_oid ) != 0 ) {
+ if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) {
continue;
}
rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
- &mra->ma_value, &value, &text, op->o_tmpmemctx );
+ &mra->ma_value, &assertedValue, &text, op->o_tmpmemctx );
if( rc != LDAP_SUCCESS ) continue;
}
- bv = a->a_nvals;
+ /* check match */
+ if (mra->ma_rule == a->a_desc->ad_type->sat_equality) {
+ bv = a->a_nvals;
+ } else {
+ bv = a->a_vals;
+ }
+
for ( j = 0; bv->bv_val != NULL; bv++, j++ ) {
int ret;
int rc;
const char *text;
rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
- bv, &value, &text );
+ bv, &assertedValue, &text );
if( rc != LDAP_SUCCESS ) {
return rc;
}
return LDAP_SUCCESS;
}
+