00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/db_page.h"
00020 #include "dbinc/db_verify.h"
00021 #include "dbinc/db_am.h"
00022
00023 static int __db_vrfy_childinc __P((DBC *, VRFY_CHILDINFO *));
00024 static int __db_vrfy_pageinfo_create __P((DB_ENV *, VRFY_PAGEINFO **));
00025
00026
00027
00028
00029
00030
00031
00032
00033 int
00034 __db_vrfy_dbinfo_create(dbenv, pgsize, vdpp)
00035 DB_ENV *dbenv;
00036 u_int32_t pgsize;
00037 VRFY_DBINFO **vdpp;
00038 {
00039 DB *cdbp, *pgdbp, *pgset;
00040 VRFY_DBINFO *vdp;
00041 int ret;
00042
00043 vdp = NULL;
00044 cdbp = pgdbp = pgset = NULL;
00045
00046 if ((ret = __os_calloc(NULL, 1, sizeof(VRFY_DBINFO), &vdp)) != 0)
00047 goto err;
00048
00049 if ((ret = db_create(&cdbp, dbenv, 0)) != 0)
00050 goto err;
00051
00052 if ((ret = __db_set_flags(cdbp, DB_DUP)) != 0)
00053 goto err;
00054
00055 if ((ret = __db_set_pagesize(cdbp, pgsize)) != 0)
00056 goto err;
00057
00058 if ((ret = __db_open(cdbp,
00059 NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) != 0)
00060 goto err;
00061
00062 if ((ret = db_create(&pgdbp, dbenv, 0)) != 0)
00063 goto err;
00064
00065 if ((ret = __db_set_pagesize(pgdbp, pgsize)) != 0)
00066 goto err;
00067
00068 if ((ret = __db_open(pgdbp,
00069 NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) != 0)
00070 goto err;
00071
00072 if ((ret = __db_vrfy_pgset(dbenv, pgsize, &pgset)) != 0)
00073 goto err;
00074
00075 LIST_INIT(&vdp->subdbs);
00076 LIST_INIT(&vdp->activepips);
00077
00078 vdp->cdbp = cdbp;
00079 vdp->pgdbp = pgdbp;
00080 vdp->pgset = pgset;
00081 *vdpp = vdp;
00082 return (0);
00083
00084 err: if (cdbp != NULL)
00085 (void)__db_close(cdbp, NULL, 0);
00086 if (pgdbp != NULL)
00087 (void)__db_close(pgdbp, NULL, 0);
00088 if (vdp != NULL)
00089 __os_free(dbenv, vdp);
00090 return (ret);
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100 int
00101 __db_vrfy_dbinfo_destroy(dbenv, vdp)
00102 DB_ENV *dbenv;
00103 VRFY_DBINFO *vdp;
00104 {
00105 VRFY_CHILDINFO *c;
00106 int t_ret, ret;
00107
00108 ret = 0;
00109
00110
00111
00112
00113
00114 while (LIST_FIRST(&vdp->activepips) != NULL)
00115 if ((t_ret = __db_vrfy_putpageinfo(
00116 dbenv, vdp, LIST_FIRST(&vdp->activepips))) != 0) {
00117 if (ret == 0)
00118 ret = t_ret;
00119 break;
00120 }
00121
00122
00123 while ((c = LIST_FIRST(&vdp->subdbs)) != NULL) {
00124 LIST_REMOVE(c, links);
00125 __os_free(NULL, c);
00126 }
00127
00128 if ((t_ret = __db_close(vdp->pgdbp, NULL, 0)) != 0)
00129 ret = t_ret;
00130
00131 if ((t_ret = __db_close(vdp->cdbp, NULL, 0)) != 0 && ret == 0)
00132 ret = t_ret;
00133
00134 if ((t_ret = __db_close(vdp->pgset, NULL, 0)) != 0 && ret == 0)
00135 ret = t_ret;
00136
00137 if (vdp->extents != NULL)
00138 __os_free(dbenv, vdp->extents);
00139 __os_free(dbenv, vdp);
00140 return (ret);
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150 int
00151 __db_vrfy_getpageinfo(vdp, pgno, pipp)
00152 VRFY_DBINFO *vdp;
00153 db_pgno_t pgno;
00154 VRFY_PAGEINFO **pipp;
00155 {
00156 DBT key, data;
00157 DB *pgdbp;
00158 VRFY_PAGEINFO *pip;
00159 int ret;
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 for (pip = LIST_FIRST(&vdp->activepips); pip != NULL;
00181 pip = LIST_NEXT(pip, links))
00182 if (pip->pgno == pgno)
00183
00184 goto found;
00185
00186
00187 pgdbp = vdp->pgdbp;
00188 memset(&key, 0, sizeof(DBT));
00189 memset(&data, 0, sizeof(DBT));
00190 F_SET(&data, DB_DBT_MALLOC);
00191 key.data = &pgno;
00192 key.size = sizeof(db_pgno_t);
00193
00194 if ((ret = __db_get(pgdbp, NULL, &key, &data, 0)) == 0) {
00195
00196 DB_ASSERT(data.size == sizeof(VRFY_PAGEINFO));
00197 pip = data.data;
00198 LIST_INSERT_HEAD(&vdp->activepips, pip, links);
00199 goto found;
00200 } else if (ret != DB_NOTFOUND)
00201 return (ret);
00202
00203
00204 if ((ret = __db_vrfy_pageinfo_create(pgdbp->dbenv, &pip)) != 0)
00205 return (ret);
00206
00207 LIST_INSERT_HEAD(&vdp->activepips, pip, links);
00208 found: pip->pi_refcount++;
00209
00210 *pipp = pip;
00211 return (0);
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221 int
00222 __db_vrfy_putpageinfo(dbenv, vdp, pip)
00223 DB_ENV *dbenv;
00224 VRFY_DBINFO *vdp;
00225 VRFY_PAGEINFO *pip;
00226 {
00227 DBT key, data;
00228 DB *pgdbp;
00229 VRFY_PAGEINFO *p;
00230 int ret;
00231
00232 if (--pip->pi_refcount > 0)
00233 return (0);
00234
00235 pgdbp = vdp->pgdbp;
00236 memset(&key, 0, sizeof(DBT));
00237 memset(&data, 0, sizeof(DBT));
00238
00239 key.data = &pip->pgno;
00240 key.size = sizeof(db_pgno_t);
00241 data.data = pip;
00242 data.size = sizeof(VRFY_PAGEINFO);
00243
00244 if ((ret = __db_put(pgdbp, NULL, &key, &data, 0)) != 0)
00245 return (ret);
00246
00247 for (p =
00248 LIST_FIRST(&vdp->activepips); p != NULL; p = LIST_NEXT(p, links))
00249 if (p == pip)
00250 break;
00251 if (p != NULL)
00252 LIST_REMOVE(p, links);
00253
00254 __os_ufree(dbenv, p);
00255 return (0);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 int
00267 __db_vrfy_pgset(dbenv, pgsize, dbpp)
00268 DB_ENV *dbenv;
00269 u_int32_t pgsize;
00270 DB **dbpp;
00271 {
00272 DB *dbp;
00273 int ret;
00274
00275 if ((ret = db_create(&dbp, dbenv, 0)) != 0)
00276 return (ret);
00277 if ((ret = __db_set_pagesize(dbp, pgsize)) != 0)
00278 goto err;
00279 if ((ret = __db_open(dbp,
00280 NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) == 0)
00281 *dbpp = dbp;
00282 else
00283 err: (void)__db_close(dbp, NULL, 0);
00284
00285 return (ret);
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295 int
00296 __db_vrfy_pgset_get(dbp, pgno, valp)
00297 DB *dbp;
00298 db_pgno_t pgno;
00299 int *valp;
00300 {
00301 DBT key, data;
00302 int ret, val;
00303
00304 memset(&key, 0, sizeof(DBT));
00305 memset(&data, 0, sizeof(DBT));
00306
00307 key.data = &pgno;
00308 key.size = sizeof(db_pgno_t);
00309 data.data = &val;
00310 data.ulen = sizeof(int);
00311 F_SET(&data, DB_DBT_USERMEM);
00312
00313 if ((ret = __db_get(dbp, NULL, &key, &data, 0)) == 0) {
00314 DB_ASSERT(data.size == sizeof(int));
00315 } else if (ret == DB_NOTFOUND)
00316 val = 0;
00317 else
00318 return (ret);
00319
00320 *valp = val;
00321 return (0);
00322 }
00323
00324
00325
00326
00327
00328
00329
00330 int
00331 __db_vrfy_pgset_inc(dbp, pgno)
00332 DB *dbp;
00333 db_pgno_t pgno;
00334 {
00335 DBT key, data;
00336 int ret;
00337 int val;
00338
00339 memset(&key, 0, sizeof(DBT));
00340 memset(&data, 0, sizeof(DBT));
00341
00342 val = 0;
00343
00344 key.data = &pgno;
00345 key.size = sizeof(db_pgno_t);
00346 data.data = &val;
00347 data.ulen = sizeof(int);
00348 F_SET(&data, DB_DBT_USERMEM);
00349
00350 if ((ret = __db_get(dbp, NULL, &key, &data, 0)) == 0) {
00351 DB_ASSERT(data.size == sizeof(int));
00352 } else if (ret != DB_NOTFOUND)
00353 return (ret);
00354
00355 data.size = sizeof(int);
00356 ++val;
00357
00358 return (__db_put(dbp, NULL, &key, &data, 0));
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368 int
00369 __db_vrfy_pgset_next(dbc, pgnop)
00370 DBC *dbc;
00371 db_pgno_t *pgnop;
00372 {
00373 DBT key, data;
00374 db_pgno_t pgno;
00375 int ret;
00376
00377 memset(&key, 0, sizeof(DBT));
00378 memset(&data, 0, sizeof(DBT));
00379
00380 F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL);
00381 F_SET(&key, DB_DBT_USERMEM);
00382 key.data = &pgno;
00383 key.ulen = sizeof(db_pgno_t);
00384
00385 if ((ret = __db_c_get(dbc, &key, &data, DB_NEXT)) != 0)
00386 return (ret);
00387
00388 DB_ASSERT(key.size == sizeof(db_pgno_t));
00389 *pgnop = pgno;
00390
00391 return (0);
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401 int
00402 __db_vrfy_childcursor(vdp, dbcp)
00403 VRFY_DBINFO *vdp;
00404 DBC **dbcp;
00405 {
00406 DB *cdbp;
00407 DBC *dbc;
00408 int ret;
00409
00410 cdbp = vdp->cdbp;
00411
00412 if ((ret = __db_cursor(cdbp, NULL, &dbc, 0)) == 0)
00413 *dbcp = dbc;
00414
00415 return (ret);
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425 int
00426 __db_vrfy_childput(vdp, pgno, cip)
00427 VRFY_DBINFO *vdp;
00428 db_pgno_t pgno;
00429 VRFY_CHILDINFO *cip;
00430 {
00431 DB *cdbp;
00432 DBC *cc;
00433 DBT key, data;
00434 VRFY_CHILDINFO *oldcip;
00435 int ret;
00436
00437 cdbp = vdp->cdbp;
00438 memset(&key, 0, sizeof(DBT));
00439 memset(&data, 0, sizeof(DBT));
00440
00441 key.data = &pgno;
00442 key.size = sizeof(db_pgno_t);
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 if ((ret = __db_vrfy_childcursor(vdp, &cc)) != 0)
00459 return (ret);
00460 for (ret = __db_vrfy_ccset(cc, pgno, &oldcip); ret == 0;
00461 ret = __db_vrfy_ccnext(cc, &oldcip))
00462 if (oldcip->pgno == cip->pgno) {
00463
00464
00465
00466
00467
00468 if ((ret = __db_vrfy_childinc(cc, oldcip)) != 0 ||
00469 (ret = __db_vrfy_ccclose(cc)) != 0)
00470 return (ret);
00471 return (0);
00472 }
00473 if (ret != DB_NOTFOUND) {
00474 (void)__db_vrfy_ccclose(cc);
00475 return (ret);
00476 }
00477 if ((ret = __db_vrfy_ccclose(cc)) != 0)
00478 return (ret);
00479
00480 cip->refcnt = 1;
00481 data.data = cip;
00482 data.size = sizeof(VRFY_CHILDINFO);
00483
00484 return (__db_put(cdbp, NULL, &key, &data, 0));
00485 }
00486
00487
00488
00489
00490
00491
00492
00493 static int
00494 __db_vrfy_childinc(dbc, cip)
00495 DBC *dbc;
00496 VRFY_CHILDINFO *cip;
00497 {
00498 DBT key, data;
00499
00500 memset(&key, 0, sizeof(DBT));
00501 memset(&data, 0, sizeof(DBT));
00502
00503 cip->refcnt++;
00504 data.data = cip;
00505 data.size = sizeof(VRFY_CHILDINFO);
00506
00507 return (__db_c_put(dbc, &key, &data, DB_CURRENT));
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517 int
00518 __db_vrfy_ccset(dbc, pgno, cipp)
00519 DBC *dbc;
00520 db_pgno_t pgno;
00521 VRFY_CHILDINFO **cipp;
00522 {
00523 DBT key, data;
00524 int ret;
00525
00526 memset(&key, 0, sizeof(DBT));
00527 memset(&data, 0, sizeof(DBT));
00528
00529 key.data = &pgno;
00530 key.size = sizeof(db_pgno_t);
00531
00532 if ((ret = __db_c_get(dbc, &key, &data, DB_SET)) != 0)
00533 return (ret);
00534
00535 DB_ASSERT(data.size == sizeof(VRFY_CHILDINFO));
00536 *cipp = (VRFY_CHILDINFO *)data.data;
00537
00538 return (0);
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 int
00550 __db_vrfy_ccnext(dbc, cipp)
00551 DBC *dbc;
00552 VRFY_CHILDINFO **cipp;
00553 {
00554 DBT key, data;
00555 int ret;
00556
00557 memset(&key, 0, sizeof(DBT));
00558 memset(&data, 0, sizeof(DBT));
00559
00560 if ((ret = __db_c_get(dbc, &key, &data, DB_NEXT_DUP)) != 0)
00561 return (ret);
00562
00563 DB_ASSERT(data.size == sizeof(VRFY_CHILDINFO));
00564 *cipp = (VRFY_CHILDINFO *)data.data;
00565
00566 return (0);
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 int
00581 __db_vrfy_ccclose(dbc)
00582 DBC *dbc;
00583 {
00584
00585 return (__db_c_close(dbc));
00586 }
00587
00588
00589
00590
00591
00592 static int
00593 __db_vrfy_pageinfo_create(dbenv, pipp)
00594 DB_ENV *dbenv;
00595 VRFY_PAGEINFO **pipp;
00596 {
00597 VRFY_PAGEINFO *pip;
00598 int ret;
00599
00600
00601
00602
00603
00604
00605
00606
00607 if ((ret = __os_umalloc(dbenv, sizeof(VRFY_PAGEINFO), &pip)) != 0)
00608 return (ret);
00609 memset(pip, 0, sizeof(VRFY_PAGEINFO));
00610
00611 *pipp = pip;
00612 return (0);
00613 }
00614
00615
00616
00617
00618
00619
00620
00621 int
00622 __db_salvage_init(vdp)
00623 VRFY_DBINFO *vdp;
00624 {
00625 DB *dbp;
00626 int ret;
00627
00628 if ((ret = db_create(&dbp, NULL, 0)) != 0)
00629 return (ret);
00630
00631 if ((ret = __db_set_pagesize(dbp, 1024)) != 0)
00632 goto err;
00633
00634 if ((ret = __db_open(dbp,
00635 NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0, PGNO_BASE_MD)) != 0)
00636 goto err;
00637
00638 vdp->salvage_pages = dbp;
00639 return (0);
00640
00641 err: (void)__db_close(dbp, NULL, 0);
00642 return (ret);
00643 }
00644
00645
00646
00647
00648
00649
00650 void
00651 __db_salvage_destroy(vdp)
00652 VRFY_DBINFO *vdp;
00653 {
00654 (void)__db_close(vdp->salvage_pages, NULL, 0);
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 int
00667 __db_salvage_getnext(vdp, dbcp, pgnop, pgtypep, skip_overflow)
00668 VRFY_DBINFO *vdp;
00669 DBC **dbcp;
00670 db_pgno_t *pgnop;
00671 u_int32_t *pgtypep;
00672 int skip_overflow;
00673 {
00674 DB *dbp;
00675 DBT key, data;
00676 int ret;
00677 u_int32_t pgtype;
00678
00679 dbp = vdp->salvage_pages;
00680
00681 memset(&key, 0, sizeof(DBT));
00682 memset(&data, 0, sizeof(DBT));
00683
00684 if (*dbcp == NULL &&
00685 (ret = __db_cursor(dbp, NULL, dbcp, 0)) != 0)
00686 return (ret);
00687
00688 while ((ret = __db_c_get(*dbcp, &key, &data, DB_NEXT)) == 0) {
00689 DB_ASSERT(data.size == sizeof(u_int32_t));
00690 memcpy(&pgtype, data.data, sizeof(pgtype));
00691
00692 if (skip_overflow && pgtype == SALVAGE_OVERFLOW)
00693 continue;
00694
00695 if ((ret = __db_c_del(*dbcp, 0)) != 0)
00696 return (ret);
00697 if (pgtype != SALVAGE_IGNORE) {
00698 DB_ASSERT(key.size == sizeof(db_pgno_t));
00699 DB_ASSERT(data.size == sizeof(u_int32_t));
00700
00701 *pgnop = *(db_pgno_t *)key.data;
00702 *pgtypep = *(u_int32_t *)data.data;
00703 break;
00704 }
00705 }
00706
00707 return (ret);
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 int
00721 __db_salvage_isdone(vdp, pgno)
00722 VRFY_DBINFO *vdp;
00723 db_pgno_t pgno;
00724 {
00725 DBT key, data;
00726 DB *dbp;
00727 int ret;
00728 u_int32_t currtype;
00729
00730 dbp = vdp->salvage_pages;
00731
00732 memset(&key, 0, sizeof(DBT));
00733 memset(&data, 0, sizeof(DBT));
00734
00735 currtype = SALVAGE_INVALID;
00736 data.data = &currtype;
00737 data.ulen = sizeof(u_int32_t);
00738 data.flags = DB_DBT_USERMEM;
00739
00740 key.data = &pgno;
00741 key.size = sizeof(db_pgno_t);
00742
00743
00744
00745
00746
00747
00748
00749 if ((ret = __db_get(dbp, NULL, &key, &data, 0)) == 0) {
00750
00751
00752
00753
00754
00755 if (currtype == SALVAGE_IGNORE)
00756 return (DB_KEYEXIST);
00757 else
00758 return (0);
00759 } else if (ret != DB_NOTFOUND)
00760 return (ret);
00761
00762
00763 return (0);
00764 }
00765
00766
00767
00768
00769
00770
00771
00772 int
00773 __db_salvage_markdone(vdp, pgno)
00774 VRFY_DBINFO *vdp;
00775 db_pgno_t pgno;
00776 {
00777 DBT key, data;
00778 DB *dbp;
00779 int pgtype, ret;
00780 u_int32_t currtype;
00781
00782 pgtype = SALVAGE_IGNORE;
00783 dbp = vdp->salvage_pages;
00784
00785 memset(&key, 0, sizeof(DBT));
00786 memset(&data, 0, sizeof(DBT));
00787
00788 currtype = SALVAGE_INVALID;
00789 data.data = &currtype;
00790 data.ulen = sizeof(u_int32_t);
00791 data.flags = DB_DBT_USERMEM;
00792
00793 key.data = &pgno;
00794 key.size = sizeof(db_pgno_t);
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 if ((ret = __db_salvage_isdone(vdp, pgno)) != 0)
00810 return (ret == DB_KEYEXIST ? DB_VERIFY_BAD : ret);
00811
00812 data.size = sizeof(u_int32_t);
00813 data.data = &pgtype;
00814
00815 return (__db_put(dbp, NULL, &key, &data, 0));
00816 }
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826 int
00827 __db_salvage_markneeded(vdp, pgno, pgtype)
00828 VRFY_DBINFO *vdp;
00829 db_pgno_t pgno;
00830 u_int32_t pgtype;
00831 {
00832 DB *dbp;
00833 DBT key, data;
00834 int ret;
00835
00836 dbp = vdp->salvage_pages;
00837
00838 memset(&key, 0, sizeof(DBT));
00839 memset(&data, 0, sizeof(DBT));
00840
00841 key.data = &pgno;
00842 key.size = sizeof(db_pgno_t);
00843
00844 data.data = &pgtype;
00845 data.size = sizeof(u_int32_t);
00846
00847
00848
00849
00850
00851
00852 ret = __db_put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
00853 return (ret == DB_KEYEXIST ? 0 : ret);
00854 }
00855
00856
00857
00858
00859
00860
00861
00862
00863 int
00864 __db_vrfy_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
00865 DBT *dbtp;
00866 int checkprint;
00867 const char *prefix;
00868 void *handle;
00869 int (*callback) __P((void *, const void *));
00870 int is_recno;
00871 VRFY_DBINFO *vdp;
00872 {
00873 if (vdp != NULL) {
00874
00875
00876
00877
00878
00879
00880
00881
00882 if (F_ISSET(vdp, SALVAGE_PRINTHEADER)) {
00883 (void)__db_prheader(
00884 NULL, "__OTHER__", 0, 0, handle, callback, vdp, 0);
00885 F_CLR(vdp, SALVAGE_PRINTHEADER);
00886 F_SET(vdp, SALVAGE_PRINTFOOTER);
00887 }
00888
00889
00890
00891
00892
00893 if (F_ISSET(vdp, SALVAGE_PRINTABLE))
00894 checkprint = 1;
00895 }
00896 return (
00897 __db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno));
00898 }