Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

db.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: db.c,v 1.12 2005/10/14 12:50:37 bostic Exp $
00008  */
00009 
00010 #include "csv.h"
00011 #include "csv_local.h"
00012 #include "csv_extern.h"
00013 
00014 static int compare_uint32(DB *, const DBT *, const DBT *);
00015 
00016 /*
00017  * csv_env_init --
00018  *      Initialize the database environment.
00019  */
00020 int
00021 csv_env_open(const char *home, int is_rdonly)
00022 {
00023         int ret;
00024 
00025         dbenv = NULL;
00026         db = NULL;
00027 
00028         /* Create a database environment handle. */
00029         if ((ret = db_env_create(&dbenv, 0)) != 0) {
00030                 fprintf(stderr,
00031                     "%s: db_env_create: %s\n", progname, db_strerror(ret));
00032                 return (1);
00033         }
00034 
00035         /*
00036          * Configure Berkeley DB error reporting to stderr, with our program
00037          * name as the prefix.
00038          */
00039         dbenv->set_errfile(dbenv, stderr);
00040         dbenv->set_errpfx(dbenv, progname);
00041 
00042         /*
00043          * The default Berkeley DB cache size is fairly small; configure a
00044          * 1MB cache for now.  This value will require tuning in the future.
00045          */
00046         if ((ret = dbenv->set_cachesize(dbenv, 0, 1048576, 1)) != 0) {
00047                 dbenv->err(dbenv, ret, "DB_ENV->set_cachesize");
00048                 return (1);
00049         }
00050 
00051         /*
00052          * We may be working with an existing environment -- try and join it.
00053          * If that fails, create a new database environment; for now, we only
00054          * need a cache, no logging, locking, or transactions.
00055          */
00056         if ((ret = dbenv->open(dbenv, home,
00057             DB_JOINENV | DB_USE_ENVIRON, 0)) != 0 &&
00058             (ret = dbenv->open(dbenv, home,
00059             DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
00060                 dbenv->err(dbenv, ret, "DB_ENV->open");
00061                 return (1);
00062         }
00063 
00064         /* Create the primary database handle. */
00065         if ((ret = db_create(&db, dbenv, 0)) != 0) {
00066                 dbenv->err(dbenv, ret, "db_create");
00067                 return (1);
00068         }
00069 
00070         /*
00071          * Records may be relatively large -- use a large page size.
00072          */
00073         if ((ret = db->set_pagesize(db, 32 * 1024)) != 0) {
00074                 dbenv->err(dbenv, ret, "DB->set_pagesize");
00075                 return (1);
00076         }
00077 
00078         /*
00079          * The primary database uses an integer as its key; on little-endian
00080          * machines, integers sort badly using the default Berkeley DB sort
00081          * function (which is lexicographic).  Specify a comparison function
00082          * for the database.
00083          */
00084         if ((ret = db->set_bt_compare(db, compare_uint32)) != 0) {
00085                 dbenv->err(dbenv, ret, "DB->set_bt_compare");
00086                 return (1);
00087         }
00088 
00089         /* Open the primary database. */
00090         if ((ret = db->open(db, NULL,
00091             "primary", NULL, DB_BTREE, is_rdonly ? 0 : DB_CREATE, 0)) != 0) {
00092                 dbenv->err(dbenv, ret, "DB->open: primary");
00093                 return (1);
00094         }
00095 
00096         /* Open the secondaries.  */
00097         if ((ret = csv_secondary_open()) != 0)
00098                 return (1);
00099 
00100         return (0);
00101 }
00102 
00103 /*
00104  * csv_env_close --
00105  *      Discard the database environment.
00106  */
00107 int
00108 csv_env_close()
00109 {
00110         int ret, t_ret;
00111 
00112         ret = 0;
00113 
00114         /* Close the secondaries. */
00115         ret = csv_secondary_close();
00116 
00117         /* Close the primary handle. */
00118         if (db != NULL && (t_ret = db->close(db, 0)) != 0) {
00119                 dbenv->err(dbenv, ret, "DB->close");
00120                 if (ret == 0)
00121                         ret = t_ret;
00122         }
00123         if ((t_ret = dbenv->close(dbenv, 0)) != 0) {
00124                 fprintf(stderr,
00125                     "%s: DB_ENV->close: %s\n", progname, db_strerror(ret));
00126                 if (ret == 0)
00127                         ret = t_ret;
00128         }
00129 
00130         return (ret);
00131 }
00132 
00133 /*
00134  * csv_secondary_open --
00135  *      Open any secondary indices.
00136  */
00137 int
00138 csv_secondary_open()
00139 {
00140         DB *sdb;
00141         DbField *f;
00142         int ret, (*fcmp)(DB *, const DBT *, const DBT *);
00143 
00144         /*
00145          * Create secondary database handles.
00146          */
00147         for (f = fieldlist; f->name != NULL; ++f) {
00148                 if (f->indx == 0)
00149                         continue;
00150 
00151                 if ((ret = db_create(&sdb, dbenv, 0)) != 0) {
00152                         dbenv->err(dbenv, ret, "db_create");
00153                         return (1);
00154                 }
00155                 sdb->app_private = f;
00156 
00157                 /* Keys are small, use a relatively small page size. */
00158                 if ((ret = sdb->set_pagesize(sdb, 8 * 1024)) != 0) {
00159                         dbenv->err(dbenv, ret, "DB->set_pagesize");
00160                         return (1);
00161                 }
00162 
00163                 /*
00164                  * Sort the database based on the underlying type.  Skip
00165                  * strings, Berkeley DB defaults to lexicographic sort.
00166                  */
00167                 switch (f->type) {
00168                 case DOUBLE:
00169                         fcmp = compare_double;
00170                         break;
00171                 case ULONG:
00172                         fcmp = compare_ulong;
00173                         break;
00174                 case NOTSET:
00175                 case STRING:
00176                 default:
00177                         fcmp = NULL;
00178                         break;
00179                 }
00180                 if (fcmp != NULL &&
00181                     (ret = sdb->set_bt_compare(sdb, fcmp)) != 0) {
00182                         dbenv->err(dbenv, ret, "DB->set_bt_compare");
00183                         return (1);
00184                 }
00185 
00186                 /* Always configure secondaries for sorted duplicates. */
00187                 if ((ret = sdb->set_flags(sdb, DB_DUPSORT)) != 0) {
00188                         dbenv->err(dbenv, ret, "DB->set_flags");
00189                         return (1);
00190                 }
00191                 if ((ret = sdb->set_dup_compare(sdb, compare_ulong)) != 0) {
00192                         dbenv->err(dbenv, ret, "DB->set_dup_compare");
00193                         return (1);
00194                 }
00195 
00196                 if ((ret = sdb->open(
00197                     sdb, NULL, f->name, NULL, DB_BTREE, DB_CREATE, 0)) != 0) {
00198                         dbenv->err(dbenv, ret, "DB->open: %s", f->name);
00199                         return (1);
00200                 }
00201                 if ((ret = sdb->associate(
00202                     db, NULL, sdb, secondary_callback, DB_CREATE)) != 0) {
00203                         dbenv->err(dbenv, ret, "DB->set_associate");
00204                         return (1);
00205                 }
00206                 f->secondary = sdb;
00207         }
00208 
00209         return (0);
00210 }
00211 
00212 /*
00213  * csv_secondary_close --
00214  *      Close any secondary indices.
00215  */
00216 int
00217 csv_secondary_close()
00218 {
00219         DbField *f;
00220         int ret, t_ret;
00221 
00222         ret = 0;
00223         for (f = fieldlist; f->name != NULL; ++f)
00224                 if (f->secondary != NULL && (t_ret =
00225                     f->secondary->close(f->secondary, 0)) != 0 && ret == 0)
00226                         ret = t_ret;
00227 
00228         return (ret);
00229 }
00230 
00231 /*
00232  * compare_uint32 --
00233  *      Compare two keys.
00234  */
00235 static int
00236 compare_uint32(DB *db_arg, const DBT *a_arg, const DBT *b_arg)
00237 {
00238         u_int32_t a, b;
00239 
00240         db_arg = db_arg;                        /* Quiet compiler. */
00241 
00242         memcpy(&a, a_arg->data, sizeof(u_int32_t));
00243         memcpy(&b, b_arg->data, sizeof(u_int32_t));
00244         return (a > b ? 1 : ((a < b) ? -1 : 0));
00245 }

Generated on Sun Dec 25 12:14:18 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2