Exemple #1
0
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);
}