+#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)
+
+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_MODE,
+ BDB_PGSIZE,
+ BDB_CHECKSUM
+};
+
+static ConfigTable bdbcfg[] = {
+ { "directory", "dir", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_DIRECTORY,
+ bdb_cf_gen, "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
+ "DESC 'Directory for database content' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "cachefree", "size", 2, 2, 0, ARG_UINT|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,
+ (void *)offsetof(struct bdb_info, bi_cache.c_maxsize),
+ "( OLcfgDbAt:1.1 NAME 'olcDbCacheSize' "
+ "DESC 'Entry cache size in entries' "
+ "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+ { "checkpoint", "kbyte> <min", 3, 3, 0, ARG_MAGIC|BDB_CHKPT,
+ 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 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> <size", 3, 3, 0, ARG_MAGIC|BDB_PGSIZE,
+ bdb_cf_gen, "( OLcfgDbAt:1.15 NAME 'olcDbPageSize' "
+ "DESC 'Page size of specified DB, in Kbytes' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { "dirtyread", NULL, 1, 2, 0,
+#ifdef SLAP_BDB_ALLOW_DIRTY_READ
+ ARG_ON_OFF|ARG_MAGIC|BDB_DIRTYR, bdb_cf_gen,
+#else
+ ARG_IGNORED, NULL,
+#endif
+ "( 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,
+ (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,
+ (void *)offsetof(struct bdb_info, bi_idl_cache_max_size),
+ "( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
+ "DESC 'IDL cache size in IDLs' "
+ "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+ { "index", "attr> <[pres,eq,approx,sub]", 2, 3, 0, ARG_MAGIC|BDB_INDEX,
+ bdb_cf_gen, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
+ "DESC 'Attribute index parameters' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { "linearindex", NULL, 1, 2, 0, ARG_ON_OFF|ARG_OFFSET,
+ (void *)offsetof(struct bdb_info, bi_linear_index),
+ "( OLcfgDbAt:1.7 NAME 'olcDbLinearIndex' "
+ "DESC 'Index attributes one at a time' "
+ "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+ { "lockdetect", "policy", 2, 2, 0, ARG_MAGIC|BDB_LOCKD,
+ bdb_cf_gen, "( OLcfgDbAt:1.8 NAME 'olcDbLockDetect' "
+ "DESC 'Deadlock detection algorithm' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "mode", "mode", 2, 2, 0, ARG_MAGIC|BDB_MODE,
+ bdb_cf_gen, "( OLcfgDbAt:0.3 NAME 'olcDbMode' "
+ "DESC 'Unix permissions of database files' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "searchstack", "depth", 2, 2, 0, ARG_INT|ARG_MAGIC|BDB_SSTACK,
+ bdb_cf_gen, "( OLcfgDbAt:1.9 NAME 'olcDbSearchStack' "
+ "DESC 'Depth of search stack in IDLs' "
+ "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+ { "shm_key", "key", 2, 2, 0, ARG_LONG|ARG_OFFSET,
+ (void *)offsetof(struct bdb_info, bi_shm_key),
+ "( OLcfgDbAt:1.10 NAME 'olcDbShmKey' "
+ "DESC 'Key for shared memory region' "
+ "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED,
+ NULL, NULL, NULL, NULL }
+};
+
+static ConfigOCs bdbocs[] = {
+ {
+#ifdef BDB_HIER
+ "( OLcfgDbOc:1.2 "
+ "NAME 'olcHdbConfig' "
+ "DESC 'HDB backend configuration' "
+#else
+ "( OLcfgDbOc:1.1 "
+ "NAME 'olcBdbConfig' "
+ "DESC 'BDB backend configuration' "
+#endif
+ "SUP olcDatabaseConfig "
+ "MUST olcDbDirectory "
+ "MAY ( olcDbCacheSize $ olcDbCheckpoint $ olcDbConfig $ "
+ "olcDbCryptFile $ olcDbCryptKey $ "
+ "olcDbNoSync $ olcDbDirtyRead $ olcDbIDLcacheSize $ "
+ "olcDbIndex $ olcDbLinearIndex $ olcDbLockDetect $ "
+ "olcDbMode $ olcDbSearchStack $ olcDbShmKey $ "
+ "olcDbCacheFree $ olcDbDNcacheSize $ olcDbPageSize ) )",
+ Cft_Database, bdbcfg },
+ { NULL, 0, NULL }
+};
+
+static slap_verbmasks bdb_lockd[] = {
+ { BER_BVC("default"), DB_LOCK_DEFAULT },
+ { BER_BVC("oldest"), DB_LOCK_OLDEST },
+ { BER_BVC("random"), DB_LOCK_RANDOM },
+ { BER_BVC("youngest"), DB_LOCK_YOUNGEST },
+ { BER_BVC("fewest"), DB_LOCK_MINLOCKS },
+ { BER_BVNULL, 0 }
+};
+
+/* perform periodic checkpoints */
+static void *
+bdb_checkpoint( void *ctx, void *arg )