db_overflow.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:17k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  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: db_overflow.c,v 11.21 2000/11/30 00:58:32 ubell Exp $";
  45. #endif /* not lint */
  46. #ifndef NO_SYSTEM_INCLUDES
  47. #include <sys/types.h>
  48. #include <string.h>
  49. #endif
  50. #include "db_int.h"
  51. #include "db_page.h"
  52. #include "db_am.h"
  53. #include "db_verify.h"
  54. /*
  55.  * Big key/data code.
  56.  *
  57.  * Big key and data entries are stored on linked lists of pages.  The initial
  58.  * reference is a structure with the total length of the item and the page
  59.  * number where it begins.  Each entry in the linked list contains a pointer
  60.  * to the next page of data, and so on.
  61.  */
  62. /*
  63.  * __db_goff --
  64.  * Get an offpage item.
  65.  *
  66.  * PUBLIC: int __db_goff __P((DB *, DBT *,
  67.  * PUBLIC:     u_int32_t, db_pgno_t, void **, u_int32_t *));
  68.  */
  69. int
  70. __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
  71. DB *dbp;
  72. DBT *dbt;
  73. u_int32_t tlen;
  74. db_pgno_t pgno;
  75. void **bpp;
  76. u_int32_t *bpsz;
  77. {
  78. DB_ENV *dbenv;
  79. PAGE *h;
  80. db_indx_t bytes;
  81. u_int32_t curoff, needed, start;
  82. u_int8_t *p, *src;
  83. int ret;
  84. dbenv = dbp->dbenv;
  85. /*
  86.  * Check if the buffer is big enough; if it is not and we are
  87.  * allowed to malloc space, then we'll malloc it.  If we are
  88.  * not (DB_DBT_USERMEM), then we'll set the dbt and return
  89.  * appropriately.
  90.  */
  91. if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
  92. start = dbt->doff;
  93. needed = dbt->dlen;
  94. } else {
  95. start = 0;
  96. needed = tlen;
  97. }
  98. /* Allocate any necessary memory. */
  99. if (F_ISSET(dbt, DB_DBT_USERMEM)) {
  100. if (needed > dbt->ulen) {
  101. dbt->size = needed;
  102. return (ENOMEM);
  103. }
  104. } else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
  105. if ((ret = __os_malloc(dbenv,
  106.     needed, dbp->db_malloc, &dbt->data)) != 0)
  107. return (ret);
  108. } else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
  109. if ((ret = __os_realloc(dbenv,
  110.     needed, dbp->db_realloc, &dbt->data)) != 0)
  111. return (ret);
  112. } else if (*bpsz == 0 || *bpsz < needed) {
  113. if ((ret = __os_realloc(dbenv, needed, NULL, bpp)) != 0)
  114. return (ret);
  115. *bpsz = needed;
  116. dbt->data = *bpp;
  117. } else
  118. dbt->data = *bpp;
  119. /*
  120.  * Step through the linked list of pages, copying the data on each
  121.  * one into the buffer.  Never copy more than the total data length.
  122.  */
  123. dbt->size = needed;
  124. for (curoff = 0, p = dbt->data; pgno != PGNO_INVALID && needed > 0;) {
  125. if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
  126. (void)__db_pgerr(dbp, pgno);
  127. return (ret);
  128. }
  129. /* Check if we need any bytes from this page. */
  130. if (curoff + OV_LEN(h) >= start) {
  131. src = (u_int8_t *)h + P_OVERHEAD;
  132. bytes = OV_LEN(h);
  133. if (start > curoff) {
  134. src += start - curoff;
  135. bytes -= start - curoff;
  136. }
  137. if (bytes > needed)
  138. bytes = needed;
  139. memcpy(p, src, bytes);
  140. p += bytes;
  141. needed -= bytes;
  142. }
  143. curoff += OV_LEN(h);
  144. pgno = h->next_pgno;
  145. memp_fput(dbp->mpf, h, 0);
  146. }
  147. return (0);
  148. }
  149. /*
  150.  * __db_poff --
  151.  * Put an offpage item.
  152.  *
  153.  * PUBLIC: int __db_poff __P((DBC *, const DBT *, db_pgno_t *));
  154.  */
  155. int
  156. __db_poff(dbc, dbt, pgnop)
  157. DBC *dbc;
  158. const DBT *dbt;
  159. db_pgno_t *pgnop;
  160. {
  161. DB *dbp;
  162. PAGE *pagep, *lastp;
  163. DB_LSN new_lsn, null_lsn;
  164. DBT tmp_dbt;
  165. db_indx_t pagespace;
  166. u_int32_t sz;
  167. u_int8_t *p;
  168. int ret;
  169. /*
  170.  * Allocate pages and copy the key/data item into them.  Calculate the
  171.  * number of bytes we get for pages we fill completely with a single
  172.  * item.
  173.  */
  174. dbp = dbc->dbp;
  175. pagespace = P_MAXSPACE(dbp->pgsize);
  176. lastp = NULL;
  177. for (p = dbt->data,
  178.     sz = dbt->size; sz > 0; p += pagespace, sz -= pagespace) {
  179. /*
  180.  * Reduce pagespace so we terminate the loop correctly and
  181.  * don't copy too much data.
  182.  */
  183. if (sz < pagespace)
  184. pagespace = sz;
  185. /*
  186.  * Allocate and initialize a new page and copy all or part of
  187.  * the item onto the page.  If sz is less than pagespace, we
  188.  * have a partial record.
  189.  */
  190. if ((ret = __db_new(dbc, P_OVERFLOW, &pagep)) != 0)
  191. return (ret);
  192. if (DB_LOGGING(dbc)) {
  193. tmp_dbt.data = p;
  194. tmp_dbt.size = pagespace;
  195. ZERO_LSN(null_lsn);
  196. if ((ret = __db_big_log(dbp->dbenv, dbc->txn,
  197.     &new_lsn, 0, DB_ADD_BIG, dbp->log_fileid,
  198.     PGNO(pagep), lastp ? PGNO(lastp) : PGNO_INVALID,
  199.     PGNO_INVALID, &tmp_dbt, &LSN(pagep),
  200.     lastp == NULL ? &null_lsn : &LSN(lastp),
  201.     &null_lsn)) != 0)
  202. return (ret);
  203. /* Move lsn onto page. */
  204. if (lastp)
  205. LSN(lastp) = new_lsn;
  206. LSN(pagep) = new_lsn;
  207. }
  208. P_INIT(pagep, dbp->pgsize,
  209.     PGNO(pagep), PGNO_INVALID, PGNO_INVALID, 0, P_OVERFLOW);
  210. OV_LEN(pagep) = pagespace;
  211. OV_REF(pagep) = 1;
  212. memcpy((u_int8_t *)pagep + P_OVERHEAD, p, pagespace);
  213. /*
  214.  * If this is the first entry, update the user's info.
  215.  * Otherwise, update the entry on the last page filled
  216.  * in and release that page.
  217.  */
  218. if (lastp == NULL)
  219. *pgnop = PGNO(pagep);
  220. else {
  221. lastp->next_pgno = PGNO(pagep);
  222. pagep->prev_pgno = PGNO(lastp);
  223. (void)memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY);
  224. }
  225. lastp = pagep;
  226. }
  227. (void)memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY);
  228. return (0);
  229. }
  230. /*
  231.  * __db_ovref --
  232.  * Increment/decrement the reference count on an overflow page.
  233.  *
  234.  * PUBLIC: int __db_ovref __P((DBC *, db_pgno_t, int32_t));
  235.  */
  236. int
  237. __db_ovref(dbc, pgno, adjust)
  238. DBC *dbc;
  239. db_pgno_t pgno;
  240. int32_t adjust;
  241. {
  242. DB *dbp;
  243. PAGE *h;
  244. int ret;
  245. dbp = dbc->dbp;
  246. if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
  247. (void)__db_pgerr(dbp, pgno);
  248. return (ret);
  249. }
  250. if (DB_LOGGING(dbc))
  251. if ((ret = __db_ovref_log(dbp->dbenv, dbc->txn,
  252.     &LSN(h), 0, dbp->log_fileid, h->pgno, adjust,
  253.     &LSN(h))) != 0)
  254. return (ret);
  255. OV_REF(h) += adjust;
  256. (void)memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
  257. return (0);
  258. }
  259. /*
  260.  * __db_doff --
  261.  * Delete an offpage chain of overflow pages.
  262.  *
  263.  * PUBLIC: int __db_doff __P((DBC *, db_pgno_t));
  264.  */
  265. int
  266. __db_doff(dbc, pgno)
  267. DBC *dbc;
  268. db_pgno_t pgno;
  269. {
  270. DB *dbp;
  271. PAGE *pagep;
  272. DB_LSN null_lsn;
  273. DBT tmp_dbt;
  274. int ret;
  275. dbp = dbc->dbp;
  276. do {
  277. if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0) {
  278. (void)__db_pgerr(dbp, pgno);
  279. return (ret);
  280. }
  281. DB_ASSERT(TYPE(pagep) == P_OVERFLOW);
  282. /*
  283.  * If it's referenced by more than one key/data item,
  284.  * decrement the reference count and return.
  285.  */
  286. if (OV_REF(pagep) > 1) {
  287. (void)memp_fput(dbp->mpf, pagep, 0);
  288. return (__db_ovref(dbc, pgno, -1));
  289. }
  290. if (DB_LOGGING(dbc)) {
  291. tmp_dbt.data = (u_int8_t *)pagep + P_OVERHEAD;
  292. tmp_dbt.size = OV_LEN(pagep);
  293. ZERO_LSN(null_lsn);
  294. if ((ret = __db_big_log(dbp->dbenv, dbc->txn,
  295.     &LSN(pagep), 0, DB_REM_BIG, dbp->log_fileid,
  296.     PGNO(pagep), PREV_PGNO(pagep), NEXT_PGNO(pagep),
  297.     &tmp_dbt, &LSN(pagep), &null_lsn, &null_lsn)) != 0)
  298. return (ret);
  299. }
  300. pgno = pagep->next_pgno;
  301. if ((ret = __db_free(dbc, pagep)) != 0)
  302. return (ret);
  303. } while (pgno != PGNO_INVALID);
  304. return (0);
  305. }
  306. /*
  307.  * __db_moff --
  308.  * Match on overflow pages.
  309.  *
  310.  * Given a starting page number and a key, return <0, 0, >0 to indicate if the
  311.  * key on the page is less than, equal to or greater than the key specified.
  312.  * We optimize this by doing chunk at a time comparison unless the user has
  313.  * specified a comparison function.  In this case, we need to materialize
  314.  * the entire object and call their comparison routine.
  315.  *
  316.  * PUBLIC: int __db_moff __P((DB *, const DBT *, db_pgno_t, u_int32_t,
  317.  * PUBLIC:     int (*)(DB *, const DBT *, const DBT *), int *));
  318.  */
  319. int
  320. __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
  321. DB *dbp;
  322. const DBT *dbt;
  323. db_pgno_t pgno;
  324. u_int32_t tlen;
  325. int (*cmpfunc) __P((DB *, const DBT *, const DBT *)), *cmpp;
  326. {
  327. PAGE *pagep;
  328. DBT local_dbt;
  329. void *buf;
  330. u_int32_t bufsize, cmp_bytes, key_left;
  331. u_int8_t *p1, *p2;
  332. int ret;
  333. /*
  334.  * If there is a user-specified comparison function, build a
  335.  * contiguous copy of the key, and call it.
  336.  */
  337. if (cmpfunc != NULL) {
  338. memset(&local_dbt, 0, sizeof(local_dbt));
  339. buf = NULL;
  340. bufsize = 0;
  341. if ((ret = __db_goff(dbp,
  342.     &local_dbt, tlen, pgno, &buf, &bufsize)) != 0)
  343. return (ret);
  344. /* Pass the key as the first argument */
  345. *cmpp = cmpfunc(dbp, dbt, &local_dbt);
  346. __os_free(buf, bufsize);
  347. return (0);
  348. }
  349. /* While there are both keys to compare. */
  350. for (*cmpp = 0, p1 = dbt->data,
  351.     key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) {
  352. if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0)
  353. return (ret);
  354. cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left;
  355. tlen -= cmp_bytes;
  356. key_left -= cmp_bytes;
  357. for (p2 =
  358.     (u_int8_t *)pagep + P_OVERHEAD; cmp_bytes-- > 0; ++p1, ++p2)
  359. if (*p1 != *p2) {
  360. *cmpp = (long)*p1 - (long)*p2;
  361. break;
  362. }
  363. pgno = NEXT_PGNO(pagep);
  364. if ((ret = memp_fput(dbp->mpf, pagep, 0)) != 0)
  365. return (ret);
  366. if (*cmpp != 0)
  367. return (0);
  368. }
  369. if (key_left > 0) /* DBT is longer than the page key. */
  370. *cmpp = 1;
  371. else if (tlen > 0) /* DBT is shorter than the page key. */
  372. *cmpp = -1;
  373. else
  374. *cmpp = 0;
  375. return (0);
  376. }
  377. /*
  378.  * __db_vrfy_overflow --
  379.  * Verify overflow page.
  380.  *
  381.  * PUBLIC: int __db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
  382.  * PUBLIC:     u_int32_t));
  383.  */
  384. int
  385. __db_vrfy_overflow(dbp, vdp, h, pgno, flags)
  386. DB *dbp;
  387. VRFY_DBINFO *vdp;
  388. PAGE *h;
  389. db_pgno_t pgno;
  390. u_int32_t flags;
  391. {
  392. VRFY_PAGEINFO *pip;
  393. int isbad, ret, t_ret;
  394. isbad = 0;
  395. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  396. return (ret);
  397. if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
  398. if (ret == DB_VERIFY_BAD)
  399. isbad = 1;
  400. else
  401. goto err;
  402. }
  403. pip->refcount = OV_REF(h);
  404. if (pip->refcount < 1) {
  405. EPRINT((dbp->dbenv,
  406.     "Overflow page %lu has zero reference count",
  407.     (u_long)pgno));
  408. isbad = 1;
  409. }
  410. /* Just store for now. */
  411. pip->olen = HOFFSET(h);
  412. err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
  413. ret = t_ret;
  414. return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
  415. }
  416. /*
  417.  * __db_vrfy_ovfl_structure --
  418.  * Walk a list of overflow pages, avoiding cycles and marking
  419.  * pages seen.
  420.  *
  421.  * PUBLIC: int __db_vrfy_ovfl_structure
  422.  * PUBLIC:     __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t));
  423.  */
  424. int
  425. __db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
  426. DB *dbp;
  427. VRFY_DBINFO *vdp;
  428. db_pgno_t pgno;
  429. u_int32_t tlen;
  430. u_int32_t flags;
  431. {
  432. DB *pgset;
  433. VRFY_PAGEINFO *pip;
  434. db_pgno_t next, prev;
  435. int isbad, p, ret, t_ret;
  436. u_int32_t refcount;
  437. pgset = vdp->pgset;
  438. DB_ASSERT(pgset != NULL);
  439. isbad = 0;
  440. /* This shouldn't happen, but just to be sure. */
  441. if (!IS_VALID_PGNO(pgno))
  442. return (DB_VERIFY_BAD);
  443. /*
  444.  * Check the first prev_pgno;  it ought to be PGNO_INVALID,
  445.  * since there's no prev page.
  446.  */
  447. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  448. return (ret);
  449. /* The refcount is stored on the first overflow page. */
  450. refcount = pip->refcount;
  451. if (pip->type != P_OVERFLOW) {
  452. EPRINT((dbp->dbenv,
  453.     "Overflow page %lu of invalid type",
  454.     (u_long)pgno, (u_long)pip->type));
  455. ret = DB_VERIFY_BAD;
  456. goto err; /* Unsafe to continue. */
  457. }
  458. prev = pip->prev_pgno;
  459. if (prev != PGNO_INVALID) {
  460. EPRINT((dbp->dbenv,
  461.     "First overflow page %lu has a prev_pgno", (u_long)pgno));
  462. isbad = 1;
  463. }
  464. for (;;) {
  465. /*
  466.  * This is slightly gross.  Btree leaf pages reference
  467.  * individual overflow trees multiple times if the overflow page
  468.  * is the key to a duplicate set.  The reference count does not
  469.  * reflect this multiple referencing.  Thus, if this is called
  470.  * during the structure verification of a btree leaf page, we
  471.  * check to see whether we've seen it from a leaf page before
  472.  * and, if we have, adjust our count of how often we've seen it
  473.  * accordingly.
  474.  *
  475.  * (This will screw up if it's actually referenced--and
  476.  * correctly refcounted--from two different leaf pages, but
  477.  * that's a very unlikely brokenness that we're not checking for
  478.  * anyway.)
  479.  */
  480. if (LF_ISSET(ST_OVFL_LEAF)) {
  481. if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) {
  482. if ((ret =
  483.     __db_vrfy_pgset_dec(pgset, pgno)) != 0)
  484. goto err;
  485. } else
  486. F_SET(pip, VRFY_OVFL_LEAFSEEN);
  487. }
  488. if ((ret = __db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
  489. goto err;
  490. /*
  491.  * We may have seen this elsewhere, if the overflow entry
  492.  * has been promoted to an internal page.
  493.  */
  494. if ((u_int32_t)p > refcount) {
  495. EPRINT((dbp->dbenv,
  496.     "Page %lu encountered twice in overflow traversal",
  497.     (u_long)pgno));
  498. ret = DB_VERIFY_BAD;
  499. goto err;
  500. }
  501. if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
  502. goto err;
  503. /* Keep a running tab on how much of the item we've seen. */
  504. tlen -= pip->olen;
  505. /* Send feedback to the application about our progress. */
  506. if (!LF_ISSET(DB_SALVAGE))
  507. __db_vrfy_struct_feedback(dbp, vdp);
  508. next = pip->next_pgno;
  509. /* Are we there yet? */
  510. if (next == PGNO_INVALID)
  511. break;
  512. /*
  513.  * We've already checked this when we saved it, but just
  514.  * to be sure...
  515.  */
  516. if (!IS_VALID_PGNO(next)) {
  517. DB_ASSERT(0);
  518. EPRINT((dbp->dbenv,
  519.     "Overflow page %lu has bad next_pgno",
  520.     (u_long)pgno));
  521. ret = DB_VERIFY_BAD;
  522. goto err;
  523. }
  524. if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 ||
  525.     (ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0)
  526. return (ret);
  527. if (pip->prev_pgno != pgno) {
  528. EPRINT((dbp->dbenv,
  529.     "Overflow page %lu has bogus prev_pgno value",
  530.     (u_long)next));
  531. isbad = 1;
  532. /*
  533.  * It's safe to continue because we have separate
  534.  * cycle detection.
  535.  */
  536. }
  537. pgno = next;
  538. }
  539. if (tlen > 0) {
  540. isbad = 1;
  541. EPRINT((dbp->dbenv,
  542.     "Overflow item incomplete on page %lu", (u_long)pgno));
  543. }
  544. err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
  545. ret = t_ret;
  546. return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
  547. }
  548. /*
  549.  * __db_safe_goff --
  550.  * Get an overflow item, very carefully, from an untrusted database,
  551.  * in the context of the salvager.
  552.  *
  553.  * PUBLIC: int __db_safe_goff __P((DB *, VRFY_DBINFO *, db_pgno_t,
  554.  * PUBLIC:     DBT *, void **, u_int32_t));
  555.  */
  556. int
  557. __db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
  558. DB *dbp;
  559. VRFY_DBINFO *vdp;
  560. db_pgno_t pgno;
  561. DBT *dbt;
  562. void **buf;
  563. u_int32_t flags;
  564. {
  565. PAGE *h;
  566. int ret, err_ret;
  567. u_int32_t bytesgot, bytes;
  568. u_int8_t *src, *dest;
  569. ret = DB_VERIFY_BAD;
  570. err_ret = 0;
  571. bytesgot = bytes = 0;
  572. while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {
  573. /*
  574.  * Mark that we're looking at this page;  if we've seen it
  575.  * already, quit.
  576.  */
  577. if ((ret = __db_salvage_markdone(vdp, pgno)) != 0)
  578. break;
  579. if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
  580. break;
  581. /*
  582.  * Make sure it's really an overflow page, unless we're
  583.  * being aggressive, in which case we pretend it is.
  584.  */
  585. if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) {
  586. ret = DB_VERIFY_BAD;
  587. break;
  588. }
  589. src = (u_int8_t *)h + P_OVERHEAD;
  590. bytes = OV_LEN(h);
  591. if (bytes + P_OVERHEAD > dbp->pgsize)
  592. bytes = dbp->pgsize - P_OVERHEAD;
  593. if ((ret = __os_realloc(dbp->dbenv,
  594.     bytesgot + bytes, 0, buf)) != 0)
  595. break;
  596. dest = (u_int8_t *)*buf + bytesgot;
  597. bytesgot += bytes;
  598. memcpy(dest, src, bytes);
  599. pgno = NEXT_PGNO(h);
  600. /* Not much we can do here--we don't want to quit. */
  601. if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
  602. err_ret = ret;
  603. }
  604. if (ret == 0) {
  605. dbt->size = bytesgot;
  606. dbt->data = *buf;
  607. }
  608. return ((err_ret != 0 && ret == 0) ? err_ret : ret);
  609. }