/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2005,2008 Oracle. All rights reserved.
*
* $Id: db.c,v 1.18 2008/01/08 20:58:23 bostic Exp $
*/
#include "csv.h"
#include "csv_local.h"
#include "csv_extern.h"
static int compare_uint32(DB *, const DBT *, const DBT *);
/*
* csv_env_init --
* Initialize the database environment.
*/
int
csv_env_open(const char *home, int is_rdonly)
{
int ret;
dbenv = NULL;
db = NULL;
/* Create a database environment handle. */
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
return (1);
}
/*
* Configure Berkeley DB error reporting to stderr, with our program
* name as the prefix.
*/
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
/*
* The default Berkeley DB cache size is fairly small; configure a
* 1MB cache for now. This value will require tuning in the future.
*/
if ((ret = dbenv->set_cachesize(dbenv, 0, 1048576, 1)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->set_cachesize");
return (1);
}
/*
* We may be working with an existing environment -- try and join it.
* If that fails, create a new database environment; for now, we only
* need a cache, no logging, locking, or transactions.
*/
if ((ret = dbenv->open(dbenv, home,
DB_JOINENV | DB_USE_ENVIRON, 0)) != 0 &&
(ret = dbenv->open(dbenv, home,
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->open");
return (1);
}
/* Create the primary database handle. */
if ((ret = db_create(&db, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
return (1);
}
/*
* Records may be relatively large -- use a large page size.
*/
if ((ret = db->set_pagesize(db, 32 * 1024)) != 0) {
dbenv->err(dbenv, ret, "DB->set_pagesize");
return (1);
}
/*
* The primary database uses an integer as its key; on little-endian
* machines, integers sort badly using the default Berkeley DB sort
* function (which is lexicographic). Specify a comparison function
* for the database.
*/
if ((ret = db->set_bt_compare(db, compare_uint32)) != 0) {
dbenv->err(dbenv, ret, "DB->set_bt_compare");
return (1);
}
/* Open the primary database. */
if ((ret = db->open(db, NULL,
"primary", NULL, DB_BTREE, is_rdonly ? 0 : DB_CREATE, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->open: primary");
return (1);
}
/* Open the secondaries. */
if ((ret = csv_secondary_open()) != 0)
return (1);
return (0);
}
/*
* csv_env_close --
* Discard the database environment.
*/
int
csv_env_close()
{
int ret, t_ret;
ret = 0;
/* Close the secondaries. */
ret = csv_secondary_close();
/* Close the primary handle. */
if (db != NULL && (t_ret = db->close(db, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->close");
if (ret == 0)
ret = t_ret;
}
if ((t_ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr,
"%s: DB_ENV->close: %s\n", progname, db_strerror(ret));
if (ret == 0)
ret = t_ret;
}
return (ret);
}
/*
* csv_secondary_open --
* Open any secondary indices.
*/
int
csv_secondary_open()
{
DB *sdb;
DbField *f;
int ret, (*fcmp)(DB *, const DBT *, const DBT *);
/*
* Create secondary database handles.
*/
for (f = fieldlist; f->name != NULL; ++f) {
if (f->indx == 0)
continue;
if ((ret = db_create(&sdb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
return (1);
}
sdb->app_private = f;
/* Keys are small, use a relatively small page size. */
if ((ret = sdb->set_pagesize(sdb, 8 * 1024)) != 0) {
dbenv->err(dbenv, ret, "DB->set_pagesize");
return (1);
}
/*
* Sort the database based on the underlying type. Skip
* strings, Berkeley DB defaults to lexicographic sort.
*/
switch (f->type) {
case DOUBLE:
fcmp = compare_double;
break;
case UNSIGNED_LONG:
fcmp = compare_ulong;
break;
case NOTSET:
case STRING:
default:
fcmp = NULL;
break;
}
if (fcmp != NULL &&
(ret = sdb->set_bt_compare(sdb, fcmp)) != 0) {
dbenv->err(dbenv, ret, "DB->set_bt_compare");
return (1);
}
/* Always configure secondaries for sorted duplicates. */
if ((ret = sdb->set_flags(sdb, DB_DUPSORT)) != 0) {
dbenv->err(dbenv, ret, "DB->set_flags");
return (1);
}
if ((ret = sdb->set_dup_compare(sdb, compare_ulong)) != 0) {
dbenv->err(dbenv, ret, "DB->set_dup_compare");
return (1);
}
if ((ret = sdb->open(
sdb, NULL, f->name, NULL, DB_BTREE, DB_CREATE, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->open: %s", f->name);
return (1);
}
if ((ret = sdb->associate(
db, NULL, sdb, secondary_callback, DB_CREATE)) != 0) {
dbenv->err(dbenv, ret, "DB->set_associate");
return (1);
}
f->secondary = sdb;
}
return (0);
}
/*
* csv_secondary_close --
* Close any secondary indices.
*/
int
csv_secondary_close()
{
DbField *f;
int ret, t_ret;
ret = 0;
for (f = fieldlist; f->name != NULL; ++f)
if (f->secondary != NULL && (t_ret =
f->secondary->close(f->secondary, 0)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
/*
* compare_uint32 --
* Compare two keys.
*/
static int
compare_uint32(DB *db_arg, const DBT *a_arg, const DBT *b_arg)
{
u_int32_t a, b;
db_arg = db_arg; /* Quiet compiler. */
memcpy(&a, a_arg->data, sizeof(u_int32_t));
memcpy(&b, b_arg->data, sizeof(u_int32_t));
return (a > b ? 1 : ((a < b) ? -1 : 0));
}
Copyright 2K16 - 2K18 Indonesian Hacker Rulez