#include "csv.h"
#include "csv_local.h"
#include "csv_extern.h"
static int compare_uint32(DB *, const DBT *, const DBT *);
int
csv_env_open(const char *home, int is_rdonly)
{
int ret;
dbenv = NULL;
db = NULL;
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
return (1);
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
if ((ret = dbenv->set_cachesize(dbenv, 0, 1048576, 1)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->set_cachesize");
return (1);
}
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);
}
if ((ret = db_create(&db, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
return (1);
}
if ((ret = db->set_pagesize(db, 32 * 1024)) != 0) {
dbenv->err(dbenv, ret, "DB->set_pagesize");
return (1);
}
if ((ret = db->set_bt_compare(db, compare_uint32)) != 0) {
dbenv->err(dbenv, ret, "DB->set_bt_compare");
return (1);
}
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);
}
if ((ret = csv_secondary_open()) != 0)
return (1);
return (0);
}
int
csv_env_close()
{
int ret, t_ret;
ret = 0;
ret = csv_secondary_close();
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);
}
int
csv_secondary_open()
{
DB *sdb;
DbField *f;
int ret, (*fcmp)(DB *, const DBT *, const DBT *);
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;
if ((ret = sdb->set_pagesize(sdb, 8 * 1024)) != 0) {
dbenv->err(dbenv, ret, "DB->set_pagesize");
return (1);
}
switch (f->type) {
case DOUBLE:
fcmp = compare_double;
break;
case ULONG:
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);
}
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);
}
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);
}
static int
compare_uint32(DB *db_arg, const DBT *a_arg, const DBT *b_arg)
{
u_int32_t a, b;
db_arg = db_arg;
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));
}