db

db_overflow.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  * Copyright (c) 1990, 1993, 1994, 1995, 1996
00009  * Keith Bostic. All rights reserved.
00010  */
00011 /*
00012  * Copyright (c) 1990, 1993, 1994, 1995
00013  * The Regents of the University of California. All rights reserved.
00014  *
00015  * This code is derived from software contributed to Berkeley by
00016  * Mike Olson.
00017  *
00018  * Redistribution and use in source and binary forms, with or without
00019  * modification, are permitted provided that the following conditions
00020  * are met:
00021  * 1. Redistributions of source code must retain the above copyright
00022  * notice, this list of conditions and the following disclaimer.
00023  * 2. Redistributions in binary form must reproduce the above copyright
00024  * notice, this list of conditions and the following disclaimer in the
00025  * documentation and/or other materials provided with the distribution.
00026  * 3. Neither the name of the University nor the names of its contributors
00027  * may be used to endorse or promote products derived from this software
00028  * without specific prior written permission.
00029  *
00030  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00031  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00032  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00033  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00034  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00035  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00036  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00037  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00038  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00039  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00040  * SUCH DAMAGE.
00041  */
00042 
00043 #include "config.h"
00044 
00045 #ifndef lint
00046 static const char revid[] = "$Id: db__overflow_8c-source.html,v 1.1 2008年06月08日 10:17:55 sebdiaz Exp $";
00047 #endif /* not lint */
00048 
00049 #ifndef NO_SYSTEM_INCLUDES
00050 #include <sys/types.h>
00051 
00052 #include <errno.h>
00053 #include <string.h>
00054 #endif
00055 
00056 #include "db_int.h"
00057 #include "db_page.h"
00058 #include "db_am.h"
00059 #include "db_verify.h"
00060 
00061 /*
00062  * Big key/data code.
00063  *
00064  * Big key and data entries are stored on linked lists of pages. The initial
00065  * reference is a structure with the total length of the item and the page
00066  * number where it begins. Each entry in the linked list contains a pointer
00067  * to the next page of data, and so on.
00068  */
00069 
00070 /*
00071  * CDB___db_goff --
00072  * Get an offpage item.
00073  *
00074  * PUBLIC: int CDB___db_goff __P((DB *, DBT *,
00075  * PUBLIC: u_int32_t, db_pgno_t, void **, u_int32_t *));
00076  */
00077 int
00078 CDB___db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
00079 DB *dbp;
00080 DBT *dbt;
00081 u_int32_t tlen;
00082 db_pgno_t pgno;
00083 void **bpp;
00084 u_int32_t *bpsz;
00085 {
00086 DB_ENV *dbenv;
00087 PAGE *h;
00088 db_indx_t bytes;
00089 u_int32_t curoff, needed, start;
00090 u_int8_t *p, *src;
00091 int ret;
00092 
00093 dbenv = dbp->dbenv;
00094 
00095 /*
00096  * Check if the buffer is big enough; if it is not and we are
00097  * allowed to malloc space, then we'll malloc it. If we are
00098  * not (DB_DBT_USERMEM), then we'll set the dbt and return
00099  * appropriately.
00100  */
00101 if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
00102 start = dbt->doff;
00103 needed = dbt->dlen;
00104 } else {
00105 start = 0;
00106 needed = tlen;
00107 }
00108 
00109 /* Allocate any necessary memory. */
00110 if (F_ISSET(dbt, DB_DBT_USERMEM)) {
00111 if (needed > dbt->ulen) {
00112 dbt->size = needed;
00113 return (ENOMEM);
00114 }
00115 } else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
00116 if ((ret = CDB___os_malloc(dbenv,
00117 needed, dbp->db_malloc, &dbt->data)) != 0)
00118 return (ret);
00119 } else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
00120 if ((ret = CDB___os_realloc(dbenv,
00121 needed, dbp->db_realloc, &dbt->data)) != 0)
00122 return (ret);
00123 } else if (*bpsz == 0 || *bpsz < needed) {
00124 if ((ret = CDB___os_realloc(dbenv, needed, NULL, bpp)) != 0)
00125 return (ret);
00126 *bpsz = needed;
00127 dbt->data = *bpp;
00128 } else
00129 dbt->data = *bpp;
00130 
00131 /*
00132  * Step through the linked list of pages, copying the data on each
00133  * one into the buffer. Never copy more than the total data length.
00134  */
00135 dbt->size = needed;
00136 for (curoff = 0, p = dbt->data; pgno != PGNO_INVALID && needed > 0;) {
00137 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
00138 (void)CDB___db_pgerr(dbp, pgno);
00139 return (ret);
00140 }
00141 /* Check if we need any bytes from this page. */
00142 if (curoff + OV_LEN(h) >= start) {
00143 src = (u_int8_t *)h + P_OVERHEAD;
00144 bytes = OV_LEN(h);
00145 if (start > curoff) {
00146 src += start - curoff;
00147 bytes -= start - curoff;
00148 }
00149 if (bytes > needed)
00150 bytes = needed;
00151 memcpy(p, src, bytes);
00152 p += bytes;
00153 needed -= bytes;
00154 }
00155 curoff += OV_LEN(h);
00156 pgno = h->next_pgno;
00157 CDB_memp_fput(dbp->mpf, h, 0);
00158 }
00159 return (0);
00160 }
00161 
00162 /*
00163  * CDB___db_poff --
00164  * Put an offpage item.
00165  *
00166  * PUBLIC: int CDB___db_poff __P((DBC *, const DBT *, db_pgno_t *));
00167  */
00168 int
00169 CDB___db_poff(dbc, dbt, pgnop)
00170 DBC *dbc;
00171 const DBT *dbt;
00172 db_pgno_t *pgnop;
00173 {
00174 DB *dbp;
00175 PAGE *pagep, *lastp;
00176 DB_LSN new_lsn, null_lsn;
00177 DBT tmp_dbt;
00178 db_indx_t pagespace;
00179 u_int32_t sz;
00180 u_int8_t *p;
00181 int ret;
00182 
00183 /*
00184  * Allocate pages and copy the key/data item into them. Calculate the
00185  * number of bytes we get for pages we fill completely with a single
00186  * item.
00187  */
00188 dbp = dbc->dbp;
00189 pagespace = P_MAXSPACE(dbp->pgsize);
00190 
00191 lastp = NULL;
00192 for (p = dbt->data,
00193 sz = dbt->size; sz > 0; p += pagespace, sz -= pagespace) {
00194 /*
00195  * Reduce pagespace so we terminate the loop correctly and
00196  * don't copy too much data.
00197  */
00198 if (sz < pagespace)
00199 pagespace = sz;
00200 
00201 /*
00202  * Allocate and initialize a new page and copy all or part of
00203  * the item onto the page. If sz is less than pagespace, we
00204  * have a partial record.
00205  */
00206 if ((ret = CDB___db_new(dbc, (P_OVERFLOW | dbp->tags), &pagep)) != 0)
00207 return (ret);
00208 if (DB_LOGGING(dbc)) {
00209 tmp_dbt.data = p;
00210 tmp_dbt.size = pagespace;
00211 ZERO_LSN(null_lsn);
00212 if ((ret = CDB___db_big_log(dbp->dbenv, dbc->txn,
00213 &new_lsn, 0, DB_ADD_BIG, dbp->log_fileid,
00214 PGNO(pagep), lastp ? PGNO(lastp) : PGNO_INVALID,
00215 PGNO_INVALID, &tmp_dbt, &LSN(pagep),
00216 lastp == NULL ? &null_lsn : &LSN(lastp),
00217 &null_lsn)) != 0)
00218 return (ret);
00219 
00220 /* Move lsn onto page. */
00221 if (lastp)
00222 LSN(lastp) = new_lsn;
00223 LSN(pagep) = new_lsn;
00224 }
00225 
00226 P_INIT(pagep, dbp->pgsize,
00227 PGNO(pagep), PGNO_INVALID, PGNO_INVALID, 0, P_OVERFLOW, dbp->tags);
00228 OV_LEN(pagep) = pagespace;
00229 OV_REF(pagep) = 1;
00230 memcpy((u_int8_t *)pagep + P_OVERHEAD, p, pagespace);
00231 
00232 /*
00233  * If this is the first entry, update the user's info.
00234  * Otherwise, update the entry on the last page filled
00235  * in and release that page.
00236  */
00237 if (lastp == NULL)
00238 *pgnop = PGNO(pagep);
00239 else {
00240 lastp->next_pgno = PGNO(pagep);
00241 pagep->prev_pgno = PGNO(lastp);
00242 (void)CDB_memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY);
00243 }
00244 lastp = pagep;
00245 }
00246 (void)CDB_memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY);
00247 return (0);
00248 }
00249 
00250 /*
00251  * CDB___db_ovref --
00252  * Increment/decrement the reference count on an overflow page.
00253  *
00254  * PUBLIC: int CDB___db_ovref __P((DBC *, db_pgno_t, int32_t));
00255  */
00256 int
00257 CDB___db_ovref(dbc, pgno, adjust)
00258 DBC *dbc;
00259 db_pgno_t pgno;
00260 int32_t adjust;
00261 {
00262 DB *dbp;
00263 PAGE *h;
00264 int ret;
00265 
00266 dbp = dbc->dbp;
00267 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
00268 (void)CDB___db_pgerr(dbp, pgno);
00269 return (ret);
00270 }
00271 
00272 if (DB_LOGGING(dbc))
00273 if ((ret = CDB___db_ovref_log(dbp->dbenv, dbc->txn,
00274 &LSN(h), 0, dbp->log_fileid, h->pgno, adjust,
00275 &LSN(h))) != 0)
00276 return (ret);
00277 OV_REF(h) += adjust;
00278 
00279 (void)CDB_memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
00280 return (0);
00281 }
00282 
00283 /*
00284  * CDB___db_doff --
00285  * Delete an offpage chain of overflow pages.
00286  *
00287  * PUBLIC: int CDB___db_doff __P((DBC *, db_pgno_t));
00288  */
00289 int
00290 CDB___db_doff(dbc, pgno)
00291 DBC *dbc;
00292 db_pgno_t pgno;
00293 {
00294 DB *dbp;
00295 PAGE *pagep;
00296 DB_LSN null_lsn;
00297 DBT tmp_dbt;
00298 int ret;
00299 
00300 dbp = dbc->dbp;
00301 do {
00302 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0) {
00303 (void)CDB___db_pgerr(dbp, pgno);
00304 return (ret);
00305 }
00306 
00307 /*
00308  * If it's an overflow page and it's referenced by more than
00309  * one key/data item, decrement the reference count and return.
00310  */
00311 if (TYPE(pagep) == P_OVERFLOW && OV_REF(pagep) > 1) {
00312 (void)CDB_memp_fput(dbp->mpf, pagep, 0);
00313 return (CDB___db_ovref(dbc, pgno, -1));
00314 }
00315 
00316 if (DB_LOGGING(dbc)) {
00317 tmp_dbt.data = (u_int8_t *)pagep + P_OVERHEAD;
00318 tmp_dbt.size = OV_LEN(pagep);
00319 ZERO_LSN(null_lsn);
00320 if ((ret = CDB___db_big_log(dbp->dbenv, dbc->txn,
00321 &LSN(pagep), 0, DB_REM_BIG, dbp->log_fileid,
00322 PGNO(pagep), PREV_PGNO(pagep), NEXT_PGNO(pagep),
00323 &tmp_dbt, &LSN(pagep), &null_lsn, &null_lsn)) != 0)
00324 return (ret);
00325 }
00326 pgno = pagep->next_pgno;
00327 if ((ret = CDB___db_free(dbc, pagep)) != 0)
00328 return (ret);
00329 } while (pgno != PGNO_INVALID);
00330 
00331 return (0);
00332 }
00333 
00334 /*
00335  * CDB___db_moff --
00336  * Match on overflow pages.
00337  *
00338  * Given a starting page number and a key, return <0, 0, >0 to indicate if the
00339  * key on the page is less than, equal to or greater than the key specified.
00340  * We optimize this by doing chunk at a time comparison unless the user has
00341  * specified a comparison function. In this case, we need to materialize
00342  * the entire object and call their comparison routine.
00343  *
00344  * PUBLIC: int CDB___db_moff __P((DB *, const DBT *, db_pgno_t, u_int32_t,
00345  * PUBLIC: int (*)(const DBT *, const DBT *), int *));
00346  */
00347 int
00348 CDB___db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
00349 DB *dbp;
00350 const DBT *dbt;
00351 db_pgno_t pgno;
00352 u_int32_t tlen;
00353 int (*cmpfunc) __P((const DBT *, const DBT *));
00354 int *cmpp;
00355 {
00356 PAGE *pagep;
00357 DBT local_dbt;
00358 void *buf;
00359 u_int32_t bufsize, cmp_bytes, key_left;
00360 u_int8_t *p1, *p2;
00361 int ret;
00362 
00363 /*
00364  * If there is a user-specified comparison function, build a
00365  * contiguous copy of the key, and call it.
00366  */
00367 if (cmpfunc != NULL) {
00368 memset(&local_dbt, 0, sizeof(local_dbt));
00369 buf = NULL;
00370 bufsize = 0;
00371 
00372 if ((ret = CDB___db_goff(dbp,
00373 &local_dbt, tlen, pgno, &buf, &bufsize)) != 0)
00374 return (ret);
00375 /* Pass the key as the first argument */
00376 *cmpp = cmpfunc(dbt, &local_dbt);
00377 CDB___os_free(buf, bufsize);
00378 return (0);
00379 }
00380 
00381 /* While there are both keys to compare. */
00382 for (*cmpp = 0, p1 = dbt->data,
00383 key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) {
00384 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0)
00385 return (ret);
00386 
00387 cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left;
00388 tlen -= cmp_bytes;
00389 key_left -= cmp_bytes;
00390 for (p2 =
00391 (u_int8_t *)pagep + P_OVERHEAD; cmp_bytes-- > 0; ++p1, ++p2)
00392 if (*p1 != *p2) {
00393 *cmpp = (long)*p1 - (long)*p2;
00394 break;
00395 }
00396 pgno = NEXT_PGNO(pagep);
00397 if ((ret = CDB_memp_fput(dbp->mpf, pagep, 0)) != 0)
00398 return (ret);
00399 if (*cmpp != 0)
00400 return (0);
00401 }
00402 if (key_left > 0) /* DBT is longer than the page key. */
00403 *cmpp = 1;
00404 else if (tlen > 0) /* DBT is shorter than the page key. */
00405 *cmpp = -1;
00406 else
00407 *cmpp = 0;
00408 
00409 return (0);
00410 }
00411 
00412 /*
00413  * CDB___db_vrfy_overflow --
00414  * Verify overflow page.
00415  *
00416  * PUBLIC: int CDB___db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
00417  * PUBLIC: u_int32_t));
00418  */
00419 int
00420 CDB___db_vrfy_overflow(dbp, vdp, h, pgno, flags)
00421 DB *dbp;
00422 VRFY_DBINFO *vdp;
00423 PAGE *h;
00424 db_pgno_t pgno;
00425 u_int32_t flags;
00426 {
00427 VRFY_PAGEINFO *pip;
00428 int isbad, ret, t_ret;
00429 
00430 isbad = 0;
00431 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00432 return (ret);
00433 
00434 if ((ret = CDB___db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
00435 if (ret == DB_VERIFY_BAD)
00436 isbad = 1;
00437 else
00438 goto err;
00439 }
00440 
00441 pip->refcount = OV_REF(h);
00442 if (pip->refcount < 1) {
00443 EPRINT((dbp->dbenv, "Overflow page %lu has zero reference count",
00444 pgno));
00445 isbad = 1;
00446 }
00447 
00448 /* Just store for now. */
00449 pip->olen = HOFFSET(h);
00450 
00451 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0)
00452 ret = t_ret;
00453 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00454 }
00455 
00456 /*
00457  * CDB___db_vrfy_ovfl_structure --
00458  * Walk a list of overflow pages, avoiding cycles and marking
00459  * pages seen.
00460  *
00461  * PUBLIC: int CDB___db_vrfy_ovfl_structure
00462  * PUBLIC: __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t));
00463  */
00464 int
00465 CDB___db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
00466 DB *dbp;
00467 VRFY_DBINFO *vdp;
00468 db_pgno_t pgno;
00469 u_int32_t tlen;
00470 u_int32_t flags;
00471 {
00472 DB *pgset;
00473 VRFY_PAGEINFO *pip;
00474 db_pgno_t next, prev;
00475 int isbad, p, ret, t_ret;
00476 u_int32_t refcount;
00477 
00478 pgset = vdp->pgset;
00479 DB_ASSERT(pgset != NULL);
00480 isbad = 0;
00481 
00482 /* This shouldn't happen, but just to be sure. */
00483 if (!IS_VALID_PGNO(pgno))
00484 return (DB_VERIFY_BAD);
00485 
00486 /*
00487  * Check the first prev_pgno; it ought to be PGNO_INVALID,
00488  * since there's no prev page.
00489  */
00490 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00491 return (ret);
00492 
00493 /* The refcount is stored on the first overflow page. */
00494 refcount = pip->refcount;
00495 
00496 if (pip->type != P_OVERFLOW) {
00497 EPRINT((dbp->dbenv,
00498 "Overflow page %lu of invalid type", pgno, pip->type));
00499 ret = DB_VERIFY_BAD;
00500 goto err; /* Unsafe to continue. */
00501 }
00502 
00503 prev = pip->prev_pgno;
00504 if (prev != PGNO_INVALID) {
00505 EPRINT((dbp->dbenv,
00506 "First overflow page %lu has a prev_pgno", pgno));
00507 isbad = 1;
00508 }
00509 
00510 for (;;) {
00511 /*
00512  * This is slightly gross. Btree leaf pages reference
00513  * individual overflow trees multiple times if the overflow page
00514  * is the key to a duplicate set. The reference count does not
00515  * reflect this multiple referencing. Thus, if this is called
00516  * during the structure verification of a btree leaf page, we
00517  * check to see whether we've seen it from a leaf page before
00518  * and, if we have, adjust our count of how often we've seen it
00519  * accordingly.
00520  *
00521  * (This will screw up if it's actually referenced--and
00522  * correctly refcounted--from two different leaf pages, but
00523  * that's a very unlikely brokenness that we're not checking for
00524  * anyway.)
00525  */
00526 
00527 if (LF_ISSET(ST_OVFL_LEAF)) {
00528 if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) {
00529 if ((ret =
00530 CDB___db_vrfy_pgset_dec(pgset, pgno)) != 0)
00531 goto err;
00532 } else
00533 F_SET(pip, VRFY_OVFL_LEAFSEEN);
00534 }
00535 
00536 if ((ret = CDB___db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
00537 goto err;
00538 
00539 /*
00540  * We may have seen this elsewhere, if the overflow entry
00541  * has been promoted to an internal page.
00542  */
00543 if ((u_int32_t)p > refcount) {
00544 EPRINT((dbp->dbenv,
00545 "Page %lu encountered twice in overflow traversal",
00546 pgno));
00547 ret = DB_VERIFY_BAD;
00548 goto err;
00549 }
00550 if ((ret = CDB___db_vrfy_pgset_inc(pgset, pgno)) != 0)
00551 goto err;
00552 
00553 /* Keep a running tab on how much of the item we've seen. */
00554 tlen -= pip->olen;
00555 
00556 next = pip->next_pgno;
00557 
00558 /* Are we there yet? */
00559 if (next == PGNO_INVALID)
00560 break;
00561 
00562 /*
00563  * We've already checked this when we saved it, but just
00564  * to be sure...
00565  */
00566 if (!IS_VALID_PGNO(next)) {
00567 DB_ASSERT(0);
00568 EPRINT((dbp->dbenv,
00569 "Overflow page %lu has bad next_pgno",
00570 pgno));
00571 ret = DB_VERIFY_BAD;
00572 goto err;
00573 }
00574 
00575 if ((ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 ||
00576 (ret = CDB___db_vrfy_getpageinfo(vdp, next, &pip)) != 0)
00577 return (ret);
00578 if (pip->prev_pgno != pgno) {
00579 EPRINT((dbp->dbenv,
00580 "Overflow page %lu has bogus prev_pgno value",
00581 next));
00582 isbad = 1;
00583 /*
00584  * It's safe to continue because we have separate
00585  * cycle detection.
00586  */
00587 }
00588 
00589 pgno = next;
00590 }
00591 
00592 if (tlen > 0) {
00593 isbad = 1;
00594 EPRINT((dbp->dbenv,
00595 "Overflow item incomplete on page %lu", pgno));
00596 }
00597 
00598 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00599 ret = t_ret;
00600 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00601 }
00602 
00603 /*
00604  * CDB___db_safe_goff --
00605  * Get an overflow item, very carefully, from an untrusted database,
00606  * in the context of the salvager.
00607  *
00608  * PUBLIC: int CDB___db_safe_goff __P((DB *, VRFY_DBINFO *, db_pgno_t,
00609  * PUBLIC: DBT *, void **, u_int32_t));
00610  */
00611 int
00612 CDB___db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
00613 DB *dbp;
00614 VRFY_DBINFO *vdp;
00615 db_pgno_t pgno;
00616 DBT *dbt;
00617 void **buf;
00618 u_int32_t flags;
00619 {
00620 PAGE *h;
00621 int ret, err_ret;
00622 u_int32_t bytesgot, bytes;
00623 u_int8_t *src, *dest;
00624 
00625 ret = DB_VERIFY_BAD;
00626 err_ret = 0;
00627 bytesgot = bytes = 0;
00628 
00629 while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {
00630 /*
00631  * Mark that we're looking at this page; if we've seen it
00632  * already, quit.
00633  */
00634 if ((ret = CDB___db_salvage_markdone(vdp, pgno)) != 0)
00635 break;
00636 
00637 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
00638 break;
00639 
00640 /*
00641  * Make sure it's really an overflow page, unless we're
00642  * being aggressive, in which case we pretend it is.
00643  */
00644 if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) {
00645 ret = DB_VERIFY_BAD;
00646 break;
00647 }
00648 
00649 src = (u_int8_t *)h + P_OVERHEAD;
00650 bytes = OV_LEN(h);
00651 
00652 if (bytes + P_OVERHEAD > dbp->pgsize)
00653 bytes = dbp->pgsize - P_OVERHEAD;
00654 
00655 if ((ret = CDB___os_realloc(dbp->dbenv,
00656 bytesgot + bytes, 0, buf)) != 0)
00657 break;
00658 
00659 dest = (u_int8_t *)*buf + bytesgot;
00660 bytesgot += bytes;
00661 
00662 memcpy(dest, src, bytes);
00663 
00664 pgno = NEXT_PGNO(h);
00665 /* Not much we can do here--we don't want to quit. */
00666 if ((ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0)
00667 err_ret = ret;
00668 }
00669 
00670 if (ret == 0) {
00671 dbt->size = bytesgot;
00672 dbt->data = *buf;
00673 }
00674 
00675 return ((err_ret != 0 && ret == 0) ? err_ret : ret);
00676 }

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

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