00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "config.h"
00011
00012 #ifndef lint
00013 static const char revid[] = "$Id: hash__verify_8c-source.html,v 1.1 2008/06/08 10:19:40 sebdiaz Exp $";
00014 #endif
00015
00016 #ifndef NO_SYSTEM_INCLUDES
00017 #include <sys/types.h>
00018
00019 #include <errno.h>
00020 #include <string.h>
00021 #endif
00022
00023 #include "db_int.h"
00024 #include "db_page.h"
00025 #include "db_verify.h"
00026 #include "btree.h"
00027 #include "hash.h"
00028
00029 static int __ham_dups_unsorted __P((DB *, u_int8_t *, u_int32_t));
00030 static int __ham_vrfy_bucket __P((DB *, VRFY_DBINFO *, HMETA *, u_int32_t,
00031 u_int32_t));
00032 static int __ham_vrfy_item __P((DB *,
00033 VRFY_DBINFO *, db_pgno_t, PAGE *, u_int32_t, u_int32_t));
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 int
00047 CDB___ham_vrfy_meta(dbp, vdp, m, pgno, flags)
00048 DB *dbp;
00049 VRFY_DBINFO *vdp;
00050 HMETA *m;
00051 db_pgno_t pgno;
00052 u_int32_t flags;
00053 {
00054 HASH *hashp;
00055 VRFY_PAGEINFO *pip;
00056 int i, ret, t_ret, isbad;
00057 u_int32_t pwr, mbucket;
00058 u_int32_t (*hfunc) __P((const void *, u_int32_t));
00059
00060 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00061 return (ret);
00062 isbad = 0;
00063
00064 hashp = dbp->h_internal;
00065
00066 if (hashp != NULL && hashp->h_hash != NULL)
00067 hfunc = hashp->h_hash;
00068 else
00069 hfunc = CDB___ham_func5;
00070
00071
00072
00073
00074
00075 if (!F_ISSET(pip, VRFY_INCOMPLETE) &&
00076 (ret = CDB___db_vrfy_meta(dbp, vdp, &m->dbmeta, pgno, flags)) != 0) {
00077 if (ret == DB_VERIFY_BAD)
00078 isbad = 1;
00079 else
00080 goto err;
00081 }
00082
00083
00084 if (!LF_ISSET(DB_NOORDERCHK))
00085 if (m->h_charkey != hfunc(CHARKEY, sizeof(CHARKEY))) {
00086 EPRINT((dbp->dbenv,
00087 "Database has different custom hash function; reverify with DB_NOORDERCHK set"
00088 ));
00089
00090
00091
00092
00093
00094 isbad = 1;
00095 goto err;
00096 }
00097
00098
00099 if (m->max_bucket > vdp->last_pgno) {
00100 EPRINT((dbp->dbenv,
00101 "Impossible max_bucket %lu on meta page %lu",
00102 m->max_bucket, pgno));
00103
00104
00105
00106
00107
00108 isbad = 1;
00109 goto err;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119 pwr = (m->max_bucket == 0) ? 1 : 1 << CDB___db_log2(m->max_bucket + 1);
00120 if (m->high_mask != pwr - 1) {
00121 EPRINT((dbp->dbenv,
00122 "Incorrect high_mask %lu on page %lu, should be %lu",
00123 m->high_mask, pgno, pwr - 1));
00124 isbad = 1;
00125 }
00126 pwr >>= 1;
00127 if (m->low_mask != pwr - 1) {
00128 EPRINT((dbp->dbenv,
00129 "Incorrect low_mask %lu on page %lu, should be %lu",
00130 m->low_mask, pgno, pwr - 1));
00131 isbad = 1;
00132 }
00133
00134
00135 pip->h_ffactor = m->ffactor;
00136
00137
00138
00139
00140
00141
00142 if (m->nelem > 0x80000000) {
00143 EPRINT((dbp->dbenv,
00144 "Suspiciously high nelem of %lu on page %lu",
00145 m->nelem, pgno));
00146 isbad = 1;
00147 pip->h_nelem = 0;
00148 } else
00149 pip->h_nelem = m->nelem;
00150
00151
00152 if (F_ISSET(&m->dbmeta, DB_HASH_DUP))
00153 F_SET(pip, VRFY_HAS_DUPS);
00154 if (F_ISSET(&m->dbmeta, DB_HASH_DUPSORT))
00155 F_SET(pip, VRFY_HAS_DUPSORT);
00156
00157
00158
00159 for (i = 0; m->spares[i] != 0 && i < NCACHED; i++) {
00160
00161
00162
00163
00164
00165 mbucket = (1 << i) - 1;
00166 if (mbucket + m->spares[CDB___db_log2(mbucket + 1)] >
00167 vdp->last_pgno) {
00168 EPRINT((dbp->dbenv,
00169 "Spares array entry %lu, page %lu is invalid",
00170 i, pgno));
00171 isbad = 1;
00172 }
00173 }
00174
00175 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00176 ret = t_ret;
00177 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187 int
00188 CDB___ham_vrfy(dbp, vdp, h, pgno, flags)
00189 DB *dbp;
00190 VRFY_DBINFO *vdp;
00191 PAGE *h;
00192 db_pgno_t pgno;
00193 u_int32_t flags;
00194 {
00195 VRFY_PAGEINFO *pip;
00196 db_indx_t ent, himark, inpend;
00197 int isbad, ret, t_ret;
00198
00199 isbad = 0;
00200 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00201 return (ret);
00202
00203
00204 if ((ret = CDB___db_fchk(dbp->dbenv, "CDB___ham_vrfy",
00205 flags, DB_AGGRESSIVE | DB_NOORDERCHK | DB_SALVAGE)) != 0)
00206 goto err;
00207
00208 if (TYPE(h) != P_HASH) {
00209 TYPE_ERR_PRINT(dbp->dbenv, "CDB___ham_vrfy", pgno, TYPE(h));
00210 DB_ASSERT(0);
00211 ret = EINVAL;
00212 goto err;
00213 }
00214
00215
00216 if ((ret = CDB___db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
00217 if (ret == DB_VERIFY_BAD)
00218 isbad = 1;
00219 else
00220 goto err;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 for (ent = 0, himark = dbp->pgsize,
00232 inpend = (u_int8_t *)h->inp - (u_int8_t *)h;
00233 ent < NUM_ENT(h); ent++)
00234 if (h->inp[ent] >= himark) {
00235 EPRINT((dbp->dbenv,
00236 "Item %lu on page %lu out of order or nonsensical",
00237 ent, pgno));
00238 isbad = 1;
00239 goto err;
00240 } else if (inpend >= himark) {
00241 EPRINT((dbp->dbenv,
00242 "inp array collided with data on page %lu",
00243 pgno));
00244 isbad = 1;
00245 goto err;
00246
00247 } else {
00248 himark = h->inp[ent];
00249 inpend += sizeof(db_indx_t);
00250 if ((ret = __ham_vrfy_item(
00251 dbp, vdp, pgno, h, ent, flags)) != 0)
00252 goto err;
00253 }
00254
00255 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00256 ret = t_ret;
00257 return (ret == 0 && isbad == 1 ? DB_VERIFY_BAD : ret);
00258 }
00259
00260
00261
00262
00263
00264
00265 static int
00266 __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
00267 DB *dbp;
00268 VRFY_DBINFO *vdp;
00269 db_pgno_t pgno;
00270 PAGE *h;
00271 u_int32_t i, flags;
00272 {
00273 HOFFPAGE hop;
00274 HOFFDUP hod;
00275 VRFY_CHILDINFO child;
00276 VRFY_PAGEINFO *pip;
00277 db_indx_t offset, len, dlen, elen;
00278 int ret, t_ret;
00279 u_int8_t *databuf;
00280
00281 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00282 return (ret);
00283
00284 switch (HPAGE_TYPE(h, i)) {
00285 case H_KEYDATA:
00286
00287 break;
00288 case H_DUPLICATE:
00289
00290 if (i % 2 == 0) {
00291 EPRINT((dbp->dbenv,
00292 "Hash key stored as duplicate at page %lu item %lu",
00293 pip->pgno, i));
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 len = LEN_HKEYDATA(h, dbp->pgsize, i);
00306 databuf = HKEYDATA_DATA(P_ENTRY(h, i));
00307 for (offset = 0; offset < len; offset += DUP_SIZE(dlen)) {
00308 memcpy(&dlen, databuf + offset, sizeof(db_indx_t));
00309
00310
00311 if (offset + DUP_SIZE(dlen) > len) {
00312 EPRINT((dbp->dbenv,
00313 "Duplicate item %lu, page %lu has bad length",
00314 i, pip->pgno));
00315 ret = DB_VERIFY_BAD;
00316 goto err;
00317 }
00318
00319
00320
00321
00322
00323 memcpy(&elen,
00324 databuf + offset + dlen + sizeof(db_indx_t),
00325 sizeof(db_indx_t));
00326 if (elen != dlen) {
00327 EPRINT((dbp->dbenv,
00328 "Duplicate item %lu, page %lu has two different lengths",
00329 i, pip->pgno));
00330 ret = DB_VERIFY_BAD;
00331 goto err;
00332 }
00333 }
00334 F_SET(pip, VRFY_HAS_DUPS);
00335 if (!LF_ISSET(DB_NOORDERCHK) &&
00336 __ham_dups_unsorted(dbp, databuf, len))
00337 F_SET(pip, VRFY_DUPS_UNSORTED);
00338 break;
00339 case H_OFFPAGE:
00340
00341 memcpy(&hop, P_ENTRY(h, i), HOFFPAGE_SIZE);
00342 if (!IS_VALID_PGNO(hop.pgno) || hop.pgno == pip->pgno ||
00343 hop.pgno == PGNO_INVALID) {
00344 EPRINT((dbp->dbenv,
00345 "Offpage item %lu, page %lu has bad page number",
00346 i, pip->pgno));
00347 ret = DB_VERIFY_BAD;
00348 goto err;
00349 }
00350 memset(&child, 0, sizeof(VRFY_CHILDINFO));
00351 child.pgno = hop.pgno;
00352 child.type = V_OVERFLOW;
00353 child.tlen = hop.tlen;
00354 if ((ret = CDB___db_vrfy_childput(vdp, pip->pgno, &child)) != 0)
00355 goto err;
00356 break;
00357 case H_OFFDUP:
00358
00359 memcpy(&hod, P_ENTRY(h, i), HOFFDUP_SIZE);
00360 if (!IS_VALID_PGNO(hod.pgno) || hod.pgno == pip->pgno ||
00361 hod.pgno == PGNO_INVALID) {
00362 EPRINT((dbp->dbenv,
00363 "Offpage item %lu, page %lu has bad page number",
00364 i, pip->pgno));
00365 ret = DB_VERIFY_BAD;
00366 goto err;
00367 }
00368 memset(&child, 0, sizeof(VRFY_CHILDINFO));
00369 child.pgno = hod.pgno;
00370 child.type = V_DUPLICATE;
00371 if ((ret = CDB___db_vrfy_childput(vdp, pip->pgno, &child)) != 0)
00372 goto err;
00373 F_SET(pip, VRFY_HAS_DUPS);
00374 break;
00375 default:
00376 EPRINT((dbp->dbenv,
00377 "Item %i, page %lu has bad type", i, pip->pgno));
00378 ret = DB_VERIFY_BAD;
00379 break;
00380 }
00381
00382 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00383 ret = t_ret;
00384 return (ret);
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394 int
00395 CDB___ham_vrfy_structure(dbp, vdp, meta_pgno, flags)
00396 DB *dbp;
00397 VRFY_DBINFO *vdp;
00398 db_pgno_t meta_pgno;
00399 u_int32_t flags;
00400 {
00401 DB *pgset;
00402 HMETA *m;
00403 PAGE *h;
00404 VRFY_PAGEINFO *pip;
00405 int isbad, p, ret, t_ret;
00406 db_pgno_t pgno;
00407 u_int32_t bucket;
00408
00409 ret = isbad = 0;
00410 h = NULL;
00411 pgset = vdp->pgset;
00412
00413 if ((ret = CDB___db_vrfy_pgset_get(pgset, meta_pgno, &p)) != 0)
00414 return (ret);
00415 if (p != 0) {
00416 EPRINT((dbp->dbenv,
00417 "Hash meta page %lu referenced twice", meta_pgno));
00418 return (DB_VERIFY_BAD);
00419 }
00420 if ((ret = CDB___db_vrfy_pgset_inc(pgset, meta_pgno)) != 0)
00421 return (ret);
00422
00423
00424 if ((ret = CDB_memp_fget(dbp->mpf, &meta_pgno, 0, &m)) != 0)
00425 return (ret);
00426
00427
00428 for (bucket = 0; bucket <= m->max_bucket; bucket++)
00429 if ((ret =
00430 __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)) != 0) {
00431 if (ret == DB_VERIFY_BAD)
00432 isbad = 1;
00433 else
00434 goto err;
00435 }
00436
00437
00438
00439
00440
00441
00442
00443 for (bucket = m->max_bucket + 1; bucket <= m->high_mask; bucket++) {
00444 pgno = bucket + m->spares[CDB___db_log2(bucket + 1)];
00445 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00446 goto err;
00447
00448
00449 F_CLR(pip, VRFY_IS_ALLZEROES);
00450
00451 if (pip->type != P_HASH) {
00452 EPRINT((dbp->dbenv,
00453 "Hash bucket %lu maps to non-hash page %lu",
00454 bucket, pgno));
00455 isbad = 1;
00456 } else if (pip->entries != 0) {
00457 EPRINT((dbp->dbenv,
00458 "Non-empty page %lu in unused hash bucket %lu",
00459 pgno, bucket));
00460 isbad = 1;
00461 } else {
00462 if ((ret = CDB___db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
00463 goto err;
00464 if (p != 0) {
00465 EPRINT((dbp->dbenv,
00466 "Hash page %lu above max_bucket referenced",
00467 pgno));
00468 isbad = 1;
00469 } else {
00470 if ((ret =
00471 CDB___db_vrfy_pgset_inc(pgset, pgno)) != 0)
00472 goto err;
00473 if ((ret =
00474 CDB___db_vrfy_putpageinfo(vdp, pip)) != 0)
00475 goto err;
00476 continue;
00477 }
00478 }
00479
00480
00481 (void)CDB___db_vrfy_putpageinfo(vdp, pip);
00482 goto err;
00483 }
00484
00485 err: if ((t_ret = CDB_memp_fput(dbp->mpf, m, 0)) != 0)
00486 return (t_ret);
00487 if (h != NULL && (t_ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0)
00488 return (t_ret);
00489 return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD: ret);
00490 }
00491
00492
00493
00494
00495
00496 static int
00497 __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
00498 DB *dbp;
00499 VRFY_DBINFO *vdp;
00500 HMETA *m;
00501 u_int32_t bucket, flags;
00502 {
00503 HASH *hashp;
00504 VRFY_CHILDINFO *child;
00505 VRFY_PAGEINFO *mip, *pip;
00506 int ret, t_ret, isbad, p;
00507 db_pgno_t pgno, next_pgno;
00508 DBC *cc;
00509 u_int32_t (*hfunc) __P((const void *, u_int32_t));
00510
00511 isbad = 0;
00512 pip = NULL;
00513 cc = NULL;
00514
00515 hashp = dbp->h_internal;
00516 if (hashp != NULL && hashp->h_hash != NULL)
00517 hfunc = hashp->h_hash;
00518 else
00519 hfunc = CDB___ham_func5;
00520
00521 if ((ret = CDB___db_vrfy_getpageinfo(vdp, PGNO(m), &mip)) != 0)
00522 return (ret);
00523
00524
00525 pgno = bucket + m->spares[CDB___db_log2(bucket + 1)];
00526
00527 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00528 goto err;
00529
00530
00531 if (pgno > vdp->last_pgno || pip->type != P_HASH) {
00532 EPRINT((dbp->dbenv, "Bucket %lu has impossible first page %lu",
00533 bucket, pgno));
00534
00535 isbad = 1;
00536 goto err;
00537 }
00538
00539 if (pip->prev_pgno != PGNO_INVALID) {
00540 EPRINT((dbp->dbenv,
00541 "First hash page %lu in bucket %lu has a prev_pgno", pgno));
00542 isbad = 1;
00543 }
00544
00545
00546
00547
00548 flags |= F_ISSET(mip, VRFY_HAS_DUPS) ? ST_DUPOK : 0;
00549 flags |= F_ISSET(mip, VRFY_HAS_DUPSORT) ? ST_DUPSORT : 0;
00550
00551
00552 for (;;) {
00553 if ((ret = CDB___db_vrfy_pgset_get(vdp->pgset, pgno, &p)) != 0)
00554 goto err;
00555 if (p != 0) {
00556 EPRINT((dbp->dbenv,
00557 "Hash page %lu referenced twice", pgno));
00558 isbad = 1;
00559
00560 goto err;
00561 } else if ((ret = CDB___db_vrfy_pgset_inc(vdp->pgset, pgno)) != 0)
00562 goto err;
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 F_CLR(pip, VRFY_IS_ALLZEROES);
00575
00576
00577 if (F_ISSET(pip, VRFY_HAS_DUPS)
00578 && !F_ISSET(mip, VRFY_HAS_DUPS)) {
00579 EPRINT((dbp->dbenv,
00580 "Duplicates present in non-duplicate database, page %lu",
00581 pgno));
00582 isbad = 1;
00583 }
00584
00585
00586
00587
00588
00589 if (F_ISSET(mip, VRFY_HAS_DUPSORT) &&
00590 F_ISSET(pip, VRFY_DUPS_UNSORTED)) {
00591 EPRINT((dbp->dbenv,
00592 "Unsorted dups in sorted-dup database, page %lu",
00593 pgno));
00594 isbad = 1;
00595 }
00596
00597
00598 if ((ret = CDB___db_vrfy_childcursor(vdp, &cc)) != 0)
00599 goto err;
00600 for (ret = CDB___db_vrfy_ccset(cc, pip->pgno, &child); ret == 0;
00601 ret = CDB___db_vrfy_ccnext(cc, &child))
00602 if (child->type == V_OVERFLOW) {
00603 if ((ret = CDB___db_vrfy_ovfl_structure(dbp, vdp,
00604 child->pgno, child->tlen, flags)) != 0) {
00605 if (ret == DB_VERIFY_BAD)
00606 isbad = 1;
00607 else
00608 goto err;
00609 }
00610 } else if (child->type == V_DUPLICATE) {
00611 if ((ret = CDB___db_vrfy_duptype(dbp,
00612 vdp, child->pgno, flags)) != 0) {
00613 isbad = 1;
00614 continue;
00615 }
00616 if ((ret = CDB___bam_vrfy_subtree(dbp, vdp,
00617 child->pgno, NULL, NULL,
00618 flags | ST_RECNUM, NULL,
00619 NULL, NULL)) != 0) {
00620 if (ret == DB_VERIFY_BAD)
00621 isbad = 1;
00622 else
00623 goto err;
00624 }
00625 }
00626 if ((ret = CDB___db_vrfy_ccclose(cc)) != 0)
00627 goto err;
00628 cc = NULL;
00629
00630
00631 if (isbad == 0 && !LF_ISSET(DB_NOORDERCHK) &&
00632 (ret = CDB___ham_vrfy_hashing(dbp, pip->entries,
00633 m, bucket, pgno, flags, hfunc)) != 0) {
00634 if (ret == DB_VERIFY_BAD)
00635 isbad = 1;
00636 else
00637 goto err;
00638 }
00639
00640 next_pgno = pip->next_pgno;
00641 ret = CDB___db_vrfy_putpageinfo(vdp, pip);
00642
00643 pip = NULL;
00644 if (ret != 0)
00645 goto err;
00646
00647 if (next_pgno == PGNO_INVALID)
00648 break;
00649
00650
00651 if (!IS_VALID_PGNO(next_pgno)) {
00652 DB_ASSERT(0);
00653 EPRINT((dbp->dbenv,
00654 "Hash page %lu has bad next_pgno", pgno));
00655 isbad = 1;
00656 goto err;
00657 }
00658
00659 if ((ret = CDB___db_vrfy_getpageinfo(vdp, next_pgno, &pip)) != 0)
00660 goto err;
00661
00662 if (pip->prev_pgno != pgno) {
00663 EPRINT((dbp->dbenv, "Hash page %lu has bad prev_pgno",
00664 next_pgno));
00665 isbad = 1;
00666 }
00667 pgno = next_pgno;
00668 }
00669
00670 err: if (cc != NULL && ((t_ret = CDB___db_vrfy_ccclose(cc)) != 0) && ret == 0)
00671 ret = t_ret;
00672 if (mip != NULL && ((t_ret = CDB___db_vrfy_putpageinfo(vdp, mip)) != 0) &&
00673 ret == 0)
00674 ret = t_ret;
00675 if (pip != NULL && ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0) &&
00676 ret == 0)
00677 ret = t_ret;
00678 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00679 }
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 int
00690 CDB___ham_vrfy_hashing(dbp, nentries, m, thisbucket, pgno, flags, hfunc)
00691 DB *dbp;
00692 u_int32_t nentries;
00693 HMETA *m;
00694 u_int32_t thisbucket;
00695 db_pgno_t pgno;
00696 u_int32_t flags;
00697 u_int32_t (*hfunc) __P((const void *, u_int32_t));
00698 {
00699 DBT dbt;
00700 PAGE *h;
00701 db_indx_t i;
00702 int ret, t_ret, isbad;
00703 u_int32_t hval, bucket;
00704
00705 ret = isbad = 0;
00706 memset(&dbt, 0, sizeof(DBT));
00707 F_SET(&dbt, DB_DBT_REALLOC);
00708
00709 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
00710 return (ret);
00711
00712 for (i = 0; i < nentries; i += 2) {
00713
00714
00715
00716
00717
00718
00719
00720
00721 if ((ret = CDB___db_ret(dbp, h, i, &dbt, NULL, NULL)) != 0)
00722 goto err;
00723 hval = hfunc(dbt.data, dbt.size);
00724
00725 bucket = hval & m->high_mask;
00726 if (bucket > m->max_bucket)
00727 bucket = bucket & m->low_mask;
00728
00729 if (bucket != thisbucket) {
00730 EPRINT((dbp->dbenv,
00731 "Item %lu on page %lu hashes incorrectly",
00732 i, pgno));
00733 isbad = 1;
00734 }
00735 }
00736
00737 err: if (dbt.data != NULL)
00738 CDB___os_free(dbt.data, 0);
00739 if ((t_ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0)
00740 return (t_ret);
00741
00742 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00743 }
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 int
00754 CDB___ham_salvage(dbp, vdp, pgno, h, handle, callback, flags)
00755 DB *dbp;
00756 VRFY_DBINFO *vdp;
00757 db_pgno_t pgno;
00758 PAGE *h;
00759 void *handle;
00760 int (*callback) __P((void *, const void *));
00761 u_int32_t flags;
00762 {
00763 DBT dbt, unkdbt;
00764 db_pgno_t dpgno;
00765 int ret, err_ret, t_ret;
00766 u_int32_t himark, tlen;
00767 u_int8_t *hk;
00768 void *buf;
00769 db_indx_t dlen, len, i;
00770
00771 memset(&dbt, 0, sizeof(DBT));
00772 dbt.flags = DB_DBT_REALLOC;
00773
00774 memset(&unkdbt, 0, sizeof(DBT));
00775 unkdbt.size = strlen("UNKNOWN") + 1;
00776 unkdbt.data = "UNKNOWN";
00777
00778 err_ret = 0;
00779
00780
00781
00782
00783
00784 if ((ret = CDB___os_malloc(dbp->dbenv, dbp->pgsize, NULL, &buf)) != 0)
00785 return (ret);
00786
00787 himark = dbp->pgsize;
00788 for (i = 0;; i++) {
00789
00790 if (!LF_ISSET(DB_AGGRESSIVE) && i >= NUM_ENT(h))
00791 break;
00792
00793
00794 ret = CDB___db_vrfy_inpitem(dbp,
00795 h, pgno, i, 0, flags, &himark, NULL);
00796
00797 if (ret == DB_VERIFY_FATAL)
00798 break;
00799
00800 if (ret == 0) {
00801 hk = P_ENTRY(h, i);
00802 len = LEN_HKEYDATA(h, dbp->pgsize, i);
00803 if ((u_int32_t)(hk + len - (u_int8_t *)h) >
00804 dbp->pgsize) {
00805
00806
00807
00808
00809
00810 if (!LF_ISSET(DB_AGGRESSIVE))
00811 continue;
00812 len = dbp->pgsize -
00813 (u_int32_t)(hk - (u_int8_t *)h);
00814 err_ret = DB_VERIFY_BAD;
00815 }
00816 switch (HPAGE_PTYPE(hk)) {
00817 default:
00818 if (!LF_ISSET(DB_AGGRESSIVE))
00819 break;
00820 err_ret = DB_VERIFY_BAD;
00821
00822 case H_KEYDATA:
00823 keydata: memcpy(buf, HKEYDATA_DATA(hk), len);
00824 dbt.size = len;
00825 dbt.data = buf;
00826 if ((ret = CDB___db_prdbt(&dbt,
00827 0, " ", handle, callback, 0, NULL)) != 0)
00828 err_ret = ret;
00829 break;
00830 case H_OFFPAGE:
00831 if (len < HOFFPAGE_SIZE) {
00832 err_ret = DB_VERIFY_BAD;
00833 continue;
00834 }
00835 memcpy(&dpgno,
00836 HOFFPAGE_PGNO(hk), sizeof(dpgno));
00837 if ((ret = CDB___db_safe_goff(dbp, vdp,
00838 dpgno, &dbt, &buf, flags)) != 0) {
00839 err_ret = ret;
00840 (void)CDB___db_prdbt(&unkdbt, 0, " ",
00841 handle, callback, 0, NULL);
00842 break;
00843 }
00844 if ((ret = CDB___db_prdbt(&dbt,
00845 0, " ", handle, callback, 0, NULL)) != 0)
00846 err_ret = ret;
00847 break;
00848 case H_OFFDUP:
00849 if (len < HOFFPAGE_SIZE) {
00850 err_ret = DB_VERIFY_BAD;
00851 continue;
00852 }
00853 memcpy(&dpgno,
00854 HOFFPAGE_PGNO(hk), sizeof(dpgno));
00855
00856 if (!IS_VALID_PGNO(dpgno) || (i % 2 == 0)) {
00857 if ((ret = CDB___db_prdbt(&unkdbt, 0, " ",
00858 handle, callback, 0, NULL)) != 0)
00859 err_ret = ret;
00860 } else if ((ret = CDB___db_salvage_duptree(dbp,
00861 vdp, dpgno, &dbt, handle, callback,
00862 flags | SA_SKIPFIRSTKEY)) != 0)
00863 err_ret = ret;
00864 break;
00865 case H_DUPLICATE:
00866
00867
00868
00869
00870
00871
00872 if (i % 2 == 0) {
00873 err_ret = ret;
00874 if (LF_ISSET(DB_AGGRESSIVE))
00875 goto keydata;
00876 break;
00877 }
00878
00879
00880 if (len <
00881 HKEYDATA_SIZE(2 * sizeof(db_indx_t))) {
00882 err_ret = DB_VERIFY_BAD;
00883 continue;
00884 }
00885
00886
00887 for (tlen = 0; tlen + sizeof(db_indx_t) < len;
00888 tlen += dlen) {
00889 tlen += sizeof(db_indx_t);
00890 memcpy(&dlen, hk, sizeof(db_indx_t));
00891
00892
00893
00894
00895 if (dlen + tlen > len)
00896 dlen = len - tlen;
00897 memcpy(buf, hk + tlen, dlen);
00898 dbt.size = dlen;
00899 dbt.data = buf;
00900 if ((ret = CDB___db_prdbt(&dbt, 0, " ",
00901 handle, callback, 0, NULL)) != 0)
00902 err_ret = ret;
00903 tlen += sizeof(db_indx_t);
00904 }
00905 break;
00906 }
00907 }
00908 }
00909
00910 if ((t_ret = CDB___db_salvage_markdone(vdp, pgno)) != 0)
00911 return (t_ret);
00912 return ((ret == 0 && err_ret != 0) ? err_ret : ret);
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 int CDB___ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
00924 DB *dbp;
00925 VRFY_DBINFO *vdp;
00926 HMETA *hmeta;
00927 u_int32_t flags;
00928 DB *pgset;
00929 {
00930 PAGE *h;
00931 db_pgno_t pgno;
00932 u_int32_t bucket, totpgs;
00933 int ret, val;
00934
00935
00936
00937
00938
00939 COMPQUIET(flags, 0);
00940
00941 DB_ASSERT(pgset != NULL);
00942
00943 totpgs = 0;
00944
00945
00946
00947
00948
00949 for (bucket = 0; bucket <= hmeta->max_bucket; bucket++) {
00950 pgno = bucket + hmeta->spares[CDB___db_log2(bucket + 1)];
00951
00952
00953
00954
00955
00956
00957
00958 for (;;) {
00959 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
00960 return (ret);
00961 if (TYPE(h) == P_HASH) {
00962
00963
00964
00965
00966
00967 if (++totpgs > vdp->last_pgno) {
00968 (void)CDB_memp_fput(dbp->mpf, h, 0);
00969 return (DB_VERIFY_BAD);
00970 }
00971 if ((ret =
00972 CDB___db_vrfy_pgset_inc(pgset, pgno)) != 0)
00973 return (ret);
00974
00975 pgno = NEXT_PGNO(h);
00976 } else
00977 pgno = PGNO_INVALID;
00978
00979 if ((ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0)
00980 return (ret);
00981
00982
00983 if (!IS_VALID_PGNO(pgno) ||
00984 pgno == PGNO_INVALID)
00985 goto nextbucket;
00986
00987
00988
00989
00990
00991 if ((ret = CDB___db_vrfy_pgset_get(pgset, pgno, &val)) != 0)
00992 return (ret);
00993 if (val != 0)
00994 goto nextbucket;
00995 }
00996 nextbucket: ;
00997 }
00998 return (0);
00999 }
01000
01001
01002
01003
01004
01005
01006
01007 static int
01008 __ham_dups_unsorted(dbp, buf, len)
01009 DB *dbp;
01010 u_int8_t *buf;
01011 u_int32_t len;
01012 {
01013 DBT a, b;
01014 db_indx_t offset, dlen;
01015 int (*func) __P((const DBT *, const DBT *));
01016
01017 memset(&a, 0, sizeof(DBT));
01018 memset(&b, 0, sizeof(DBT));
01019
01020 func = (dbp->dup_compare == NULL) ? CDB___bam_defcmp : dbp->dup_compare;
01021
01022
01023
01024
01025
01026
01027 for (offset = 0; offset < len; offset += DUP_SIZE(dlen)) {
01028 memcpy(&dlen, buf + offset, sizeof(db_indx_t));
01029 b.data = buf + offset + sizeof(db_indx_t);
01030 b.size = dlen;
01031
01032 if (a.data != NULL && func(&a, &b) > 0)
01033 return (1);
01034
01035 a.data = b.data;
01036 a.size = b.size;
01037 }
01038
01039 return (0);
01040 }