bt_open.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. /*
  8.  * Copyright (c) 1990, 1993, 1994, 1995, 1996
  9.  * Keith Bostic.  All rights reserved.
  10.  */
  11. /*
  12.  * Copyright (c) 1990, 1993, 1994, 1995
  13.  * The Regents of the University of California.  All rights reserved.
  14.  *
  15.  * This code is derived from software contributed to Berkeley by
  16.  * Mike Olson.
  17.  *
  18.  * Redistribution and use in source and binary forms, with or without
  19.  * modification, are permitted provided that the following conditions
  20.  * are met:
  21.  * 1. Redistributions of source code must retain the above copyright
  22.  *    notice, this list of conditions and the following disclaimer.
  23.  * 2. Redistributions in binary form must reproduce the above copyright
  24.  *    notice, this list of conditions and the following disclaimer in the
  25.  *    documentation and/or other materials provided with the distribution.
  26.  * 3. Neither the name of the University nor the names of its contributors
  27.  *    may be used to endorse or promote products derived from this software
  28.  *    without specific prior written permission.
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  31.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  34.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  38.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  40.  * SUCH DAMAGE.
  41.  */
  42. #include "db_config.h"
  43. #ifndef lint
  44. static const char revid[] = "$Id: bt_open.c,v 11.76 2002/09/04 19:06:42 margo Exp $";
  45. #endif /* not lint */
  46. #ifndef NO_SYSTEM_INCLUDES
  47. #include <sys/types.h>
  48. #include <limits.h>
  49. #include <string.h>
  50. #endif
  51. #include "db_int.h"
  52. #include "dbinc/crypto.h"
  53. #include "dbinc/db_page.h"
  54. #include "dbinc/db_swap.h"
  55. #include "dbinc/btree.h"
  56. #include "dbinc/db_shash.h"
  57. #include "dbinc/lock.h"
  58. #include "dbinc/log.h"
  59. #include "dbinc/fop.h"
  60. static void __bam_init_meta __P((DB *, BTMETA *, db_pgno_t, DB_LSN *));
  61. /*
  62.  * __bam_open --
  63.  * Open a btree.
  64.  *
  65.  * PUBLIC: int __bam_open __P((DB *,
  66.  * PUBLIC:      DB_TXN *, const char *, db_pgno_t, u_int32_t));
  67.  */
  68. int
  69. __bam_open(dbp, txn, name, base_pgno, flags)
  70. DB *dbp;
  71. DB_TXN *txn;
  72. const char *name;
  73. db_pgno_t base_pgno;
  74. u_int32_t flags;
  75. {
  76. BTREE *t;
  77. COMPQUIET(name, NULL);
  78. t = dbp->bt_internal;
  79. /* Initialize the remaining fields/methods of the DB. */
  80. dbp->key_range = __bam_key_range;
  81. dbp->stat = __bam_stat;
  82. /*
  83.  * We don't permit the user to specify a prefix routine if they didn't
  84.  * also specify a comparison routine, they can't know enough about our
  85.  * comparison routine to get it right.
  86.  */
  87. if (t->bt_compare == __bam_defcmp && t->bt_prefix != __bam_defpfx) {
  88. __db_err(dbp->dbenv,
  89. "prefix comparison may not be specified for default comparison routine");
  90. return (EINVAL);
  91. }
  92. /*
  93.  * Verify that the bt_minkey value specified won't cause the
  94.  * calculation of ovflsize to underflow [#2406] for this pagesize.
  95.  */
  96. if (B_MINKEY_TO_OVFLSIZE(dbp, t->bt_minkey, dbp->pgsize) >
  97.     B_MINKEY_TO_OVFLSIZE(dbp, DEFMINKEYPAGE, dbp->pgsize)) {
  98. __db_err(dbp->dbenv,
  99.     "bt_minkey value of %lu too high for page size of %lu",
  100.     (u_long)t->bt_minkey, (u_long)dbp->pgsize);
  101. return (EINVAL);
  102. }
  103. /* Start up the tree. */
  104. return (__bam_read_root(dbp, txn, base_pgno, flags));
  105. }
  106. /*
  107.  * __bam_metachk --
  108.  *
  109.  * PUBLIC: int __bam_metachk __P((DB *, const char *, BTMETA *));
  110.  */
  111. int
  112. __bam_metachk(dbp, name, btm)
  113. DB *dbp;
  114. const char *name;
  115. BTMETA *btm;
  116. {
  117. DB_ENV *dbenv;
  118. u_int32_t vers;
  119. int ret;
  120. dbenv = dbp->dbenv;
  121. /*
  122.  * At this point, all we know is that the magic number is for a Btree.
  123.  * Check the version, the database may be out of date.
  124.  */
  125. vers = btm->dbmeta.version;
  126. if (F_ISSET(dbp, DB_AM_SWAP))
  127. M_32_SWAP(vers);
  128. switch (vers) {
  129. case 6:
  130. case 7:
  131. __db_err(dbenv,
  132.     "%s: btree version %lu requires a version upgrade",
  133.     name, (u_long)vers);
  134. return (DB_OLD_VERSION);
  135. case 8:
  136. case 9:
  137. break;
  138. default:
  139. __db_err(dbenv,
  140.     "%s: unsupported btree version: %lu", name, (u_long)vers);
  141. return (EINVAL);
  142. }
  143. /* Swap the page if we need to. */
  144. if (F_ISSET(dbp, DB_AM_SWAP) && (ret = __bam_mswap((PAGE *)btm)) != 0)
  145. return (ret);
  146. /*
  147.  * Check application info against metadata info, and set info, flags,
  148.  * and type based on metadata info.
  149.  */
  150. if ((ret =
  151.     __db_fchk(dbenv, "DB->open", btm->dbmeta.flags, BTM_MASK)) != 0)
  152. return (ret);
  153. if (F_ISSET(&btm->dbmeta, BTM_RECNO)) {
  154. if (dbp->type == DB_BTREE)
  155. goto wrong_type;
  156. dbp->type = DB_RECNO;
  157. DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
  158. } else {
  159. if (dbp->type == DB_RECNO)
  160. goto wrong_type;
  161. dbp->type = DB_BTREE;
  162. DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
  163. }
  164. if (F_ISSET(&btm->dbmeta, BTM_DUP))
  165. F_SET(dbp, DB_AM_DUP);
  166. else
  167. if (F_ISSET(dbp, DB_AM_DUP)) {
  168. __db_err(dbenv,
  169. "%s: DB_DUP specified to open method but not set in database",
  170.     name);
  171. return (EINVAL);
  172. }
  173. if (F_ISSET(&btm->dbmeta, BTM_RECNUM)) {
  174. if (dbp->type != DB_BTREE)
  175. goto wrong_type;
  176. F_SET(dbp, DB_AM_RECNUM);
  177. if ((ret = __db_fcchk(dbenv,
  178.     "DB->open", dbp->flags, DB_AM_DUP, DB_AM_RECNUM)) != 0)
  179. return (ret);
  180. } else
  181. if (F_ISSET(dbp, DB_AM_RECNUM)) {
  182. __db_err(dbenv,
  183.     "%s: DB_RECNUM specified to open method but not set in database",
  184.     name);
  185. return (EINVAL);
  186. }
  187. if (F_ISSET(&btm->dbmeta, BTM_FIXEDLEN)) {
  188. if (dbp->type != DB_RECNO)
  189. goto wrong_type;
  190. F_SET(dbp, DB_AM_FIXEDLEN);
  191. } else
  192. if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
  193. __db_err(dbenv,
  194. "%s: DB_FIXEDLEN specified to open method but not set in database",
  195.     name);
  196. return (EINVAL);
  197. }
  198. if (F_ISSET(&btm->dbmeta, BTM_RENUMBER)) {
  199. if (dbp->type != DB_RECNO)
  200. goto wrong_type;
  201. F_SET(dbp, DB_AM_RENUMBER);
  202. } else
  203. if (F_ISSET(dbp, DB_AM_RENUMBER)) {
  204. __db_err(dbenv,
  205.     "%s: DB_RENUMBER specified to open method but not set in database",
  206.     name);
  207. return (EINVAL);
  208. }
  209. if (F_ISSET(&btm->dbmeta, BTM_SUBDB))
  210. F_SET(dbp, DB_AM_SUBDB);
  211. else
  212. if (F_ISSET(dbp, DB_AM_SUBDB)) {
  213. __db_err(dbenv,
  214.     "%s: multiple databases specified but not supported by file",
  215.     name);
  216. return (EINVAL);
  217. }
  218. if (F_ISSET(&btm->dbmeta, BTM_DUPSORT)) {
  219. if (dbp->dup_compare == NULL)
  220. dbp->dup_compare = __bam_defcmp;
  221. F_SET(dbp, DB_AM_DUPSORT);
  222. } else
  223. if (dbp->dup_compare != NULL) {
  224. __db_err(dbenv,
  225. "%s: duplicate sort specified but not supported in database",
  226.     name);
  227. return (EINVAL);
  228. }
  229. /* Set the page size. */
  230. dbp->pgsize = btm->dbmeta.pagesize;
  231. /* Copy the file's ID. */
  232. memcpy(dbp->fileid, btm->dbmeta.uid, DB_FILE_ID_LEN);
  233. return (0);
  234. wrong_type:
  235. if (dbp->type == DB_BTREE)
  236. __db_err(dbenv,
  237.     "open method type is Btree, database type is Recno");
  238. else
  239. __db_err(dbenv,
  240.     "open method type is Recno, database type is Btree");
  241. return (EINVAL);
  242. }
  243. /*
  244.  * __bam_read_root --
  245.  * Read the root page and check a tree.
  246.  *
  247.  * PUBLIC: int __bam_read_root __P((DB *, DB_TXN *, db_pgno_t, u_int32_t));
  248.  */
  249. int
  250. __bam_read_root(dbp, txn, base_pgno, flags)
  251. DB *dbp;
  252. DB_TXN *txn;
  253. db_pgno_t base_pgno;
  254. u_int32_t flags;
  255. {
  256. BTMETA *meta;
  257. BTREE *t;
  258. DBC *dbc;
  259. DB_LOCK metalock;
  260. DB_MPOOLFILE *mpf;
  261. int ret, t_ret;
  262. meta = NULL;
  263. t = dbp->bt_internal;
  264. LOCK_INIT(metalock);
  265. mpf = dbp->mpf;
  266. ret = 0;
  267. /* Get a cursor.  */
  268. if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
  269. return (ret);
  270. /* Get the metadata page. */
  271. if ((ret =
  272.     __db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0)
  273. goto err;
  274. if ((ret = mpf->get(mpf, &base_pgno, 0, (PAGE **)&meta)) != 0)
  275. goto err;
  276. /*
  277.  * If the magic number is set, the tree has been created.  Correct
  278.  * any fields that may not be right.  Note, all of the local flags
  279.  * were set by DB->open.
  280.  *
  281.  * Otherwise, we'd better be in recovery or abort, in which case the
  282.  * metadata page will be created/initialized elsewhere.
  283.  */
  284. DB_ASSERT(meta->dbmeta.magic != 0 ||
  285.     IS_RECOVERING(dbp->dbenv) || F_ISSET(dbp, DB_AM_RECOVER));
  286. t->bt_maxkey = meta->maxkey;
  287. t->bt_minkey = meta->minkey;
  288. t->re_pad = meta->re_pad;
  289. t->re_len = meta->re_len;
  290. t->bt_meta = base_pgno;
  291. t->bt_root = meta->root;
  292. /*
  293.  * !!!
  294.  * If creating a subdatabase, we've already done an insert when
  295.  * we put the subdatabase's entry into the master database, so
  296.  * our last-page-inserted value is wrongly initialized for the
  297.  * master database, not the subdatabase we're creating.  I'm not
  298.  * sure where the *right* place to clear this value is, it's not
  299.  * intuitively obvious that it belongs here.
  300.  */
  301. t->bt_lpgno = PGNO_INVALID;
  302. /* We must initialize last_pgno, it could be stale. */
  303. if (!LF_ISSET(DB_RDONLY) && dbp->meta_pgno == PGNO_BASE_MD) {
  304. mpf->last_pgno(mpf, &meta->dbmeta.last_pgno);
  305. ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
  306. } else
  307. ret = mpf->put(mpf, meta, 0);
  308. meta = NULL;
  309. err: /* Put the metadata page back. */
  310. if (meta != NULL && (t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
  311. ret = t_ret;
  312. if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
  313. ret = t_ret;
  314. if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
  315. ret = t_ret;
  316. return (ret);
  317. }
  318. /*
  319.  * __bam_init_meta --
  320.  *
  321.  * Initialize a btree meta-data page.  The following fields may need
  322.  * to be updated later: last_pgno, root.
  323.  */
  324. static void
  325. __bam_init_meta(dbp, meta, pgno, lsnp)
  326. DB *dbp;
  327. BTMETA *meta;
  328. db_pgno_t pgno;
  329. DB_LSN *lsnp;
  330. {
  331. BTREE *t;
  332. memset(meta, 0, sizeof(BTMETA));
  333. meta->dbmeta.lsn = *lsnp;
  334. meta->dbmeta.pgno = pgno;
  335. meta->dbmeta.magic = DB_BTREEMAGIC;
  336. meta->dbmeta.version = DB_BTREEVERSION;
  337. meta->dbmeta.pagesize = dbp->pgsize;
  338. if (F_ISSET(dbp, DB_AM_CHKSUM))
  339. FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM);
  340. if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
  341. meta->dbmeta.encrypt_alg =
  342.     ((DB_CIPHER *)dbp->dbenv->crypto_handle)->alg;
  343. DB_ASSERT(meta->dbmeta.encrypt_alg != 0);
  344. meta->crypto_magic = meta->dbmeta.magic;
  345. }
  346. meta->dbmeta.type = P_BTREEMETA;
  347. meta->dbmeta.free = PGNO_INVALID;
  348. meta->dbmeta.last_pgno = pgno;
  349. if (F_ISSET(dbp, DB_AM_DUP))
  350. F_SET(&meta->dbmeta, BTM_DUP);
  351. if (F_ISSET(dbp, DB_AM_FIXEDLEN))
  352. F_SET(&meta->dbmeta, BTM_FIXEDLEN);
  353. if (F_ISSET(dbp, DB_AM_RECNUM))
  354. F_SET(&meta->dbmeta, BTM_RECNUM);
  355. if (F_ISSET(dbp, DB_AM_RENUMBER))
  356. F_SET(&meta->dbmeta, BTM_RENUMBER);
  357. if (F_ISSET(dbp, DB_AM_SUBDB))
  358. F_SET(&meta->dbmeta, BTM_SUBDB);
  359. if (dbp->dup_compare != NULL)
  360. F_SET(&meta->dbmeta, BTM_DUPSORT);
  361. if (dbp->type == DB_RECNO)
  362. F_SET(&meta->dbmeta, BTM_RECNO);
  363. memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
  364. t = dbp->bt_internal;
  365. meta->maxkey = t->bt_maxkey;
  366. meta->minkey = t->bt_minkey;
  367. meta->re_len = t->re_len;
  368. meta->re_pad = t->re_pad;
  369. }
  370. /*
  371.  * __bam_new_file --
  372.  * Create the necessary pages to begin a new database file.
  373.  *
  374.  * This code appears more complex than it is because of the two cases (named
  375.  * and unnamed).  The way to read the code is that for each page being created,
  376.  * there are three parts: 1) a "get page" chunk (which either uses malloc'd
  377.  * memory or calls mpf->get), 2) the initialization, and 3) the "put page"
  378.  * chunk which either does a fop write or an mpf->put.
  379.  *
  380.  * PUBLIC: int __bam_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
  381.  */
  382. int
  383. __bam_new_file(dbp, txn, fhp, name)
  384. DB *dbp;
  385. DB_TXN *txn;
  386. DB_FH *fhp;
  387. const char *name;
  388. {
  389. BTMETA *meta;
  390. DB_ENV *dbenv;
  391. DB_LSN lsn;
  392. DB_MPOOLFILE *mpf;
  393. DB_PGINFO pginfo;
  394. DBT pdbt;
  395. PAGE *root;
  396. db_pgno_t pgno;
  397. int ret;
  398. void *buf;
  399. dbenv = dbp->dbenv;
  400. mpf = dbp->mpf;
  401. root = NULL;
  402. meta = NULL;
  403. memset(&pdbt, 0, sizeof(pdbt));
  404. /* Build meta-data page. */
  405. if (name == NULL) {
  406. pgno = PGNO_BASE_MD;
  407. ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &meta);
  408. } else {
  409. pginfo.db_pagesize = dbp->pgsize;
  410. pginfo.flags =
  411.     F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
  412. pginfo.type = dbp->type;
  413. pdbt.data = &pginfo;
  414. pdbt.size = sizeof(pginfo);
  415. ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf);
  416. meta = (BTMETA *)buf;
  417. }
  418. if (ret != 0)
  419. return (ret);
  420. LSN_NOT_LOGGED(lsn);
  421. __bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
  422. meta->root = 1;
  423. meta->dbmeta.last_pgno = 1;
  424. if (name == NULL)
  425. ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
  426. else {
  427. if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
  428. goto err;
  429. ret = __fop_write(dbenv,
  430.     txn, name, DB_APP_DATA, fhp, 0, buf, dbp->pgsize, 1);
  431. }
  432. if (ret != 0)
  433. goto err;
  434. meta = NULL;
  435. /* Now build root page. */
  436. if (name == NULL) {
  437. pgno = 1;
  438. if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0)
  439. goto err;
  440. } else {
  441. #ifdef DIAGNOSTIC
  442. memset(buf, 0, dbp->pgsize);
  443. #endif
  444. root = (PAGE *)buf;
  445. }
  446. P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
  447.     LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
  448. LSN_NOT_LOGGED(root->lsn);
  449. if (name == NULL)
  450. ret = mpf->put(mpf, root, DB_MPOOL_DIRTY);
  451. else {
  452. if ((ret = __db_pgout(dbenv, root->pgno, root, &pdbt)) != 0)
  453. goto err;
  454. ret = __fop_write(dbenv, txn,
  455.     name, DB_APP_DATA, fhp, dbp->pgsize, buf, dbp->pgsize, 1);
  456. }
  457. if (ret != 0)
  458. goto err;
  459. root = NULL;
  460. err: if (name != NULL)
  461. __os_free(dbenv, buf);
  462. else {
  463. if (meta != NULL)
  464. (void)mpf->put(mpf, meta, 0);
  465. if (root != NULL)
  466. (void)mpf->put(mpf, root, 0);
  467. }
  468. return (ret);
  469. }
  470. /*
  471.  * __bam_new_subdb --
  472.  * Create a metadata page and a root page for a new btree.
  473.  *
  474.  * PUBLIC: int __bam_new_subdb __P((DB *, DB *, DB_TXN *));
  475.  */
  476. int
  477. __bam_new_subdb(mdbp, dbp, txn)
  478. DB *mdbp, *dbp;
  479. DB_TXN *txn;
  480. {
  481. BTMETA *meta;
  482. DBC *dbc;
  483. DB_ENV *dbenv;
  484. DB_LOCK metalock;
  485. DB_LSN lsn;
  486. DB_MPOOLFILE *mpf;
  487. PAGE *root;
  488. int ret, t_ret;
  489. dbenv = mdbp->dbenv;
  490. mpf = mdbp->mpf;
  491. dbc = NULL;
  492. meta = NULL;
  493. root = NULL;
  494. if ((ret = mdbp->cursor(mdbp, txn,
  495.     &dbc, CDB_LOCKING(dbenv) ?  DB_WRITECURSOR : 0)) != 0)
  496. return (ret);
  497. /* Get, and optionally create the metadata page. */
  498. if ((ret = __db_lget(dbc,
  499.     0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
  500. goto err;
  501. if ((ret = mpf->get(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
  502. goto err;
  503. /* Build meta-data page. */
  504. lsn = meta->dbmeta.lsn;
  505. __bam_init_meta(dbp, meta, dbp->meta_pgno, &lsn);
  506. if ((ret = __db_log_page(mdbp,
  507.     txn, &meta->dbmeta.lsn, dbp->meta_pgno, (PAGE *)meta)) != 0)
  508. goto err;
  509. /* Create and initialize a root page. */
  510. if ((ret = __db_new(dbc,
  511.     dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE, &root)) != 0)
  512. goto err;
  513. root->level = LEAFLEVEL;
  514. if (DBENV_LOGGING(dbenv) &&
  515.     (ret = __bam_root_log(mdbp, txn, &meta->dbmeta.lsn, 0,
  516.     meta->dbmeta.pgno, root->pgno, &meta->dbmeta.lsn)) != 0)
  517. goto err;
  518. meta->root = root->pgno;
  519. if ((ret =
  520.     __db_log_page(mdbp, txn, &root->lsn, root->pgno, root)) != 0)
  521. goto err;
  522. /* Release the metadata and root pages. */
  523. if ((ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0)
  524. goto err;
  525. meta = NULL;
  526. if ((ret = mpf->put(mpf, root, DB_MPOOL_DIRTY)) != 0)
  527. goto err;
  528. root = NULL;
  529. err:
  530. if (meta != NULL)
  531. if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
  532. ret = t_ret;
  533. if (root != NULL)
  534. if ((t_ret = mpf->put(mpf, root, 0)) != 0 && ret == 0)
  535. ret = t_ret;
  536. if (LOCK_ISSET(metalock))
  537. if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
  538. ret = t_ret;
  539. if (dbc != NULL)
  540. if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
  541. ret = t_ret;
  542. return (ret);
  543. }