int ldbm_initialize( const char* home ) { #if DB_VERSION_MAJOR < 3 int err; u_int32_t envFlags; #endif if(ldbm_initialized++) return 1; { char *version; int major, minor, patch; version = db_version( &major, &minor, &patch ); if( major != DB_VERSION_MAJOR || minor < DB_VERSION_MINOR ) { #ifdef LDAP_SYSLOG syslog( LOG_INFO, "ldbm_initialize(): version mismatch\nexpected: %s\ngot: %s\n", DB_VERSION_STRING, version ); #endif return 1; } } #if DB_VERSION_MAJOR < 3 ldbm_Env = calloc( 1, sizeof( DB_ENV )); if( ldbm_Env == NULL ) return 1; ldbm_Env->db_errcall = ldbm_db_errcall; ldbm_Env->db_errpfx = "==>"; envFlags = DB_CREATE | DB_USE_ENVIRON; /* add optional flags */ #ifdef DB_PRIVATE envFlags |= DB_PRIVATE; #endif #ifdef HAVE_BERKELEY_DB_THREAD envFlags |= DB_THREAD; #endif err = db_appinit( home, NULL, ldbm_Env, envFlags ); if ( err ) { #ifdef LDAP_SYSLOG syslog( LOG_INFO, "ldbm_initialize(): " "FATAL error (%d) in db_appinit()\n", err ); #endif return( 1 ); } #endif LDBM_RWLOCK_INIT; return 0; }
int main(int argc) { DB *dbp; DB_INFO dbinfo; DB_ENV dbenv; int ret = 0, delta = 1, j, i; u_int32_t key = 0, data = 0; memset(&dbenv, 0, sizeof(DB_ENV)); if ((errno = db_appinit(DATAHOME, NULL, &dbenv, DB_CREATE|DB_INIT_LOCK|DB_INIT_MPOOL)) != 0) { #error "[PM] 4.0 strerror is not thread safe. use strerror_r instead" fprintf(stderr, "db: %s: %s\n", DATAHOME, strerror(errno)); return 1; } if ((errno = LOCK_DETECT(dbenv, dbenv.lk_info, DB_LOCK_CONFLICT, 0)) != 0) { #error "[PM] 4.0 strerror is not thread safe. use strerror_r instead" fprintf(stderr, "db: %s\n", strerror(errno)); ret = 1; goto exit; } memset(&dbinfo, 0, sizeof(DB_INFO)); dbinfo.h_hash = identity; if (argc > 1) { /* sorting speeds up things (3/4), which is quite a wonder */ dbinfo.flags = DB_DUP|DB_DUPSORT; delta = 0; fprintf(stderr, "storing duplicates...\n"); } if ((errno = db_open(DATABASE, DB_HASH, DB_CREATE, 0664, &dbenv, &dbinfo, &dbp)) != 0) { #error "[PM] 4.0 strerror is not thread safe. use strerror_r instead" fprintf(stderr, "db: %s: %s\n", DATABASE, strerror(errno)); ret = 1; goto exit; } for (j = 1; j <= MAX_KEYL; ++j) STAT(for (i = 1; i <= MAX_KEYN; ++i, key += delta, ++data) if (put(dbp, i, key, data)) goto close_db, fprintf(stderr, "#%.3d: ", j)); close_db: if ((errno = dbp->close(dbp, 0)) != 0) { fprintf(stderr, "db: close: %s\n", strerror(errno)); /* [PM] strerror not thread safe (but not using threads here) */ ret = 1; } exit: db_appexit(&dbenv); return ret; }
/* *************************************************************************** * init database * init all databases present in the name array if 'index' is < 0 * otherwise initialize only the specific database pointed to by 'index' * * Exception: if index == DB_RUNRECOVERY, then DBENV->remove * is performed before the environment is opened. * *************************************************************************** Returns: 0 on success, or error code */ int dbtp_init(DBTPD * dbtp, unsigned char * home, int index) { u_int32_t eflags = DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL; u_int32_t dflags = DB_CREATE; u_int32_t info = DB_RECNUM; DBTYPE type = DB_BTREE; int mode = 0664; int ai; /* * OPEN / CREATE ENVIRONMENT * * Since the databases are not transactional, we really don't run recovery. * All that is typically corrupted is the DB environment so destroy the * environment files and recreate them instead. If this does not work, * operator intervention will be necessary. */ #if DB_VERSION_MAJOR == 2 if (index == DB_RUNRECOVERY) goto DBTP_env_err; /* sorry, can't do recovery unless > version 2 */ if ((dbtp->dbenv = (DB_ENV *) calloc(sizeof(DB_ENV), 1)) == NULL ) return (dbtp->dberr = errno); if (dbtp->dberr = db_appinit(home, NULL, dbtp->dbenv, eflags | DB_USE_ENVIRON) != 0) { free(dbtp->dbenv); DBTP_env_err: dbtp->dbenv = NULL; return(dbtp->dberr); } #else /* DB_VERSION_MAJOR > 2 */ DBTP_reopen: if ((dbtp->dberr = db_env_create(&dbtp->dbenv,0)) != 0) goto DBTP_env_err; if (index == DB_RUNRECOVERY) { #ifdef IS_DB_3_0_x if ((dbtp->dberr = dbtp->dbenv->remove(dbtp->dbenv, (char *)home, NULL, DB_FORCE)) != 0) #else /* > 3.0 */ if ((dbtp->dberr = dbtp->dbenv->remove(dbtp->dbenv, (char *)home, DB_FORCE)) != 0) #endif goto DBTP_env_err; index = -1; dbtp->dbenv = NULL; goto DBTP_reopen; } #ifdef IS_DB_3_0_x if ((dbtp->dberr = dbtp->dbenv->open(dbtp->dbenv, (char *)home, NULL, eflags, mode)) != 0) { #else /* > 3.0 */ if ((dbtp->dberr = dbtp->dbenv->open(dbtp->dbenv, (char *)home, eflags, mode)) != 0) { #endif (void)dbtp->dbenv->close(dbtp->dbenv, 0); DBTP_env_err: dbtp->dbenv = NULL; return(dbtp->dberr); } #endif /* DB_VERSION_MAJOR > 2 */ /* * CREATE / OPEN DATABASE's */ for(ai=0; ai<DBTP_MAXdbf; ai++) { if (index < 0) { if (dbtp->dbfile[ai] == NULL) { if (ai) return(dbtp->dberr); /* last status if end of array and something opened */ else { dbtp_env_close(dbtp); return(dbtp->dberr = ENODATA); /* fatal if nothing to open */ } } } else { ai = index; index = 1; /* always 'positive' if active */ } if ((dbtp->dberr = db_create(&dbtp->dbaddr[ai],dbtp->dbenv,0)) != 0) { Bail: dbtp_close(dbtp); return(dbtp->dberr); } if ((dbtp->dberr = dbtp->dbaddr[ai]->set_flags(dbtp->dbaddr[ai], info)) != 0) goto Bail; #if DB_VERSION_MAJOR > 2 #ifdef AT_LEAST_DB_4_1 if ((dbtp->dberr = (dbtp->dbaddr[ai]->open(dbtp->dbaddr[ai], NULL, dbtp->dbfile[ai], NULL, type, dflags, mode))) != 0) #else if ((dbtp->dberr = (dbtp->dbaddr[ai]->open(dbtp->dbaddr[ai], dbtp->dbfile[ai], NULL, type, dflags, mode))) != 0) #endif /* AT_LEAST_DB_4_1 */ #else /* DB_VERSION_MAJOR == 2 */ if ((dbtp->dberr = db_open(dbtp->dbfile[ai], type, dflags, mode, dbtp->dbenv, info, &dbtp->dbaddr[ai]))) != 0) #endif /* DB_VERSION_MAJOR == 2 */ goto Bail; if (index > 0) break; } return(dbtp->dberr); } /* returns 0 if addr and *addr are valid * else it returns DB_KEYEMPTY */ int _dbtp_set(DBTPD * dbtp, void * addr, size_t size) { if (size != sizeof(u_int32_t) || addr == NULL || *(u_int32_t *)addr == 0) return(DB_KEYEMPTY); memset(&dbtp->keydbt, 0, sizeof(DBT)); memset(&dbtp->mgdbt, 0, sizeof(DBT)); dbtp->keydbt.data = addr; dbtp->keydbt.size = (u_int32_t)size; return(0); } /* **************************** * * return 0 on success * * or the bdb error code * * external data structure * * mgdbt is filled * * * typedef struct { * void *data; * u_int32_t size; * u_int32_t ulen; * u_int32_t dlen; * u_int32_t doff; * u_int32_t flags; * } DBT; * */ int dbtp_get(DBTPD * dbtp, int ai, void * addr, size_t size) { if(dbtp->dbaddr[ai] == NULL) return(dbtp->dberr = ENODATA); if ((dbtp->dberr = _dbtp_set(dbtp,addr,size))) return(dbtp->dberr); return(dbtp->dberr = dbtp->dbaddr[ai]->get(dbtp->dbaddr[ai], NULL, &dbtp->keydbt, &dbtp->mgdbt, 0)); } /* **************************** * * return 0 on success * * or the bdb error code * * external data structure * * mgdbt and keydbt are * * filled * * * typedef struct { * void *data; * u_int32_t size; * u_int32_t ulen; * u_int32_t dlen; * u_int32_t doff; * u_int32_t flags; * } DBT; * */ int dbtp_getrecno(DBTPD * dbtp, int ai, u_int32_t cursor) { if(dbtp->dbaddr[ai] == NULL) return(dbtp->dberr = ENODATA); REGET_by_cursor: memset(&dbtp->keydbt, 0, sizeof(DBT)); memset(&dbtp->mgdbt, 0, sizeof(DBT)); dbtp->keydbt.data = &cursor; dbtp->keydbt.size = (u_int32_t)sizeof(cursor); return(dbtp->dberr = dbtp->dbaddr[ai]->get(dbtp->dbaddr[ai], NULL, &dbtp->keydbt, &dbtp->mgdbt, DB_SET_RECNO)); dbtp->dberr = dbtp->dbaddr[ai]->get(dbtp->dbaddr[ai], NULL, &dbtp->keydbt, &dbtp->mgdbt, DB_SET_RECNO); if (! dbtp->dberr && dbtp->keydbt.size != sizeof(INADDR_BROADCAST)) { dbtp_del(dbtp,ai,dbtp->keydbt.data,dbtp->keydbt.size); goto REGET_by_cursor; } return(dbtp->dberr); } /* get the number of keys or records from the target database, by index */ u_int32_t dbtp_stati(DBTPD * dbtp, int ai) { DB_BTREE_STAT * statistics = NULL; u_int32_t bt_nkeys; if(dbtp->dbaddr[ai] == NULL) { dbtp->dberr = DB_NOTFOUND; return(0); } #ifdef AT_LEAST_DB_4_3 dbtp->dberr = dbtp->dbaddr[ai]->stat(dbtp->dbaddr[ai],NULL,&statistics,DB_FAST_STAT); #else # ifdef AT_LEAST_DB_3_3 dbtp->dberr = dbtp->dbaddr[ai]->stat(dbtp->dbaddr[ai],&statistics,DB_FAST_STAT); # else dbtp->dberr = dbtp->dbaddr[ai]->stat(dbtp->dbaddr[ai],&statistics,NULL,DB_RECORDCOUNT); # endif #endif if (dbtp->dberr) bt_nkeys = 0; else #ifdef AT_LEAST_DB_3_1 bt_nkeys = statistics->bt_nkeys; #else bt_nkeys = statistics->bt_nrecs; #endif free(statistics); return(bt_nkeys); }