db

db_vrfyutil.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2000
00005  * Sleepycat Software. All rights reserved.
00006  *
00007  * $Id: db__vrfyutil_8c-source.html,v 1.1 2008年06月08日 10:18:32 sebdiaz Exp $
00008  */
00009 
00010 #include "config.h"
00011 
00012 #ifndef lint
00013 static const char revid[] = "$Id: db__vrfyutil_8c-source.html,v 1.1 2008年06月08日 10:18:32 sebdiaz Exp $";
00014 #endif /* not lint */
00015 
00016 #ifndef NO_SYSTEM_INCLUDES
00017 #include <sys/types.h>
00018 
00019 #include <string.h>
00020 #endif
00021 
00022 #include "db_int.h"
00023 #include "db_page.h"
00024 #include "db_verify.h"
00025 #include "db_ext.h"
00026 
00027 static int __db_vrfy_pgset_iinc __P((DB *, db_pgno_t, int));
00028 
00029 /*
00030  * CDB___db_vrfy_dbinfo_create --
00031  * Allocate and initialize a VRFY_DBINFO structure.
00032  *
00033  * PUBLIC: int CDB___db_vrfy_dbinfo_create
00034  * PUBLIC: __P((DB_ENV *, u_int32_t, VRFY_DBINFO **));
00035  */
00036 int
00037 CDB___db_vrfy_dbinfo_create (dbenv, pgsize, vdpp)
00038 DB_ENV *dbenv;
00039 u_int32_t pgsize;
00040 VRFY_DBINFO **vdpp;
00041 {
00042 DB *cdbp, *pgdbp, *pgset;
00043 VRFY_DBINFO *vdp;
00044 int ret;
00045 
00046 vdp = NULL;
00047 cdbp = pgdbp = pgset = NULL;
00048 
00049 if ((ret = CDB___os_calloc(NULL,
00050 1, sizeof(VRFY_DBINFO), (void **)&vdp)) != 0)
00051 goto err;
00052 
00053 if ((ret = CDB_db_create(&cdbp, dbenv, 0)) != 0)
00054 goto err;
00055 
00056 if ((ret = cdbp->set_flags(cdbp, DB_DUP | DB_DUPSORT)) != 0)
00057 goto err;
00058 
00059 if ((ret = cdbp->set_pagesize(cdbp, pgsize)) != 0)
00060 goto err;
00061 
00062 if ((ret =
00063 cdbp->open(cdbp, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
00064 goto err;
00065 
00066 if ((ret = CDB_db_create(&pgdbp, dbenv, 0)) != 0)
00067 goto err;
00068 
00069 if ((ret = pgdbp->set_pagesize(pgdbp, pgsize)) != 0)
00070 goto err;
00071 
00072 if ((ret =
00073 pgdbp->open(pgdbp, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
00074 goto err;
00075 
00076 if ((ret = CDB___db_vrfy_pgset(dbenv, pgsize, &pgset)) != 0)
00077 goto err;
00078 
00079 LIST_INIT(&vdp->subdbs);
00080 LIST_INIT(&vdp->activepips);
00081 
00082 vdp->cdbp = cdbp;
00083 vdp->pgdbp = pgdbp;
00084 vdp->pgset = pgset;
00085 *vdpp = vdp;
00086 return (0);
00087 
00088 err: if (cdbp != NULL)
00089 (void)cdbp->close(cdbp, 0);
00090 if (pgdbp != NULL)
00091 (void)pgdbp->close(pgdbp, 0);
00092 if (vdp != NULL)
00093 CDB___os_free(vdp, sizeof(VRFY_DBINFO));
00094 return (ret);
00095 }
00096 
00097 /*
00098  * CDB___db_vrfy_dbinfo_destroy --
00099  * Destructor for VRFY_DBINFO. Destroys VRFY_PAGEINFOs and deallocates
00100  * structure.
00101  *
00102  * PUBLIC: int CDB___db_vrfy_dbinfo_destroy __P((VRFY_DBINFO *));
00103  */
00104 int
00105 CDB___db_vrfy_dbinfo_destroy(vdp)
00106 VRFY_DBINFO *vdp;
00107 {
00108 VRFY_CHILDINFO *c, *d;
00109 int t_ret, ret;
00110 
00111 ret = 0;
00112 
00113 for (c = LIST_FIRST(&vdp->subdbs); c != NULL; c = d) {
00114 d = LIST_NEXT(c, links);
00115 CDB___os_free(c, 0);
00116 }
00117 
00118 if ((t_ret = vdp->pgdbp->close(vdp->pgdbp, 0)) != 0)
00119 ret = t_ret;
00120 
00121 if ((t_ret = vdp->cdbp->close(vdp->cdbp, 0)) != 0 && ret == 0)
00122 ret = t_ret;
00123 
00124 if ((t_ret = vdp->pgset->close(vdp->pgset, 0)) != 0 && ret == 0)
00125 ret = t_ret;
00126 
00127 DB_ASSERT(LIST_FIRST(&vdp->activepips) == NULL);
00128 
00129 CDB___os_free(vdp, sizeof(VRFY_DBINFO));
00130 return (ret);
00131 }
00132 
00133 /*
00134  * CDB___db_vrfy_getpageinfo --
00135  * Get a PAGEINFO structure for a given page, creating it if necessary.
00136  *
00137  * PUBLIC: int CDB___db_vrfy_getpageinfo
00138  * PUBLIC: __P((VRFY_DBINFO *, db_pgno_t, VRFY_PAGEINFO **));
00139  */
00140 int
00141 CDB___db_vrfy_getpageinfo(vdp, pgno, pipp)
00142 VRFY_DBINFO *vdp;
00143 db_pgno_t pgno;
00144 VRFY_PAGEINFO **pipp;
00145 {
00146 DBT key, data;
00147 DB *pgdbp;
00148 VRFY_PAGEINFO *pip;
00149 int ret;
00150 
00151 /*
00152  * We want a page info struct. There are three places to get it from,
00153  * in decreasing order of preference:
00154  *
00155  * 1. vdp->activepips. If it's already "checked out", we're
00156  * already using it, we return the same exact structure with a
00157  * bumped refcount. This is necessary because this code is
00158  * replacing array accesses, and it's common for f() to make some
00159  * changes to a pip, and then call g() and h() which each make
00160  * changes to the same pip. vdps are never shared between threads
00161  * (they're never returned to the application), so this is safe.
00162  * 2. The pgdbp. It's not in memory, but it's in the database, so
00163  * get it, give it a refcount of 1, and stick it on activepips.
00164  * 3. malloc. It doesn't exist yet; create it, then stick it on
00165  * activepips. We'll put it in the database when we putpageinfo
00166  * later.
00167  */
00168 
00169 /* Case 1. */
00170 for (pip = LIST_FIRST(&vdp->activepips); pip != NULL;
00171 pip = LIST_NEXT(pip, links))
00172 if (pip->pgno == pgno)
00173 /* Found it. */
00174 goto found;
00175 
00176 /* Case 2. */
00177 pgdbp = vdp->pgdbp;
00178 memset(&key, 0, sizeof(DBT));
00179 memset(&data, 0, sizeof(DBT));
00180 F_SET(&data, DB_DBT_MALLOC);
00181 key.data = &pgno;
00182 key.size = sizeof(db_pgno_t);
00183 
00184 if ((ret = pgdbp->get(pgdbp, NULL, &key, &data, 0)) == 0) {
00185 /* Found it. */
00186 DB_ASSERT(data.size = sizeof(VRFY_PAGEINFO));
00187 pip = data.data;
00188 DB_ASSERT(pip->pi_refcount == 0);
00189 LIST_INSERT_HEAD(&vdp->activepips, pip, links);
00190 goto found;
00191 } else if (ret != DB_NOTFOUND) /* Something nasty happened. */
00192 return (ret);
00193 
00194 /* Case 3 */
00195 if ((ret = CDB___db_vrfy_pageinfo_create(&pip)) != 0)
00196 return (ret);
00197 
00198 LIST_INSERT_HEAD(&vdp->activepips, pip, links);
00199 found: pip->pi_refcount++;
00200 
00201 *pipp = pip;
00202 
00203 DB_ASSERT(pip->pi_refcount > 0);
00204 return (0);
00205 }
00206 
00207 /*
00208  * CDB___db_vrfy_putpageinfo --
00209  * Put back a VRFY_PAGEINFO that we're done with.
00210  *
00211  * PUBLIC: int CDB___db_vrfy_putpageinfo __P((VRFY_DBINFO *, VRFY_PAGEINFO *));
00212  */
00213 int
00214 CDB___db_vrfy_putpageinfo(vdp, pip)
00215 VRFY_DBINFO *vdp;
00216 VRFY_PAGEINFO *pip;
00217 {
00218 DBT key, data;
00219 DB *pgdbp;
00220 VRFY_PAGEINFO *p;
00221 int ret;
00222 #ifdef DIAGNOSTIC
00223 int found;
00224 
00225 found = 0;
00226 #endif
00227 
00228 if (--pip->pi_refcount > 0)
00229 return (0);
00230 
00231 pgdbp = vdp->pgdbp;
00232 memset(&key, 0, sizeof(DBT));
00233 memset(&data, 0, sizeof(DBT));
00234 
00235 key.data = &pip->pgno;
00236 key.size = sizeof(db_pgno_t);
00237 data.data = pip;
00238 data.size = sizeof(VRFY_PAGEINFO);
00239 
00240 if ((ret = pgdbp->put(pgdbp, NULL, &key, &data, 0)) != 0)
00241 return (ret);
00242 
00243 for (p = LIST_FIRST(&vdp->activepips); p != NULL;
00244 p = LIST_NEXT(p, links))
00245 if (p == pip) {
00246 #ifdef DIAGNOSTIC
00247 found++;
00248 #endif
00249 DB_ASSERT(p->pi_refcount == 0);
00250 LIST_REMOVE(p, links);
00251 break;
00252 }
00253 #ifdef DIAGNOSTIC
00254 DB_ASSERT(found == 1);
00255 #endif
00256 
00257 DB_ASSERT(pip->pi_refcount == 0);
00258 CDB___os_free(pip, 0);
00259 return (0);
00260 }
00261 
00262 /*
00263  * CDB___db_vrfy_pgset --
00264  * Create a temporary database for the storing of sets of page numbers.
00265  * (A mapping from page number to int, used by the *_meta2pgset functions,
00266  * as well as for keeping track of which pages the verifier has seen.)
00267  *
00268  * PUBLIC: int CDB___db_vrfy_pgset __P((DB_ENV *, u_int32_t, DB **));
00269  */
00270 int
00271 CDB___db_vrfy_pgset(dbenv, pgsize, dbpp)
00272 DB_ENV *dbenv;
00273 u_int32_t pgsize;
00274 DB **dbpp;
00275 {
00276 DB *dbp;
00277 int ret;
00278 
00279 if ((ret = CDB_db_create(&dbp, dbenv, 0)) != 0)
00280 return (ret);
00281 if ((ret = dbp->set_pagesize(dbp, pgsize)) != 0)
00282 goto err;
00283 if ((ret = dbp->open(dbp, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) == 0)
00284 *dbpp = dbp;
00285 else
00286 err: (void)dbp->close(dbp, 0);
00287 
00288 return (ret);
00289 }
00290 
00291 /*
00292  * CDB___db_vrfy_pgset_get --
00293  * Get the value associated in a page set with a given pgno. Return
00294  * a 0 value (and succeed) if we've never heard of this page.
00295  *
00296  * PUBLIC: int CDB___db_vrfy_pgset_get __P((DB *, db_pgno_t, int *));
00297  */
00298 int
00299 CDB___db_vrfy_pgset_get(dbp, pgno, valp)
00300 DB *dbp;
00301 db_pgno_t pgno;
00302 int *valp;
00303 {
00304 DBT key, data;
00305 int ret, val;
00306 
00307 memset(&key, 0, sizeof(DBT));
00308 memset(&data, 0, sizeof(DBT));
00309 
00310 key.data = &pgno;
00311 key.size = sizeof(db_pgno_t);
00312 data.data = &val;
00313 data.ulen = sizeof(int);
00314 F_SET(&data, DB_DBT_USERMEM);
00315 
00316 if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) == 0) {
00317 DB_ASSERT(data.size = sizeof(int));
00318 memcpy(&val, data.data, sizeof(int));
00319 } else if (ret == DB_NOTFOUND)
00320 val = 0;
00321 else
00322 return (ret);
00323 
00324 *valp = val;
00325 return (0);
00326 }
00327 
00328 /*
00329  * CDB___db_vrfy_pgset_inc --
00330  * Increment the value associated with a pgno by 1.
00331  *
00332  * PUBLIC: int CDB___db_vrfy_pgset_inc __P((DB *, db_pgno_t));
00333  */
00334 int
00335 CDB___db_vrfy_pgset_inc(dbp, pgno)
00336 DB *dbp;
00337 db_pgno_t pgno;
00338 {
00339 
00340 return (__db_vrfy_pgset_iinc(dbp, pgno, 1));
00341 }
00342 
00343 /*
00344  * CDB___db_vrfy_pgset_dec --
00345  * Increment the value associated with a pgno by 1.
00346  *
00347  * PUBLIC: int CDB___db_vrfy_pgset_dec __P((DB *, db_pgno_t));
00348  */
00349 int
00350 CDB___db_vrfy_pgset_dec(dbp, pgno)
00351 DB *dbp;
00352 db_pgno_t pgno;
00353 {
00354 
00355 return (__db_vrfy_pgset_iinc(dbp, pgno, -1));
00356 }
00357 
00358 /*
00359  * __db_vrfy_pgset_iinc --
00360  * Increment the value associated with a pgno by i.
00361  *
00362  */
00363 static int
00364 __db_vrfy_pgset_iinc(dbp, pgno, i)
00365 DB *dbp;
00366 db_pgno_t pgno;
00367 int i;
00368 {
00369 DBT key, data;
00370 int ret;
00371 int val;
00372 
00373 memset(&key, 0, sizeof(DBT));
00374 memset(&data, 0, sizeof(DBT));
00375 
00376 val = 0;
00377 
00378 key.data = &pgno;
00379 key.size = sizeof(db_pgno_t);
00380 data.data = &val;
00381 data.ulen = sizeof(int);
00382 F_SET(&data, DB_DBT_USERMEM);
00383 
00384 if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) == 0) {
00385 DB_ASSERT(data.size = sizeof(int));
00386 memcpy(&val, data.data, sizeof(int));
00387 } else if (ret != DB_NOTFOUND)
00388 return (ret);
00389 
00390 data.size = sizeof(int);
00391 val += i;
00392 
00393 return (dbp->put(dbp, NULL, &key, &data, 0));
00394 }
00395 
00396 /*
00397  * CDB___db_vrfy_pgset_next --
00398  * Given a cursor open in a pgset database, get the next page in the
00399  * set.
00400  *
00401  * PUBLIC: int CDB___db_vrfy_pgset_next __P((DBC *, db_pgno_t *));
00402  */
00403 int
00404 CDB___db_vrfy_pgset_next(dbc, pgnop)
00405 DBC *dbc;
00406 db_pgno_t *pgnop;
00407 {
00408 DBT key, data;
00409 db_pgno_t pgno;
00410 int ret;
00411 
00412 memset(&key, 0, sizeof(DBT));
00413 memset(&data, 0, sizeof(DBT));
00414 /* We don't care about the data, just the keys. */
00415 F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL);
00416 F_SET(&key, DB_DBT_USERMEM);
00417 key.data = &pgno;
00418 key.ulen = sizeof(db_pgno_t);
00419 
00420 if ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) != 0)
00421 return (ret);
00422 
00423 DB_ASSERT(key.size == sizeof(db_pgno_t));
00424 *pgnop = pgno;
00425 
00426 return (0);
00427 }
00428 
00429 /*
00430  * CDB___db_vrfy_childcursor --
00431  * Create a cursor to walk the child list with. Returns with a nonzero
00432  * final argument if the specified page has no children.
00433  *
00434  * PUBLIC: int CDB___db_vrfy_childcursor __P((VRFY_DBINFO *, DBC **));
00435  */
00436 int
00437 CDB___db_vrfy_childcursor(vdp, dbcp)
00438 VRFY_DBINFO *vdp;
00439 DBC **dbcp;
00440 {
00441 DB *cdbp;
00442 DBC *dbc;
00443 int ret;
00444 
00445 cdbp = vdp->cdbp;
00446 
00447 if ((ret = cdbp->cursor(cdbp, NULL, &dbc, 0)) == 0)
00448 *dbcp = dbc;
00449 
00450 return (ret);
00451 }
00452 
00453 /*
00454  * CDB___db_vrfy_childput --
00455  * Add a child structure to the set for a given page.
00456  *
00457  * PUBLIC: int CDB___db_vrfy_childput
00458  * PUBLIC: __P((VRFY_DBINFO *, db_pgno_t, VRFY_CHILDINFO *));
00459  */
00460 int
00461 CDB___db_vrfy_childput(vdp, pgno, cip)
00462 VRFY_DBINFO *vdp;
00463 db_pgno_t pgno;
00464 VRFY_CHILDINFO *cip;
00465 {
00466 DBT key, data;
00467 DB *cdbp;
00468 int ret;
00469 
00470 cdbp = vdp->cdbp;
00471 memset(&key, 0, sizeof(DBT));
00472 memset(&data, 0, sizeof(DBT));
00473 
00474 key.data = &pgno;
00475 key.size = sizeof(db_pgno_t);
00476 
00477 data.data = cip;
00478 data.size = sizeof(VRFY_CHILDINFO);
00479 
00480 /*
00481  * Don't add duplicate (data) entries for a given child, and accept
00482  * DB_KEYEXIST as a successful return; we only need to verify
00483  * each child once, even if a child (such as an overflow key) is
00484  * multiply referenced.
00485  */
00486 ret = cdbp->put(cdbp, NULL, &key, &data, DB_NODUPDATA);
00487 return (ret == DB_KEYEXIST ? 0 : ret);
00488 }
00489 
00490 /*
00491  * CDB___db_vrfy_ccset --
00492  * Sets a cursor created with CDB___db_vrfy_childcursor to the first
00493  * child of the given pgno, and returns it in the third arg.
00494  *
00495  * PUBLIC: int CDB___db_vrfy_ccset __P((DBC *, db_pgno_t, VRFY_CHILDINFO **));
00496  */
00497 int
00498 CDB___db_vrfy_ccset(dbc, pgno, cipp)
00499 DBC *dbc;
00500 db_pgno_t pgno;
00501 VRFY_CHILDINFO **cipp;
00502 {
00503 DBT key, data;
00504 int ret;
00505 
00506 memset(&key, 0, sizeof(DBT));
00507 memset(&data, 0, sizeof(DBT));
00508 
00509 key.data = &pgno;
00510 key.size = sizeof(db_pgno_t);
00511 
00512 if ((ret = dbc->c_get(dbc, &key, &data, DB_SET)) != 0)
00513 return (ret);
00514 
00515 DB_ASSERT(data.size == sizeof(VRFY_CHILDINFO));
00516 *cipp = (VRFY_CHILDINFO *)data.data;
00517 
00518 return (0);
00519 }
00520 
00521 /*
00522  * CDB___db_vrfy_ccnext --
00523  * Gets the next child of the given cursor created with
00524  * CDB___db_vrfy_childcursor, and returns it in the memory provided in the
00525  * second arg.
00526  *
00527  * PUBLIC: int CDB___db_vrfy_ccnext __P((DBC *, VRFY_CHILDINFO **));
00528  */
00529 int
00530 CDB___db_vrfy_ccnext(dbc, cipp)
00531 DBC *dbc;
00532 VRFY_CHILDINFO **cipp;
00533 {
00534 DBT key, data;
00535 int ret;
00536 
00537 memset(&key, 0, sizeof(DBT));
00538 memset(&data, 0, sizeof(DBT));
00539 
00540 if ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT_DUP)) != 0)
00541 return (ret);
00542 
00543 DB_ASSERT(data.size == sizeof(VRFY_CHILDINFO));
00544 *cipp = (VRFY_CHILDINFO *)data.data;
00545 
00546 return (0);
00547 }
00548 
00549 /*
00550  * CDB___db_vrfy_ccclose --
00551  * Closes the cursor created with CDB___db_vrfy_childcursor.
00552  *
00553  * This doesn't actually do anything interesting now, but it's
00554  * not inconceivable that we might change the internal database CDB_usage
00555  * and keep the interfaces the same, and a function call here or there
00556  * seldom hurts anyone.
00557  *
00558  * PUBLIC: int CDB___db_vrfy_ccclose __P((DBC *));
00559  */
00560 int
00561 CDB___db_vrfy_ccclose(dbc)
00562 DBC *dbc;
00563 {
00564 
00565 return (dbc->c_close(dbc));
00566 }
00567 
00568 /*
00569  * CDB___db_vrfy_pageinfo_create --
00570  * Constructor for VRFY_PAGEINFO; allocates and initializes.
00571  *
00572  * PUBLIC: int CDB___db_vrfy_pageinfo_create __P((VRFY_PAGEINFO **));
00573  */
00574 int
00575 CDB___db_vrfy_pageinfo_create(pgipp)
00576 VRFY_PAGEINFO **pgipp;
00577 {
00578 VRFY_PAGEINFO *pgip;
00579 int ret;
00580 
00581 if ((ret = CDB___os_calloc(NULL,
00582 1, sizeof(VRFY_PAGEINFO), (void **)&pgip)) != 0)
00583 return (ret);
00584 
00585 DB_ASSERT(pgip->pi_refcount == 0);
00586 
00587 *pgipp = pgip;
00588 return (0);
00589 }
00590 
00591 /*
00592  * CDB___db_salvage_init --
00593  * Set up salvager database.
00594  *
00595  * PUBLIC: int CDB___db_salvage_init __P((VRFY_DBINFO *));
00596  */
00597 int
00598 CDB___db_salvage_init(vdp)
00599 VRFY_DBINFO *vdp;
00600 {
00601 DB *dbp;
00602 int ret;
00603 
00604 if ((ret = CDB_db_create(&dbp, NULL, 0)) != 0)
00605 return (ret);
00606 
00607 if ((ret = dbp->set_pagesize(dbp, 1024)) != 0)
00608 goto err;
00609 
00610 if ((ret = dbp->open(dbp, NULL, NULL, DB_BTREE, DB_CREATE, 0)) != 0)
00611 goto err;
00612 
00613 vdp->salvage_pages = dbp;
00614 return (0);
00615 
00616 err: (void)dbp->close(dbp, 0);
00617 return (ret);
00618 }
00619 
00620 /*
00621  * CDB___db_salvage_destroy --
00622  * Close salvager database.
00623  * PUBLIC: void CDB___db_salvage_destroy __P((VRFY_DBINFO *));
00624  */
00625 void
00626 CDB___db_salvage_destroy(vdp)
00627 VRFY_DBINFO *vdp;
00628 {
00629 (void)vdp->salvage_pages->close(vdp->salvage_pages, 0);
00630 }
00631 
00632 /*
00633  * CDB___db_salvage_getnext --
00634  * Get the next (first) unprinted page in the database of pages we need to
00635  * print still. Delete entries for any already-printed pages we encounter
00636  * in this search, as well as the page we're returning.
00637  *
00638  * PUBLIC: int CDB___db_salvage_getnext
00639  * PUBLIC: __P((VRFY_DBINFO *, db_pgno_t *, u_int32_t *));
00640  */
00641 int
00642 CDB___db_salvage_getnext(vdp, pgnop, pgtypep)
00643 VRFY_DBINFO *vdp;
00644 db_pgno_t *pgnop;
00645 u_int32_t *pgtypep;
00646 {
00647 DB *dbp;
00648 DBC *dbc;
00649 DBT key, data;
00650 int ret;
00651 u_int32_t pgtype;
00652 
00653 dbp = vdp->salvage_pages;
00654 
00655 memset(&key, 0, sizeof(DBT));
00656 memset(&data, 0, sizeof(DBT));
00657 
00658 if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
00659 return (ret);
00660 
00661 while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) {
00662 DB_ASSERT(data.size == sizeof(u_int32_t));
00663 memcpy(&pgtype, data.data, sizeof(pgtype));
00664 
00665 if ((ret = dbc->c_del(dbc, 0)) != 0)
00666 goto err;
00667 if (pgtype != SALVAGE_IGNORE)
00668 goto found;
00669 }
00670 
00671 /* No more entries--ret probably equals DB_NOTFOUND. */
00672 
00673 if (0) {
00674 found: DB_ASSERT(key.size == sizeof(db_pgno_t));
00675 DB_ASSERT(data.size == sizeof(u_int32_t));
00676 
00677 *pgnop = *(db_pgno_t *)key.data;
00678 *pgtypep = *(u_int32_t *)data.data;
00679 }
00680 
00681 err: (void)dbc->c_close(dbc);
00682 return (ret);
00683 }
00684 
00685 /*
00686  * CDB___db_salvage_isdone --
00687  * Return whether or not the given pgno is already marked
00688  * SALVAGE_IGNORE (meaning that we don't need to print it again).
00689  *
00690  * Returns DB_KEYEXIST if it is marked, 0 if not, or another error on
00691  * error.
00692  *
00693  * PUBLIC: int CDB___db_salvage_isdone __P((VRFY_DBINFO *, db_pgno_t));
00694  */
00695 int
00696 CDB___db_salvage_isdone(vdp, pgno)
00697 VRFY_DBINFO *vdp;
00698 db_pgno_t pgno;
00699 {
00700 DBT key, data;
00701 DB *dbp;
00702 int ret;
00703 u_int32_t currtype;
00704 
00705 dbp = vdp->salvage_pages;
00706 
00707 memset(&key, 0, sizeof(DBT));
00708 memset(&data, 0, sizeof(DBT));
00709 
00710 currtype = SALVAGE_INVALID;
00711 data.data = &currtype;
00712 data.ulen = sizeof(u_int32_t);
00713 data.flags = DB_DBT_USERMEM;
00714 
00715 key.data = &pgno;
00716 key.size = sizeof(db_pgno_t);
00717 
00718 /*
00719  * Put an entry for this page, with pgno as key and type as data,
00720  * unless it's already there and is marked done.
00721  * If it's there and is marked anything else, that's fine--we
00722  * want to mark it done.
00723  */
00724 ret = dbp->get(dbp, NULL, &key, &data, 0);
00725 if (ret == 0) {
00726 /*
00727  * The key's already here. Check and see if it's already
00728  * marked done. If it is, return DB_KEYEXIST. If it's not,
00729  * return 0.
00730  */
00731 if (currtype == SALVAGE_IGNORE)
00732 return (DB_KEYEXIST);
00733 else
00734 return (0);
00735 } else if (ret != DB_NOTFOUND)
00736 return (ret);
00737 
00738 /* The pgno is not yet marked anything; return 0. */
00739 return (0);
00740 }
00741 
00742 /*
00743  * CDB___db_salvage_markdone --
00744  * Mark as done a given page.
00745  *
00746  * PUBLIC: int CDB___db_salvage_markdone __P((VRFY_DBINFO *, db_pgno_t));
00747  */
00748 int
00749 CDB___db_salvage_markdone(vdp, pgno)
00750 VRFY_DBINFO *vdp;
00751 db_pgno_t pgno;
00752 {
00753 DBT key, data;
00754 DB *dbp;
00755 int pgtype, ret;
00756 u_int32_t currtype;
00757 
00758 pgtype = SALVAGE_IGNORE;
00759 dbp = vdp->salvage_pages;
00760 
00761 memset(&key, 0, sizeof(DBT));
00762 memset(&data, 0, sizeof(DBT));
00763 
00764 currtype = SALVAGE_INVALID;
00765 data.data = &currtype;
00766 data.ulen = sizeof(u_int32_t);
00767 data.flags = DB_DBT_USERMEM;
00768 
00769 key.data = &pgno;
00770 key.size = sizeof(db_pgno_t);
00771 
00772 /*
00773  * Put an entry for this page, with pgno as key and type as data,
00774  * unless it's already there and is marked done.
00775  * If it's there and is marked anything else, that's fine--we
00776  * want to mark it done, but db_salvage_isdone only lets
00777  * us know if it's marked IGNORE.
00778  */
00779 if ((ret = CDB___db_salvage_isdone(vdp, pgno)) != 0)
00780 return (ret);
00781 
00782 data.size = sizeof(u_int32_t);
00783 data.data = &pgtype;
00784 
00785 return (dbp->put(dbp, NULL, &key, &data, 0));
00786 }
00787 
00788 /*
00789  * CDB___db_salvage_markneeded --
00790  * If it has not yet been printed, make note of the fact that a page
00791  * must be dealt with later.
00792  *
00793  * PUBLIC: int CDB___db_salvage_markneeded
00794  * PUBLIC: __P((VRFY_DBINFO *, db_pgno_t, u_int32_t));
00795  */
00796 int
00797 CDB___db_salvage_markneeded(vdp, pgno, pgtype)
00798 VRFY_DBINFO *vdp;
00799 db_pgno_t pgno;
00800 u_int32_t pgtype;
00801 {
00802 DB *dbp;
00803 DBT key, data;
00804 int ret;
00805 
00806 dbp = vdp->salvage_pages;
00807 
00808 memset(&key, 0, sizeof(DBT));
00809 memset(&data, 0, sizeof(DBT));
00810 
00811 key.data = &pgno;
00812 key.size = sizeof(db_pgno_t);
00813 
00814 data.data = &pgtype;
00815 data.size = sizeof(u_int32_t);
00816 
00817 /*
00818  * Put an entry for this page, with pgno as key and type as data,
00819  * unless it's already there, in which case it's presumably
00820  * already been marked done.
00821  */
00822 ret = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
00823 return (ret == DB_KEYEXIST ? 0 : ret);
00824 }

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

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