00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "config.h"
00011
00012 #ifndef lint
00013 static const char revid[] = "$Id: bt__verify_8c-source.html,v 1.1 2008/06/08 10:13:47 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
00028 static int __bam_safe_getdata __P((DB *, PAGE *, u_int32_t, int, DBT *, int *));
00029 static int __bam_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
00030 db_indx_t *, u_int32_t));
00031 static int __bam_vrfy_treeorder __P((DB *, db_pgno_t, PAGE *, BINTERNAL *,
00032 BINTERNAL *, u_int32_t));
00033 static int __ram_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
00034 db_indx_t *, u_int32_t));
00035
00036 #define OKFLAGS (DB_AGGRESSIVE | DB_NOORDERCHK | DB_SALVAGE)
00037
00038
00039
00040
00041
00042
00043
00044
00045 int
00046 CDB___bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
00047 DB *dbp;
00048 VRFY_DBINFO *vdp;
00049 BTMETA *meta;
00050 db_pgno_t pgno;
00051 u_int32_t flags;
00052 {
00053 VRFY_PAGEINFO *pip;
00054 int isbad, t_ret, ret;
00055
00056 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00057 return (ret);
00058
00059 isbad = 0;
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 if (!F_ISSET(pip, VRFY_INCOMPLETE) &&
00071 (ret = CDB___db_vrfy_meta(dbp, vdp, &meta->dbmeta, pgno, flags)) != 0) {
00072 if (ret == DB_VERIFY_BAD)
00073 isbad = 1;
00074 else
00075 goto err;
00076 }
00077
00078
00079 if (meta->minkey < 2 ||
00080 meta->minkey > (dbp->pgsize / BKEYDATA_PSIZE(0))) {
00081 pip->bt_minkey = 0;
00082 isbad = 1;
00083 EPRINT((dbp->dbenv,
00084 "Nonsensical bt_minkey value %lu on metadata page %lu",
00085 meta->minkey, pgno));
00086 } else
00087 pip->bt_minkey = meta->minkey;
00088
00089
00090 pip->bt_maxkey = meta->maxkey;
00091
00092
00093 pip->re_len = meta->re_len;
00094
00095
00096
00097
00098
00099
00100 pip->root = 0;
00101 if (meta->root == PGNO_INVALID
00102 || meta->root == pgno || !IS_VALID_PGNO(meta->root) ||
00103 (pgno == PGNO_BASE_MD && meta->root != 1)) {
00104 isbad = 1;
00105 EPRINT((dbp->dbenv,
00106 "Nonsensical root page %lu on metadata page %lu",
00107 meta->root, vdp->last_pgno));
00108 } else
00109 pip->root = meta->root;
00110
00111
00112 if (F_ISSET(&meta->dbmeta, BTM_RENUMBER))
00113 F_SET(pip, VRFY_IS_RRECNO);
00114
00115 if (F_ISSET(&meta->dbmeta, BTM_SUBDB)) {
00116
00117
00118
00119
00120 if (F_ISSET(&meta->dbmeta, BTM_DUP) && pgno == PGNO_BASE_MD) {
00121 isbad = 1;
00122 EPRINT((dbp->dbenv,
00123 "Btree metadata page %lu has both duplicates and multiple databases",
00124 pgno));
00125 }
00126 F_SET(pip, VRFY_HAS_SUBDBS);
00127 }
00128
00129 if (F_ISSET(&meta->dbmeta, BTM_DUP))
00130 F_SET(pip, VRFY_HAS_DUPS);
00131 if (F_ISSET(&meta->dbmeta, BTM_DUPSORT))
00132 F_SET(pip, VRFY_HAS_DUPSORT);
00133 if (F_ISSET(&meta->dbmeta, BTM_RECNUM))
00134 F_SET(pip, VRFY_HAS_RECNUMS);
00135 if (F_ISSET(pip, VRFY_HAS_RECNUMS) && F_ISSET(pip, VRFY_HAS_DUPS)) {
00136 EPRINT((dbp->dbenv,
00137 "Btree metadata page %lu illegally has both recnums and dups",
00138 pgno));
00139 isbad = 1;
00140 }
00141
00142 if (F_ISSET(&meta->dbmeta, BTM_RECNO)) {
00143 F_SET(pip, VRFY_IS_RECNO);
00144 dbp->type = DB_RECNO;
00145 } else if (F_ISSET(pip, VRFY_IS_RRECNO)) {
00146 isbad = 1;
00147 EPRINT((dbp->dbenv,
00148 "Metadata page %lu has renumber flag set but is not recno",
00149 pgno));
00150 }
00151
00152 if (F_ISSET(pip, VRFY_IS_RECNO) && F_ISSET(pip, VRFY_HAS_DUPS)) {
00153 EPRINT((dbp->dbenv,
00154 "Recno metadata page %lu specifies duplicates", pgno));
00155 isbad = 1;
00156 }
00157
00158 if (F_ISSET(&meta->dbmeta, BTM_FIXEDLEN))
00159 F_SET(pip, VRFY_IS_FIXEDLEN);
00160 else if (pip->re_len > 0) {
00161
00162
00163
00164
00165 isbad = 1;
00166 EPRINT((dbp->dbenv,
00167 "re_len of %lu in non-fixed-length database",
00168 pip->re_len));
00169 }
00170
00171
00172
00173
00174
00175
00176 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00177 ret = t_ret;
00178 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188 int
00189 CDB___ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
00190 DB *dbp;
00191 VRFY_DBINFO *vdp;
00192 PAGE *h;
00193 db_pgno_t pgno;
00194 u_int32_t flags;
00195 {
00196 BKEYDATA *bk;
00197 VRFY_PAGEINFO *pip;
00198 db_indx_t i;
00199 int ret, t_ret, isbad;
00200 u_int32_t re_len_guess, len;
00201
00202 isbad = 0;
00203 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00204 return (ret);
00205
00206 if ((ret = CDB___db_fchk(dbp->dbenv,
00207 "CDB___ram_vrfy_leaf", flags, OKFLAGS)) != 0)
00208 goto err;
00209
00210 if (TYPE(h) != P_LRECNO) {
00211
00212 TYPE_ERR_PRINT(dbp->dbenv, "CDB___ram_vrfy_leaf", pgno, TYPE(h));
00213 DB_ASSERT(0);
00214 ret = EINVAL;
00215 goto err;
00216 }
00217
00218
00219
00220
00221
00222 if ((ret = CDB___db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
00223 if (ret == DB_VERIFY_BAD)
00224 isbad = 1;
00225 else
00226 goto err;
00227 }
00228
00229
00230
00231
00232
00233 if ((ret = __bam_vrfy_inp(dbp,
00234 vdp, h, pgno, &pip->entries, flags)) != 0)
00235 goto err;
00236
00237 if (F_ISSET(pip, VRFY_HAS_DUPS)) {
00238 EPRINT((dbp->dbenv,
00239 "Recno database has dups on page %lu", pgno));
00240 ret = DB_VERIFY_BAD;
00241 goto err;
00242 }
00243
00244
00245
00246
00247
00248
00249
00250 re_len_guess = 0;
00251 for (i = 0; i < NUM_ENT(h); i++) {
00252 bk = GET_BKEYDATA(h, i);
00253
00254 if (B_DISSET(bk->type))
00255 continue;
00256 if (bk->type == B_OVERFLOW)
00257 len = ((BOVERFLOW *)bk)->tlen;
00258 else if (bk->type == B_KEYDATA)
00259 len = bk->len;
00260 else {
00261 isbad = 1;
00262 EPRINT((dbp->dbenv, "Nonsensical type for item %lu, page %lu",
00263 i, pgno));
00264 continue;
00265 }
00266 if (re_len_guess == 0)
00267 re_len_guess = len;
00268
00269
00270
00271
00272
00273
00274 if (re_len_guess != len) {
00275 re_len_guess = 0;
00276 break;
00277 }
00278 }
00279 pip->re_len = re_len_guess;
00280
00281
00282 pip->rec_cnt = NUM_ENT(h);
00283
00284 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00285 ret = t_ret;
00286 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : 0);
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296 int
00297 CDB___bam_vrfy(dbp, vdp, h, pgno, flags)
00298 DB *dbp;
00299 VRFY_DBINFO *vdp;
00300 PAGE *h;
00301 db_pgno_t pgno;
00302 u_int32_t flags;
00303 {
00304 VRFY_PAGEINFO *pip;
00305 int ret, t_ret, isbad;
00306
00307 isbad = 0;
00308 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00309 return (ret);
00310
00311 switch (TYPE(h)) {
00312 case P_IBTREE:
00313 case P_IRECNO:
00314 case P_LBTREE:
00315 case P_LDUP:
00316 break;
00317 default:
00318 TYPE_ERR_PRINT(dbp->dbenv, "CDB___bam_vrfy", pgno, TYPE(h));
00319 DB_ASSERT(0);
00320 ret = EINVAL;
00321 goto err;
00322 }
00323
00324
00325
00326
00327
00328 if ((ret = CDB___db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
00329 if (ret == DB_VERIFY_BAD)
00330 isbad = 1;
00331 else
00332 goto err;
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342 pip->rec_cnt = RE_NREC(h);
00343
00344
00345
00346
00347 if (TYPE(h) == P_IRECNO) {
00348 if ((ret = __ram_vrfy_inp(dbp,
00349 vdp, h, pgno, &pip->entries, flags)) != 0)
00350 goto err;
00351 } else if ((ret = __bam_vrfy_inp(dbp,
00352 vdp, h, pgno, &pip->entries, flags)) != 0) {
00353 if (ret == DB_VERIFY_BAD)
00354 isbad = 1;
00355 else
00356 goto err;
00357 EPRINT((dbp->dbenv,
00358 "item order check on page %lu unsafe: skipping", pgno));
00359 } else if (!LF_ISSET(DB_NOORDERCHK) && (ret =
00360 CDB___bam_vrfy_itemorder(dbp, vdp, h, pgno, 0, 0, 0, flags)) != 0) {
00361
00362
00363
00364
00365
00366 if (ret == DB_VERIFY_BAD)
00367 isbad = 1;
00368 else
00369 goto err;
00370 }
00371
00372 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00373 ret = t_ret;
00374 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : 0);
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384 static int
00385 __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
00386 DB *dbp;
00387 VRFY_DBINFO *vdp;
00388 PAGE *h;
00389 db_pgno_t pgno;
00390 db_indx_t *nentriesp;
00391 u_int32_t flags;
00392 {
00393 RINTERNAL *ri;
00394 VRFY_CHILDINFO child;
00395 VRFY_PAGEINFO *pip;
00396 int ret, t_ret, isbad;
00397 db_indx_t himark, i, offset, nentries;
00398 u_int8_t *pagelayout, *p;
00399
00400 isbad = 0;
00401 memset(&child, 0, sizeof(VRFY_CHILDINFO));
00402 nentries = 0;
00403 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00404 return (ret);
00405
00406 if (TYPE(h) != P_IRECNO) {
00407 TYPE_ERR_PRINT(dbp->dbenv, "__ram_vrfy_inp", pgno, TYPE(h));
00408 DB_ASSERT(0);
00409 ret = EINVAL;
00410 goto err;
00411 }
00412
00413 himark = dbp->pgsize;
00414 if ((ret =
00415 CDB___os_malloc(dbp->dbenv, dbp->pgsize, NULL, &pagelayout)) != 0)
00416 goto err;
00417 memset(pagelayout, 0, dbp->pgsize);
00418 for (i = 0; i < NUM_ENT(h); i++) {
00419 if ((u_int8_t *)h->inp + i >= (u_int8_t *)h + himark) {
00420 EPRINT((dbp->dbenv,
00421 "Page %lu entries listing %lu overlaps data",
00422 pgno, i));
00423 ret = DB_VERIFY_BAD;
00424 goto err;
00425 }
00426 offset = h->inp[i];
00427
00428
00429
00430
00431
00432 if (offset <= ((u_int8_t *)h->inp + i - (u_int8_t *)h) ||
00433 offset > dbp->pgsize - RINTERNAL_SIZE) {
00434 isbad = 1;
00435 EPRINT((dbp->dbenv,
00436 "Bad offset %lu at page %lu index %lu",
00437 offset, pgno, i));
00438 continue;
00439 }
00440
00441
00442 if (offset < himark)
00443 himark = offset;
00444
00445 nentries++;
00446
00447
00448 ri = GET_RINTERNAL(h, i);
00449 if (pagelayout[offset] == 0) {
00450 pagelayout[offset] = 1;
00451 child.pgno = ri->pgno;
00452 child.type = V_RECNO;
00453 child.nrecs = ri->nrecs;
00454 if ((ret = CDB___db_vrfy_childput(vdp, pgno, &child)) != 0)
00455 goto err;
00456 } else {
00457 EPRINT((dbp->dbenv,
00458 "RINTERNAL structure at offset %lu, page %lu referenced twice",
00459 offset, pgno));
00460 isbad = 1;
00461 }
00462 }
00463
00464 for (p = pagelayout + himark;
00465 p < pagelayout + dbp->pgsize;
00466 p += RINTERNAL_SIZE)
00467 if (*p != 1) {
00468 EPRINT((dbp->dbenv,
00469 "Gap between items at offset %lu, page %lu",
00470 p - pagelayout, pgno));
00471 isbad = 1;
00472 }
00473
00474 if (himark != HOFFSET(h)) {
00475 EPRINT((dbp->dbenv, "Bad HOFFSET %lu, appears to be %lu",
00476 HOFFSET(h), himark));
00477 isbad = 1;
00478 }
00479
00480 *nentriesp = nentries;
00481
00482 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00483 ret = t_ret;
00484 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00485 }
00486
00487
00488
00489
00490
00491
00492 static int
00493 __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
00494 DB *dbp;
00495 VRFY_DBINFO *vdp;
00496 PAGE *h;
00497 db_pgno_t pgno;
00498 db_indx_t *nentriesp;
00499 u_int32_t flags;
00500 {
00501 BKEYDATA *bk;
00502 BOVERFLOW *bo;
00503 VRFY_CHILDINFO child;
00504 VRFY_PAGEINFO *pip;
00505 int isbad, initem, isdupitem, ret, t_ret;
00506 u_int32_t himark, offset;
00507 db_indx_t i, endoff, nentries;
00508 u_int8_t *pagelayout;
00509
00510 isbad = isdupitem = 0;
00511 nentries = 0;
00512 memset(&child, 0, sizeof(VRFY_CHILDINFO));
00513 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00514 return (ret);
00515
00516 switch (TYPE(h)) {
00517 case P_IBTREE:
00518 case P_LBTREE:
00519 case P_LDUP:
00520 case P_LRECNO:
00521 break;
00522 default:
00523
00524
00525
00526
00527
00528 if (LF_ISSET(DB_SALVAGE))
00529 break;
00530 TYPE_ERR_PRINT(dbp->dbenv, "__bam_vrfy_inp", pgno, TYPE(h));
00531 DB_ASSERT(0);
00532 ret = EINVAL;
00533 goto err;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 himark = dbp->pgsize;
00548 if ((ret = CDB___os_malloc(dbp->dbenv,
00549 dbp->pgsize, NULL, &pagelayout)) != 0)
00550 goto err;
00551 memset(pagelayout, 0, dbp->pgsize);
00552 for (i = 0; i < NUM_ENT(h); i++) {
00553
00554 ret = CDB___db_vrfy_inpitem(dbp,
00555 h, pgno, i, 1, flags, &himark, &offset);
00556 if (ret == DB_VERIFY_BAD) {
00557 isbad = 1;
00558 continue;
00559 } else if (ret == DB_VERIFY_FATAL) {
00560 isbad = 1;
00561 goto err;
00562 } else if (ret != 0)
00563 DB_ASSERT(0);
00564
00565
00566
00567
00568
00569
00570
00571
00572 bk = GET_BKEYDATA(h, i);
00573 #define ITEM_BEGIN 1
00574 #define ITEM_END 2
00575 if (pagelayout[offset] == 0)
00576 pagelayout[offset] = ITEM_BEGIN;
00577 else if (pagelayout[offset] == ITEM_BEGIN) {
00578
00579
00580
00581
00582
00583
00584 if ((i % P_INDX == 0) && (TYPE(h) == P_LBTREE)) {
00585
00586 F_SET(pip, VRFY_HAS_DUPS);
00587
00588
00589 nentries++;
00590
00591
00592
00593
00594
00595 isdupitem = 1;
00596 } else {
00597 isbad = 1;
00598 EPRINT((dbp->dbenv, "Duplicated item %lu on page %lu",
00599 i, pgno));
00600 }
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610 switch(B_TYPE(bk->type)) {
00611 case B_KEYDATA:
00612 if (TYPE(h) == P_IBTREE)
00613
00614 endoff = offset + BINTERNAL_SIZE(bk->len) - 1;
00615 else
00616 endoff = offset + BKEYDATA_SIZE(bk->len) - 1;
00617 break;
00618 case B_DUPLICATE:
00619
00620
00621
00622
00623 F_SET(pip, VRFY_HAS_DUPS);
00624
00625 case B_OVERFLOW:
00626
00627
00628
00629
00630
00631 endoff = offset +
00632 ((TYPE(h) == P_IBTREE) ?
00633 BINTERNAL_SIZE(BOVERFLOW_SIZE) :
00634 BOVERFLOW_SIZE) - 1;
00635 break;
00636 default:
00637
00638
00639
00640
00641 endoff = offset + BKEYDATA_SIZE(0) - 1;
00642 break;
00643 }
00644
00645
00646
00647
00648
00649 if (isdupitem && pagelayout[endoff] != ITEM_END) {
00650 EPRINT((dbp->dbenv, "Duplicated item %lu on page %lu", i,
00651 pgno));
00652 isbad = 1;
00653 } else if (pagelayout[endoff] == 0)
00654 pagelayout[endoff] = ITEM_END;
00655 isdupitem = 0;
00656
00657
00658
00659
00660
00661 if (B_DISSET(bk->type) && TYPE(h) != P_LRECNO) {
00662 isbad = 1;
00663 EPRINT((dbp->dbenv,
00664 "Item %lu on page %lu marked deleted", i, pgno));
00665 }
00666
00667
00668
00669
00670
00671 switch (B_TYPE(bk->type)) {
00672 case B_KEYDATA:
00673
00674
00675
00676
00677
00678 break;
00679 case B_DUPLICATE:
00680 if (TYPE(h) == P_IBTREE) {
00681 isbad = 1;
00682 EPRINT((dbp->dbenv,
00683 "Duplicate page referenced by internal btree page %lu at item %lu",
00684 pgno, i));
00685 break;
00686 } else if (TYPE(h) == P_LRECNO) {
00687 isbad = 1;
00688 EPRINT((dbp->dbenv,
00689 "Duplicate page referenced by recno page %lu at item %lu",
00690 pgno, i));
00691 break;
00692 }
00693
00694 case B_OVERFLOW:
00695 bo = (TYPE(h) == P_IBTREE) ?
00696 (BOVERFLOW *)(((BINTERNAL *)bk)->data) :
00697 (BOVERFLOW *)bk;
00698
00699 if (B_TYPE(bk->type) == B_OVERFLOW)
00700
00701 if (bo->tlen > dbp->pgsize * vdp->last_pgno) {
00702 isbad = 1;
00703 EPRINT((dbp->dbenv,
00704 "Impossible tlen %lu, item %lu, page %lu",
00705 bo->tlen, i, pgno));
00706
00707 break;
00708 }
00709
00710 if (!IS_VALID_PGNO(bo->pgno) || bo->pgno == pgno ||
00711 bo->pgno == PGNO_INVALID) {
00712 isbad = 1;
00713 EPRINT((dbp->dbenv,
00714 "Offpage item %lu, page %lu has bad pgno",
00715 i, pgno));
00716
00717 break;
00718 }
00719
00720 child.pgno = bo->pgno;
00721 child.type = (B_TYPE(bk->type) == B_OVERFLOW ?
00722 V_OVERFLOW : V_DUPLICATE);
00723 child.tlen = bo->tlen;
00724 if ((ret = CDB___db_vrfy_childput(vdp, pgno, &child)) != 0)
00725 goto err;
00726 break;
00727 default:
00728 isbad = 1;
00729 EPRINT((dbp->dbenv,
00730 "Item %lu on page %lu of invalid type %lu",
00731 i, pgno));
00732 break;
00733 }
00734 }
00735
00736
00737
00738
00739
00740 initem = 0;
00741 for (i = himark; i < dbp->pgsize; i++)
00742 if (initem == 0)
00743 switch (pagelayout[i]) {
00744 case 0:
00745
00746 if (i != ALIGN(i, 4))
00747 continue;
00748
00749 isbad = 1;
00750 EPRINT((dbp->dbenv,
00751 "Gap between items, page %lu offset %lu",
00752 pgno, i));
00753
00754 for ( ; pagelayout[i + 1] == 0 &&
00755 (size_t)(i + 1) < dbp->pgsize; i++)
00756 ;
00757 break;
00758 case ITEM_BEGIN:
00759
00760 if (i != ALIGN(i, 4)) {
00761 isbad = 1;
00762 EPRINT((dbp->dbenv,
00763 "Offset %lu page %lu unaligned",
00764 i, pgno));
00765 }
00766 initem = 1;
00767 nentries++;
00768 break;
00769 case ITEM_END:
00770
00771
00772
00773
00774
00775 isbad = 1;
00776 EPRINT((dbp->dbenv,
00777 "Overlapping items, page %lu offset %lu",
00778 pgno, i));
00779 break;
00780 default:
00781
00782 DB_ASSERT(0);
00783 ret = EINVAL;
00784 goto err;
00785 }
00786 else
00787 switch (pagelayout[i]) {
00788 case 0:
00789
00790 break;
00791 case ITEM_END:
00792
00793 initem = 0;
00794 break;
00795 case ITEM_BEGIN:
00796
00797
00798
00799
00800 isbad = 1;
00801 EPRINT((dbp->dbenv,
00802 "Overlapping items, page %lu offset %lu",
00803 pgno, i));
00804 break;
00805 }
00806
00807 (void)CDB___os_free(pagelayout, dbp->pgsize);
00808
00809
00810 if (himark != HOFFSET(h)) {
00811 EPRINT((dbp->dbenv, "Bad HOFFSET %lu, appears to be %lu",
00812 HOFFSET(h), himark));
00813 isbad = 1;
00814 }
00815
00816 err: if (nentriesp != NULL)
00817 *nentriesp = nentries;
00818
00819 if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
00820 ret = t_ret;
00821
00822 return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 int
00842 CDB___bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
00843 DB *dbp;
00844 VRFY_DBINFO *vdp;
00845 PAGE *h;
00846 db_pgno_t pgno;
00847 u_int32_t nentries;
00848 int ovflok, hasdups;
00849 u_int32_t flags;
00850 {
00851 DBT dbta, dbtb, dup1, dup2, *p1, *p2, *tmp;
00852 BTREE *bt;
00853 BINTERNAL *bi;
00854 BKEYDATA *bk;
00855 BOVERFLOW *bo;
00856 VRFY_PAGEINFO *pip;
00857 db_indx_t i;
00858 int cmp, freedup1, freedup2, isbad, ret, t_ret;
00859 int (*dupfunc) __P((const DBT *, const DBT *));
00860 int (*func) __P((const DBT *, const DBT *));
00861 void *buf1, *buf2, *tmpbuf;
00862
00863
00864
00865
00866
00867
00868 if (vdp != NULL) {
00869 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00870 return (ret);
00871 nentries = pip->entries;
00872 } else
00873 pip = NULL;
00874
00875 ret = isbad = 0;
00876 bo = NULL;
00877
00878 memset(&dbta, 0, sizeof(DBT));
00879 F_SET(&dbta, DB_DBT_REALLOC);
00880
00881 memset(&dbtb, 0, sizeof(DBT));
00882 F_SET(&dbtb, DB_DBT_REALLOC);
00883
00884 buf1 = buf2 = NULL;
00885
00886 DB_ASSERT(!LF_ISSET(DB_NOORDERCHK));
00887
00888 dupfunc = (dbp->dup_compare == NULL) ? CDB___bam_defcmp : dbp->dup_compare;
00889 if (TYPE(h) == P_LDUP)
00890 func = dupfunc;
00891 else {
00892 func = CDB___bam_defcmp;
00893 if (dbp->bt_internal != NULL) {
00894 bt = (BTREE *)dbp->bt_internal;
00895 if (bt->bt_compare != NULL)
00896 func = bt->bt_compare;
00897 }
00898 }
00899
00900
00901
00902
00903
00904
00905 p1 = &dbta;
00906 p2 = &dbtb;
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918 for (i = (TYPE(h) == P_IBTREE) ? 1 : 0; i < nentries;
00919 i += (TYPE(h) == P_LBTREE) ? P_INDX : O_INDX) {
00920
00921
00922
00923 tmp = p1;
00924 p1 = p2;
00925 p2 = tmp;
00926 tmpbuf = buf1;
00927 buf1 = buf2;
00928 buf2 = tmpbuf;
00929
00930
00931
00932
00933 switch (TYPE(h)) {
00934 case P_IBTREE:
00935 bi = GET_BINTERNAL(h, i);
00936 if (B_TYPE(bi->type) == B_OVERFLOW) {
00937 bo = (BOVERFLOW *)(bi->data);
00938 goto overflow;
00939 } else {
00940 p2->data = bi->data;
00941 p2->size = bi->len;
00942 }
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 #if 0
00955 if (i == 0 && bi->len != 0) {
00956 isbad = 1;
00957 EPRINT((dbp->dbenv,
00958 "Lowest key on internal page %lu of nonzero length",
00959 pgno));
00960 }
00961 #endif
00962 break;
00963 case P_LBTREE:
00964 case P_LDUP:
00965 bk = GET_BKEYDATA(h, i);
00966 if (B_TYPE(bk->type) == B_OVERFLOW) {
00967 bo = (BOVERFLOW *)bk;
00968 goto overflow;
00969 } else {
00970 p2->data = bk->data;
00971 p2->size = bk->len;
00972 }
00973 break;
00974 default:
00975
00976
00977
00978
00979 TYPE_ERR_PRINT(dbp->dbenv,
00980 "CDB___bam_vrfy_itemorder", pgno, TYPE(h))
00981 DB_ASSERT(0);
00982 ret = EINVAL;
00983 goto err;
00984
00985 }
00986
00987 if (0) {
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 overflow: if (!ovflok) {
00999 F_SET(pip, VRFY_INCOMPLETE);
01000 goto err;
01001 }
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012 p2->data = buf2;
01013 if ((ret = CDB___db_goff(dbp,
01014 p2, bo->tlen, bo->pgno, NULL, NULL)) != 0) {
01015 isbad = 1;
01016 EPRINT((dbp->dbenv,
01017 "Error %lu in fetching overflow item %lu, page %lu",
01018 ret, i, pgno));
01019 }
01020
01021 buf2 = p2->data;
01022 }
01023
01024
01025 if (p1->data != NULL && p2->data != NULL) {
01026 cmp = func(p1, p2);
01027
01028
01029 if (cmp > 0) {
01030 isbad = 1;
01031 EPRINT((dbp->dbenv,
01032 "Out-of-order key, page %lu item %lu",
01033 pgno, i));
01034
01035 } else if (cmp == 0) {
01036
01037
01038
01039
01040
01041
01042 if (pip != NULL)
01043 F_SET(pip, VRFY_HAS_DUPS);
01044 else if (hasdups == 0) {
01045 isbad = 1;
01046 EPRINT((dbp->dbenv,
01047 "Database with no duplicates has duplicated keys on page %lu", pgno));
01048 }
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 if (TYPE(h) == P_LBTREE) {
01063
01064
01065
01066
01067 if (i + 1 >= (db_indx_t)nentries)
01068 continue;
01069
01070
01071
01072
01073
01074
01075
01076
01077 if (((ret = __bam_safe_getdata(dbp,
01078 h, i - 1, ovflok, &dup1,
01079 &freedup1)) != 0) ||
01080 ((ret = __bam_safe_getdata(dbp,
01081 h, i + 1, ovflok, &dup2,
01082 &freedup2)) != 0))
01083 goto err;
01084
01085
01086
01087
01088
01089
01090
01091 if (dup1.data == NULL ||
01092 dup2.data == NULL) {
01093 DB_ASSERT(!ovflok);
01094 F_SET(pip, VRFY_INCOMPLETE);
01095 goto err;
01096 }
01097
01098
01099
01100
01101
01102
01103
01104 if (dupfunc(&dup1, &dup2) > 0)
01105 F_SET(pip, VRFY_DUPS_UNSORTED);
01106
01107 if (freedup1)
01108 CDB___os_free(dup1.data, 0);
01109 if (freedup2)
01110 CDB___os_free(dup2.data, 0);
01111 }
01112 }
01113 }
01114 }
01115
01116 err: if (pip != NULL &&
01117 ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0) && ret == 0)
01118 ret = t_ret;
01119
01120 if (buf1 != NULL)
01121 CDB___os_free(buf1, 0);
01122 if (buf2 != NULL)
01123 CDB___os_free(buf2, 0);
01124
01125 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 int
01137 CDB___bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
01138 DB *dbp;
01139 VRFY_DBINFO *vdp;
01140 db_pgno_t meta_pgno;
01141 u_int32_t flags;
01142 {
01143 DB *pgset;
01144 VRFY_PAGEINFO *mip, *rip;
01145 db_pgno_t root, p;
01146 int t_ret, ret;
01147 u_int32_t nrecs, level, relen, stflags;
01148
01149 mip = rip = 0;
01150 pgset = vdp->pgset;
01151
01152 if ((ret = CDB___db_vrfy_getpageinfo(vdp, meta_pgno, &mip)) != 0)
01153 return (ret);
01154
01155 if ((ret = CDB___db_vrfy_pgset_get(pgset, meta_pgno, (int *)&p)) != 0)
01156 goto err;
01157 if (p != 0) {
01158 EPRINT((dbp->dbenv,
01159 "Btree metadata page number %lu observed twice",
01160 meta_pgno));
01161 ret = DB_VERIFY_BAD;
01162 goto err;
01163 }
01164 if ((ret = CDB___db_vrfy_pgset_inc(pgset, meta_pgno)) != 0)
01165 goto err;
01166
01167 root = mip->root;
01168
01169 if (root == 0) {
01170 EPRINT((dbp->dbenv,
01171 "Btree metadata page %lu has no root", meta_pgno));
01172 ret = DB_VERIFY_BAD;
01173 goto err;
01174 }
01175
01176 if ((ret = CDB___db_vrfy_getpageinfo(vdp, root, &rip)) != 0)
01177 goto err;
01178
01179 switch (rip->type) {
01180 case P_IBTREE:
01181 case P_LBTREE:
01182 stflags = flags | ST_TOPLEVEL;
01183 if (F_ISSET(mip, VRFY_HAS_DUPS))
01184 stflags |= ST_DUPOK;
01185 if (F_ISSET(mip, VRFY_HAS_DUPSORT))
01186 stflags |= ST_DUPSORT;
01187 if (F_ISSET(mip, VRFY_HAS_RECNUMS))
01188 stflags |= ST_RECNUM;
01189 ret = CDB___bam_vrfy_subtree(dbp,
01190 vdp, root, NULL, NULL, stflags, NULL, NULL, NULL);
01191 break;
01192 case P_IRECNO:
01193 case P_LRECNO:
01194 stflags = flags | ST_RECNUM | ST_IS_RECNO | ST_TOPLEVEL;
01195 if (mip->re_len > 0)
01196 stflags |= ST_RELEN;
01197 if ((ret = CDB___bam_vrfy_subtree(dbp, vdp,
01198 root, NULL, NULL, stflags, &level, &nrecs, &relen)) != 0)
01199 goto err;
01200
01201
01202
01203
01204
01205
01206 if (mip->re_len > 0 && relen > 0 && mip->re_len != relen) {
01207 EPRINT((dbp->dbenv,
01208 "Recno database with meta page %lu has bad re_len %lu",
01209 meta_pgno, relen));
01210 ret = DB_VERIFY_BAD;
01211 goto err;
01212 }
01213 ret = 0;
01214 break;
01215 case P_LDUP:
01216 EPRINT((dbp->dbenv,
01217 "Duplicate tree referenced from metadata page %lu",
01218 meta_pgno));
01219 ret = DB_VERIFY_BAD;
01220 break;
01221 default:
01222 EPRINT((dbp->dbenv, "%s%s", "Btree root of incorrect type ",
01223 "%lu specified on meta page %lu", rip->type, meta_pgno));
01224 ret = DB_VERIFY_BAD;
01225 break;
01226 }
01227
01228 err: if (mip != NULL &&
01229 ((t_ret = CDB___db_vrfy_putpageinfo(vdp, mip)) != 0) && ret == 0)
01230 t_ret = ret;
01231 if (rip != NULL &&
01232 ((t_ret = CDB___db_vrfy_putpageinfo(vdp, rip)) != 0) && ret == 0)
01233 t_ret = ret;
01234 return (ret);
01235 }
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247 int
01248 CDB___bam_vrfy_subtree(dbp,
01249 vdp, pgno, l, r, flags, levelp, nrecsp, relenp)
01250 DB *dbp;
01251 VRFY_DBINFO *vdp;
01252 db_pgno_t pgno;
01253 void *l, *r;
01254 u_int32_t flags, *levelp, *nrecsp, *relenp;
01255 {
01256 BINTERNAL *li, *ri, *lp, *rp;
01257 DB *pgset;
01258 PAGE *h;
01259 VRFY_CHILDINFO *child;
01260 VRFY_PAGEINFO *pip;
01261 db_recno_t nrecs, child_nrecs;
01262 db_indx_t i;
01263 int ret, t_ret, isbad, toplevel, p;
01264 u_int32_t level, child_level, stflags, child_relen, relen;
01265 DBC *cc;
01266
01267 ret = isbad = 0;
01268 nrecs = 0;
01269 h = NULL;
01270 relen = 0;
01271 rp = (BINTERNAL *)r;
01272 lp = (BINTERNAL *)l;
01273
01274 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
01275 return (ret);
01276
01277 cc = NULL;
01278 level = pip->bt_level;
01279
01280 toplevel = LF_ISSET(ST_TOPLEVEL);
01281 LF_CLR(ST_TOPLEVEL);
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 switch (pip->type) {
01309 case P_LRECNO:
01310 case P_LDUP:
01311 case P_LBTREE:
01312
01313
01314
01315
01316 if ((ret = CDB___db_vrfy_childcursor(vdp, &cc)) != 0)
01317 goto err;
01318 for (ret = CDB___db_vrfy_ccset(cc, pgno, &child); ret == 0;
01319 ret = CDB___db_vrfy_ccnext(cc, &child))
01320 if (child->type == V_OVERFLOW &&
01321 (ret = CDB___db_vrfy_ovfl_structure(dbp, vdp,
01322 child->pgno, child->tlen,
01323 flags | ST_OVFL_LEAF)) != 0) {
01324 if (ret == DB_VERIFY_BAD)
01325 isbad = 1;
01326 else
01327 goto done;
01328 }
01329
01330 if ((ret = CDB___db_vrfy_ccclose(cc)) != 0)
01331 goto err;
01332 cc = NULL;
01333
01334
01335 if (pip->type == P_LRECNO) {
01336 if (!LF_ISSET(ST_IS_RECNO) &&
01337 !(LF_ISSET(ST_DUPOK) && !LF_ISSET(ST_DUPSORT))) {
01338 isbad = 1;
01339 EPRINT((dbp->dbenv,
01340 "Recno leaf page %lu in non-recno tree",
01341 pgno));
01342 goto done;
01343 }
01344 goto leaf;
01345 } else if (LF_ISSET(ST_IS_RECNO)){
01346
01347
01348
01349
01350 isbad = 1;
01351 EPRINT((dbp->dbenv,
01352 "Non-recno leaf page %lu in recno tree",
01353 pgno));
01354 goto done;
01355 }
01356
01357
01358 if (pip->type == P_LDUP)
01359 goto leaf;
01360
01361
01362
01363
01364 if (F_ISSET(pip, VRFY_HAS_DUPS)) {
01365
01366 if (!LF_ISSET(ST_DUPOK)) {
01367 isbad = 1;
01368 EPRINT((dbp->dbenv,
01369 "Duplicates on page %lu in non-dup btree",
01370 pgno));
01371 } else {
01372
01373
01374
01375
01376 if ((ret =
01377 CDB___db_vrfy_childcursor(vdp, &cc)) != 0)
01378 goto err;
01379 for (ret = CDB___db_vrfy_ccset(cc, pgno, &child);
01380 ret == 0;
01381 ret = CDB___db_vrfy_ccnext(cc, &child)) {
01382 stflags = flags | ST_RECNUM;
01383
01384 if (child->type == V_DUPLICATE) {
01385 if ((ret = CDB___db_vrfy_duptype(
01386 dbp, vdp, child->pgno,
01387 stflags)) != 0) {
01388 isbad = 1;
01389
01390 continue;
01391 }
01392 if ((ret = CDB___bam_vrfy_subtree(
01393 dbp, vdp, child->pgno, NULL,
01394 NULL, stflags, NULL, NULL,
01395 NULL)) != 0) {
01396 if (ret !=
01397 DB_VERIFY_BAD)
01398 goto err;
01399 else
01400 isbad = 1;
01401 }
01402 }
01403 }
01404
01405 if ((ret = CDB___db_vrfy_ccclose(cc)) != 0)
01406 goto err;
01407 cc = NULL;
01408
01409
01410
01411
01412
01413 if (F_ISSET(pip, VRFY_DUPS_UNSORTED) &&
01414 LF_ISSET(ST_DUPSORT)) {
01415 EPRINT((dbp->dbenv,
01416 "Unsorted duplicate set at page %lu in sorted-dup database",
01417 pgno));
01418 isbad = 1;
01419 }
01420 }
01421 }
01422 goto leaf;
01423 break;
01424 case P_IBTREE:
01425 case P_IRECNO:
01426
01427 break;
01428 default:
01429
01430 TYPE_ERR_PRINT(dbp->dbenv, "CDB___bam_vrfy_subtree", pgno, pip->type);
01431 DB_ASSERT(0);
01432 ret = EINVAL;
01433 goto done;
01434
01435 }
01436
01437
01438
01439
01440
01441
01442 if ((ret = CDB___db_vrfy_childcursor(vdp, &cc)) != 0)
01443 goto err;
01444 for (ret = CDB___db_vrfy_ccset(cc, pgno, &child); ret == 0;
01445 ret = CDB___db_vrfy_ccnext(cc, &child))
01446 if (child->type == V_RECNO) {
01447 if (pip->type != P_IRECNO) {
01448 TYPE_ERR_PRINT(dbp->dbenv, "CDB___bam_vrfy_subtree",
01449 pgno, pip->type);
01450 DB_ASSERT(0);
01451 ret = EINVAL;
01452 goto err;
01453 }
01454 if ((ret = CDB___bam_vrfy_subtree(dbp, vdp, child->pgno,
01455 NULL, NULL, flags, &child_level, &child_nrecs,
01456 &child_relen)) != 0) {
01457 if (ret != DB_VERIFY_BAD)
01458 goto done;
01459 else
01460 isbad = 1;
01461 }
01462
01463 if (LF_ISSET(ST_RELEN)) {
01464 if (relen == 0)
01465 relen = child_relen;
01466
01467
01468
01469
01470 else if (child_relen > 0 &&
01471 relen != child_relen) {
01472 isbad = 1;
01473 EPRINT((dbp->dbenv,
01474 "Recno page %lu returned bad re_len",
01475 child->pgno));
01476 }
01477 if (relenp)
01478 *relenp = relen;
01479 }
01480 if (LF_ISSET(ST_RECNUM))
01481 nrecs += child_nrecs;
01482 if (level != child_level + 1) {
01483 isbad = 1;
01484 EPRINT((dbp->dbenv, "%s%lu%s%lu%s%lu",
01485 "Recno level incorrect on page ",
01486 child->pgno, ": got ", child_level,
01487 ", expected ", level - 1));
01488 }
01489 } else if (child->type == V_OVERFLOW &&
01490 (ret = CDB___db_vrfy_ovfl_structure(dbp, vdp,
01491 child->pgno, child->tlen, flags)) != 0) {
01492 if (ret == DB_VERIFY_BAD)
01493 isbad = 1;
01494 else
01495 goto done;
01496 }
01497
01498 if ((ret = CDB___db_vrfy_ccclose(cc)) != 0)
01499 goto err;
01500 cc = NULL;
01501
01502
01503 if (pip->type == P_IRECNO)
01504 goto done;
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516 if (h == NULL && (ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
01517 goto err;
01518 for (i = 0; i < pip->entries; i += O_INDX) {
01519 li = GET_BINTERNAL(h, i);
01520 ri = (i + O_INDX < pip->entries) ?
01521 GET_BINTERNAL(h, i + O_INDX) : NULL;
01522
01523
01524
01525
01526
01527 if ((ret = CDB___bam_vrfy_subtree(dbp, vdp, li->pgno,
01528 i == 0 ? NULL : li, ri, flags, &child_level,
01529 &child_nrecs, NULL)) != 0) {
01530 if (ret != DB_VERIFY_BAD)
01531 goto done;
01532 else
01533 isbad = 1;
01534 }
01535
01536 if (LF_ISSET(ST_RECNUM)) {
01537
01538
01539
01540
01541
01542 nrecs += child_nrecs;
01543
01544
01545
01546
01547
01548 if (li->nrecs != child_nrecs) {
01549 isbad = 1;
01550 EPRINT((dbp->dbenv,
01551 "Item %lu page %lu has incorrect record count of %lu, should be %lu",
01552 i, pgno, li->nrecs, child_nrecs));
01553 }
01554 }
01555
01556 if (level != child_level + 1) {
01557 isbad = 1;
01558 EPRINT((dbp->dbenv, "%s%lu%s%lu%s%lu",
01559 "Btree level incorrect on page ", li->pgno,
01560 ": got ", child_level, ", expected ", level - 1));
01561 }
01562 }
01563
01564 if (0) {
01565 leaf: level = LEAFLEVEL;
01566 if (LF_ISSET(ST_RECNUM))
01567 nrecs = pip->rec_cnt;
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577 if (LF_ISSET(ST_RELEN) && relenp)
01578 *relenp = pip->re_len;
01579 }
01580 done: if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
01581
01582
01583
01584
01585
01586
01587 if (h == NULL && (ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
01588 goto err;
01589 if ((ret = CDB___bam_vrfy_itemorder(dbp,
01590 vdp, h, pgno, 0, 1, 0, flags)) != 0)
01591 goto err;
01592 F_CLR(pip, VRFY_INCOMPLETE);
01593 }
01594
01595
01596
01597
01598
01599
01600 if (isbad == 0 && ret == 0 && !LF_ISSET(DB_NOORDERCHK) && lp != NULL) {
01601 if (h == NULL && (ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
01602 goto err;
01603 if ((ret =
01604 __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, flags)) != 0) {
01605 if (ret == DB_VERIFY_BAD)
01606 isbad = 1;
01607 else
01608 goto err;
01609 }
01610 }
01611
01612
01613
01614
01615
01616
01617
01618 if (LF_ISSET(ST_RECNUM) && nrecs != pip->rec_cnt && toplevel) {
01619 isbad = 1;
01620 EPRINT((dbp->dbenv,
01621 "Bad record count on page %lu: got %lu, expected %lu",
01622 pgno, nrecs, pip->rec_cnt));
01623 }
01624
01625 if (levelp)
01626 *levelp = level;
01627 if (nrecsp)
01628 *nrecsp = nrecs;
01629
01630 pgset = vdp->pgset;
01631 if ((ret = CDB___db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
01632 goto err;
01633 if (p != 0) {
01634 isbad = 1;
01635 EPRINT((dbp->dbenv, "Page %lu linked twice", pgno));
01636 } else if ((ret = CDB___db_vrfy_pgset_inc(pgset, pgno)) != 0)
01637 goto err;
01638
01639 err: if (h != NULL && (t_ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0)
01640 ret = t_ret;
01641 if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
01642 ret = t_ret;
01643 if (cc != NULL && ((t_ret = CDB___db_vrfy_ccclose(cc)) != 0) && ret == 0)
01644 ret = t_ret;
01645 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
01646 }
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661 static int
01662 __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, flags)
01663 DB *dbp;
01664 db_pgno_t pgno;
01665 PAGE *h;
01666 BINTERNAL *lp, *rp;
01667 u_int32_t flags;
01668 {
01669 BOVERFLOW *bo;
01670 BTREE *t;
01671 DBT dbt;
01672 db_indx_t last;
01673 int (*func)__P((const DBT *, const DBT *));
01674 int ret, cmp;
01675
01676 memset(&dbt, 0, sizeof(DBT));
01677 F_SET(&dbt, DB_DBT_MALLOC);
01678 t = dbp->bt_internal;
01679 func = (t->bt_compare != NULL) ? t->bt_compare : CDB___bam_defcmp;
01680 ret = 0;
01681
01682 switch (TYPE(h)) {
01683 case P_IBTREE:
01684 case P_LDUP:
01685 last = NUM_ENT(h) - O_INDX;
01686 break;
01687 case P_LBTREE:
01688 last = NUM_ENT(h) - P_INDX;
01689 break;
01690 default:
01691 TYPE_ERR_PRINT(dbp->dbenv, "__bam_vrfy_treeorder", pgno, TYPE(h));
01692 DB_ASSERT(0);
01693 return (EINVAL);
01694 }
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709 if (lp != NULL && TYPE(h) != P_IBTREE) {
01710 if (lp->type == B_KEYDATA) {
01711 dbt.data = lp->data;
01712 dbt.size = lp->len;
01713 } else if (lp->type == B_OVERFLOW) {
01714 bo = (BOVERFLOW *)lp->data;
01715 if ((ret = CDB___db_goff(dbp, &dbt, bo->tlen, bo->pgno,
01716 NULL, NULL)) != 0)
01717 return (ret);
01718 } else {
01719 DB_ASSERT(0);
01720 EPRINT((dbp->dbenv, "Unknown type for internal record"));
01721 return (EINVAL);
01722 }
01723
01724
01725 if ((ret = CDB___bam_cmp(dbp, &dbt, h, 0, func, &cmp)) == 0) {
01726 if (cmp > 0) {
01727 EPRINT((dbp->dbenv,
01728 "First item on page %lu sorted greater than parent entry",
01729 PGNO(h)));
01730 ret = DB_VERIFY_BAD;
01731 }
01732 } else
01733 EPRINT((dbp->dbenv,
01734 "First item on page %lu had comparison error",
01735 PGNO(h)));
01736
01737 if (dbt.data != lp->data)
01738 CDB___os_free(dbt.data, 0);
01739 if (ret != 0)
01740 return (ret);
01741 }
01742
01743 if (rp != NULL) {
01744 if (rp->type == B_KEYDATA) {
01745 dbt.data = rp->data;
01746 dbt.size = rp->len;
01747 } else if (rp->type == B_OVERFLOW) {
01748 bo = (BOVERFLOW *)rp->data;
01749 if ((ret = CDB___db_goff(dbp, &dbt, bo->tlen, bo->pgno,
01750 NULL, NULL)) != 0)
01751 return (ret);
01752 } else {
01753 DB_ASSERT(0);
01754 EPRINT((dbp->dbenv, "Unknown type for internal record"));
01755 return (EINVAL);
01756 }
01757
01758
01759 if ((ret = CDB___bam_cmp(dbp, &dbt, h, last, func, &cmp)) == 0) {
01760 if (cmp < 0) {
01761 EPRINT((dbp->dbenv,
01762 "Last item on page %lu sorted greater than parent entry",
01763 PGNO(h)));
01764 ret = DB_VERIFY_BAD;
01765 }
01766 } else
01767 EPRINT((dbp->dbenv,
01768 "Last item on page %lu had comparison error",
01769 PGNO(h)));
01770
01771 if (dbt.data != rp->data)
01772 CDB___os_free(dbt.data, 0);
01773 }
01774
01775 return (ret);
01776 }
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787 int
01788 CDB___bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
01789 DB *dbp;
01790 VRFY_DBINFO *vdp;
01791 db_pgno_t pgno;
01792 u_int32_t pgtype;
01793 PAGE *h;
01794 void *handle;
01795 int (*callback) __P((void *, const void *));
01796 DBT *key;
01797 u_int32_t flags;
01798 {
01799 DBT dbt, unkdbt;
01800 BKEYDATA *bk;
01801 BOVERFLOW *bo;
01802 db_indx_t i, beg, end;
01803 u_int32_t himark;
01804 u_int8_t *pgmap;
01805 void *ovflbuf;
01806 int t_ret, ret, err_ret;
01807
01808
01809 COMPQUIET(end, 0);
01810
01811 ovflbuf = pgmap = NULL;
01812 err_ret = ret = 0;
01813
01814 memset(&dbt, 0, sizeof(DBT));
01815 dbt.flags = DB_DBT_REALLOC;
01816
01817 memset(&unkdbt, 0, sizeof(DBT));
01818 unkdbt.size = strlen("UNKNOWN") + 1;
01819 unkdbt.data = "UNKNOWN";
01820
01821
01822
01823
01824
01825 if ((ret = CDB___os_malloc(dbp->dbenv, dbp->pgsize, NULL, &ovflbuf)) != 0)
01826 return (ret);
01827
01828 if (LF_ISSET(DB_AGGRESSIVE)) {
01829 if ((ret =
01830 CDB___os_malloc(dbp->dbenv, dbp->pgsize, NULL, &pgmap)) != 0)
01831 goto err;
01832 memset(pgmap, 0, dbp->pgsize);
01833 }
01834
01835
01836
01837
01838
01839
01840
01841
01842 i = 0;
01843 himark = dbp->pgsize;
01844 for (;;) {
01845
01846 if (!LF_ISSET(DB_AGGRESSIVE) && i >= NUM_ENT(h))
01847 break;
01848
01849
01850 ret = CDB___db_vrfy_inpitem(dbp,
01851 h, pgno, i, 1, flags, &himark, NULL);
01852
01853 if (ret == DB_VERIFY_FATAL)
01854 break;
01855
01856
01857
01858
01859 if (ret == 0) {
01860
01861
01862
01863
01864
01865
01866 if (key != NULL &&
01867 (i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY)))
01868 if ((ret = CDB___db_prdbt(key,
01869 0, " ", handle, callback, 0, NULL)) != 0)
01870 err_ret = ret;
01871
01872 bk = GET_BKEYDATA(h, i);
01873 beg = h->inp[i];
01874 switch (bk->type) {
01875 case B_DUPLICATE:
01876 end = beg + BOVERFLOW_SIZE - 1;
01877
01878
01879
01880
01881
01882
01883
01884
01885 if (pgtype != P_LBTREE)
01886 break;
01887
01888 bo = (BOVERFLOW *)bk;
01889
01890
01891
01892
01893
01894
01895
01896
01897 if (!IS_VALID_PGNO(bo->pgno) ||
01898 (i % P_INDX == 0)) {
01899
01900 if ((ret = CDB___db_prdbt(&unkdbt, 0, " ",
01901 handle, callback, 0, NULL)) != 0)
01902 err_ret = ret;
01903 break;
01904 }
01905
01906 if ((ret = CDB___db_salvage_duptree(dbp,
01907 vdp, bo->pgno, &dbt, handle, callback,
01908 flags | SA_SKIPFIRSTKEY)) != 0)
01909 err_ret = ret;
01910
01911 break;
01912 default:
01913
01914
01915
01916
01917
01918
01919 if (!LF_ISSET(DB_AGGRESSIVE))
01920 break;
01921
01922 case B_KEYDATA:
01923 end = ALIGN(beg + bk->len, 4) - 1;
01924 dbt.data = bk->data;
01925 dbt.size = bk->len;
01926 if ((ret = CDB___db_prdbt(&dbt,
01927 0, " ", handle, callback, 0, NULL)) != 0)
01928 err_ret = ret;
01929 break;
01930 case B_OVERFLOW:
01931 end = beg + BOVERFLOW_SIZE - 1;
01932 bo = (BOVERFLOW *)bk;
01933 if ((ret = CDB___db_safe_goff(dbp, vdp,
01934 bo->pgno, &dbt, &ovflbuf, flags)) != 0) {
01935 err_ret = ret;
01936
01937 (void)CDB___db_prdbt(&unkdbt, 0, " ",
01938 handle, callback, 0, NULL);
01939 break;
01940 }
01941 if ((ret = CDB___db_prdbt(&dbt,
01942 0, " ", handle, callback, 0, NULL)) != 0)
01943 err_ret = ret;
01944 break;
01945 }
01946
01947
01948
01949
01950
01951
01952
01953 if (LF_ISSET(DB_AGGRESSIVE)) {
01954 pgmap[beg] = ITEM_BEGIN;
01955 pgmap[end] = ITEM_END;
01956 }
01957 }
01958 i += O_INDX;
01959 }
01960
01961
01962
01963
01964
01965 if (pgtype == P_LBTREE && (i % P_INDX == 1) && ((ret =
01966 CDB___db_prdbt(&unkdbt, 0, " ", handle, callback, 0, NULL)) != 0))
01967 err_ret = ret;
01968
01969 err: if (pgmap != NULL)
01970 CDB___os_free(pgmap, 0);
01971 CDB___os_free(ovflbuf, 0);
01972
01973
01974 if ((t_ret = CDB___db_salvage_markdone(vdp, pgno)) != 0)
01975 return (t_ret);
01976
01977 return ((err_ret != 0) ? err_ret : ret);
01978 }
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988 int
01989 CDB___bam_salvage_walkdupint(dbp, vdp, h, key, handle, callback, flags)
01990 DB *dbp;
01991 VRFY_DBINFO *vdp;
01992 PAGE *h;
01993 DBT *key;
01994 void *handle;
01995 int (*callback) __P((void *, const void *));
01996 u_int32_t flags;
01997 {
01998 RINTERNAL *ri;
01999 BINTERNAL *bi;
02000 int ret, t_ret;
02001 db_indx_t i;
02002
02003 ret = 0;
02004 for (i = 0; i < NUM_ENT(h); i++) {
02005 switch (TYPE(h)) {
02006 case P_IBTREE:
02007 bi = GET_BINTERNAL(h, i);
02008 if ((t_ret = CDB___db_salvage_duptree(dbp,
02009 vdp, bi->pgno, key, handle, callback, flags)) != 0)
02010 ret = t_ret;
02011 case P_IRECNO:
02012 ri = GET_RINTERNAL(h, i);
02013 if ((t_ret = CDB___db_salvage_duptree(dbp,
02014 vdp, ri->pgno, key, handle, callback, flags)) != 0)
02015 ret = t_ret;
02016 break;
02017 default:
02018 CDB___db_err(dbp->dbenv,
02019 "CDB___bam_salvage_walkdupint called on non-int. page");
02020 DB_ASSERT(0);
02021 return (EINVAL);
02022 }
02023
02024 flags &= ~LF_ISSET(SA_SKIPFIRSTKEY);
02025 }
02026
02027 return (ret);
02028 }
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047 int
02048 CDB___bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
02049 DB *dbp;
02050 VRFY_DBINFO *vdp;
02051 BTMETA *btmeta;
02052 u_int32_t flags;
02053 DB *pgset;
02054 {
02055 BINTERNAL *bi;
02056 PAGE *h;
02057 RINTERNAL *ri;
02058 db_pgno_t current, p;
02059 int err_ret, ret;
02060
02061 h = NULL;
02062 ret = err_ret = 0;
02063 DB_ASSERT(pgset != NULL);
02064 for (current = btmeta->root;;) {
02065 if (!IS_VALID_PGNO(current) || current == PGNO(btmeta)) {
02066 err_ret = DB_VERIFY_BAD;
02067 goto err;
02068 }
02069 if ((ret = CDB_memp_fget(dbp->mpf, ¤t, 0, &h)) != 0) {
02070 err_ret = ret;
02071 goto err;
02072 }
02073
02074 switch (TYPE(h)) {
02075 case P_IBTREE:
02076 case P_IRECNO:
02077 if ((ret = CDB___bam_vrfy(dbp,
02078 vdp, h, current, flags | DB_NOORDERCHK)) != 0) {
02079 err_ret = ret;
02080 goto err;
02081 }
02082 if (TYPE(h) == P_IBTREE) {
02083 bi = GET_BINTERNAL(h, 0);
02084 current = bi->pgno;
02085 } else {
02086 ri = GET_RINTERNAL(h, 0);
02087 current = ri->pgno;
02088 }
02089 break;
02090 case P_LBTREE:
02091 case P_LRECNO:
02092 goto traverse;
02093
02094 default:
02095 err_ret = DB_VERIFY_BAD;
02096 goto err;
02097 }
02098
02099 if ((ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0)
02100 err_ret = ret;
02101 h = NULL;
02102 }
02103
02104
02105
02106
02107
02108 traverse:
02109 while (IS_VALID_PGNO(current) && current != PGNO_INVALID) {
02110 if (h == NULL &&
02111 (ret = CDB_memp_fget(dbp->mpf, ¤t, 0, &h) != 0)) {
02112 err_ret = ret;
02113 break;
02114 }
02115
02116 if ((ret = CDB___db_vrfy_pgset_get(pgset, current, (int *)&p)) != 0)
02117 goto err;
02118
02119 if (p != 0) {
02120
02121
02122
02123
02124
02125 break;
02126 }
02127 if ((ret = CDB___db_vrfy_pgset_inc(pgset, current)) != 0)
02128 goto err;
02129
02130 current = NEXT_PGNO(h);
02131 if ((ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0)
02132 err_ret = ret;
02133 h = NULL;
02134 }
02135
02136 err: if (h != NULL)
02137 (void)CDB_memp_fput(dbp->mpf, h, 0);
02138
02139 return (ret == 0 ? err_ret : ret);
02140 }
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150 static int
02151 __bam_safe_getdata(dbp, h, i, ovflok, dbt, freedbtp)
02152 DB *dbp;
02153 PAGE *h;
02154 u_int32_t i;
02155 int ovflok;
02156 DBT *dbt;
02157 int *freedbtp;
02158 {
02159 BKEYDATA *bk;
02160 BOVERFLOW *bo;
02161
02162 memset(dbt, 0, sizeof(DBT));
02163 *freedbtp = 0;
02164
02165 bk = GET_BKEYDATA(h, i);
02166 if (B_TYPE(bk->type) == B_OVERFLOW) {
02167 if (!ovflok)
02168 return(0);
02169
02170 bo = (BOVERFLOW *)bk;
02171 F_SET(dbt, DB_DBT_MALLOC);
02172
02173 *freedbtp = 1;
02174 return (CDB___db_goff(dbp, dbt, bo->tlen, bo->pgno, NULL, NULL));
02175
02176 } else {
02177 dbt->data = bk->data;
02178 dbt->size = bk->len;
02179 }
02180
02181 return (0);
02182 }