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_shash.h"
00021 #include "dbinc/log.h"
00022 #include "dbinc/mp.h"
00023 #include "dbinc/hash.h"
00024
00025 static int __db_pg_free_recover_int __P((DB_ENV *,
00026 __db_pg_freedata_args *, DB *, DB_LSN *, DB_MPOOLFILE *, db_recops, int));
00027
00028
00029
00030
00031
00032
00033
00034
00035 int
00036 __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
00037 DB_ENV *dbenv;
00038 DBT *dbtp;
00039 DB_LSN *lsnp;
00040 db_recops op;
00041 void *info;
00042 {
00043 __db_addrem_args *argp;
00044 DB *file_dbp;
00045 DBC *dbc;
00046 DB_MPOOLFILE *mpf;
00047 PAGE *pagep;
00048 u_int32_t change;
00049 int cmp_n, cmp_p, ret;
00050
00051 pagep = NULL;
00052 COMPQUIET(info, NULL);
00053 REC_PRINT(__db_addrem_print);
00054 REC_INTRO(__db_addrem_read, 1, 1);
00055
00056 REC_FGET(mpf, argp->pgno, &pagep, done);
00057
00058 cmp_n = log_compare(lsnp, &LSN(pagep));
00059 cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
00060 CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->pagelsn);
00061 change = 0;
00062 if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) ||
00063 (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_DUP)) {
00064
00065
00066 if ((ret = __db_pitem(dbc, pagep, argp->indx, argp->nbytes,
00067 argp->hdr.size == 0 ? NULL : &argp->hdr,
00068 argp->dbt.size == 0 ? NULL : &argp->dbt)) != 0)
00069 goto out;
00070
00071 change = DB_MPOOL_DIRTY;
00072
00073 } else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_DUP) ||
00074 (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_DUP)) {
00075
00076 if ((ret = __db_ditem(dbc,
00077 pagep, argp->indx, argp->nbytes)) != 0)
00078 goto out;
00079 change = DB_MPOOL_DIRTY;
00080 }
00081
00082 if (change) {
00083 if (DB_REDO(op))
00084 LSN(pagep) = *lsnp;
00085 else
00086 LSN(pagep) = argp->pagelsn;
00087 }
00088
00089 if ((ret = __memp_fput(mpf, pagep, change)) != 0)
00090 goto out;
00091 pagep = NULL;
00092
00093 done: *lsnp = argp->prev_lsn;
00094 ret = 0;
00095
00096 out: if (pagep != NULL)
00097 (void)__memp_fput(mpf, pagep, 0);
00098 REC_CLOSE;
00099 }
00100
00101
00102
00103
00104
00105 int
00106 __db_big_recover(dbenv, dbtp, lsnp, op, info)
00107 DB_ENV *dbenv;
00108 DBT *dbtp;
00109 DB_LSN *lsnp;
00110 db_recops op;
00111 void *info;
00112 {
00113 __db_big_args *argp;
00114 DB *file_dbp;
00115 DBC *dbc;
00116 DB_MPOOLFILE *mpf;
00117 PAGE *pagep;
00118 u_int32_t change;
00119 int cmp_n, cmp_p, ret;
00120
00121 pagep = NULL;
00122 COMPQUIET(info, NULL);
00123 REC_PRINT(__db_big_print);
00124 REC_INTRO(__db_big_read, 1, 0);
00125
00126 REC_FGET(mpf, argp->pgno, &pagep, ppage);
00127
00128
00129
00130
00131
00132
00133
00134 cmp_n = log_compare(lsnp, &LSN(pagep));
00135 cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
00136 CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->pagelsn);
00137 change = 0;
00138 if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
00139 (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
00140
00141 P_INIT(pagep, file_dbp->pgsize, argp->pgno, argp->prev_pgno,
00142 argp->next_pgno, 0, P_OVERFLOW);
00143 OV_LEN(pagep) = argp->dbt.size;
00144 OV_REF(pagep) = 1;
00145 memcpy((u_int8_t *)pagep + P_OVERHEAD(file_dbp), argp->dbt.data,
00146 argp->dbt.size);
00147 PREV_PGNO(pagep) = argp->prev_pgno;
00148 change = DB_MPOOL_DIRTY;
00149 } else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||
00150 (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {
00151
00152
00153
00154
00155
00156 change = DB_MPOOL_DIRTY;
00157 }
00158 if (change)
00159 LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
00160
00161 if ((ret = __memp_fput(mpf, pagep, change)) != 0)
00162 goto out;
00163 pagep = NULL;
00164
00165
00166
00167
00168
00169 if (argp->opcode == DB_REM_BIG)
00170 goto done;
00171
00172
00173 ppage: if (argp->prev_pgno != PGNO_INVALID) {
00174 change = 0;
00175 REC_FGET(mpf, argp->prev_pgno, &pagep, npage);
00176
00177 cmp_n = log_compare(lsnp, &LSN(pagep));
00178 cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
00179 CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->prevlsn);
00180
00181 if (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) {
00182
00183 NEXT_PGNO(pagep) = argp->pgno;
00184 change = DB_MPOOL_DIRTY;
00185 } else if (cmp_n == 0 &&
00186 DB_UNDO(op) && argp->opcode == DB_ADD_BIG) {
00187
00188 NEXT_PGNO(pagep) = argp->next_pgno;
00189 change = DB_MPOOL_DIRTY;
00190 }
00191 if (change)
00192 LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
00193 if ((ret = __memp_fput(mpf, pagep, change)) != 0)
00194 goto out;
00195 }
00196 pagep = NULL;
00197
00198
00199 npage: if (argp->next_pgno != PGNO_INVALID) {
00200 change = 0;
00201 REC_FGET(mpf, argp->next_pgno, &pagep, done);
00202
00203 cmp_n = log_compare(lsnp, &LSN(pagep));
00204 cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
00205 CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->nextlsn);
00206 if (cmp_p == 0 && DB_REDO(op)) {
00207 PREV_PGNO(pagep) = PGNO_INVALID;
00208 change = DB_MPOOL_DIRTY;
00209 } else if (cmp_n == 0 && DB_UNDO(op)) {
00210 PREV_PGNO(pagep) = argp->pgno;
00211 change = DB_MPOOL_DIRTY;
00212 }
00213 if (change)
00214 LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
00215 if ((ret = __memp_fput(mpf, pagep, change)) != 0)
00216 goto out;
00217 }
00218 pagep = NULL;
00219
00220 done: *lsnp = argp->prev_lsn;
00221 ret = 0;
00222
00223 out: if (pagep != NULL)
00224 (void)__memp_fput(mpf, pagep, 0);
00225 REC_CLOSE;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235 int
00236 __db_ovref_recover(dbenv, dbtp, lsnp, op, info)
00237 DB_ENV *dbenv;
00238 DBT *dbtp;
00239 DB_LSN *lsnp;
00240 db_recops op;
00241 void *info;
00242 {
00243 __db_ovref_args *argp;
00244 DB *file_dbp;
00245 DBC *dbc;
00246 DB_MPOOLFILE *mpf;
00247 PAGE *pagep;
00248 int cmp, modified, ret;
00249
00250 pagep = NULL;
00251 COMPQUIET(info, NULL);
00252 REC_PRINT(__db_ovref_print);
00253 REC_INTRO(__db_ovref_read, 1, 0);
00254
00255 REC_FGET(mpf, argp->pgno, &pagep, done);
00256
00257 modified = 0;
00258 cmp = log_compare(&LSN(pagep), &argp->lsn);
00259 CHECK_LSN(dbenv, op, cmp, &LSN(pagep), &argp->lsn);
00260 if (cmp == 0 && DB_REDO(op)) {
00261
00262 OV_REF(pagep) += argp->adjust;
00263
00264 pagep->lsn = *lsnp;
00265 modified = 1;
00266 } else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
00267
00268 OV_REF(pagep) -= argp->adjust;
00269
00270 pagep->lsn = argp->lsn;
00271 modified = 1;
00272 }
00273 if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
00274 goto out;
00275 pagep = NULL;
00276
00277 done: *lsnp = argp->prev_lsn;
00278 ret = 0;
00279
00280 out: if (pagep != NULL)
00281 (void)__memp_fput(mpf, pagep, 0);
00282 REC_CLOSE;
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292 int
00293 __db_debug_recover(dbenv, dbtp, lsnp, op, info)
00294 DB_ENV *dbenv;
00295 DBT *dbtp;
00296 DB_LSN *lsnp;
00297 db_recops op;
00298 void *info;
00299 {
00300 __db_debug_args *argp;
00301 int ret;
00302
00303 COMPQUIET(dbenv, NULL);
00304 COMPQUIET(op, DB_TXN_ABORT);
00305 COMPQUIET(info, NULL);
00306
00307 REC_PRINT(__db_debug_print);
00308 REC_NOOP_INTRO(__db_debug_read);
00309
00310 *lsnp = argp->prev_lsn;
00311 ret = 0;
00312
00313 REC_NOOP_CLOSE;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323 int
00324 __db_noop_recover(dbenv, dbtp, lsnp, op, info)
00325 DB_ENV *dbenv;
00326 DBT *dbtp;
00327 DB_LSN *lsnp;
00328 db_recops op;
00329 void *info;
00330 {
00331 __db_noop_args *argp;
00332 DB *file_dbp;
00333 DBC *dbc;
00334 DB_MPOOLFILE *mpf;
00335 PAGE *pagep;
00336 u_int32_t change;
00337 int cmp_n, cmp_p, ret;
00338
00339 pagep = NULL;
00340 COMPQUIET(info, NULL);
00341 REC_PRINT(__db_noop_print);
00342 REC_INTRO(__db_noop_read, 0, 0);
00343
00344 REC_FGET(mpf, argp->pgno, &pagep, done);
00345
00346 cmp_n = log_compare(lsnp, &LSN(pagep));
00347 cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
00348 CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->prevlsn);
00349 change = 0;
00350 if (cmp_p == 0 && DB_REDO(op)) {
00351 LSN(pagep) = *lsnp;
00352 change = DB_MPOOL_DIRTY;
00353 } else if (cmp_n == 0 && DB_UNDO(op)) {
00354 LSN(pagep) = argp->prevlsn;
00355 change = DB_MPOOL_DIRTY;
00356 }
00357 ret = __memp_fput(mpf, pagep, change);
00358 pagep = NULL;
00359
00360 done: *lsnp = argp->prev_lsn;
00361 out: if (pagep != NULL)
00362 (void)__memp_fput(mpf, pagep, 0);
00363 REC_CLOSE;
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373 int
00374 __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
00375 DB_ENV *dbenv;
00376 DBT *dbtp;
00377 DB_LSN *lsnp;
00378 db_recops op;
00379 void *info;
00380 {
00381 __db_pg_alloc_args *argp;
00382 DB *file_dbp;
00383 DBC *dbc;
00384 DBMETA *meta;
00385 DB_MPOOLFILE *mpf;
00386 PAGE *pagep;
00387 db_pgno_t pgno;
00388 int cmp_n, cmp_p, created, level, meta_modified, modified, ret;
00389
00390 meta = NULL;
00391 pagep = NULL;
00392 created = meta_modified = modified = 0;
00393 REC_PRINT(__db_pg_alloc_print);
00394 REC_INTRO(__db_pg_alloc_read, 0, 0);
00395
00396
00397
00398
00399
00400
00401
00402 pgno = PGNO_BASE_MD;
00403 if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
00404
00405 if (DB_REDO(op)) {
00406 ret = __db_pgerr(file_dbp, pgno, ret);
00407 goto out;
00408 } else
00409 goto done;
00410 }
00411 cmp_n = log_compare(lsnp, &LSN(meta));
00412 cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
00413 CHECK_LSN(dbenv, op, cmp_p, &LSN(meta), &argp->meta_lsn);
00414 if (cmp_p == 0 && DB_REDO(op)) {
00415
00416 LSN(meta) = *lsnp;
00417 meta->free = argp->next;
00418 meta_modified = 1;
00419 if (argp->pgno > meta->last_pgno)
00420 meta->last_pgno = argp->pgno;
00421 } else if (cmp_n == 0 && DB_UNDO(op)) {
00422
00423 LSN(meta) = argp->meta_lsn;
00424
00425
00426
00427
00428
00429 if (!IS_ZERO_LSN(argp->page_lsn))
00430 meta->free = argp->pgno;
00431 #ifdef HAVE_FTRUNCATE
00432
00433
00434
00435
00436
00437 meta->last_pgno = argp->last_pgno;
00438 #endif
00439 meta_modified = 1;
00440 }
00441
00442 #ifdef HAVE_FTRUNCATE
00443
00444
00445
00446
00447
00448 if (op == DB_TXN_ABORT && !IS_ZERO_LSN(argp->page_lsn)) {
00449 db_pgno_t *list;
00450 u_int32_t nelem;
00451
00452 if ((ret = __memp_get_freelist(mpf, &nelem, &list)) != 0)
00453 goto out;
00454 if (list != NULL) {
00455 if ((ret =
00456 __memp_extend_freelist(mpf, nelem + 1, &list)) != 0)
00457 goto out;
00458 if (nelem != 0)
00459 memmove(list + 1, list, nelem * sizeof(list));
00460 *list = argp->pgno;
00461 }
00462 }
00463 #endif
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
00474
00475
00476
00477
00478
00479
00480
00481
00482 #ifdef HAVE_FTRUNCATE
00483 if (DB_UNDO(op))
00484 goto do_truncate;
00485 #endif
00486 if ((ret = __memp_fget(
00487 mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
00488 if (DB_UNDO(op) && ret == ENOSPC)
00489 goto do_truncate;
00490 ret = __db_pgerr(file_dbp, argp->pgno, ret);
00491 goto out;
00492 }
00493 created = modified = 1;
00494 }
00495
00496
00497 cmp_n = log_compare(lsnp, &LSN(pagep));
00498 cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
00499
00500
00501
00502
00503
00504
00505
00506
00507 if (IS_ZERO_LSN(LSN(pagep)) ||
00508 (IS_ZERO_LSN(argp->page_lsn) && IS_INIT_LSN(LSN(pagep))))
00509 cmp_p = 0;
00510
00511 CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->page_lsn);
00512
00513
00514
00515
00516
00517
00518 if (DB_REDO(op) && cmp_p == 0) {
00519
00520 switch (argp->ptype) {
00521 case P_LBTREE:
00522 case P_LRECNO:
00523 case P_LDUP:
00524 level = LEAFLEVEL;
00525 break;
00526 default:
00527 level = 0;
00528 break;
00529 }
00530 P_INIT(pagep, file_dbp->pgsize,
00531 argp->pgno, PGNO_INVALID, PGNO_INVALID, level, argp->ptype);
00532
00533 pagep->lsn = *lsnp;
00534 modified = 1;
00535 } else if (DB_UNDO(op) && (cmp_n == 0 || created)) {
00536
00537
00538
00539
00540
00541
00542 P_INIT(pagep, file_dbp->pgsize,
00543 argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
00544
00545 pagep->lsn = argp->page_lsn;
00546 modified = 1;
00547 }
00548
00549 do_truncate:
00550
00551
00552
00553
00554 if ((pagep == NULL || IS_ZERO_LSN(LSN(pagep))) &&
00555 IS_ZERO_LSN(argp->page_lsn) && DB_UNDO(op)) {
00556 #ifdef HAVE_FTRUNCATE
00557 COMPQUIET(info, NULL);
00558
00559 if (pagep != NULL) {
00560 if ((ret =
00561 __memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0)
00562 goto out;
00563 pagep = NULL;
00564
00565 if (meta->last_pgno <= argp->pgno &&
00566 (ret = __memp_ftruncate(mpf, argp->pgno, 0)) != 0)
00567 goto out;
00568 }
00569 #else
00570
00571 if ((ret = __db_add_limbo(dbenv,
00572 info, argp->fileid, argp->pgno, 1)) != 0)
00573 goto out;
00574
00575 if (argp->pgno > meta->last_pgno) {
00576 meta->last_pgno = argp->pgno;
00577 meta_modified = 1;
00578 }
00579 #endif
00580 }
00581
00582 if (pagep != NULL &&
00583 (ret = __memp_fput(mpf,
00584 pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
00585 goto out;
00586 pagep = NULL;
00587
00588 if ((ret = __memp_fput(mpf,
00589 meta, meta_modified ? DB_MPOOL_DIRTY : 0)) != 0)
00590 goto out;
00591 meta = NULL;
00592
00593 done: *lsnp = argp->prev_lsn;
00594 ret = 0;
00595
00596 out: if (pagep != NULL)
00597 (void)__memp_fput(mpf, pagep, 0);
00598 if (meta != NULL)
00599 (void)__memp_fput(mpf, meta, 0);
00600 if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
00601 ret = 0;
00602 REC_CLOSE;
00603 }
00604
00605
00606
00607
00608 static int
00609 __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
00610 DB_ENV *dbenv;
00611 __db_pg_freedata_args *argp;
00612 DB *file_dbp;
00613 DB_LSN *lsnp;
00614 DB_MPOOLFILE *mpf;
00615 db_recops op;
00616 int data;
00617 {
00618 DBMETA *meta;
00619 DB_LSN copy_lsn;
00620 PAGE *pagep, *prevp;
00621 int cmp_n, cmp_p, is_meta, meta_modified, modified, ret;
00622
00623 meta = NULL;
00624 pagep = NULL;
00625 prevp = NULL;
00626 meta_modified = modified = 0;
00627
00628
00629
00630
00631
00632
00633
00634 is_meta = argp->meta_pgno == PGNO_BASE_MD;
00635
00636 REC_FGET(mpf, argp->meta_pgno, &meta, check_meta);
00637
00638 if (argp->meta_pgno != PGNO_BASE_MD)
00639 prevp = (PAGE *)meta;
00640
00641 cmp_n = log_compare(lsnp, &LSN(meta));
00642 cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
00643 CHECK_LSN(dbenv, op, cmp_p, &LSN(meta), &argp->meta_lsn);
00644
00645
00646
00647
00648
00649 if (cmp_p == 0 && DB_REDO(op)) {
00650 #ifdef HAVE_FTRUNCATE
00651
00652
00653
00654
00655 if (argp->pgno == argp->last_pgno)
00656 meta->last_pgno = argp->pgno - 1;
00657 else if (prevp == NULL)
00658 meta->free = argp->pgno;
00659 else
00660 NEXT_PGNO(prevp) = argp->pgno;
00661 #else
00662
00663 if (prevp == NULL)
00664 meta->free = argp->pgno;
00665 else
00666 NEXT_PGNO(prevp) = argp->pgno;
00667
00668
00669
00670
00671
00672 if (prevp == NULL && meta->last_pgno < meta->free)
00673 meta->last_pgno = meta->free;
00674 #endif
00675 LSN(meta) = *lsnp;
00676 meta_modified = 1;
00677 } else if (cmp_n == 0 && DB_UNDO(op)) {
00678
00679 if (prevp == NULL)
00680 meta->free = argp->next;
00681 else
00682 NEXT_PGNO(prevp) = argp->next;
00683 LSN(meta) = argp->meta_lsn;
00684 if (prevp == NULL && meta->last_pgno < argp->pgno)
00685 meta->last_pgno = argp->pgno;
00686 meta_modified = 1;
00687 }
00688
00689 check_meta:
00690 if (ret != 0 && is_meta) {
00691
00692 ret = __db_pgerr(file_dbp, argp->meta_pgno, ret);
00693 goto out;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 #ifdef HAVE_FTRUNCATE
00706 if (DB_REDO(op) || (is_meta && meta->last_pgno < argp->pgno)) {
00707 if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
00708 if (ret == DB_PAGE_NOTFOUND)
00709 goto done;
00710 goto out;
00711 }
00712 } else
00713 #endif
00714 if ((ret =
00715 __memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
00716 goto out;
00717
00718 (void)__ua_memcpy(©_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
00719 cmp_n = IS_ZERO_LSN(LSN(pagep)) ? 0 : log_compare(lsnp, &LSN(pagep));
00720 cmp_p = log_compare(&LSN(pagep), ©_lsn);
00721
00722 #ifdef HAVE_FTRUNCATE
00723
00724
00725
00726
00727
00728 if (IS_ZERO_LSN(LSN(pagep)))
00729 cmp_p = 0;
00730 #endif
00731
00732 CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), ©_lsn);
00733 if (DB_REDO(op) &&
00734 (cmp_p == 0 ||
00735 (IS_ZERO_LSN(copy_lsn) &&
00736 log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
00737
00738 #ifdef HAVE_FTRUNCATE
00739
00740
00741
00742
00743 if (is_meta && meta->last_pgno <= argp->pgno &&
00744 argp->last_pgno <= argp->pgno) {
00745 if ((ret =
00746 __memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0)
00747 goto out;
00748 pagep = NULL;
00749 if ((ret = __memp_ftruncate(mpf, argp->pgno, 0)) != 0)
00750 goto out;
00751 } else if (argp->last_pgno == argp->pgno) {
00752
00753 P_INIT(pagep, 0, PGNO_INVALID,
00754 PGNO_INVALID, PGNO_INVALID, 0, P_INVALID);
00755 ZERO_LSN(pagep->lsn);
00756 modified = 1;
00757 } else
00758 #endif
00759 {
00760 P_INIT(pagep, file_dbp->pgsize,
00761 argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
00762 pagep->lsn = *lsnp;
00763
00764 modified = 1;
00765 }
00766 } else if (cmp_n == 0 && DB_UNDO(op)) {
00767
00768 memcpy(pagep, argp->header.data, argp->header.size);
00769 if (data)
00770 memcpy((u_int8_t*)pagep + HOFFSET(pagep),
00771 argp->data.data, argp->data.size);
00772
00773 modified = 1;
00774 }
00775 if (pagep != NULL &&
00776 (ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
00777 goto out;
00778
00779 pagep = NULL;
00780 #ifdef HAVE_FTRUNCATE
00781
00782
00783
00784
00785 if (op == DB_TXN_ABORT && argp->pgno != argp->last_pgno) {
00786 db_pgno_t *lp;
00787 u_int32_t nelem, pos;
00788
00789 if ((ret = __memp_get_freelist(mpf, &nelem, &lp)) != 0)
00790 goto out;
00791 if (lp != NULL) {
00792 pos = 0;
00793 if (!is_meta && nelem != 0) {
00794 __db_freelist_pos(argp->pgno, lp, nelem, &pos);
00795
00796 DB_ASSERT(argp->pgno == lp[pos]);
00797 DB_ASSERT(argp->meta_pgno == lp[pos - 1]);
00798 }
00799
00800 if (nelem != 0 && pos != nelem)
00801 memmove(&lp[pos], &lp[pos + 1],
00802 (nelem - pos) * sizeof(*lp));
00803
00804
00805 if ((ret =
00806 __memp_extend_freelist(mpf, nelem - 1, &lp)) != 0)
00807 goto out;
00808 }
00809 }
00810 done:
00811 #endif
00812 if (meta != NULL && (ret = __memp_fput(mpf,
00813 meta, meta_modified ? DB_MPOOL_DIRTY : 0)) != 0)
00814 goto out;
00815 meta = NULL;
00816
00817 ret = 0;
00818
00819 out: if (pagep != NULL)
00820 (void)__memp_fput(mpf, pagep, 0);
00821 if (meta != NULL)
00822 (void)__memp_fput(mpf, meta, 0);
00823
00824 return (ret);
00825 }
00826
00827
00828
00829
00830
00831
00832
00833
00834 int
00835 __db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
00836 DB_ENV *dbenv;
00837 DBT *dbtp;
00838 DB_LSN *lsnp;
00839 db_recops op;
00840 void *info;
00841 {
00842 DB *file_dbp;
00843 DBC *dbc;
00844 DB_MPOOLFILE *mpf;
00845 __db_pg_free_args *argp;
00846 int ret;
00847
00848 COMPQUIET(info, NULL);
00849 REC_PRINT(__db_pg_free_print);
00850 REC_INTRO(__db_pg_free_read, 1, 0);
00851
00852 ret = __db_pg_free_recover_int(dbenv,
00853 (__db_pg_freedata_args *)argp, file_dbp, lsnp, mpf, op, 0);
00854
00855 done: *lsnp = argp->prev_lsn;
00856 out:
00857 REC_CLOSE;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 int
00869 __db_pg_new_recover(dbenv, dbtp, lsnp, op, info)
00870 DB_ENV *dbenv;
00871 DBT *dbtp;
00872 DB_LSN *lsnp;
00873 db_recops op;
00874 void *info;
00875 {
00876 #ifndef HAVE_FTRUNCATE
00877 DB *file_dbp;
00878 DBC *dbc;
00879 DB_MPOOLFILE *mpf;
00880 __db_pg_free_args *argp;
00881 int ret;
00882
00883 REC_PRINT(__db_pg_free_print);
00884 REC_INTRO(__db_pg_free_read, 1, 0);
00885 COMPQUIET(op, DB_TXN_ABORT);
00886
00887 if ((ret =
00888 __db_add_limbo(dbenv, info, argp->fileid, argp->pgno, 1)) == 0)
00889 *lsnp = argp->prev_lsn;
00890
00891 done:
00892 out:
00893 REC_CLOSE;
00894 #else
00895 COMPQUIET(dbenv, NULL);
00896 COMPQUIET(dbtp, NULL);
00897 COMPQUIET(lsnp, NULL);
00898 COMPQUIET(op, DB_TXN_PRINT);
00899 COMPQUIET(info, NULL);
00900 return (0);
00901 #endif
00902 }
00903
00904
00905
00906
00907
00908
00909
00910
00911 int
00912 __db_pg_freedata_recover(dbenv, dbtp, lsnp, op, info)
00913 DB_ENV *dbenv;
00914 DBT *dbtp;
00915 DB_LSN *lsnp;
00916 db_recops op;
00917 void *info;
00918 {
00919 DB *file_dbp;
00920 DBC *dbc;
00921 DB_MPOOLFILE *mpf;
00922 __db_pg_freedata_args *argp;
00923 int ret;
00924
00925 COMPQUIET(info, NULL);
00926 REC_PRINT(__db_pg_freedata_print);
00927 REC_INTRO(__db_pg_freedata_read, 1, 0);
00928
00929 ret = __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, 1);
00930
00931 done: *lsnp = argp->prev_lsn;
00932 out:
00933 REC_CLOSE;
00934 }
00935
00936
00937
00938
00939
00940
00941
00942
00943 int
00944 __db_cksum_recover(dbenv, dbtp, lsnp, op, info)
00945 DB_ENV *dbenv;
00946 DBT *dbtp;
00947 DB_LSN *lsnp;
00948 db_recops op;
00949 void *info;
00950 {
00951 __db_cksum_args *argp;
00952
00953 int ret;
00954
00955 COMPQUIET(info, NULL);
00956 COMPQUIET(lsnp, NULL);
00957 COMPQUIET(op, DB_TXN_ABORT);
00958
00959 REC_PRINT(__db_cksum_print);
00960
00961 if ((ret = __db_cksum_read(dbenv, dbtp->data, &argp)) != 0)
00962 return (ret);
00963
00964
00965
00966
00967
00968 if (F_ISSET(dbenv, DB_ENV_FATAL))
00969 ret = 0;
00970 else {
00971 __db_err(dbenv,
00972 "Checksum failure requires catastrophic recovery");
00973 ret = __db_panic(dbenv, DB_RUNRECOVERY);
00974 }
00975
00976 __os_free(dbenv, argp);
00977 return (ret);
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987 int
00988 __db_pg_prepare_recover(dbenv, dbtp, lsnp, op, info)
00989 DB_ENV *dbenv;
00990 DBT *dbtp;
00991 DB_LSN *lsnp;
00992 db_recops op;
00993 void *info;
00994 {
00995 #ifndef HAVE_FTRUNCATE
00996 __db_pg_prepare_args *argp;
00997 DB *file_dbp;
00998 DBC *dbc;
00999 DB_MPOOLFILE *mpf;
01000 PAGE *pagep;
01001 int ret, t_ret;
01002
01003 REC_PRINT(__db_pg_prepare_print);
01004 REC_INTRO(__db_pg_prepare_read, 1, 0);
01005
01006 mpf = file_dbp->mpf;
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 if (op == DB_TXN_ABORT) {
01025 if ((ret = __memp_fget(
01026 mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
01027 goto out;
01028 P_INIT(pagep, file_dbp->pgsize,
01029 argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, P_INVALID);
01030 ZERO_LSN(pagep->lsn);
01031 ret = __db_add_limbo(dbenv, info, argp->fileid, argp->pgno, 1);
01032 if ((t_ret =
01033 __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
01034 ret = t_ret;
01035 }
01036
01037 done: if (ret == 0)
01038 *lsnp = argp->prev_lsn;
01039 out: REC_CLOSE;
01040 #else
01041 COMPQUIET(dbenv, NULL);
01042 COMPQUIET(dbtp, NULL);
01043 COMPQUIET(lsnp, NULL);
01044 COMPQUIET(op, DB_TXN_PRINT);
01045 COMPQUIET(info, NULL);
01046 return (0);
01047 #endif
01048
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058 int
01059 __db_pg_init_recover(dbenv, dbtp, lsnp, op, info)
01060 DB_ENV *dbenv;
01061 DBT *dbtp;
01062 DB_LSN *lsnp;
01063 db_recops op;
01064 void *info;
01065 {
01066 __db_pg_init_args *argp;
01067 DB *file_dbp;
01068 DBC *dbc;
01069 DB_LSN copy_lsn;
01070 DB_MPOOLFILE *mpf;
01071 PAGE *pagep;
01072 int cmp_n, cmp_p, modified, ret, type;
01073
01074 COMPQUIET(info, NULL);
01075 REC_PRINT(__db_pg_init_print);
01076 REC_INTRO(__db_pg_init_read, 1, 0);
01077
01078 mpf = file_dbp->mpf;
01079 REC_FGET(mpf, argp->pgno, &pagep, done);
01080
01081 modified = 0;
01082 (void)__ua_memcpy(©_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
01083 cmp_n = log_compare(lsnp, &LSN(pagep));
01084 cmp_p = log_compare(&LSN(pagep), ©_lsn);
01085 CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), ©_lsn);
01086
01087 if (cmp_p == 0 && DB_REDO(op)) {
01088 if (TYPE(pagep) == P_HASH)
01089 type = P_HASH;
01090 else
01091 type = file_dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE;
01092 P_INIT(pagep, file_dbp->pgsize, PGNO(pagep), PGNO_INVALID,
01093 PGNO_INVALID, TYPE(pagep) == P_HASH ? 0 : 1, type);
01094 pagep->lsn = *lsnp;
01095 modified = 1;
01096 } else if (cmp_n == 0 && DB_UNDO(op)) {
01097
01098 memcpy(pagep, argp->header.data, argp->header.size);
01099 if (argp->data.size > 0)
01100 memcpy((u_int8_t*)pagep + HOFFSET(pagep),
01101 argp->data.data, argp->data.size);
01102
01103 modified = 1;
01104 }
01105 if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
01106 goto out;
01107
01108 done: *lsnp = argp->prev_lsn;
01109 out:
01110 REC_CLOSE;
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120 int
01121 __db_pg_sort_recover(dbenv, dbtp, lsnp, op, info)
01122 DB_ENV *dbenv;
01123 DBT *dbtp;
01124 DB_LSN *lsnp;
01125 db_recops op;
01126 void *info;
01127 {
01128 #ifdef HAVE_FTRUNCATE
01129 __db_pg_sort_args *argp;
01130 DB *file_dbp;
01131 DBC *dbc;
01132 DBMETA *meta;
01133 DB_MPOOLFILE *mpf;
01134 PAGE *pagep;
01135 db_pgno_t pgno, *list;
01136 u_int32_t felem, nelem;
01137 struct pglist *pglist, *lp;
01138 int modified, ret;
01139
01140 COMPQUIET(info, NULL);
01141
01142 REC_PRINT(__db_pg_sort_print);
01143 REC_INTRO(__db_pg_sort_read, 1, 1);
01144
01145 modified = 0;
01146
01147 pglist = (struct pglist *) argp->list.data;
01148 nelem = argp->list.size / sizeof(struct pglist);
01149 if (DB_REDO(op)) {
01150 pgno = argp->last_pgno;
01151 if ((ret = __db_pg_truncate(mpf,
01152 pglist, NULL, &nelem, &pgno, lsnp, 1)) != 0)
01153 goto out;
01154
01155 if (argp->last_free != PGNO_INVALID) {
01156 if ((ret = __memp_fget(mpf,
01157 &argp->last_free, 0, &meta)) == 0) {
01158 if (log_compare(&LSN(meta),
01159 &argp->last_lsn) == 0) {
01160 NEXT_PGNO(meta) = PGNO_INVALID;
01161 LSN(meta) = *lsnp;
01162 modified = 1;
01163 }
01164 if ((ret = __memp_fput(mpf,
01165 meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
01166 goto out;
01167 meta = NULL;
01168 modified = 0;
01169 } else if (ret != DB_PAGE_NOTFOUND)
01170 goto out;
01171 }
01172 if ((ret = __memp_fget(mpf, &argp->meta, 0, &meta)) != 0)
01173 goto out;
01174 if (log_compare(&LSN(meta), &argp->meta_lsn) == 0) {
01175 if (argp->last_free == PGNO_INVALID) {
01176 if (nelem == 0)
01177 meta->free = PGNO_INVALID;
01178 else
01179 meta->free = pglist->pgno;
01180 }
01181 meta->last_pgno = pgno;
01182 LSN(meta) = *lsnp;
01183 modified = 1;
01184 }
01185 } else {
01186
01187 for (lp = pglist; lp < &pglist[nelem]; lp++) {
01188 if ((ret = __memp_fget(mpf,
01189 &lp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
01190 goto out;
01191 if (IS_ZERO_LSN(LSN(pagep)) ||
01192 log_compare(&LSN(pagep), lsnp) == 0) {
01193 if (lp == &pglist[nelem - 1])
01194 pgno = PGNO_INVALID;
01195 else
01196 pgno = lp[1].pgno;
01197
01198 P_INIT(pagep, file_dbp->pgsize,
01199 lp->pgno, PGNO_INVALID, pgno, 0, P_INVALID);
01200 LSN(pagep) = lp->lsn;
01201 modified = 1;
01202 }
01203 if ((ret = __memp_fput(mpf,
01204 pagep, modified ? DB_MPOOL_DIRTY: 0)) != 0)
01205 goto out;
01206 }
01207 if (argp->last_free != PGNO_INVALID) {
01208 if ((ret = __memp_fget(mpf,
01209 &argp->last_free, 0, &meta)) == 0) {
01210 if (log_compare(&LSN(meta), lsnp) == 0) {
01211 NEXT_PGNO(meta) = pglist->pgno;
01212 LSN(meta) = argp->last_lsn;
01213 modified = 1;
01214 }
01215 if ((ret = __memp_fput(mpf,
01216 meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
01217 goto out;
01218 } else if (ret != DB_PAGE_NOTFOUND)
01219 goto out;
01220 modified = 0;
01221 meta = NULL;
01222 }
01223 if ((ret = __memp_fget(mpf, &argp->meta, 0, &meta)) != 0)
01224 goto out;
01225 if (log_compare(&LSN(meta), lsnp) == 0) {
01226 meta->last_pgno = argp->last_pgno;
01227 if (argp->last_pgno == PGNO_INVALID)
01228 meta->free = pglist->pgno;
01229 LSN(meta) = argp->meta_lsn;
01230 modified = 1;
01231 }
01232 }
01233 if (op == DB_TXN_ABORT) {
01234 if ((ret = __memp_get_freelist(mpf, &felem, &list)) != 0)
01235 goto out;
01236 if (list != NULL) {
01237 DB_ASSERT(felem == 0 ||
01238 argp->last_free == list[felem - 1]);
01239 if ((ret = __memp_extend_freelist(
01240 mpf, felem + nelem, &list)) != 0)
01241 goto out;
01242 for (lp = pglist; lp < &pglist[nelem]; lp++)
01243 list[felem++] = lp->pgno;
01244 }
01245 }
01246
01247 if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
01248 goto out;
01249
01250 done: *lsnp = argp->prev_lsn;
01251 ret = 0;
01252
01253 out: REC_CLOSE;
01254 #else
01255
01256
01257
01258
01259 COMPQUIET(dbenv, NULL);
01260 COMPQUIET(dbtp, NULL);
01261 COMPQUIET(lsnp, NULL);
01262 COMPQUIET(op, DB_TXN_ABORT);
01263 COMPQUIET(info, NULL);
01264 return (EINVAL);
01265 #endif
01266 }