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/crypto.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/hmac.h"
00022 #include "dbinc/log.h"
00023 #include "dbinc/hash.h"
00024
00025 typedef enum { L_ALREADY, L_ACQUIRED, L_NONE } RLOCK;
00026
00027 static int __log_c_close_pp __P((DB_LOGC *, u_int32_t));
00028 static int __log_c_get_pp __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
00029 static int __log_c_get_int __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
00030 static int __log_c_hdrchk __P((DB_LOGC *, DB_LSN *, HDR *, int *));
00031 static int __log_c_incursor __P((DB_LOGC *, DB_LSN *, HDR *, u_int8_t **));
00032 static int __log_c_inregion __P((DB_LOGC *,
00033 DB_LSN *, RLOCK *, DB_LSN *, HDR *, u_int8_t **, int *));
00034 static int __log_c_io __P((DB_LOGC *,
00035 u_int32_t, u_int32_t, void *, size_t *, int *));
00036 static int __log_c_ondisk __P((DB_LOGC *,
00037 DB_LSN *, DB_LSN *, u_int32_t, HDR *, u_int8_t **, int *));
00038 static int __log_c_set_maxrec __P((DB_LOGC *, char *));
00039 static int __log_c_shortread __P((DB_LOGC *, DB_LSN *, int));
00040
00041
00042
00043
00044
00045
00046
00047 int
00048 __log_cursor_pp(dbenv, logcp, flags)
00049 DB_ENV *dbenv;
00050 DB_LOGC **logcp;
00051 u_int32_t flags;
00052 {
00053 DB_THREAD_INFO *ip;
00054 int ret;
00055
00056 PANIC_CHECK(dbenv);
00057 ENV_REQUIRES_CONFIG(dbenv,
00058 dbenv->lg_handle, "DB_ENV->log_cursor", DB_INIT_LOG);
00059
00060
00061 if ((ret = __db_fchk(dbenv, "DB_ENV->log_cursor", flags, 0)) != 0)
00062 return (ret);
00063
00064 ENV_ENTER(dbenv, ip);
00065 REPLICATION_WRAP(dbenv, (__log_cursor(dbenv, logcp)), ret);
00066 ENV_LEAVE(dbenv, ip);
00067 return (ret);
00068 }
00069
00070
00071
00072
00073
00074
00075
00076 int
00077 __log_cursor(dbenv, logcp)
00078 DB_ENV *dbenv;
00079 DB_LOGC **logcp;
00080 {
00081 DB_LOGC *logc;
00082 int ret;
00083
00084 *logcp = NULL;
00085
00086
00087 if ((ret = __os_calloc(dbenv, 1, sizeof(DB_LOGC), &logc)) != 0)
00088 return (ret);
00089
00090 logc->bp_size = DB_LOGC_BUF_SIZE;
00091
00092
00093
00094 logc->bp_maxrec = MEGABYTE;
00095 if ((ret = __os_malloc(dbenv, logc->bp_size, &logc->bp)) != 0) {
00096 __os_free(dbenv, logc);
00097 return (ret);
00098 }
00099
00100 logc->dbenv = dbenv;
00101 logc->close = __log_c_close_pp;
00102 logc->get = __log_c_get_pp;
00103
00104 *logcp = logc;
00105 return (0);
00106 }
00107
00108
00109
00110
00111
00112 static int
00113 __log_c_close_pp(logc, flags)
00114 DB_LOGC *logc;
00115 u_int32_t flags;
00116 {
00117 DB_THREAD_INFO *ip;
00118 DB_ENV *dbenv;
00119 int ret;
00120
00121 dbenv = logc->dbenv;
00122
00123 PANIC_CHECK(dbenv);
00124 if ((ret = __db_fchk(dbenv, "DB_LOGC->close", flags, 0)) != 0)
00125 return (ret);
00126
00127 ENV_ENTER(dbenv, ip);
00128 REPLICATION_WRAP(dbenv, (__log_c_close(logc)), ret);
00129 ENV_LEAVE(dbenv, ip);
00130 return (ret);
00131 }
00132
00133
00134
00135
00136
00137
00138
00139 int
00140 __log_c_close(logc)
00141 DB_LOGC *logc;
00142 {
00143 DB_ENV *dbenv;
00144
00145 dbenv = logc->dbenv;
00146
00147 if (logc->c_fhp != NULL) {
00148 (void)__os_closehandle(dbenv, logc->c_fhp);
00149 logc->c_fhp = NULL;
00150 }
00151
00152 if (logc->c_dbt.data != NULL)
00153 __os_free(dbenv, logc->c_dbt.data);
00154
00155 __os_free(dbenv, logc->bp);
00156 __os_free(dbenv, logc);
00157
00158 return (0);
00159 }
00160
00161
00162
00163
00164
00165 static int
00166 __log_c_get_pp(logc, alsn, dbt, flags)
00167 DB_LOGC *logc;
00168 DB_LSN *alsn;
00169 DBT *dbt;
00170 u_int32_t flags;
00171 {
00172 DB_ENV *dbenv;
00173 DB_THREAD_INFO *ip;
00174 int ret;
00175
00176 dbenv = logc->dbenv;
00177
00178 PANIC_CHECK(dbenv);
00179
00180
00181 switch (flags) {
00182 case DB_CURRENT:
00183 case DB_FIRST:
00184 case DB_LAST:
00185 case DB_NEXT:
00186 case DB_PREV:
00187 break;
00188 case DB_SET:
00189 if (IS_ZERO_LSN(*alsn)) {
00190 __db_err(dbenv, "DB_LOGC->get: invalid LSN: %lu/%lu",
00191 (u_long)alsn->file, (u_long)alsn->offset);
00192 return (EINVAL);
00193 }
00194 break;
00195 default:
00196 return (__db_ferr(dbenv, "DB_LOGC->get", 1));
00197 }
00198
00199 ENV_ENTER(dbenv, ip);
00200 REPLICATION_WRAP(dbenv, (__log_c_get(logc, alsn, dbt, flags)), ret);
00201 ENV_LEAVE(dbenv, ip);
00202 return (ret);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211 int
00212 __log_c_get(logc, alsn, dbt, flags)
00213 DB_LOGC *logc;
00214 DB_LSN *alsn;
00215 DBT *dbt;
00216 u_int32_t flags;
00217 {
00218 DB_ENV *dbenv;
00219 DB_LSN saved_lsn;
00220 int ret;
00221
00222 dbenv = logc->dbenv;
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 saved_lsn = *alsn;
00239
00240
00241
00242
00243
00244
00245 if ((ret = __log_c_get_int(logc, alsn, dbt, flags)) != 0) {
00246 *alsn = saved_lsn;
00247 return (ret);
00248 }
00249 if (alsn->offset == 0 && (flags == DB_FIRST ||
00250 flags == DB_NEXT || flags == DB_LAST || flags == DB_PREV)) {
00251 switch (flags) {
00252 case DB_FIRST:
00253 flags = DB_NEXT;
00254 break;
00255 case DB_LAST:
00256 flags = DB_PREV;
00257 break;
00258 case DB_NEXT:
00259 case DB_PREV:
00260 default:
00261 break;
00262 }
00263 if (F_ISSET(dbt, DB_DBT_MALLOC)) {
00264 __os_free(dbenv, dbt->data);
00265 dbt->data = NULL;
00266 }
00267 if ((ret = __log_c_get_int(logc, alsn, dbt, flags)) != 0) {
00268 *alsn = saved_lsn;
00269 return (ret);
00270 }
00271 }
00272
00273 return (0);
00274 }
00275
00276
00277
00278
00279
00280 static int
00281 __log_c_get_int(logc, alsn, dbt, flags)
00282 DB_LOGC *logc;
00283 DB_LSN *alsn;
00284 DBT *dbt;
00285 u_int32_t flags;
00286 {
00287 DB_CIPHER *db_cipher;
00288 DB_ENV *dbenv;
00289 DB_LOG *dblp;
00290 DB_LSN last_lsn, nlsn;
00291 HDR hdr;
00292 LOG *lp;
00293 RLOCK rlock;
00294 logfile_validity status;
00295 u_int32_t cnt;
00296 u_int8_t *rp;
00297 int eof, is_hmac, need_cksum, ret;
00298
00299 dbenv = logc->dbenv;
00300 db_cipher = dbenv->crypto_handle;
00301 dblp = dbenv->lg_handle;
00302 lp = dblp->reginfo.primary;
00303 is_hmac = 0;
00304
00305
00306
00307
00308
00309 rlock = F_ISSET(logc, DB_LOG_LOCKED) ? L_ALREADY : L_NONE;
00310
00311 nlsn = logc->c_lsn;
00312 switch (flags) {
00313 case DB_NEXT:
00314 if (!IS_ZERO_LSN(nlsn)) {
00315
00316 nlsn.offset += logc->c_len;
00317 break;
00318 }
00319 flags = DB_FIRST;
00320
00321 case DB_FIRST:
00322
00323 if ((ret = __log_find(dblp, 1, &cnt, &status)) != 0)
00324 goto err;
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 switch (status) {
00343 case DB_LV_INCOMPLETE:
00344 DB_ASSERT(lp->lsn.file == cnt);
00345
00346 case DB_LV_NORMAL:
00347 case DB_LV_OLD_READABLE:
00348 nlsn.file = cnt;
00349 break;
00350 case DB_LV_NONEXISTENT:
00351 nlsn.file = 1;
00352 DB_ASSERT(lp->lsn.file == nlsn.file);
00353 break;
00354 case DB_LV_OLD_UNREADABLE:
00355 nlsn.file = cnt + 1;
00356 DB_ASSERT(lp->lsn.file == nlsn.file);
00357 break;
00358 }
00359 nlsn.offset = 0;
00360 break;
00361 case DB_CURRENT:
00362 break;
00363 case DB_PREV:
00364 if (!IS_ZERO_LSN(nlsn)) {
00365
00366 if (nlsn.offset == 0) {
00367 if (nlsn.file == 1) {
00368 ret = DB_NOTFOUND;
00369 goto err;
00370 }
00371 if ((!lp->db_log_inmemory &&
00372 (__log_valid(dblp, nlsn.file - 1, 0, NULL,
00373 0, &status) != 0 ||
00374 (status != DB_LV_NORMAL &&
00375 status != DB_LV_OLD_READABLE)))) {
00376 ret = DB_NOTFOUND;
00377 goto err;
00378 }
00379
00380 --nlsn.file;
00381 }
00382 nlsn.offset = logc->c_prev;
00383 break;
00384 }
00385
00386 case DB_LAST:
00387 if (rlock == L_NONE) {
00388 rlock = L_ACQUIRED;
00389 LOG_SYSTEM_LOCK(dbenv);
00390 }
00391 nlsn.file = lp->lsn.file;
00392 nlsn.offset = lp->lsn.offset - lp->len;
00393 break;
00394 case DB_SET:
00395 nlsn = *alsn;
00396 break;
00397 default:
00398 DB_ASSERT(0);
00399 ret = EINVAL;
00400 goto err;
00401 }
00402
00403 if (0) {
00404 next_file: ++nlsn.file;
00405 nlsn.offset = 0;
00406 }
00407
00408
00409
00410
00411
00412
00413 if (CRYPTO_ON(dbenv)) {
00414 hdr.size = HDR_CRYPTO_SZ;
00415 is_hmac = 1;
00416 } else {
00417 hdr.size = HDR_NORMAL_SZ;
00418 is_hmac = 0;
00419 }
00420
00421
00422
00423
00424
00425 if ((ret = __log_c_incursor(logc, &nlsn, &hdr, &rp)) != 0)
00426 goto err;
00427 if (rp != NULL)
00428 goto cksum;
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 ZERO_LSN(last_lsn);
00446 if (!F_ISSET(logc, DB_LOG_DISK) ||
00447 log_compare(&nlsn, &logc->c_lsn) > 0) {
00448 F_CLR(logc, DB_LOG_DISK);
00449
00450 if ((ret = __log_c_inregion(logc,
00451 &nlsn, &rlock, &last_lsn, &hdr, &rp, &need_cksum)) != 0)
00452 goto err;
00453 if (rp != NULL) {
00454
00455
00456
00457
00458
00459 if (need_cksum)
00460 goto cksum;
00461 goto from_memory;
00462 }
00463 if (lp->db_log_inmemory)
00464 goto nohdr;
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 if (rlock == L_ACQUIRED) {
00476 rlock = L_NONE;
00477 LOG_SYSTEM_UNLOCK(dbenv);
00478 }
00479 if ((ret = __log_c_ondisk(
00480 logc, &nlsn, &last_lsn, flags, &hdr, &rp, &eof)) != 0)
00481 goto err;
00482 if (eof) {
00483
00484
00485
00486
00487 if (flags != DB_NEXT || nlsn.offset == 0)
00488 return (DB_NOTFOUND);
00489 goto next_file;
00490 }
00491 F_SET(logc, DB_LOG_DISK);
00492
00493 cksum:
00494
00495
00496
00497
00498
00499 if (rlock == L_ACQUIRED) {
00500 rlock = L_NONE;
00501 LOG_SYSTEM_UNLOCK(dbenv);
00502 }
00503
00504
00505
00506
00507
00508
00509
00510 if ((ret = __db_check_chksum(dbenv, db_cipher,
00511 hdr.chksum, rp + hdr.size, hdr.len - hdr.size, is_hmac)) != 0) {
00512 if (F_ISSET(logc, DB_LOG_SILENT_ERR)) {
00513 if (ret == 0 || ret == -1)
00514 ret = EIO;
00515 } else if (ret == -1) {
00516 __db_err(dbenv,
00517 "DB_LOGC->get: log record LSN %lu/%lu: checksum mismatch",
00518 (u_long)nlsn.file, (u_long)nlsn.offset);
00519 __db_err(dbenv,
00520 "DB_LOGC->get: catastrophic recovery may be required");
00521 ret = __db_panic(dbenv, DB_RUNRECOVERY);
00522 }
00523 goto err;
00524 }
00525
00526
00527
00528
00529
00530
00531 if (hdr.len == 0) {
00532 nohdr: switch (flags) {
00533 case DB_FIRST:
00534 case DB_NEXT:
00535
00536 goto next_file;
00537 case DB_LAST:
00538 case DB_PREV:
00539
00540
00541
00542
00543
00544
00545
00546
00547 __db_err(dbenv,
00548 "Encountered zero length records while traversing backwards");
00549 DB_ASSERT(0);
00550 ret = __db_panic(dbenv, DB_RUNRECOVERY);
00551 goto err;
00552 case DB_SET:
00553 default:
00554
00555 break;
00556 }
00557 }
00558
00559 from_memory:
00560
00561
00562
00563
00564
00565
00566 if (rlock == L_ACQUIRED) {
00567 rlock = L_NONE;
00568 LOG_SYSTEM_UNLOCK(dbenv);
00569 }
00570
00571
00572 if ((ret = __db_retcopy(dbenv, dbt, rp + hdr.size,
00573 (u_int32_t)(hdr.len - hdr.size),
00574 &logc->c_dbt.data, &logc->c_dbt.ulen)) != 0)
00575 goto err;
00576
00577 if (CRYPTO_ON(dbenv)) {
00578 if ((ret = db_cipher->decrypt(dbenv, db_cipher->data,
00579 hdr.iv, dbt->data, hdr.len - hdr.size)) != 0) {
00580 ret = EAGAIN;
00581 goto err;
00582 }
00583
00584
00585
00586
00587
00588
00589
00590 dbt->size = hdr.orig_size;
00591 }
00592
00593
00594 *alsn = nlsn;
00595 logc->c_lsn = nlsn;
00596 logc->c_len = hdr.len;
00597 logc->c_prev = hdr.prev;
00598
00599 err: if (rlock == L_ACQUIRED)
00600 LOG_SYSTEM_UNLOCK(dbenv);
00601
00602 return (ret);
00603 }
00604
00605
00606
00607
00608
00609 static int
00610 __log_c_incursor(logc, lsn, hdr, pp)
00611 DB_LOGC *logc;
00612 DB_LSN *lsn;
00613 HDR *hdr;
00614 u_int8_t **pp;
00615 {
00616 u_int8_t *p;
00617 int eof;
00618
00619 *pp = NULL;
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 if (logc->bp_lsn.file != lsn->file)
00632 return (0);
00633 if (logc->bp_lsn.offset > lsn->offset)
00634 return (0);
00635 if (logc->bp_lsn.offset + logc->bp_rlen <= lsn->offset + hdr->size)
00636 return (0);
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648 p = logc->bp + (lsn->offset - logc->bp_lsn.offset);
00649 memcpy(hdr, p, hdr->size);
00650 if (__log_c_hdrchk(logc, lsn, hdr, &eof))
00651 return (DB_NOTFOUND);
00652 if (eof || logc->bp_lsn.offset + logc->bp_rlen < lsn->offset + hdr->len)
00653 return (0);
00654
00655 *pp = p;
00656
00657 return (0);
00658 }
00659
00660
00661
00662
00663
00664 static int
00665 __log_c_inregion(logc, lsn, rlockp, last_lsn, hdr, pp, need_cksump)
00666 DB_LOGC *logc;
00667 DB_LSN *lsn, *last_lsn;
00668 RLOCK *rlockp;
00669 HDR *hdr;
00670 u_int8_t **pp;
00671 int *need_cksump;
00672 {
00673 DB_ENV *dbenv;
00674 DB_LOG *dblp;
00675 LOG *lp;
00676 size_t b_region, len, nr;
00677 u_int32_t b_disk;
00678 int eof, ret;
00679 u_int8_t *p;
00680
00681 dbenv = logc->dbenv;
00682 dblp = dbenv->lg_handle;
00683 lp = ((DB_LOG *)logc->dbenv->lg_handle)->reginfo.primary;
00684
00685 ret = 0;
00686 b_region = 0;
00687 *pp = NULL;
00688 *need_cksump = 0;
00689
00690
00691 if (*rlockp == L_NONE) {
00692 *rlockp = L_ACQUIRED;
00693 LOG_SYSTEM_LOCK(dbenv);
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 *last_lsn = lp->lsn;
00707 if (!lp->db_log_inmemory && last_lsn->offset > lp->w_off)
00708 last_lsn->offset = lp->w_off;
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 if (IS_ZERO_LSN(lp->lsn))
00733 return (0);
00734 if (log_compare(lsn, &lp->lsn) >= 0)
00735 return (DB_NOTFOUND);
00736 else if (lp->db_log_inmemory) {
00737 if ((ret = __log_inmem_lsnoff(dblp, lsn, &b_region)) != 0)
00738 return (ret);
00739 } else if (lp->b_off == 0 || log_compare(lsn, &lp->f_lsn) < 0)
00740 return (0);
00741
00742
00743
00744
00745
00746
00747 logc->bp_rlen = 0;
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 if (lp->db_log_inmemory || log_compare(lsn, &lp->f_lsn) > 0) {
00764 if (!lp->db_log_inmemory)
00765 b_region = lsn->offset - lp->w_off;
00766 __log_inmem_copyout(dblp, b_region, hdr, hdr->size);
00767 if (__log_c_hdrchk(logc, lsn, hdr, &eof) != 0)
00768 return (DB_NOTFOUND);
00769 if (eof)
00770 return (0);
00771 if (lp->db_log_inmemory) {
00772 if (RINGBUF_LEN(lp, b_region, lp->b_off) < hdr->len)
00773 return (DB_NOTFOUND);
00774 } else if (lsn->offset + hdr->len > lp->w_off + lp->buffer_size)
00775 return (DB_NOTFOUND);
00776 if (logc->bp_size <= hdr->len) {
00777 len = (size_t)DB_ALIGN((uintmax_t)hdr->len * 2, 128);
00778 if ((ret =
00779 __os_realloc(logc->dbenv, len, &logc->bp)) != 0)
00780 return (ret);
00781 logc->bp_size = (u_int32_t)len;
00782 }
00783 __log_inmem_copyout(dblp, b_region, logc->bp, hdr->len);
00784 *pp = logc->bp;
00785 return (0);
00786 }
00787
00788 DB_ASSERT(!lp->db_log_inmemory);
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805 b_disk = lp->w_off - lsn->offset;
00806 if (lp->b_off <= lp->len)
00807 b_region = (u_int32_t)lp->b_off;
00808 else
00809 for (p = dblp->bufp + (lp->b_off - lp->len);;) {
00810 memcpy(hdr, p, hdr->size);
00811 if (hdr->prev == lsn->offset) {
00812 b_region = (u_int32_t)(p - dblp->bufp);
00813 break;
00814 }
00815 p = dblp->bufp + (hdr->prev - lp->w_off);
00816 }
00817
00818
00819
00820
00821
00822
00823
00824
00825 if (logc->bp_size <= b_region + b_disk) {
00826 len = (size_t)DB_ALIGN((uintmax_t)(b_region + b_disk) * 2, 128);
00827 if ((ret = __os_realloc(logc->dbenv, len, &logc->bp)) != 0)
00828 return (ret);
00829 logc->bp_size = (u_int32_t)len;
00830 }
00831
00832
00833 p = (logc->bp + logc->bp_size) - b_region;
00834 memcpy(p, dblp->bufp, b_region);
00835
00836
00837 if (*rlockp == L_ACQUIRED) {
00838 *rlockp = L_NONE;
00839 LOG_SYSTEM_UNLOCK(dbenv);
00840 }
00841
00842
00843
00844
00845
00846 if (b_disk != 0) {
00847 p -= b_disk;
00848 nr = b_disk;
00849 if ((ret = __log_c_io(
00850 logc, lsn->file, lsn->offset, p, &nr, NULL)) != 0)
00851 return (ret);
00852 if (nr < b_disk)
00853 return (__log_c_shortread(logc, lsn, 0));
00854
00855
00856 *need_cksump = 1;
00857 }
00858
00859
00860 memcpy(hdr, p, hdr->size);
00861
00862 *pp = p;
00863 return (0);
00864 }
00865
00866
00867
00868
00869
00870 static int
00871 __log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)
00872 DB_LOGC *logc;
00873 DB_LSN *lsn, *last_lsn;
00874 u_int32_t flags;
00875 int *eofp;
00876 HDR *hdr;
00877 u_int8_t **pp;
00878 {
00879 DB_ENV *dbenv;
00880 size_t len, nr;
00881 u_int32_t offset;
00882 int ret;
00883
00884 dbenv = logc->dbenv;
00885 *eofp = 0;
00886
00887 nr = hdr->size;
00888 if ((ret =
00889 __log_c_io(logc, lsn->file, lsn->offset, hdr, &nr, eofp)) != 0)
00890 return (ret);
00891 if (*eofp)
00892 return (0);
00893
00894
00895
00896
00897
00898
00899
00900
00901 if (nr < hdr->size) {
00902 *eofp = 1;
00903 return (0);
00904 }
00905
00906
00907 if ((ret = __log_c_hdrchk(logc, lsn, hdr, eofp)) != 0)
00908 return (ret);
00909 if (*eofp)
00910 return (0);
00911
00912
00913
00914
00915
00916 logc->bp_rlen = 0;
00917
00918
00919
00920
00921
00922
00923 if (logc->bp_size <= hdr->len) {
00924 len = (size_t)DB_ALIGN((uintmax_t)hdr->len * 2, 128);
00925 if ((ret = __os_realloc(dbenv, len, &logc->bp)) != 0)
00926 return (ret);
00927 logc->bp_size = (u_int32_t)len;
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 if (flags == DB_FIRST || flags == DB_NEXT)
00942 offset = lsn->offset;
00943 else if (lsn->offset + hdr->len < logc->bp_size)
00944 offset = 0;
00945 else
00946 offset = (lsn->offset + hdr->len) - logc->bp_size;
00947
00948 nr = logc->bp_size;
00949 if (lsn->file == last_lsn->file && offset + nr >= last_lsn->offset)
00950 nr = last_lsn->offset - offset;
00951
00952 if ((ret =
00953 __log_c_io(logc, lsn->file, offset, logc->bp, &nr, eofp)) != 0)
00954 return (ret);
00955
00956
00957
00958
00959
00960 if (nr < (lsn->offset + hdr->len) - offset)
00961 return (__log_c_shortread(logc, lsn, 1));
00962
00963
00964
00965
00966
00967
00968
00969 logc->bp_rlen = (u_int32_t)nr;
00970 logc->bp_lsn.offset = offset;
00971
00972 *pp = logc->bp + (lsn->offset - offset);
00973
00974 return (0);
00975 }
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 static int
00998 __log_c_hdrchk(logc, lsn, hdr, eofp)
00999 DB_LOGC *logc;
01000 DB_LSN *lsn;
01001 HDR *hdr;
01002 int *eofp;
01003 {
01004 DB_ENV *dbenv;
01005 int ret;
01006
01007 dbenv = logc->dbenv;
01008
01009
01010
01011
01012 if (eofp != NULL) {
01013 if (hdr->prev == 0 && hdr->chksum[0] == 0 && hdr->len == 0) {
01014 *eofp = 1;
01015 return (0);
01016 }
01017 *eofp = 0;
01018 }
01019
01020
01021
01022
01023
01024 if (hdr->len <= hdr->size)
01025 goto err;
01026
01027
01028
01029
01030
01031 if (logc->bp_maxrec != 0 && hdr->len > logc->bp_maxrec) {
01032
01033
01034
01035
01036
01037 if ((ret = __log_c_set_maxrec(logc, NULL)) != 0) {
01038 __db_err(dbenv, "DB_LOGC->get: %s", db_strerror(ret));
01039 return (ret);
01040 }
01041 if (logc->bp_maxrec != 0 && hdr->len > logc->bp_maxrec)
01042 goto err;
01043 }
01044 return (0);
01045
01046 err: if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
01047 __db_err(dbenv,
01048 "DB_LOGC->get: LSN %lu/%lu: invalid log record header",
01049 (u_long)lsn->file, (u_long)lsn->offset);
01050 return (EIO);
01051 }
01052
01053
01054
01055
01056
01057 static int
01058 __log_c_io(logc, fnum, offset, p, nrp, eofp)
01059 DB_LOGC *logc;
01060 u_int32_t fnum, offset;
01061 void *p;
01062 size_t *nrp;
01063 int *eofp;
01064 {
01065 DB_ENV *dbenv;
01066 DB_LOG *dblp;
01067 LOG *lp;
01068 int ret;
01069 char *np;
01070
01071 dbenv = logc->dbenv;
01072 dblp = dbenv->lg_handle;
01073 lp = dblp->reginfo.primary;
01074
01075
01076
01077
01078
01079 if (logc->c_fhp != NULL && logc->bp_lsn.file != fnum) {
01080 ret = __os_closehandle(dbenv, logc->c_fhp);
01081 logc->c_fhp = NULL;
01082 logc->bp_lsn.file = 0;
01083
01084 if (ret != 0)
01085 return (ret);
01086 }
01087 if (logc->c_fhp == NULL) {
01088 if ((ret = __log_name(dblp, fnum,
01089 &np, &logc->c_fhp, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {
01090
01091
01092
01093
01094 if (eofp != NULL) {
01095 *eofp = 1;
01096 ret = 0;
01097 } else if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
01098 __db_err(dbenv, "DB_LOGC->get: %s: %s",
01099 np, db_strerror(ret));
01100 __os_free(dbenv, np);
01101 return (ret);
01102 }
01103
01104 if ((ret = __log_c_set_maxrec(logc, np)) != 0) {
01105 __db_err(dbenv,
01106 "DB_LOGC->get: %s: %s", np, db_strerror(ret));
01107 __os_free(dbenv, np);
01108 return (ret);
01109 }
01110 __os_free(dbenv, np);
01111
01112 logc->bp_lsn.file = fnum;
01113 }
01114
01115
01116 if ((ret = __os_seek(dbenv,
01117 logc->c_fhp, 0, 0, offset, 0, DB_OS_SEEK_SET)) != 0) {
01118 if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
01119 __db_err(dbenv,
01120 "DB_LOGC->get: LSN: %lu/%lu: seek: %s",
01121 (u_long)fnum, (u_long)offset, db_strerror(ret));
01122 return (ret);
01123 }
01124
01125
01126 ++lp->stat.st_rcount;
01127 if ((ret = __os_read(dbenv, logc->c_fhp, p, *nrp, nrp)) != 0) {
01128 if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
01129 __db_err(dbenv,
01130 "DB_LOGC->get: LSN: %lu/%lu: read: %s",
01131 (u_long)fnum, (u_long)offset, db_strerror(ret));
01132 return (ret);
01133 }
01134
01135 return (0);
01136 }
01137
01138
01139
01140
01141
01142 static int
01143 __log_c_shortread(logc, lsn, check_silent)
01144 DB_LOGC *logc;
01145 DB_LSN *lsn;
01146 int check_silent;
01147 {
01148 if (!check_silent || !F_ISSET(logc, DB_LOG_SILENT_ERR))
01149 __db_err(logc->dbenv, "DB_LOGC->get: LSN: %lu/%lu: short read",
01150 (u_long)lsn->file, (u_long)lsn->offset);
01151 return (EIO);
01152 }
01153
01154
01155
01156
01157
01158 static int
01159 __log_c_set_maxrec(logc, np)
01160 DB_LOGC *logc;
01161 char *np;
01162 {
01163 DB_ENV *dbenv;
01164 DB_LOG *dblp;
01165 LOG *lp;
01166 u_int32_t mbytes, bytes;
01167 int ret;
01168
01169 dbenv = logc->dbenv;
01170 dblp = dbenv->lg_handle;
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 if (logc->c_fhp != NULL) {
01182 if ((ret = __os_ioinfo(dbenv, np, logc->c_fhp,
01183 &mbytes, &bytes, NULL)) != 0)
01184 return (ret);
01185 if (logc->bp_maxrec < (mbytes * MEGABYTE + bytes))
01186 logc->bp_maxrec = mbytes * MEGABYTE + bytes;
01187 }
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201 lp = dblp->reginfo.primary;
01202 if (logc->bp_maxrec < lp->buffer_size)
01203 logc->bp_maxrec = lp->buffer_size;
01204
01205 return (0);
01206 }
01207
01208 #ifdef HAVE_REPLICATION
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 int
01219 __log_rep_split(dbenv, rp, rec, ret_lsnp)
01220 DB_ENV *dbenv;
01221 REP_CONTROL *rp;
01222 DBT *rec;
01223 DB_LSN *ret_lsnp;
01224 {
01225 DB_LSN save_lsn, tmp_lsn;
01226 DB_REP *db_rep;
01227 DBT logrec;
01228 REP *rep;
01229 REP_CONTROL tmprp;
01230 u_int32_t len;
01231 int is_dup, is_perm, ret, save_ret;
01232 u_int8_t *p, *ep;
01233 #ifdef DIAGNOSTIC
01234 DB_MSGBUF mb;
01235 #endif
01236
01237 memset(&logrec, 0, sizeof(logrec));
01238 memset(&save_lsn, 0, sizeof(save_lsn));
01239 memset(&tmp_lsn, 0, sizeof(tmp_lsn));
01240
01241
01242
01243
01244 memcpy(&tmprp, rp, sizeof(tmprp));
01245
01246
01247
01248
01249
01250
01251 is_perm = F_ISSET(rp, DB_LOG_PERM);
01252 F_CLR(&tmprp, DB_LOG_PERM);
01253 ret = save_ret = 0;
01254 db_rep = dbenv->rep_handle;
01255 rep = db_rep->region;
01256 for (ep = (u_int8_t *)rec->data + rec->size, p = (u_int8_t *)rec->data;
01257 p < ep; ) {
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267 memcpy(&len, p, sizeof(len));
01268 p += sizeof(len);
01269 memcpy(&tmprp.lsn, p, sizeof(DB_LSN));
01270 p += sizeof(DB_LSN);
01271 logrec.data = p;
01272 logrec.size = len;
01273 RPRINT(dbenv, rep, (dbenv, &mb,
01274 "log_rep_split: Processing LSN [%lu][%lu]",
01275 (u_long)tmprp.lsn.file, (u_long)tmprp.lsn.offset));
01276 RPRINT(dbenv, rep, (dbenv, &mb,
01277 "log_rep_split: p %#lx ep %#lx logrec data %#lx, size %lu (%#lx)",
01278 P_TO_ULONG(p), P_TO_ULONG(ep), P_TO_ULONG(logrec.data),
01279 (u_long)logrec.size, (u_long)logrec.size));
01280 is_dup = 0;
01281 p += len;
01282 if (p >= ep && is_perm)
01283 F_SET(&tmprp, DB_LOG_PERM);
01284 ret = __rep_apply(dbenv, &tmprp, &logrec, &tmp_lsn, &is_dup);
01285 RPRINT(dbenv, rep, (dbenv, &mb,
01286 "log_split: rep_apply ret %d, tmp_lsn [%lu][%lu]",
01287 ret, (u_long)tmp_lsn.file, (u_long)tmp_lsn.offset));
01288 #if 0
01289
01290
01291
01292
01293 if (is_dup)
01294 goto out;
01295 #endif
01296 switch (ret) {
01297
01298
01299
01300
01301
01302 case DB_REP_LOGREADY:
01303 goto out;
01304
01305
01306
01307 case DB_REP_ISPERM:
01308 case DB_REP_NOTPERM:
01309 case DB_REP_STARTUPDONE:
01310 save_ret = ret;
01311 save_lsn = tmp_lsn;
01312 ret = 0;
01313 break;
01314
01315
01316
01317 case 0:
01318 break;
01319
01320
01321
01322 default:
01323 goto out;
01324 }
01325 }
01326 out:
01327
01328
01329
01330
01331 if (ret == 0) {
01332 ret = save_ret;
01333 *ret_lsnp = save_lsn;
01334 }
01335 return (ret);
01336 }
01337 #endif