db

env_open.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  * Sleepycat Software. All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifndef lint
00011 static const char revid[] = "$Id: env__open_8c-source.html,v 1.1 2008年06月08日 10:18:42 sebdiaz Exp $";
00012 #endif /* not lint */
00013 
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016 
00017 #include <ctype.h>
00018 #include <errno.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <unistd.h>
00022 #endif
00023 
00024 #include "db_int.h"
00025 #include "db_page.h"
00026 #include "db_shash.h"
00027 #include "btree.h"
00028 #include "hash.h"
00029 #include "qam.h"
00030 #include "lock.h"
00031 #include "log.h"
00032 #include "mp.h"
00033 #include "txn.h"
00034 #include "clib.h"
00035 
00036 static int __dbenv_config __P((DB_ENV *, const char *, u_int32_t));
00037 static int __dbenv_refresh __P((DB_ENV *));
00038 static int __db_home __P((DB_ENV *, const char *, u_int32_t));
00039 static int __db_parse __P((DB_ENV *, char *));
00040 static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, DB_FH *));
00041 
00042 /*
00043  * CDB_db_version --
00044  * Return version information.
00045  */
00046 char *
00047 CDB_db_version(majverp, minverp, patchp)
00048 int *majverp, *minverp, *patchp;
00049 {
00050 if (majverp != NULL)
00051 *majverp = DB_VERSION_MAJOR;
00052 if (minverp != NULL)
00053 *minverp = DB_VERSION_MINOR;
00054 if (patchp != NULL)
00055 *patchp = DB_VERSION_PATCH;
00056 return ((char *)DB_VERSION_STRING);
00057 }
00058 
00059 /*
00060  * CDB___dbenv_open --
00061  * Initialize an environment.
00062  *
00063  * PUBLIC: int CDB___dbenv_open __P((DB_ENV *, const char *, u_int32_t, int));
00064  */
00065 int
00066 CDB___dbenv_open(dbenv, db_home, flags, mode)
00067 DB_ENV *dbenv;
00068 const char *db_home;
00069 u_int32_t flags;
00070 int mode;
00071 {
00072 DB_ENV *rm_dbenv;
00073 int ret;
00074 
00075 #undef OKFLAGS
00076 #define OKFLAGS \
00077  DB_CREATE | DB_INIT_CDB | DB_INIT_LOCK | DB_INIT_LOG | \
00078  DB_INIT_MPOOL | DB_INIT_TXN | DB_LOCKDOWN | DB_NOMMAP | \
00079  DB_PRIVATE | DB_RECOVER | DB_RECOVER_FATAL | DB_SYSTEM_MEM | \
00080  DB_THREAD | DB_TXN_NOSYNC | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT
00081 #undef OKFLAGS_CDB
00082 #define OKFLAGS_CDB \
00083  DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL | DB_LOCKDOWN | \
00084  DB_NOMMAP | DB_PRIVATE | DB_SYSTEM_MEM | DB_THREAD | \
00085  DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT
00086 
00087 if ((ret = CDB___db_fchk(dbenv, "DBENV->open", flags, OKFLAGS)) != 0)
00088 return (ret);
00089 if (LF_ISSET(DB_INIT_CDB) &&
00090 (ret = CDB___db_fchk(dbenv, "DBENV->open", flags, OKFLAGS_CDB)) != 0)
00091 return (ret);
00092 if ((ret = CDB___db_fcchk(dbenv,
00093 "DBENV->open", flags, DB_PRIVATE, DB_SYSTEM_MEM)) != 0)
00094 return (ret);
00095 
00096 /*
00097  * If we're doing recovery, destroy the environment so that we create
00098  * all the regions from scratch. I'd like to reuse already created
00099  * regions, but that's hard. We would have to create the environment
00100  * region from scratch, at least, as we have no way of knowing if its
00101  * linked lists are corrupted.
00102  *
00103  * I suppose we could set flags while modifying those links, but that
00104  * is going to be difficult to get right. The major concern I have
00105  * is if the application stomps the environment with a rogue pointer.
00106  * We have no way of detecting that, and we could be forced into a
00107  * situation where we start up and then crash, repeatedly.
00108  *
00109  * Note that we do not check any flags like DB_PRIVATE before calling
00110  * remove. We don't care if the current environment was private or
00111  * not, we just want to nail any files that are left-over for whatever
00112  * reason, from whatever session.
00113  */
00114 if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) {
00115 if ((ret = CDB_db_env_create(&rm_dbenv, 0)) != 0)
00116 return (ret);
00117 if ((ret = dbenv->remove(rm_dbenv, db_home, DB_FORCE)) != 0)
00118 return (ret);
00119 }
00120 
00121 /* Initialize the DB_ENV structure. */
00122 if ((ret = __dbenv_config(dbenv, db_home, flags)) != 0)
00123 goto err;
00124 
00125 /* Convert the DBENV->open flags to internal flags. */
00126 if (LF_ISSET(DB_CREATE))
00127 F_SET(dbenv, DB_ENV_CREATE);
00128 if (LF_ISSET(DB_LOCKDOWN))
00129 F_SET(dbenv, DB_ENV_LOCKDOWN);
00130 if (LF_ISSET(DB_NOMMAP))
00131 F_SET(dbenv, DB_ENV_NOMMAP);
00132 if (LF_ISSET(DB_PRIVATE))
00133 F_SET(dbenv, DB_ENV_PRIVATE);
00134 if (LF_ISSET(DB_SYSTEM_MEM))
00135 F_SET(dbenv, DB_ENV_SYSTEM_MEM);
00136 if (LF_ISSET(DB_THREAD))
00137 F_SET(dbenv, DB_ENV_THREAD);
00138 if (LF_ISSET(DB_TXN_NOSYNC))
00139 F_SET(dbenv, DB_ENV_TXN_NOSYNC);
00140 
00141 /* Default permissions are read-write for both owner and group. */
00142 dbenv->db_mode = mode == 0 ? CDB___db_omode("rwrw--") : mode;
00143 
00144 /* Initialize for CDB product. */
00145 if (LF_ISSET(DB_INIT_CDB)) {
00146 LF_SET(DB_INIT_LOCK);
00147 F_SET(dbenv, DB_ENV_CDB);
00148 }
00149 
00150 /* Create/join the environment. */
00151 if ((ret = CDB___db_e_attach(dbenv)) != 0)
00152 goto err;
00153 
00154 /*
00155  * Initialize the subsystems. Transactions imply logging but do not
00156  * imply locking. While almost all applications want both locking
00157  * and logging, it would not be unreasonable for a single threaded
00158  * process to want transactions for atomicity guarantees, but not
00159  * necessarily need concurrency.
00160  */
00161 if (LF_ISSET(DB_INIT_MPOOL))
00162 if ((ret = CDB___memp_open(dbenv)) != 0)
00163 goto err;
00164 if (LF_ISSET(DB_INIT_LOG | DB_INIT_TXN))
00165 if ((ret = CDB___log_open(dbenv)) != 0)
00166 goto err;
00167 if (LF_ISSET(DB_INIT_LOCK))
00168 if ((ret = CDB___lock_open(dbenv)) != 0)
00169 goto err;
00170 if (LF_ISSET(DB_INIT_TXN)) {
00171 if ((ret = CDB___txn_open(dbenv)) != 0)
00172 goto err;
00173 
00174 /*
00175  * If the application is running with transactions, initialize
00176  * the function tables.
00177  */
00178 if ((ret = CDB___bam_init_recover(dbenv)) != 0)
00179 goto err;
00180 if ((ret = CDB___crdel_init_recover(dbenv)) != 0)
00181 goto err;
00182 if ((ret = CDB___db_init_recover(dbenv)) != 0)
00183 goto err;
00184 if ((ret = CDB___ham_init_recover(dbenv)) != 0)
00185 goto err;
00186 if ((ret = CDB___log_init_recover(dbenv)) != 0)
00187 goto err;
00188 if ((ret = CDB___qam_init_recover(dbenv)) != 0)
00189 goto err;
00190 if ((ret = CDB___txn_init_recover(dbenv)) != 0)
00191 goto err;
00192 
00193 /*
00194  * If the application specified their own recovery
00195  * initialization function, call it.
00196  */
00197 if (dbenv->db_recovery_init != NULL &&
00198 (ret = dbenv->db_recovery_init(dbenv)) != 0)
00199 goto err;
00200 
00201 /* Perform recovery for any previous run. */
00202 if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
00203 (ret = CDB___db_apprec(dbenv,
00204 LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
00205 goto err;
00206 }
00207 return (0);
00208 
00209 err: (void)__dbenv_refresh(dbenv);
00210 return (ret);
00211 }
00212 
00213 /*
00214  * CDB___dbenv_remove --
00215  * Discard an environment.
00216  *
00217  * PUBLIC: int CDB___dbenv_remove __P((DB_ENV *, const char *, u_int32_t));
00218  */
00219 int
00220 CDB___dbenv_remove(dbenv, db_home, flags)
00221 DB_ENV *dbenv;
00222 const char *db_home;
00223 u_int32_t flags;
00224 {
00225 int ret, t_ret;
00226 
00227 #undef OKFLAGS
00228 #define OKFLAGS \
00229  DB_FORCE | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT
00230 
00231 /* Validate arguments. */
00232 if ((ret = CDB___db_fchk(dbenv, "DBENV->remove", flags, OKFLAGS)) != 0)
00233 return (ret);
00234 
00235 /* Initialize the DB_ENV structure. */
00236 if ((ret = __dbenv_config(dbenv, db_home, flags)) != 0)
00237 goto err;
00238 
00239 /* Remove the environment. */
00240 ret = CDB___db_e_remove(dbenv, LF_ISSET(DB_FORCE) ? 1 : 0);
00241 
00242 /* Discard any resources we've acquired. */
00243 err: if ((t_ret = __dbenv_refresh(dbenv)) != 0 && ret == 0)
00244 ret = t_ret;
00245 
00246 memset(dbenv, CLEAR_BYTE, sizeof(DB_ENV));
00247 CDB___os_free(dbenv, sizeof(DB_ENV));
00248 
00249 return (ret);
00250 }
00251 
00252 /*
00253  * __dbenv_config --
00254  * Initialize the DB_ENV structure.
00255  */
00256 static int
00257 __dbenv_config(dbenv, db_home, flags)
00258 DB_ENV *dbenv;
00259 const char *db_home;
00260 u_int32_t flags;
00261 {
00262 FILE *fp;
00263 int ret;
00264 char *lp, buf[MAXPATHLEN * 2];
00265 
00266 /* Set the database home. */
00267 if ((ret = __db_home(dbenv, db_home, flags)) != 0)
00268 return (ret);
00269 
00270 /*
00271  * Parse the config file.
00272  *
00273  * !!!
00274  * Don't use sprintf(3)/snprintf(3) -- the former is dangerous, and
00275  * the latter isn't standard, and we're manipulating strings handed
00276  * us by the application.
00277  */
00278 if (dbenv->db_home != NULL) {
00279 #define CONFIG_NAME "/DB_CONFIG"
00280 if (strlen(dbenv->db_home) +
00281 strlen(CONFIG_NAME) + 1 > sizeof(buf)) {
00282 ret = ENAMETOOLONG;
00283 return (ret);
00284 }
00285 (void)strcpy(buf, dbenv->db_home);
00286 (void)strcat(buf, CONFIG_NAME);
00287 if ((fp = fopen(buf, "r")) != NULL) {
00288 while (fgets(buf, sizeof(buf), fp) != NULL) {
00289 if ((lp = strchr(buf, '\n')) == NULL) {
00290 CDB___db_err(dbenv,
00291 "%s: line too long", CONFIG_NAME);
00292 (void)fclose(fp);
00293 ret = EINVAL;
00294 return (ret);
00295 }
00296 *lp = '0円';
00297 if (buf[0] == '0円' ||
00298 buf[0] == '#' || isspace((int)buf[0]))
00299 continue;
00300 
00301 if ((ret = __db_parse(dbenv, buf)) != 0) {
00302 (void)fclose(fp);
00303 return (ret);
00304 }
00305 }
00306 (void)fclose(fp);
00307 }
00308 }
00309 
00310 /* Set up the tmp directory path. */
00311 if (dbenv->db_tmp_dir == NULL && (ret = CDB___os_tmpdir(dbenv, flags)) != 0)
00312 return (ret);
00313 
00314 /*
00315  * The locking file descriptor is rarely on. Set the fd to -1, not
00316  * because it's ever tested, but to make sure we catch mistakes.
00317  */
00318 if ((ret =
00319 CDB___os_calloc(dbenv,
00320 1, sizeof(*dbenv->lockfhp), &dbenv->lockfhp)) != 0)
00321 return (ret);
00322 dbenv->lockfhp->fd = -1;
00323 
00324 /*
00325  * Flag that the DB_ENV structure has been initialized. Note, this
00326  * must be set before calling into the subsystems as it's used during
00327  * file naming.
00328  */
00329 F_SET(dbenv, DB_ENV_OPEN_CALLED);
00330 
00331 return (0);
00332 }
00333 
00334 /*
00335  * CDB___dbenv_close --
00336  * DB_ENV destructor.
00337  *
00338  * PUBLIC: int CDB___dbenv_close __P((DB_ENV *, u_int32_t));
00339  */
00340 int
00341 CDB___dbenv_close(dbenv, flags)
00342 DB_ENV *dbenv;
00343 u_int32_t flags;
00344 {
00345 int ret;
00346 
00347 COMPQUIET(flags, 0);
00348 
00349 PANIC_CHECK(dbenv);
00350 
00351 ret = __dbenv_refresh(dbenv);
00352 
00353 /* Discard the structure if we allocated it. */
00354 if (!F_ISSET(dbenv, DB_ENV_USER_ALLOC)) {
00355 memset(dbenv, CLEAR_BYTE, sizeof(DB_ENV));
00356 CDB___os_free(dbenv, sizeof(DB_ENV));
00357 }
00358 
00359 return (ret);
00360 }
00361 
00362 /*
00363  * __dbenv_refresh --
00364  * Refresh the DB_ENV structure, releasing any allocated resources.
00365  */
00366 static int
00367 __dbenv_refresh(dbenv)
00368 DB_ENV *dbenv;
00369 {
00370 int ret, t_ret;
00371 char **p;
00372 
00373 ret = 0;
00374 
00375 /*
00376  * Close subsystems, in the reverse order they were opened (txn
00377  * must be first, it may want to discard locks and flush the log).
00378  */
00379 if (TXN_ON(dbenv)) {
00380 if ((t_ret = CDB___txn_close(dbenv)) != 0 && ret == 0)
00381 ret = t_ret;
00382 }
00383 
00384 if (LOCKING_ON(dbenv)) {
00385 if ((t_ret = CDB___lock_close(dbenv)) != 0 && ret == 0)
00386 ret = t_ret;
00387 }
00388 CDB___lock_dbenv_close(dbenv);
00389 
00390 if (LOGGING_ON(dbenv)) {
00391 if ((t_ret = CDB___log_close(dbenv)) != 0 && ret == 0)
00392 ret = t_ret;
00393 }
00394 
00395 if (MPOOL_ON(dbenv)) {
00396 if ((t_ret = CDB___memp_close(dbenv)) != 0 && ret == 0)
00397 ret = t_ret;
00398 }
00399 
00400 /* Detach from the region. */
00401 if (dbenv->reginfo != NULL) {
00402 if ((t_ret = CDB___db_e_detach(dbenv, 0)) != 0 && ret == 0)
00403 ret = t_ret;
00404 /*
00405  * !!!
00406  * Don't free dbenv->reginfo or set the reference to NULL,
00407  * that was done by CDB___db_e_detach().
00408  */
00409 }
00410 
00411 /* Clean up the structure. */
00412 dbenv->db_panic = 0;
00413 
00414 if (dbenv->db_home != NULL) {
00415 CDB___os_freestr(dbenv->db_home);
00416 dbenv->db_home = NULL;
00417 }
00418 if (dbenv->db_log_dir != NULL) {
00419 CDB___os_freestr(dbenv->db_log_dir);
00420 dbenv->db_log_dir = NULL;
00421 }
00422 if (dbenv->db_tmp_dir != NULL) {
00423 CDB___os_freestr(dbenv->db_tmp_dir);
00424 dbenv->db_tmp_dir = NULL;
00425 }
00426 if (dbenv->db_data_dir != NULL) {
00427 for (p = dbenv->db_data_dir; *p != NULL; ++p)
00428 CDB___os_freestr(*p);
00429 CDB___os_free(dbenv->db_data_dir,
00430 dbenv->data_cnt * sizeof(char **));
00431 dbenv->db_data_dir = NULL;
00432 }
00433 dbenv->data_cnt = dbenv->data_next = 0;
00434 
00435 dbenv->db_mode = 0;
00436 
00437 if (dbenv->lockfhp != NULL) {
00438 CDB___os_free(dbenv->lockfhp, sizeof(*dbenv->lockfhp));
00439 dbenv->lockfhp = NULL;
00440 }
00441 
00442 if (dbenv->dtab != NULL) {
00443 CDB___os_free(dbenv->dtab,
00444 dbenv->dtab_size * sizeof(dbenv->dtab[0]));
00445 dbenv->dtab = NULL;
00446 dbenv->dtab_size = 0;
00447 }
00448 
00449 dbenv->mp_mmapsize = 0;
00450 dbenv->links.tqe_next = NULL;
00451 dbenv->links.tqe_prev = NULL;
00452 dbenv->xa_rmid = 0;
00453 dbenv->xa_txn = 0;
00454 
00455 F_CLR(dbenv, ~(DB_ENV_STANDALONE | DB_ENV_USER_ALLOC));
00456 
00457 return (ret);
00458 }
00459 
00460 #define DB_ADDSTR(add) { \
00461  if ((add) != NULL) { \
00462 /* If leading slash, start over. */ \
00463 if (CDB___os_abspath(add)) { \
00464 p = str; \
00465 slash = 0; \
00466 } \
00467 /* Append to the current string. */ \
00468 len = strlen(add); \
00469 if (slash) \
00470 *p++ = PATH_SEPARATOR[0]; \
00471 memcpy(p, add, len); \
00472 p += len; \
00473 slash = strchr(PATH_SEPARATOR, p[-1]) == NULL; \
00474 } \
00475 }
00476 
00477 /*
00478  * CDB___db_appname --
00479  * Given an optional DB environment, directory and file name and type
00480  * of call, build a path based on the DBENV->open rules, and return
00481  * it in allocated space.
00482  *
00483  * PUBLIC: int CDB___db_appname __P((DB_ENV *, APPNAME,
00484  * PUBLIC: const char *, const char *, u_int32_t, DB_FH *, char **));
00485  */
00486 int
00487 CDB___db_appname(dbenv, appname, dir, file, tmp_oflags, fhp, namep)
00488 DB_ENV *dbenv;
00489 APPNAME appname;
00490 const char *dir, *file;
00491 u_int32_t tmp_oflags;
00492 DB_FH *fhp;
00493 char **namep;
00494 {
00495 DB_ENV etmp;
00496 size_t len, str_len;
00497 int data_entry, ret, slash, tmp_create, tmp_free;
00498 const char *a, *b, *c;
00499 char *p, *str;
00500 
00501 a = b = c = NULL;
00502 data_entry = -1;
00503 tmp_create = tmp_free = 0;
00504 
00505 /*
00506  * We don't return a name when creating temporary files, just a
00507  * file handle. Default to an error now.
00508  */
00509 if (fhp != NULL)
00510 F_CLR(fhp, DB_FH_VALID);
00511 if (namep != NULL)
00512 *namep = NULL;
00513 
00514 /*
00515  * Absolute path names are never modified. If the file is an absolute
00516  * path, we're done. If the directory is, simply append the file and
00517  * return.
00518  */
00519 if (file != NULL && CDB___os_abspath(file))
00520 return (CDB___os_strdup(dbenv, file, namep));
00521 if (dir != NULL && CDB___os_abspath(dir)) {
00522 a = dir;
00523 goto done;
00524 }
00525 
00526 /*
00527  * DB_ENV DIR APPNAME RESULT
00528  * -------------------------------------------
00529  * null null none <tmp>/file
00530  * null set none DIR/file
00531  * set null none DB_HOME/file
00532  * set set none DB_HOME/DIR/file
00533  *
00534  * DB_ENV FILE APPNAME RESULT
00535  * -------------------------------------------
00536  * null null DB_APP_DATA <tmp>/<create>
00537  * null set DB_APP_DATA ./file
00538  * set null DB_APP_DATA <tmp>/<create>
00539  * set set DB_APP_DATA DB_HOME/DB_DATA_DIR/file
00540  *
00541  * DB_ENV DIR APPNAME RESULT
00542  * -------------------------------------------
00543  * null null DB_APP_LOG <tmp>/file
00544  * null set DB_APP_LOG DIR/file
00545  * set null DB_APP_LOG DB_HOME/DB_LOG_DIR/file
00546  * set set DB_APP_LOG DB_HOME/DB_LOG_DIR/DIR/file
00547  *
00548  * DB_ENV APPNAME RESULT
00549  * -------------------------------------------
00550  * null DB_APP_TMP* <tmp>/<create>
00551  * set DB_APP_TMP* DB_HOME/DB_TMP_DIR/<create>
00552  */
00553 retry: switch (appname) {
00554 case DB_APP_NONE:
00555 if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
00556 if (dir == NULL)
00557 goto tmp;
00558 a = dir;
00559 } else {
00560 a = dbenv->db_home;
00561 b = dir;
00562 }
00563 break;
00564 case DB_APP_DATA:
00565 if (dir != NULL) {
00566 CDB___db_err(dbenv,
00567 "DB_APP_DATA: illegal directory specification");
00568 return (EINVAL);
00569 }
00570 
00571 if (file == NULL) {
00572 tmp_create = 1;
00573 goto tmp;
00574 }
00575 if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED))
00576 a = PATH_DOT;
00577 else {
00578 a = dbenv->db_home;
00579 if (dbenv->db_data_dir != NULL &&
00580 (b = dbenv->db_data_dir[++data_entry]) == NULL) {
00581 data_entry = -1;
00582 b = dbenv->db_data_dir[0];
00583 }
00584 }
00585 break;
00586 case DB_APP_LOG:
00587 if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
00588 if (dir == NULL)
00589 goto tmp;
00590 a = dir;
00591 } else {
00592 a = dbenv->db_home;
00593 b = dbenv->db_log_dir;
00594 c = dir;
00595 }
00596 break;
00597 case DB_APP_TMP:
00598 if (dir != NULL || file != NULL) {
00599 CDB___db_err(dbenv,
00600 "DB_APP_TMP: illegal directory or file specification");
00601 return (EINVAL);
00602 }
00603 
00604 tmp_create = 1;
00605 if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED))
00606 goto tmp;
00607 else {
00608 a = dbenv->db_home;
00609 b = dbenv->db_tmp_dir;
00610 }
00611 break;
00612 }
00613 
00614 /* Reference a file from the appropriate temporary directory. */
00615 if (0) {
00616 tmp: if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
00617 memset(&etmp, 0, sizeof(etmp));
00618 if ((ret = CDB___os_tmpdir(&etmp, DB_USE_ENVIRON)) != 0)
00619 return (ret);
00620 tmp_free = 1;
00621 a = etmp.db_tmp_dir;
00622 } else
00623 a = dbenv->db_tmp_dir;
00624 }
00625 
00626 done: len =
00627 (a == NULL ? 0 : strlen(a) + 1) +
00628 (b == NULL ? 0 : strlen(b) + 1) +
00629 (c == NULL ? 0 : strlen(c) + 1) +
00630 (file == NULL ? 0 : strlen(file) + 1);
00631 
00632 /*
00633  * Allocate space to hold the current path information, as well as any
00634  * temporary space that we're going to need to create a temporary file
00635  * name.
00636  */
00637 #define DB_TRAIL "BDBXXXXXX"
00638 str_len = len + sizeof(DB_TRAIL) + 10;
00639 if ((ret = CDB___os_malloc(dbenv, str_len, NULL, &str)) != 0) {
00640 if (tmp_free)
00641 CDB___os_freestr(etmp.db_tmp_dir);
00642 return (ret);
00643 }
00644 
00645 slash = 0;
00646 p = str;
00647 DB_ADDSTR(a);
00648 DB_ADDSTR(b);
00649 DB_ADDSTR(file);
00650 *p = '0円';
00651 
00652 /* Discard any space allocated to find the temp directory. */
00653 if (tmp_free) {
00654 CDB___os_freestr(etmp.db_tmp_dir);
00655 tmp_free = 0;
00656 }
00657 
00658 /*
00659  * If we're opening a data file, see if it exists. If it does,
00660  * return it, otherwise, try and find another one to open.
00661  */
00662 if (data_entry != -1 && CDB___os_exists(str, NULL) != 0) {
00663 CDB___os_free(str, str_len);
00664 a = b = c = NULL;
00665 goto retry;
00666 }
00667 
00668 /* Create the file if so requested. */
00669 if (tmp_create &&
00670 (ret = __db_tmp_open(dbenv, tmp_oflags, str, fhp)) != 0) {
00671 CDB___os_free(str, str_len);
00672 return (ret);
00673 }
00674 
00675 if (namep == NULL)
00676 CDB___os_free(str, str_len);
00677 else
00678 *namep = str;
00679 return (0);
00680 }
00681 
00682 /*
00683  * __db_home --
00684  * Find the database home.
00685  */
00686 static int
00687 __db_home(dbenv, db_home, flags)
00688 DB_ENV *dbenv;
00689 const char *db_home;
00690 u_int32_t flags;
00691 {
00692 const char *p;
00693 
00694 /*
00695  * Use db_home by default, this allows utilities to reasonably
00696  * override the environment either explicitly or by using a -h
00697  * option. Otherwise, use the environment if it's permitted
00698  * and initialized.
00699  */
00700 if ((p = db_home) == NULL &&
00701 (LF_ISSET(DB_USE_ENVIRON) ||
00702 (LF_ISSET(DB_USE_ENVIRON_ROOT) && CDB___os_isroot() == 0)) &&
00703 (p = getenv("DB_HOME")) != NULL && p[0] == '0円') {
00704 CDB___db_err(dbenv, "illegal DB_HOME environment variable");
00705 return (EINVAL);
00706 }
00707 
00708 return (p == NULL ? 0 : CDB___os_strdup(dbenv, p, &dbenv->db_home));
00709 }
00710 
00711 /*
00712  * __db_parse --
00713  * Parse a single NAME VALUE pair.
00714  */
00715 static int
00716 __db_parse(dbenv, s)
00717 DB_ENV *dbenv;
00718 char *s;
00719 {
00720 u_long v1, v2, v3;
00721 u_int32_t flags;
00722 char *name, *p, *value, v4;
00723 
00724 /*
00725  * !!!
00726  * The value of 40 is hard-coded into format arguments to sscanf
00727  * below, it can't be changed here without changing it there, too.
00728  */
00729 char arg[40];
00730 
00731 /*
00732  * Name/value pairs are parsed as two white-space separated strings.
00733  * Leading and trailing white-space is trimmed from the value, but
00734  * it may contain embedded white-space. Note: we use the isspace(3)
00735  * macro because it's more portable, but that means that you can use
00736  * characters like form-feed to separate the strings.
00737  */
00738 name = s;
00739 for (p = name; *p != '0円' && !isspace((int)*p); ++p)
00740 ;
00741 if (*p == '0円' || p == name)
00742 goto illegal;
00743 *p = '0円';
00744 for (++p; isspace((int)*p); ++p)
00745 ;
00746 if (*p == '0円')
00747 goto illegal;
00748 value = p;
00749 for (++p; *p != '0円'; ++p)
00750 ;
00751 for (--p; isspace((int)*p); --p)
00752 ;
00753 ++p;
00754 if (p == value) {
00755 illegal: CDB___db_err(dbenv, "mis-formatted name-value pair: %s", s);
00756 return (EINVAL);
00757 }
00758 *p = '0円';
00759 
00760 if (!strcasecmp(name, "set_cachesize")) {
00761 if (sscanf(value, "%lu %lu %lu %c", &v1, &v2, &v3, &v4) != 3)
00762 goto badarg;
00763 return (dbenv->set_cachesize(dbenv, v1, v2, v3));
00764 }
00765 
00766 if (!strcasecmp(name, "set_data_dir") ||
00767 !strcasecmp(name, "db_data_dir")) /* Compatibility. */
00768 return (dbenv->set_data_dir(dbenv, value));
00769 
00770 if (!strcasecmp(name, "set_lg_bsize")) {
00771 if (sscanf(value, "%lu %c", &v1, &v4) != 1)
00772 goto badarg;
00773 return (dbenv->set_lg_bsize(dbenv, v1));
00774 }
00775 
00776 if (!strcasecmp(name, "set_lg_max")) {
00777 if (sscanf(value, "%lu %c", &v1, &v4) != 1)
00778 goto badarg;
00779 return (dbenv->set_lg_max(dbenv, v1));
00780 }
00781 
00782 if (!strcasecmp(name, "set_lg_dir") ||
00783 !strcasecmp(name, "db_log_dir")) /* Compatibility. */
00784 return (dbenv->set_lg_dir(dbenv, value));
00785 
00786 if (!strcasecmp(name, "set_lk_detect")) {
00787 if (sscanf(value, "%40s %c", arg, &v4) != 1)
00788 goto badarg;
00789 if (!strcasecmp(value, "db_lock_default"))
00790 flags = DB_LOCK_DEFAULT;
00791 else if (!strcasecmp(value, "db_lock_oldest"))
00792 flags = DB_LOCK_OLDEST;
00793 else if (!strcasecmp(value, "db_lock_random"))
00794 flags = DB_LOCK_RANDOM;
00795 else if (!strcasecmp(value, "db_lock_youngest"))
00796 flags = DB_LOCK_YOUNGEST;
00797 else
00798 goto badarg;
00799 return (dbenv->set_lk_detect(dbenv, flags));
00800 }
00801 
00802 if (!strcasecmp(name, "set_lk_max")) {
00803 if (sscanf(value, "%lu %c", &v1, &v4) != 1)
00804 goto badarg;
00805 return (dbenv->set_lk_max(dbenv, v1));
00806 }
00807 
00808 if (!strcasecmp(name, "set_mp_mmapsize")) {
00809 if (sscanf(value, "%lu %c", &v1, &v4) != 1)
00810 goto badarg;
00811 return (dbenv->set_mp_mmapsize(dbenv, v1));
00812 }
00813 
00814 if (!strcasecmp(name, "set_region_init")) {
00815 if (sscanf(value, "%lu %c", &v1, &v4) != 1 || v1 != 1)
00816 goto badarg;
00817 return (CDB_db_env_set_region_init(v1));
00818 }
00819 
00820 if (!strcasecmp(name, "set_shm_key")) {
00821 if (sscanf(value, "%lu %c", &v1, &v4) != 1)
00822 goto badarg;
00823 return (dbenv->set_shm_key(dbenv, (long)v1));
00824 }
00825 
00826 if (!strcasecmp(name, "set_tas_spins")) {
00827 if (sscanf(value, "%lu %c", &v1, &v4) != 1)
00828 goto badarg;
00829 return (CDB_db_env_set_tas_spins(v1));
00830 }
00831 
00832 if (!strcasecmp(name, "set_tmp_dir") ||
00833 !strcasecmp(name, "db_tmp_dir")) /* Compatibility.*/
00834 return (dbenv->set_tmp_dir(dbenv, value));
00835 
00836 if (!strcasecmp(name, "set_tx_max")) {
00837 if (sscanf(value, "%lu %c", &v1, &v4) != 1)
00838 goto badarg;
00839 return (dbenv->set_tx_max(dbenv, v1));
00840 }
00841 
00842 if (!strcasecmp(name, "set_verbose")) {
00843 if (sscanf(value, "%40s %c", arg, &v4) != 1)
00844 goto badarg;
00845 
00846 if (!strcasecmp(value, "db_verb_chkpoint"))
00847 flags = DB_VERB_CHKPOINT;
00848 else if (!strcasecmp(value, "db_verb_deadlock"))
00849 flags = DB_VERB_DEADLOCK;
00850 else if (!strcasecmp(value, "db_verb_recovery"))
00851 flags = DB_VERB_RECOVERY;
00852 else if (!strcasecmp(value, "db_verb_waitsfor"))
00853 flags = DB_VERB_WAITSFOR;
00854 else
00855 goto badarg;
00856 return (dbenv->set_verbose(dbenv, flags, 1));
00857 }
00858 
00859 CDB___db_err(dbenv, "unrecognized name-value pair: %s", s);
00860 return (EINVAL);
00861 
00862 badarg: CDB___db_err(dbenv, "incorrect arguments for name-value pair: %s", s);
00863 return (EINVAL);
00864 }
00865 
00866 /*
00867  * __db_tmp_open --
00868  * Create a temporary file.
00869  */
00870 static int
00871 __db_tmp_open(dbenv, tmp_oflags, path, fhp)
00872 DB_ENV *dbenv;
00873 u_int32_t tmp_oflags;
00874 char *path;
00875 DB_FH *fhp;
00876 {
00877 u_long pid;
00878 int mode, isdir, ret;
00879 const char *p;
00880 char *trv;
00881 
00882 /*
00883  * Check the target directory; if you have six X's and it doesn't
00884  * exist, this runs for a *very* long time.
00885  */
00886 if ((ret = CDB___os_exists(path, &isdir)) != 0) {
00887 CDB___db_err(dbenv, "%s: %s", path, CDB_db_strerror(ret));
00888 return (ret);
00889 }
00890 if (!isdir) {
00891 CDB___db_err(dbenv, "%s: %s", path, CDB_db_strerror(EINVAL));
00892 return (EINVAL);
00893 }
00894 
00895 /* Build the path. */
00896 for (trv = path; *trv != '0円'; ++trv)
00897 ;
00898 *trv = PATH_SEPARATOR[0];
00899 for (p = DB_TRAIL; (*++trv = *p) != '0円'; ++p)
00900 ;
00901 
00902 /*
00903  * Replace the X's with the process ID. Pid should be a pid_t,
00904  * but we use unsigned long for portability.
00905  */
00906 for (pid = getpid(); *--trv == 'X'; pid /= 10)
00907 switch (pid % 10) {
00908 case 0: *trv = '0'; break;
00909 case 1: *trv = '1'; break;
00910 case 2: *trv = '2'; break;
00911 case 3: *trv = '3'; break;
00912 case 4: *trv = '4'; break;
00913 case 5: *trv = '5'; break;
00914 case 6: *trv = '6'; break;
00915 case 7: *trv = '7'; break;
00916 case 8: *trv = '8'; break;
00917 case 9: *trv = '9'; break;
00918 }
00919 ++trv;
00920 
00921 /* Set up open flags and mode. */
00922 mode = CDB___db_omode("rw----");
00923 
00924 /* Loop, trying to open a file. */
00925 for (;;) {
00926 if ((ret = CDB___os_open(dbenv, path,
00927 tmp_oflags | DB_OSO_CREATE | DB_OSO_EXCL, mode, fhp)) == 0)
00928 return (0);
00929 
00930 /*
00931  * !!!:
00932  * If we don't get an EEXIST error, then there's something
00933  * seriously wrong. Unfortunately, if the implementation
00934  * doesn't return EEXIST for O_CREAT and O_EXCL regardless
00935  * of other possible errors, we've lost.
00936  */
00937 if (ret != EEXIST) {
00938 CDB___db_err(dbenv,
00939 "tmp_open: %s: %s", path, CDB_db_strerror(ret));
00940 return (ret);
00941 }
00942 
00943 /*
00944  * Tricky little algorithm for backward compatibility.
00945  * Assumes sequential ordering of lower-case characters.
00946  */
00947 for (;;) {
00948 if (*trv == '0円')
00949 return (EINVAL);
00950 if (*trv == 'z')
00951 *trv++ = 'a';
00952 else {
00953 if (isdigit((int)*trv))
00954 *trv = 'a';
00955 else
00956 ++*trv;
00957 break;
00958 }
00959 }
00960 }
00961 /* NOTREACHED */
00962 }

Generated on Sun Jun 8 10:56:37 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /