📄 db_open.c
字号:
case DB_QUEUE: ret = __qam_new_file(dbp, txn, fhp, name); break; default: __db_err(dbp->dbenv, "%s: Invalid type %d specified", name, dbp->type); ret = EINVAL; break; } DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOGMETA, ret, name); /* Sync the file in preparation for moving it into place. */ if (ret == 0 && fhp != NULL) ret = __os_fsync(dbp->dbenv, fhp); DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, name);DB_TEST_RECOVERY_LABEL return (ret);}/* * __db_init_subdb -- * Initialize the dbp for a subdb. * * PUBLIC: int __db_init_subdb __P((DB *, DB *, const char *, DB_TXN *)); */int__db_init_subdb(mdbp, dbp, name, txn) DB *mdbp, *dbp; const char *name; DB_TXN *txn;{ DBMETA *meta; DB_MPOOLFILE *mpf; int ret, t_ret; ret = 0; if (!F_ISSET(dbp, DB_AM_CREATED)) { /* Subdb exists; read meta-data page and initialize. */ mpf = mdbp->mpf; if ((ret = mpf->get(mpf, &dbp->meta_pgno, 0, &meta)) != 0) goto err; ret = __db_meta_setup(mdbp->dbenv, dbp, name, meta, 0, 0); if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0) ret = t_ret; /* * If __db_meta_setup found that the meta-page hadn't * been written out during recovery, we can just return. */ if (ret == ENOENT) ret = 0; goto err; } /* Handle the create case here. */ switch (dbp->type) { case DB_BTREE: case DB_RECNO: ret = __bam_new_subdb(mdbp, dbp, txn); break; case DB_HASH: ret = __ham_new_subdb(mdbp, dbp, txn); break; case DB_QUEUE: ret = EINVAL; break; default: __db_err(dbp->dbenv, "Invalid subdatabase type %d specified", dbp->type); return (EINVAL); }err: return (ret);}/* * __db_chk_meta -- * Take a buffer containing a meta-data page and check it for a checksum * (and verify the checksum if necessary) and possibly decrypt it. * * Return 0 on success, >0 (errno) on error, -1 on checksum mismatch. * * PUBLIC: int __db_chk_meta __P((DB_ENV *, DB *, DBMETA *, int)); */int__db_chk_meta(dbenv, dbp, meta, do_metachk) DB_ENV *dbenv; DB *dbp; DBMETA *meta; int do_metachk;{ int is_hmac, ret; u_int8_t *chksum; ret = 0; if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) { if (dbp != NULL) F_SET(dbp, DB_AM_CHKSUM); is_hmac = meta->encrypt_alg == 0 ? 0 : 1; chksum = ((BTMETA *)meta)->chksum; if (do_metachk && ((ret = __db_check_chksum(dbenv, (DB_CIPHER *)dbenv->crypto_handle, chksum, meta, DBMETASIZE, is_hmac)) != 0)) return (ret); }#ifdef HAVE_CRYPTO ret = __crypto_decrypt_meta(dbenv, dbp, (u_int8_t *)meta, do_metachk);#endif return (ret);}/* * __db_meta_setup -- * * Take a buffer containing a meta-data page and figure out if it's * valid, and if so, initialize the dbp from the meta-data page. * * PUBLIC: int __db_meta_setup __P((DB_ENV *, * PUBLIC: DB *, const char *, DBMETA *, u_int32_t, int)); */int__db_meta_setup(dbenv, dbp, name, meta, oflags, do_metachk) DB_ENV *dbenv; DB *dbp; const char *name; DBMETA *meta; u_int32_t oflags; int do_metachk;{ u_int32_t flags, magic; int ret; ret = 0; /* * Figure out what access method we're dealing with, and then * call access method specific code to check error conditions * based on conflicts between the found file and application * arguments. A found file overrides some user information -- * we don't consider it an error, for example, if the user set * an expected byte order and the found file doesn't match it. */ F_CLR(dbp, DB_AM_SWAP); magic = meta->magic;swap_retry: switch (magic) { case DB_BTREEMAGIC: case DB_HASHMAGIC: case DB_QAMMAGIC: case DB_RENAMEMAGIC: break; case 0: /* * The only time this should be 0 is if we're in the * midst of opening a subdb during recovery and that * subdatabase had its meta-data page allocated, but * not yet initialized. */ if (F_ISSET(dbp, DB_AM_SUBDB) && ((IS_RECOVERING(dbenv) && F_ISSET((DB_LOG *) dbenv->lg_handle, DBLOG_FORCE_OPEN)) || meta->pgno != PGNO_INVALID)) return (ENOENT); goto bad_format; default: if (F_ISSET(dbp, DB_AM_SWAP)) goto bad_format; M_32_SWAP(magic); F_SET(dbp, DB_AM_SWAP); goto swap_retry; } /* * We can only check the meta page if we are sure we have a meta page. * If it is random data, then this check can fail. So only now can we * checksum and decrypt. Don't distinguish between configuration and * checksum match errors here, because we haven't opened the database * and even a checksum error isn't a reason to panic the environment. */ if ((ret = __db_chk_meta(dbenv, dbp, meta, do_metachk)) != 0) { if (ret == -1) __db_err(dbenv, "%s: metadata page checksum error", name); goto bad_format; } switch (magic) { case DB_BTREEMAGIC: flags = meta->flags; if (F_ISSET(dbp, DB_AM_SWAP)) M_32_SWAP(flags); if (LF_ISSET(BTM_RECNO)) dbp->type = DB_RECNO; else dbp->type = DB_BTREE; if ((oflags & DB_TRUNCATE) == 0 && (ret = __bam_metachk(dbp, name, (BTMETA *)meta)) != 0) return (ret); break; case DB_HASHMAGIC: dbp->type = DB_HASH; if ((oflags & DB_TRUNCATE) == 0 && (ret = __ham_metachk(dbp, name, (HMETA *)meta)) != 0) return (ret); break; case DB_QAMMAGIC: dbp->type = DB_QUEUE; if ((oflags & DB_TRUNCATE) == 0 && (ret = __qam_metachk(dbp, name, (QMETA *)meta)) != 0) return (ret); break; case DB_RENAMEMAGIC: F_SET(dbp, DB_AM_IN_RENAME); break; } return (0);bad_format: __db_err(dbenv, "%s: unexpected file type or format", name); return (ret == 0 ? EINVAL : ret);}/* * __db_openchk -- * Interface error checking for open calls. */static int__db_openchk(dbp, txn, name, subdb, type, flags) DB *dbp; DB_TXN *txn; const char *name, *subdb; DBTYPE type; u_int32_t flags;{ DB_ENV *dbenv; int ret; u_int32_t ok_flags; dbenv = dbp->dbenv; /* Validate arguments. */#define OKFLAGS \ (DB_AUTO_COMMIT | DB_CREATE | DB_DIRTY_READ | DB_EXCL | \ DB_FCNTL_LOCKING | DB_NOMMAP | DB_RDONLY | DB_RDWRMASTER | \ DB_THREAD | DB_TRUNCATE | DB_WRITEOPEN) if ((ret = __db_fchk(dbenv, "DB->open", flags, OKFLAGS)) != 0) return (ret); if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE)) return (__db_ferr(dbenv, "DB->open", 1)); if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE)) return (__db_ferr(dbenv, "DB->open", 1));#ifdef HAVE_VXWORKS if (LF_ISSET(DB_TRUNCATE)) { __db_err(dbenv, "DB_TRUNCATE unsupported in VxWorks"); return (__db_eopnotsup(dbenv)); }#endif switch (type) { case DB_UNKNOWN: if (LF_ISSET(DB_CREATE|DB_TRUNCATE)) { __db_err(dbenv, "%s: DB_UNKNOWN type specified with DB_CREATE or DB_TRUNCATE", name); return (EINVAL); } ok_flags = 0; break; case DB_BTREE: ok_flags = DB_OK_BTREE; break; case DB_HASH: ok_flags = DB_OK_HASH; break; case DB_QUEUE: ok_flags = DB_OK_QUEUE; break; case DB_RECNO: ok_flags = DB_OK_RECNO; break; default: __db_err(dbenv, "unknown type: %lu", (u_long)type); return (EINVAL); } if (ok_flags) DB_ILLEGAL_METHOD(dbp, ok_flags); /* The environment may have been created, but never opened. */ if (!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_OPEN_CALLED)) { __db_err(dbenv, "environment not yet opened"); return (EINVAL); } /* * Historically, you could pass in an environment that didn't have a * mpool, and DB would create a private one behind the scenes. This * no longer works. */ if (!F_ISSET(dbenv, DB_ENV_DBLOCAL) && !MPOOL_ON(dbenv)) { __db_err(dbenv, "environment did not include a memory pool"); return (EINVAL); } /* * You can't specify threads during DB->open if subsystems in the * environment weren't configured with them. */ if (LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_THREAD)) { __db_err(dbenv, "environment not created using DB_THREAD"); return (EINVAL); } /* DB_TRUNCATE is not transaction recoverable. */ if (LF_ISSET(DB_TRUNCATE) && txn != NULL) { __db_err(dbenv, "DB_TRUNCATE illegal with transaction specified"); return (EINVAL); } /* Subdatabase checks. */ if (subdb != NULL) { /* Subdatabases must be created in named files. */ if (name == NULL) { __db_err(dbenv, "multiple databases cannot be created in temporary files"); return (EINVAL); } /* Truncate is a physical file operation */ if (LF_ISSET(DB_TRUNCATE)) { __db_err(dbenv, "DB_TRUNCATE illegal with multiple databases"); return (EINVAL); } /* QAM can't be done as a subdatabase. */ if (type == DB_QUEUE) { __db_err(dbenv, "Queue databases must be one-per-file"); return (EINVAL); } } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -