OpenLDAP 2.4 Change Log
OpenLDAP 2.4.18 Engineering
+ Fixed slapd dncachesize behavior to unlimited by default (ITS#6222)
Fixed slapd incorrectly applying writetimeout when not set (ITS#6220)
Fixed slapd subordinate needs a suffix (ITS#6216)
Fixed slapd tools to properly close database (ITS#6214)
will return a different result.
.TP
.BI dncachesize \ <integer>
-Specify the maximum number of DNs in the in-memory DN cache. The
-default is twice the \fBcachesize\fP. Ideally this cache should be
+Specify the maximum number of DNs in the in-memory DN cache.
+Ideally this cache should be
large enough to contain the DNs of every entry in the database. If
set to a smaller value than the \fBcachesize\fP it will be silently
-increased to equal the \fBcachesize\fP.
+increased to equal the \fBcachesize\fP. The default value is 0 which
+means unlimited, i.e. the DN cache will grow without bound.
It should be noted that the \fBDN cache\fP is allowed to temporarily
grow beyond the configured size. It does this if many entries are
EntryInfo *c_lruhead; /* lru - add accessed entries here */
EntryInfo *c_lrutail; /* lru - rem lru entries from here */
EntryInfo c_dntree;
- unsigned c_maxsize;
- int c_cursize;
- unsigned c_minfree;
- unsigned c_eimax;
- int c_eiused; /* EntryInfo's in use */
- int c_leaves; /* EntryInfo leaf nodes */
+ ID c_maxsize;
+ ID c_cursize;
+ ID c_minfree;
+ ID c_eimax;
+ ID c_eiused; /* EntryInfo's in use */
+ ID c_leaves; /* EntryInfo leaf nodes */
int c_purging;
DB_TXN *c_txn; /* used by lru cleaner */
ldap_pvt_thread_rdwr_t c_rwlock;
ID bi_lastid;
ldap_pvt_thread_mutex_t bi_lastid_mutex;
- unsigned bi_idl_cache_max_size;
- int bi_idl_cache_size;
+ ID bi_idl_cache_max_size;
+ ID bi_idl_cache_size;
Avlnode *bi_idl_tree;
bdb_idl_cache_entry_t *bi_idl_lru_head;
bdb_idl_cache_entry_t *bi_idl_lru_tail;
{
DB_LOCK lock, *lockp;
EntryInfo *elru, *elnext = NULL;
- int count, islocked, eimax;
- int efree = 0, eifree = 0, eicount, ecount;
+ int islocked;
+ ID eicount, ecount;
+ ID count, efree, eifree = 0;
#ifdef LDAP_DEBUG
int iter;
#endif
/* Wait for the mutex; we're the only one trying to purge. */
ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
+ if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
+ efree = bdb->bi_cache.c_cursize - bdb->bi_cache.c_maxsize;
+ efree += bdb->bi_cache.c_minfree;
+ } else {
+ efree = 0;
+ }
+
/* maximum number of EntryInfo leaves to cache. In slapcat
* we always free all leaf nodes.
*/
- if ( slapMode & SLAP_TOOL_READONLY )
- eimax = 0;
- else
- eimax = bdb->bi_cache.c_eimax;
-
- efree = bdb->bi_cache.c_cursize - bdb->bi_cache.c_maxsize;
- if ( efree < 1 )
- efree = 0;
- else
- efree += bdb->bi_cache.c_minfree;
- if ( bdb->bi_cache.c_leaves > eimax ) {
+ if ( slapMode & SLAP_TOOL_READONLY ) {
+ eifree = bdb->bi_cache.c_leaves;
+ } else if ( bdb->bi_cache.c_eimax &&
+ bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
eifree = bdb->bi_cache.c_minfree * 10;
- if ( eifree >= eimax )
- eifree = eimax / 2;
+ if ( eifree >= bdb->bi_cache.c_leaves )
+ eifree /= 2;
}
if ( !efree && !eifree ) {
int purge = 0;
if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ||
- bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
+ ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax )) {
ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
if ( !bdb->bi_cache.c_purging ) {
if ( load && !( flag & ID_NOCACHE )) {
purge = 1;
bdb->bi_cache.c_purging = 1;
}
- } else if ( bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
+ } else if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
purge = 1;
bdb->bi_cache.c_purging = 1;
}
"DESC 'Directory for database content' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
- { "cachefree", "size", 2, 2, 0, ARG_UINT|ARG_OFFSET,
+ { "cachefree", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_cache.c_minfree),
"( OLcfgDbAt:1.11 NAME 'olcDbCacheFree' "
"DESC 'Number of extra entries to free when max is reached' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
- { "cachesize", "size", 2, 2, 0, ARG_UINT|ARG_OFFSET,
+ { "cachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_cache.c_maxsize),
"( OLcfgDbAt:1.1 NAME 'olcDbCacheSize' "
"DESC 'Entry cache size in entries' "
"( OLcfgDbAt:1.5 NAME 'olcDbDirtyRead' "
"DESC 'Allow reads of uncommitted data' "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
- { "dncachesize", "size", 2, 2, 0, ARG_UINT|ARG_OFFSET,
+ { "dncachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_cache.c_eimax),
"( OLcfgDbAt:1.12 NAME 'olcDbDNcacheSize' "
"DESC 'DN cache size' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
- { "idlcachesize", "size", 2, 2, 0, ARG_UINT|ARG_OFFSET,
+ { "idlcachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_idl_cache_max_size),
"( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
"DESC 'IDL cache size in IDLs' "
}
bdb->bi_idl_lru_head = ee;
- if ( ++bdb->bi_idl_cache_size > bdb->bi_idl_cache_max_size ) {
+ if ( bdb->bi_idl_cache_size >= bdb->bi_idl_cache_max_size ) {
int i;
ee = bdb->bi_idl_lru_tail;
for ( i = 0; ee != NULL && i < 10; i++, ee = eprev ) {
assert( bdb->bi_idl_lru_tail != NULL
|| bdb->bi_idl_lru_head == NULL );
}
+ bdb->bi_idl_cache_size++;
ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
}
}
#endif
- /* Default dncache to 2x entrycache */
- if ( bdb->bi_cache.c_maxsize && !bdb->bi_cache.c_eimax ) {
- bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize * 2;
- }
-
- /* dncache must be >= entrycache */
- if ( bdb->bi_cache.c_eimax < bdb->bi_cache.c_maxsize ) {
+ /* dncache defaults to 0 == unlimited
+ * must be >= entrycache
+ */
+ if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_eimax < bdb->bi_cache.c_maxsize ) {
bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize;
}
a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
assert( a != NULL );
bv.bv_val = buf;
- bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_cursize );
+ bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_cursize );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
a = attr_find( e->e_attrs, ad_olmBDBDNCache );
assert( a != NULL );
- bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_eiused );
+ bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_eiused );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
assert( a != NULL );
- bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_idl_cache_size );
+ bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_idl_cache_size );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
#ifdef BDB_MONITOR_IDX
int rc, arg_user, arg_type, arg_syn, iarg;
unsigned uiarg;
long larg;
+ unsigned long ularg;
ber_len_t barg;
if(Conf->arg_type == ARG_IGNORED) {
return(ARG_BAD_CONF);
}
break;
+ case ARG_ULONG:
+ if ( lutil_atoulx( &ularg, c->argv[1], 0 ) != 0 ) {
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "<%s> unable to parse \"%s\" as unsigned long",
+ c->argv[0], c->argv[1] );
+ Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
+ c->log, c->cr_msg, 0);
+ return(ARG_BAD_CONF);
+ }
+ break;
case ARG_BER_LEN_T: {
unsigned long l;
if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
case ARG_INT: c->value_int = iarg; break;
case ARG_UINT: c->value_uint = uiarg; break;
case ARG_LONG: c->value_long = larg; break;
+ case ARG_ULONG: c->value_ulong = ularg; break;
case ARG_BER_LEN_T: c->value_ber_t = barg; break;
}
}
case ARG_INT: *(int*)ptr = c->value_int; break;
case ARG_UINT: *(unsigned*)ptr = c->value_uint; break;
case ARG_LONG: *(long*)ptr = c->value_long; break;
+ case ARG_ULONG: *(unsigned long*)ptr = c->value_ulong; break;
case ARG_BER_LEN_T: *(ber_len_t*)ptr = c->value_ber_t; break;
case ARG_STRING: {
char *cc = *(char**)ptr;
case ARG_INT: c->value_int = *(int *)ptr; break;
case ARG_UINT: c->value_uint = *(unsigned *)ptr; break;
case ARG_LONG: c->value_long = *(long *)ptr; break;
+ case ARG_ULONG: c->value_ulong = *(unsigned long *)ptr; break;
case ARG_BER_LEN_T: c->value_ber_t = *(ber_len_t *)ptr; break;
case ARG_STRING:
if ( *(char **)ptr )
case ARG_INT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%d", c->value_int); break;
case ARG_UINT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%u", c->value_uint); break;
case ARG_LONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_long); break;
+ case ARG_ULONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%lu", c->value_ulong); break;
case ARG_BER_LEN_T: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_ber_t); break;
case ARG_ON_OFF: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%s",
c->value_int ? "TRUE" : "FALSE"); break;
#define ARG_DN 0x00007000
#define ARG_UINT 0x00008000
#define ARG_ATDESC 0x00009000
+#define ARG_ULONG 0x0000a000
#define ARGS_SYNTAX 0xffff0000
#define ARG_IGNORED 0x00080000
int v_int;
unsigned v_uint;
long v_long;
+ unsigned long v_ulong;
ber_len_t v_ber_t;
char *v_string;
struct berval v_bv;
#define value_int values.v_int
#define value_uint values.v_uint
#define value_long values.v_long
+#define value_ulong values.v_ulong
#define value_ber_t values.v_ber_t
#define value_string values.v_string
#define value_bv values.v_bv