📄 env_open.c
字号:
* Discard an environment, internal version. */static int__dbenv_remove_int(dbenv, db_home, flags) DB_ENV *dbenv; const char *db_home; u_int32_t flags;{ int ret; /* Initialize the DB_ENV structure. */ if ((ret = __dbenv_config(dbenv, db_home, flags)) != 0) return (ret); /* Remove the environment. */ return (__db_e_remove(dbenv, flags));}/* * __dbenv_config -- * Minor initialization of the DB_ENV structure, read the DB_CONFIG file. */static int__dbenv_config(dbenv, db_home, flags) DB_ENV *dbenv; const char *db_home; u_int32_t flags;{ FILE *fp; int ret; char *p, buf[256]; /* * Set the database home. Do this before calling __db_appname, * it uses the home directory. */ if ((ret = __db_home(dbenv, db_home, flags)) != 0) return (ret); /* Parse the config file. */ p = NULL; if ((ret = __db_appname(dbenv, DB_APP_NONE, "DB_CONFIG", 0, NULL, &p)) != 0) return (ret); if (p == NULL) fp = NULL; else { fp = fopen(p, "r"); __os_free(dbenv, p); } if (fp != NULL) { while (fgets(buf, sizeof(buf), fp) != NULL) { if ((p = strchr(buf, '\n')) != NULL) *p = '\0'; else if (strlen(buf) + 1 == sizeof(buf)) { __db_err(dbenv, "DB_CONFIG: line too long"); (void)fclose(fp); return (EINVAL); } if (buf[0] == '\0' || buf[0] == '#' || isspace((int)buf[0])) continue; if ((ret = __db_parse(dbenv, buf)) != 0) { (void)fclose(fp); return (ret); } } (void)fclose(fp); } /* * If no temporary directory path was specified in the config file, * choose one. */ if (dbenv->db_tmp_dir == NULL && (ret = __os_tmpdir(dbenv, flags)) != 0) return (ret); /* Flag that the DB_ENV structure has been initialized. */ F_SET(dbenv, DB_ENV_OPEN_CALLED); return (0);}/* * __dbenv_close_pp -- * DB_ENV->close pre/post processor. * * PUBLIC: int __dbenv_close_pp __P((DB_ENV *, u_int32_t)); */int__dbenv_close_pp(dbenv, flags) DB_ENV *dbenv; u_int32_t flags;{ int rep_check, ret, t_ret; ret = 0; PANIC_CHECK(dbenv); /* * Validate arguments, but as a DB_ENV handle destructor, we can't * fail. */ if (flags != 0 && (t_ret = __db_ferr(dbenv, "DB_ENV->close", 0)) != 0 && ret == 0) ret = t_ret; rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0; if (rep_check) __env_rep_enter(dbenv); if ((t_ret = __dbenv_close(dbenv, rep_check)) != 0 && ret == 0) ret = t_ret; return (ret);}/* * __dbenv_close -- * DB_ENV->close. * * PUBLIC: int __dbenv_close __P((DB_ENV *, int)); */int__dbenv_close(dbenv, rep_check) DB_ENV *dbenv; int rep_check;{ int ret, t_ret; char **p; ret = 0; /* * Before checking the reference count, we have to see if we were in * the middle of restoring transactions and need to close the open * files. */ if (TXN_ON(dbenv) && (t_ret = __txn_preclose(dbenv)) != 0 && ret == 0) ret = t_ret; if (REP_ON(dbenv) && (t_ret = __rep_preclose(dbenv, 1)) != 0 && ret == 0) ret = t_ret; /* * Detach from the regions and undo the allocations done by * DB_ENV->open. */ if ((t_ret = __dbenv_refresh(dbenv, 0, rep_check)) != 0 && ret == 0) ret = t_ret; /* Do per-subsystem close. */ if ((t_ret = __lock_dbenv_close(dbenv)) != 0 && ret == 0) ret = t_ret; if ((t_ret = __rep_dbenv_close(dbenv)) != 0 && ret == 0) ret = t_ret;#ifdef HAVE_CRYPTO /* * Crypto comes last, because higher level close functions need * cryptography. */ if ((t_ret = __crypto_dbenv_close(dbenv)) != 0 && ret == 0) ret = t_ret;#endif /* Release any string-based configuration parameters we've copied. */ if (dbenv->db_log_dir != NULL) __os_free(dbenv, dbenv->db_log_dir); if (dbenv->db_tmp_dir != NULL) __os_free(dbenv, dbenv->db_tmp_dir); if (dbenv->db_data_dir != NULL) { for (p = dbenv->db_data_dir; *p != NULL; ++p) __os_free(dbenv, *p); __os_free(dbenv, dbenv->db_data_dir); } /* Discard the structure. */ memset(dbenv, CLEAR_BYTE, sizeof(DB_ENV)); __os_free(NULL, dbenv); return (ret);}/* * __dbenv_refresh -- * Refresh the DB_ENV structure, releasing resources allocated by * DB_ENV->open, and returning it to the state it was in just before * open was called. (Note that this means that any state set by * pre-open configuration functions must be preserved.) */static int__dbenv_refresh(dbenv, orig_flags, rep_check) DB_ENV *dbenv; u_int32_t orig_flags; int rep_check;{ DB *ldbp; DB_MPOOL *dbmp; int ret, t_ret; dbmp = dbenv->mp_handle; ret = 0; /* * Refresh subsystems, in the reverse order they were opened (txn * must be first, it may want to discard locks and flush the log). * * !!! * Note that these functions, like all of __dbenv_refresh, only undo * the effects of __dbenv_open. Functions that undo work done by * db_env_create or by a configuration function should go in * __dbenv_close. */ if (TXN_ON(dbenv) && (t_ret = __txn_dbenv_refresh(dbenv)) != 0 && ret == 0) ret = t_ret; if (LOGGING_ON(dbenv) && (t_ret = __log_dbenv_refresh(dbenv)) != 0 && ret == 0) ret = t_ret; /* * Locking should come after logging, because closing log results * in files closing which may require locks being released. */ if (LOCKING_ON(dbenv)) { if (!F_ISSET(dbenv, DB_ENV_THREAD) && dbenv->env_lid != DB_LOCK_INVALIDID && (t_ret = __lock_id_free(dbenv, dbenv->env_lid)) != 0 && ret == 0) ret = t_ret; dbenv->env_lid = DB_LOCK_INVALIDID; if ((t_ret = __lock_dbenv_refresh(dbenv)) != 0 && ret == 0) ret = t_ret; } /* * Discard DB list and its mutex. * Discard the MT mutex. * * !!! * This must be done before we close the mpool region because we * may have allocated the DB handle mutex in the mpool region. * It must be done *after* we close the log region, though, because * we close databases and try to acquire the mutex when we close * log file handles. Ick. */ if (dbenv->db_ref != 0) { __db_err(dbenv, "Database handles remain at environment close"); for (ldbp = LIST_FIRST(&dbenv->dblist); ldbp != NULL; ldbp = LIST_NEXT(ldbp, dblistlinks)) __db_err(dbenv, "Open database handle: %s%s%s", ldbp->fname, ldbp->dname == NULL ? "" : "/", ldbp->dname == NULL ? "" : ldbp->dname); if (ret == 0) ret = EINVAL; } LIST_INIT(&dbenv->dblist); if (dbenv->dblist_mutexp != NULL) __db_mutex_free(dbenv, dbmp->reginfo, dbenv->dblist_mutexp); if (dbenv->mt_mutexp != NULL) __db_mutex_free(dbenv, dbmp->reginfo, dbenv->mt_mutexp); if (dbenv->mt != NULL) { __os_free(dbenv, dbenv->mt); dbenv->mt = NULL; } if (MPOOL_ON(dbenv)) { /* * If it's a private environment, flush the contents to disk. * Recovery would have put everything back together, but it's * faster and cleaner to flush instead. */ if (F_ISSET(dbenv, DB_ENV_PRIVATE) && (t_ret = __memp_sync(dbenv, NULL)) != 0 && ret == 0) ret = t_ret; if ((t_ret = __memp_dbenv_refresh(dbenv)) != 0 && ret == 0) ret = t_ret; } /* * If we're included in a shared replication handle count, this * is our last chance to decrement that count. * * !!! * We can't afford to do anything dangerous after we decrement the * handle count, of course, as replication may be proceeding with * client recovery. However, since we're discarding the regions * as soon as we drop the handle count, there's little opportunity * to do harm. */ if (rep_check) __env_db_rep_exit(dbenv); /* * Detach from the region. * * Must come after we call __env_db_rep_exit above. */ __rep_dbenv_refresh(dbenv); if (dbenv->reginfo != NULL) { if ((t_ret = __db_e_detach(dbenv, 0)) != 0 && ret == 0) ret = t_ret; /* * !!! * Don't free dbenv->reginfo or set the reference to NULL, * that was done by __db_e_detach(). */ } /* Undo changes and allocations done by __dbenv_open. */ if (dbenv->db_home != NULL) { __os_free(dbenv, dbenv->db_home); dbenv->db_home = NULL; } dbenv->open_flags = 0; dbenv->db_mode = 0; if (dbenv->recover_dtab != NULL) { __os_free(dbenv, dbenv->recover_dtab); dbenv->recover_dtab = NULL; dbenv->recover_dtab_size = 0; } dbenv->flags = orig_flags; return (ret);}#define DB_ADDSTR(add) { \ /* \ * The string might be NULL or zero-length, and the p[-1] \ * might indirect to before the beginning of our buffer. \ */ \ if ((add) != NULL && (add)[0] != '\0') { \ /* If leading slash, start over. */ \ if (__os_abspath(add)) { \ p = str; \ slash = 0; \ } \ /* Append to the current string. */ \ len = strlen(add); \ if (slash) \ *p++ = PATH_SEPARATOR[0]; \ memcpy(p, add, len); \ p += len; \ slash = strchr(PATH_SEPARATOR, p[-1]) == NULL; \ } \}/* * __dbenv_get_open_flags * Retrieve the flags passed to DB_ENV->open. * * PUBLIC: int __dbenv_get_open_flags __P((DB_ENV *, u_int32_t *)); */int__dbenv_get_open_flags(dbenv, flagsp) DB_ENV *dbenv; u_int32_t *flagsp;{ ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->get_open_flags"); *flagsp = dbenv->open_flags; return (0);}/* * __db_appname -- * Given an optional DB environment, directory and file name and type * of call, build a path based on the DB_ENV->open rules, and return * it in allocated space. * * PUBLIC: int __db_appname __P((DB_ENV *, APPNAME, * PUBLIC: const char *, u_int32_t, DB_FH **, char **)); */int__db_appname(dbenv, appname, file, tmp_oflags, fhpp, namep) DB_ENV *dbenv; APPNAME appname; const char *file; u_int32_t tmp_oflags; DB_FH **fhpp; char **namep;{ size_t len, str_len; int data_entry, ret, slash, tmp_create; const char *a, *b; char *p, *str; a = b = NULL; data_entry = -1; tmp_create = 0; /* * We don't return a name when creating temporary files, just a file * handle. Default to an error now. */ if (fhpp != NULL) *fhpp = NULL; if (namep != NULL) *namep = NULL; /* * Absolute path names are never modified. If the file is an absolute * path, we're done. */ if (file != NULL && __os_abspath(file)) return (__os_strdup(dbenv, file, namep)); /* Everything else is relative to the environment home. */ if (dbenv != NULL) a = dbenv->db_home;retry: /* * DB_APP_NONE: * DB_HOME/file * DB_APP_DATA: * DB_HOME/DB_DATA_DIR/file * DB_APP_LOG: * DB_HOME/DB_LOG_DIR/file * DB_APP_TMP: * DB_HOME/DB_TMP_DIR/<create> */ switch (appname) { case DB_APP_NONE: break; case DB_APP_DATA: if (dbenv != NULL && dbenv->db_data_dir != NULL && (b = dbenv->db_data_dir[++data_entry]) == NULL) { data_entry = -1; b = dbenv->db_data_dir[0]; } break; case DB_APP_LOG: if (dbenv != NULL) b = dbenv->db_log_dir; break; case DB_APP_TMP: if (dbenv != NULL) b = dbenv->db_tmp_dir; tmp_create = 1; break; } len =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -