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