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 }