X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fconfig.c;h=2cfa96ac65faca23c8ece93b654ad408941aa967;hb=6018fe9671dcbb90e3845bc14851858c5d9fdf2a;hp=82169471e98f9e1a5f49a2e1806cefd140d93358;hpb=ee2c377d08b33ac5c1d83d7dfec2e49c484b4845;p=openldap diff --git a/servers/slapd/back-bdb/config.c b/servers/slapd/back-bdb/config.c index 82169471e9..2cfa96ac65 100644 --- a/servers/slapd/back-bdb/config.c +++ b/servers/slapd/back-bdb/config.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2005 The OpenLDAP Foundation. + * Copyright 2000-2011 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -19,6 +19,7 @@ #include #include #include +#include #include "back-bdb.h" @@ -31,7 +32,7 @@ # define SLAP_BDB_ALLOW_DIRTY_READ #endif -#define bdb_cf_gen BDB_SYMBOL(cf_gen) +#define bdb_cf_gen BDB_SYMBOL(cf_gen) #define bdb_cf_cleanup BDB_SYMBOL(cf_cleanup) #define bdb_checkpoint BDB_SYMBOL(checkpoint) #define bdb_online_index BDB_SYMBOL(online_index) @@ -41,12 +42,17 @@ static ConfigDriver bdb_cf_gen; enum { BDB_CHKPT = 1, BDB_CONFIG, + BDB_CRYPTFILE, + BDB_CRYPTKEY, BDB_DIRECTORY, BDB_NOSYNC, BDB_DIRTYR, BDB_INDEX, BDB_LOCKD, - BDB_SSTACK + BDB_SSTACK, + BDB_MODE, + BDB_PGSIZE, + BDB_CHECKSUM }; static ConfigTable bdbcfg[] = { @@ -55,7 +61,12 @@ static ConfigTable bdbcfg[] = { "DESC 'Directory for database content' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, - { "cachesize", "size", 2, 2, 0, ARG_INT|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_ULONG|ARG_OFFSET, (void *)offsetof(struct bdb_info, bi_cache.c_maxsize), "( OLcfgDbAt:1.1 NAME 'olcDbCacheSize' " "DESC 'Entry cache size in entries' " @@ -64,14 +75,31 @@ static ConfigTable bdbcfg[] = { bdb_cf_gen, "( OLcfgDbAt:1.2 NAME 'olcDbCheckpoint' " "DESC 'Database checkpoint interval in kbytes and minutes' " "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL }, + { "checksum", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_CHECKSUM, + bdb_cf_gen, "( OLcfgDbAt:1.16 NAME 'olcDbChecksum' " + "DESC 'Enable database checksum validation' " + "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, + { "cryptfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_CRYPTFILE, + bdb_cf_gen, "( OLcfgDbAt:1.13 NAME 'olcDbCryptFile' " + "DESC 'Pathname of file containing the DB encryption key' " + "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL }, + { "cryptkey", "key", 2, 2, 0, ARG_BERVAL|ARG_MAGIC|BDB_CRYPTKEY, + bdb_cf_gen, "( OLcfgDbAt:1.14 NAME 'olcDbCryptKey' " + "DESC 'DB encryption key' " + "SYNTAX OMsOctetString SINGLE-VALUE )",NULL, NULL }, { "dbconfig", "DB_CONFIG setting", 1, 0, 0, ARG_MAGIC|BDB_CONFIG, bdb_cf_gen, "( OLcfgDbAt:1.3 NAME 'olcDbConfig' " "DESC 'BerkeleyDB DB_CONFIG configuration directives' " - "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",NULL, NULL }, + "SYNTAX OMsIA5String X-ORDERED 'VALUES' )", NULL, NULL }, { "dbnosync", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_NOSYNC, bdb_cf_gen, "( OLcfgDbAt:1.4 NAME 'olcDbNoSync' " "DESC 'Disable synchronous database writes' " "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, + { "dbpagesize", "db> be_private; Connection conn = {0}; - char opbuf[OPERATION_BUFFER_SIZE]; - Operation *op = (Operation *)opbuf; + OperationBuffer opbuf; + Operation *op; DBC *curs; DBT key, data; DB_TXN *txn; DB_LOCK lock; - u_int32_t locker; ID id, nid; EntryInfo *ei; int rc, getnext = 1; + int i; - connection_fake_init( &conn, op, ctx ); + connection_fake_init( &conn, &opbuf, ctx ); + op = &opbuf.ob_op; op->o_bd = be; @@ -206,7 +241,6 @@ bdb_online_index( void *ctx, void *arg ) rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &txn, bdb->bi_db_opflags ); if ( rc ) break; - locker = TXN_ID( txn ); if ( getnext ) { getnext = 0; BDB_ID2DISK( id, &nid ); @@ -232,7 +266,7 @@ bdb_online_index( void *ctx, void *arg ) } ei = NULL; - rc = bdb_cache_find_id( op, txn, id, &ei, 0, locker, &lock ); + rc = bdb_cache_find_id( op, txn, id, &ei, 0, &lock ); if ( rc ) { TXN_ABORT( txn ); if ( rc == DB_LOCK_DEADLOCK ) { @@ -264,6 +298,16 @@ bdb_online_index( void *ctx, void *arg ) getnext = 1; } + for ( i = 0; i < bdb->bi_nattrs; i++ ) { + if ( bdb->bi_attrs[ i ]->ai_indexmask & BDB_INDEX_DELETING + || bdb->bi_attrs[ i ]->ai_newmask == 0 ) + { + continue; + } + bdb->bi_attrs[ i ]->ai_indexmask = bdb->bi_attrs[ i ]->ai_newmask; + bdb->bi_attrs[ i ]->ai_newmask = 0; + } + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); ldap_pvt_runqueue_stoptask( &slapd_rq, rtask ); bdb->bi_index_task = NULL; @@ -302,21 +346,24 @@ bdb_cf_cleanup( ConfigArgs *c ) if ( bdb->bi_flags & BDB_RE_OPEN ) { bdb->bi_flags ^= BDB_RE_OPEN; - rc = c->be->bd_info->bi_db_close( c->be ); + rc = c->be->bd_info->bi_db_close( c->be, &c->reply ); if ( rc == 0 ) - rc = c->be->bd_info->bi_db_open( c->be ); + rc = c->be->bd_info->bi_db_open( c->be, &c->reply ); /* If this fails, we need to restart */ if ( rc ) { slapd_shutdown = 2; + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "failed to reopen database, rc=%d", rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_cf_cleanup) - ": failed to reopen database, rc=%d", rc, 0, 0 ); + ": %s\n", c->cr_msg, 0, 0 ); + rc = LDAP_OTHER; } } return rc; } static int -bdb_cf_gen(ConfigArgs *c) +bdb_cf_gen( ConfigArgs *c ) { struct bdb_info *bdb = c->be->be_private; int rc; @@ -324,15 +371,50 @@ bdb_cf_gen(ConfigArgs *c) if ( c->op == SLAP_CONFIG_EMIT ) { rc = 0; switch( c->type ) { + case BDB_MODE: { + char buf[64]; + struct berval bv; + bv.bv_len = snprintf( buf, sizeof(buf), "0%o", bdb->bi_dbenv_mode ); + if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) { + bv.bv_val = buf; + value_add_one( &c->rvalue_vals, &bv ); + } else { + rc = 1; + } + } break; + case BDB_CHKPT: - if (bdb->bi_txn_cp ) { + if ( bdb->bi_txn_cp ) { char buf[64]; struct berval bv; - bv.bv_len = sprintf( buf, "%d %d", bdb->bi_txn_cp_kbyte, - bdb->bi_txn_cp_min ); - bv.bv_val = buf; - value_add_one( &c->rvalue_vals, &bv ); - } else{ + bv.bv_len = snprintf( buf, sizeof(buf), "%ld %ld", + (long) bdb->bi_txn_cp_kbyte, (long) bdb->bi_txn_cp_min ); + if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) { + bv.bv_val = buf; + value_add_one( &c->rvalue_vals, &bv ); + } else { + rc = 1; + } + } else { + rc = 1; + } + break; + + case BDB_CRYPTFILE: + if ( bdb->bi_db_crypt_file ) { + c->value_string = ch_strdup( bdb->bi_db_crypt_file ); + } else { + rc = 1; + } + break; + + /* If a crypt file has been set, its contents are copied here. + * But we don't want the key to be incorporated here. + */ + case BDB_CRYPTKEY: + if ( !bdb->bi_db_crypt_file && !BER_BVISNULL( &bdb->bi_db_crypt_key )) { + value_add_one( &c->rvalue_vals, &bdb->bi_db_crypt_key ); + } else { rc = 1; } break; @@ -346,8 +428,9 @@ bdb_cf_gen(ConfigArgs *c) break; case BDB_CONFIG: - if (( slapMode&SLAP_SERVER_MODE ) && !( bdb->bi_flags&BDB_IS_OPEN ) - && !bdb->bi_db_config ) { + if ( !( bdb->bi_flags & BDB_IS_OPEN ) + && !bdb->bi_db_config ) + { char buf[SLAP_TEXT_BUFLEN]; FILE *f = fopen( bdb->bi_db_config_path, "r" ); struct berval bv; @@ -389,6 +472,11 @@ bdb_cf_gen(ConfigArgs *c) c->value_int = 1; break; + case BDB_CHECKSUM: + if ( bdb->bi_flags & BDB_CHKSUM ) + c->value_int = 1; + break; + case BDB_INDEX: bdb_attr_index_unparse( bdb, &c->rvalue_vals ); if ( !c->rvalue_vals ) rc = 1; @@ -399,7 +487,7 @@ bdb_cf_gen(ConfigArgs *c) if ( bdb->bi_lock_detect != DB_LOCK_DEFAULT ) { int i; for (i=0; !BER_BVISNULL(&bdb_lockd[i].word); i++) { - if ( bdb->bi_lock_detect == bdb_lockd[i].mask ) { + if ( bdb->bi_lock_detect == (u_int32_t)bdb_lockd[i].mask ) { value_add_one( &c->rvalue_vals, &bdb_lockd[i].word ); rc = 0; break; @@ -411,11 +499,36 @@ bdb_cf_gen(ConfigArgs *c) case BDB_SSTACK: c->value_int = bdb->bi_search_stack_depth; break; + + case BDB_PGSIZE: { + struct bdb_db_pgsize *ps; + char buf[SLAP_TEXT_BUFLEN]; + struct berval bv; + int rc = 1; + + bv.bv_val = buf; + for ( ps = bdb->bi_pagesizes; ps; ps = ps->bdp_next ) { + bv.bv_len = sprintf( buf, "%s %d", ps->bdp_name.bv_val, + ps->bdp_size / 1024 ); + value_add_one( &c->rvalue_vals, &bv ); + rc = 0; + + } + break; + } } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { rc = 0; switch( c->type ) { + case BDB_MODE: +#if 0 + /* FIXME: does it make any sense to change the mode, + * if we don't exec a chmod()? */ + bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE; + break; +#endif + /* single-valued no-ops */ case BDB_LOCKD: case BDB_SSTACK: @@ -425,9 +538,11 @@ bdb_cf_gen(ConfigArgs *c) if ( bdb->bi_txn_cp_task ) { struct re_s *re = bdb->bi_txn_cp_task; bdb->bi_txn_cp_task = NULL; - if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re )) + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); + if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) ) ldap_pvt_runqueue_stoptask( &slapd_rq, re ); ldap_pvt_runqueue_remove( &slapd_rq, re ); + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); } bdb->bi_txn_cp = 0; break; @@ -444,6 +559,21 @@ bdb_cf_gen(ConfigArgs *c) bdb->bi_flags |= BDB_UPD_CONFIG; c->cleanup = bdb_cf_cleanup; break; + /* Doesn't really make sense to change these on the fly; + * the entire DB must be dumped and reloaded + */ + case BDB_CRYPTFILE: + if ( bdb->bi_db_crypt_file ) { + ch_free( bdb->bi_db_crypt_file ); + bdb->bi_db_crypt_file = NULL; + } + /* FALLTHRU */ + case BDB_CRYPTKEY: + if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) { + ch_free( bdb->bi_db_crypt_key.bv_val ); + BER_BVZERO( &bdb->bi_db_crypt_key ); + } + break; case BDB_DIRECTORY: bdb->bi_flags |= BDB_RE_OPEN; bdb->bi_flags ^= BDB_HAS_CONFIG; @@ -453,30 +583,83 @@ bdb_cf_gen(ConfigArgs *c) bdb->bi_db_config_path = NULL; c->cleanup = bdb_cf_cleanup; ldap_pvt_thread_pool_purgekey( bdb->bi_dbenv ); - ldap_pvt_thread_pool_purgekey( ((char *)bdb->bi_dbenv) + 1 ); break; case BDB_NOSYNC: bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC, 0 ); break; - case BDB_INDEX: { - AttributeDescription *ad = NULL; - struct berval bv, def = BER_BVC("default"); - char *ptr; - const char *text; - for (ptr = c->line; !isspace( *ptr ); ptr++); - bv.bv_val = c->line; - bv.bv_len = ptr - bv.bv_val; - if ( bvmatch( &bv, &def )) { - bdb->bi_defaultmask = 0; + case BDB_CHECKSUM: + bdb->bi_flags &= ~BDB_CHKSUM; + break; + case BDB_INDEX: + if ( c->valx == -1 ) { + int i; + + /* delete all (FIXME) */ + for ( i = 0; i < bdb->bi_nattrs; i++ ) { + bdb->bi_attrs[i]->ai_indexmask |= BDB_INDEX_DELETING; + } + bdb->bi_flags |= BDB_DEL_INDEX; + c->cleanup = bdb_cf_cleanup; + } else { - slap_bv2ad( &bv, &ad, &text ); - if ( ad ) { - AttrInfo *ai = bdb_attr_mask( bdb, ad ); - ai->ai_indexmask |= BDB_INDEX_DELETING; - bdb->bi_flags |= BDB_DEL_INDEX; - c->cleanup = bdb_cf_cleanup; + struct berval bv, def = BER_BVC("default"); + char *ptr; + + for (ptr = c->line; !isspace( (unsigned char) *ptr ); ptr++); + + bv.bv_val = c->line; + bv.bv_len = ptr - bv.bv_val; + if ( bvmatch( &bv, &def )) { + bdb->bi_defaultmask = 0; + + } else { + int i; + char **attrs; + char sep; + + sep = bv.bv_val[ bv.bv_len ]; + bv.bv_val[ bv.bv_len ] = '\0'; + attrs = ldap_str2charray( bv.bv_val, "," ); + + for ( i = 0; attrs[ i ]; i++ ) { + AttributeDescription *ad = NULL; + const char *text; + AttrInfo *ai; + + slap_str2ad( attrs[ i ], &ad, &text ); + /* if we got here... */ + assert( ad != NULL ); + + ai = bdb_attr_mask( bdb, ad ); + /* if we got here... */ + assert( ai != NULL ); + + ai->ai_indexmask |= BDB_INDEX_DELETING; + bdb->bi_flags |= BDB_DEL_INDEX; + c->cleanup = bdb_cf_cleanup; + } + + bv.bv_val[ bv.bv_len ] = sep; + ldap_charray_free( attrs ); } } + break; + /* doesn't make sense on the fly; the DB file must be + * recreated + */ + case BDB_PGSIZE: { + struct bdb_db_pgsize *ps, **prev; + int i; + + for ( i = 0, prev = &bdb->bi_pagesizes, ps = *prev; ps; + prev = &ps->bdp_next, ps = ps->bdp_next, i++ ) { + if ( c->valx == -1 || i == c->valx ) { + *prev = ps->bdp_next; + ch_free( ps ); + ps = *prev; + if ( i == c->valx ) break; + } + } } break; } @@ -484,10 +667,63 @@ bdb_cf_gen(ConfigArgs *c) } switch( c->type ) { - case BDB_CHKPT: + case BDB_MODE: + if ( ASCII_DIGIT( c->argv[1][0] ) ) { + long mode; + char *next; + errno = 0; + mode = strtol( c->argv[1], &next, 0 ); + if ( errno != 0 || next == c->argv[1] || next[0] != '\0' ) { + fprintf( stderr, "%s: " + "unable to parse mode=\"%s\".\n", + c->log, c->argv[1] ); + return 1; + } + bdb->bi_dbenv_mode = mode; + + } else { + char *m = c->argv[1]; + int who, what, mode = 0; + + if ( strlen( m ) != STRLENOF("-rwxrwxrwx") ) { + return 1; + } + + if ( m[0] != '-' ) { + return 1; + } + + m++; + for ( who = 0; who < 3; who++ ) { + for ( what = 0; what < 3; what++, m++ ) { + if ( m[0] == '-' ) { + continue; + } else if ( m[0] != "rwx"[what] ) { + return 1; + } + mode += ((1 << (2 - what)) << 3*(2 - who)); + } + } + bdb->bi_dbenv_mode = mode; + } + break; + case BDB_CHKPT: { + long l; bdb->bi_txn_cp = 1; - bdb->bi_txn_cp_kbyte = strtol( c->argv[1], NULL, 0 ); - bdb->bi_txn_cp_min = strtol( c->argv[2], NULL, 0 ); + if ( lutil_atolx( &l, c->argv[1], 0 ) != 0 ) { + fprintf( stderr, "%s: " + "invalid kbyte \"%s\" in \"checkpoint\".\n", + c->log, c->argv[1] ); + return 1; + } + bdb->bi_txn_cp_kbyte = l; + if ( lutil_atolx( &l, c->argv[2], 0 ) != 0 ) { + fprintf( stderr, "%s: " + "invalid minutes \"%s\" in \"checkpoint\".\n", + c->log, c->argv[2] ); + return 1; + } + bdb->bi_txn_cp_min = l; /* If we're in server mode and time-based checkpointing is enabled, * submit a task to perform periodic checkpoints. */ @@ -502,12 +738,14 @@ bdb_cf_gen(ConfigArgs *c) c->log ); return 1; } + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); bdb->bi_txn_cp_task = ldap_pvt_runqueue_insert( &slapd_rq, bdb->bi_txn_cp_min * 60, bdb_checkpoint, bdb, LDAP_XSTRING(bdb_checkpoint), c->be->be_suffix[0].bv_val ); + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); } } - break; + } break; case BDB_CONFIG: { char *ptr = c->line; @@ -515,8 +753,8 @@ bdb_cf_gen(ConfigArgs *c) if ( c->op == SLAP_CONFIG_ADD ) { ptr += STRLENOF("dbconfig"); - while (!isspace(*ptr)) ptr++; - while (isspace(*ptr)) ptr++; + while (!isspace((unsigned char)*ptr)) ptr++; + while (isspace((unsigned char)*ptr)) ptr++; } if ( bdb->bi_flags & BDB_IS_OPEN ) { @@ -543,9 +781,44 @@ bdb_cf_gen(ConfigArgs *c) } break; + case BDB_CRYPTFILE: + rc = lutil_get_filed_password( c->value_string, &bdb->bi_db_crypt_key ); + if ( rc == 0 ) { + bdb->bi_db_crypt_file = c->value_string; + } + break; + + /* Cannot set key if file was already set */ + case BDB_CRYPTKEY: + if ( bdb->bi_db_crypt_file ) { + rc = 1; + } else { + bdb->bi_db_crypt_key = c->value_bv; + } + break; + case BDB_DIRECTORY: { FILE *f; - char *ptr; + char *ptr, *testpath; + int len; + + len = strlen( c->value_string ); + testpath = ch_malloc( len + STRLENOF(LDAP_DIRSEP) + STRLENOF("DUMMY") + 1 ); + ptr = lutil_strcopy( testpath, c->value_string ); + *ptr++ = LDAP_DIRSEP[0]; + strcpy( ptr, "DUMMY" ); + f = fopen( testpath, "w" ); + if ( f ) { + fclose( f ); + unlink( testpath ); + } + ch_free( testpath ); + if ( !f ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid path: %s", + c->log, strerror( errno )); + Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 ); + return -1; + } if ( bdb->bi_dbenv_home ) ch_free( bdb->bi_dbenv_home ); @@ -554,7 +827,7 @@ bdb_cf_gen(ConfigArgs *c) /* See if a DB_CONFIG file already exists here */ if ( bdb->bi_db_config_path ) ch_free( bdb->bi_db_config_path ); - bdb->bi_db_config_path = ch_malloc( strlen( bdb->bi_dbenv_home ) + + bdb->bi_db_config_path = ch_malloc( len + STRLENOF(LDAP_DIRSEP) + STRLENOF("DB_CONFIG") + 1 ); ptr = lutil_strcopy( bdb->bi_db_config_path, bdb->bi_dbenv_home ); *ptr++ = LDAP_DIRSEP[0]; @@ -579,9 +852,16 @@ bdb_cf_gen(ConfigArgs *c) } break; + case BDB_CHECKSUM: + if ( c->value_int ) + bdb->bi_flags |= BDB_CHKSUM; + else + bdb->bi_flags &= ~BDB_CHKSUM; + break; + case BDB_INDEX: rc = bdb_attr_index_config( bdb, c->fname, c->lineno, - c->argc - 1, &c->argv[1] ); + c->argc - 1, &c->argv[1], &c->reply); if( rc != LDAP_SUCCESS ) return 1; if (( bdb->bi_flags & BDB_IS_OPEN ) && !bdb->bi_index_task ) { @@ -594,9 +874,11 @@ bdb_cf_gen(ConfigArgs *c) c->log ); return 1; } + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); bdb->bi_index_task = ldap_pvt_runqueue_insert( &slapd_rq, 36000, bdb_online_index, c->be, LDAP_XSTRING(bdb_online_index), c->be->be_suffix[0].bv_val ); + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); } break; @@ -608,7 +890,7 @@ bdb_cf_gen(ConfigArgs *c) c->log, c->argv[1] ); return 1; } - bdb->bi_lock_detect = rc; + bdb->bi_lock_detect = (u_int32_t)rc; break; case BDB_SSTACK: @@ -620,6 +902,31 @@ bdb_cf_gen(ConfigArgs *c) } bdb->bi_search_stack_depth = c->value_int; break; + + case BDB_PGSIZE: { + struct bdb_db_pgsize *ps, **prev; + int i, s; + + s = atoi(c->argv[2]); + if ( s < 1 || s > 64 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s: size must be > 0 and <= 64: %d", + c->log, s ); + Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 ); + return -1; + } + i = strlen(c->argv[1]); + ps = ch_malloc( sizeof(struct bdb_db_pgsize) + i + 1 ); + ps->bdp_next = NULL; + ps->bdp_name.bv_len = i; + ps->bdp_name.bv_val = (char *)(ps+1); + strcpy( ps->bdp_name.bv_val, c->argv[1] ); + ps->bdp_size = s * 1024; + for ( prev = &bdb->bi_pagesizes; *prev; prev = &(*prev)->bdp_next ) + ; + *prev = ps; + } + break; } return 0; }