00001
package com.quadcap.sql.file;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
import java.io.File;
00042
import java.io.FileOutputStream;
00043
import java.io.IOException;
00044
import java.io.RandomAccessFile;
00045
00046
import java.util.ArrayList;
00047
import java.util.List;
00048
import java.util.Map;
00049
import java.util.Properties;
00050
00051
import javax.concurrent.BoundedBuffer;
00052
import javax.concurrent.Channel;
00053
import javax.concurrent.Latch;
00054
00055
import com.quadcap.sql.lock.Transaction;
00056
import com.quadcap.sql.lock.TransactionObserver;
00057
00058
import com.quadcap.util.collections.LongMap;
00059
00060
import com.quadcap.util.ConfigNumber;
00061
import com.quadcap.util.Debug;
00062
import com.quadcap.util.Util;
00063
00064
00065
00066
00067
00068
00069
00070
00071 public class Log1 implements Log {
00072
00073 private Datafile db;
00074
00075
00076 private BlockFile dbFile;
00077
00078
00079 Logger logger;
00080
00081
00082 private File
dbRootDir;
00083
00084
00085 LogSync logSync;
00086
00087
00088 Latch
closeLatch =
new Latch();
00089
00090
00092
00093
00094 Object
fileLock;
00095
00096
00097 LongMap
rowIdMap =
new LongMap(256);
00098
00099
00100 FileOutputStream
bfo;
00101 boolean bfoActive =
false;
00102
00103 boolean recovering =
false;
00104
00105 int blockSize;
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
long minSyncInterval
00116 =
ConfigNumber.find(
"qed.minSyncInterval",
"15000").longValue();
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
long maxSyncInterval
00129 =
ConfigNumber.find(
"qed.maxSyncInterval",
"60000").longValue();
00130
00131 int syncMap = 0 +
00132 (1 << 1) +
00133 (1 << 2) +
00134
00135 (1 << 4) +
00136 (1 << 5) +
00137 (1 << 6) +
00138 (1 << 7) +
00139 0;
00140
00141
00142 String[]
syncStrs = {
00143
"Log1.reallyFlush from Log2.flushLog",
00144
"Log1.reallyFlush: bfo.sync()",
00145
"Log1.reallyFlush: logger.sync()",
00146
"Log1.reallyFlush: db.tempFile.flush(!)",
00147
"Log1.reallyCheckpoint: dbfile.flush(!)",
00148
"Log1.reallyCheckpoint: logger.sync()",
00149
"Log1.reallyCheckpoint: dbfile.checkpoint(!)",
00150
"Log1.saveBlock: bfo.sync"
00151 };
00152
00153 int[]
syncCnts =
new int[
syncStrs.length];
00154
00155 protected boolean checksync(
int x) {
00156
00157
syncCnts[x]++;
00158
00159
00160
boolean ret = (
syncMap & (1 << x)) != 0;
00161
return ret;
00162 }
00163
00164
00165
00166
00167
00168 public Log1() {}
00169
00170
00171
00172
00173
00174
00175
00176
00177 public void init(
Datafile db,
boolean create, Properties props)
00178
throws IOException
00179 {
00180
this.db =
db;
00181
this.dbFile =
db.
file;
00182
this.
blockSize =
dbFile.
getBlockSize();
00183
this.dbRootDir =
db.
dbRootDir;
00184
this.fileLock =
db.
getFileLock();
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
this.minSyncInterval =
00207 Long.parseLong(props.getProperty(
"minSyncInterval",
00208 String.valueOf(
minSyncInterval)));
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
this.maxSyncInterval =
00220 Long.parseLong(props.getProperty(
"maxSyncInterval",
00221 String.valueOf(
maxSyncInterval)));
00222
00223
00224
00225 String loggerClass = props.getProperty(
"loggerClass");
00226
try {
00227
this.logger = (
Logger)(Class.forName(loggerClass).newInstance());
00228 }
catch (Throwable t) {
00229
this.logger =
new Logger1();
00230 }
00231
logger.
init(
this, create, props);
00232
00233 }
00234
00235 public void start() {
00236
logSync =
new LogSync(
this);
00237
logSync.setDaemon(
true);
00238
logSync.start();
00239 }
00240
00241 public void remove() throws IOException {
00242
new File(
dbRootDir,
"logfile").delete();
00243 }
00244
00245
00246
00247
00248 public Datafile getDatafile() {
return db; }
00249
00250
00251
00252
00253 public File
getDbRootDir() {
return dbRootDir; }
00254
00255
00256
00257
00258 int pendingBegins = 0;
00259 public void addEntry(
LogEntry entry)
00260
throws IOException
00261 {
00262
if (entry.getCode() ==
LogEntry.BEGIN_TRANSACTION) {
00263
pendingBegins++;
00264 }
00265
put(entry);
00266 }
00267
00268
00269
00270
00271 public void close() throws IOException {
00272
put(
opClose);
00273
try {
00274
closeLatch.acquire();
00275 }
catch (InterruptedException ex) {
00276 }
00277 }
00278
00279
00280
00281
00282
00283 public void flushLog() throws IOException {
00284
put(
opFlush);
00285 }
00286
00287
00288
00289
00290 public void checkpoint() throws IOException {
00291
put(
opCheckpoint);
00292 }
00293
00294
00295
00296
00297 public void sync() throws IOException {
00298 Latch latch =
new Latch();
00299
put(
new Sync(latch));
00300
try {
00301 latch.acquire();
00302 }
catch (InterruptedException ex) {
00303 }
00304 }
00305
00306
00307
00308
00309 public void rollbackTransaction(
Transaction trans)
00310
throws IOException
00311 {
00312
put(
new Rollback(trans));
00313
sync();
00314 }
00315
00316
00317
00318
00319 public void rollbackStatement(
Transaction trans,
int stmtId)
00320
throws IOException
00321 {
00322
put(
new Rollback(trans, stmtId));
00323
sync();
00324 }
00325
00326
00327
00328
00329 public void restart() throws Exception {
00330
reallyRestart();
00331 }
00332
00333
00334
00335
00336
00337
00338 public final long getRowMap(
long rowId) {
00339
long ret = rowId;
00340
if (
rowIdMap != null) {
00341 Long mapped = (Long)
rowIdMap.get(rowId);
00342
if (mapped != null) ret = mapped.longValue();
00343 }
00344
return ret;
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 public final void putRowMap(
long logRow,
long fileRow) {
00356
if (
rowIdMap == null)
rowIdMap =
new LongMap(256);
00357
rowIdMap.put(logRow,
new Long(fileRow));
00358 }
00359
00360 public final void removeRowMap(
long row) {
00361
if (
rowIdMap != null)
rowIdMap.remove(row);
00362 }
00363
00364 void reallyFlush() throws IOException {
00365
00366
if (
Trace.bit(18)) {
00367
Debug.println(
this +
".reallyFlush()");
00368 }
00369
00370
if (checksync(2))
logger.
sync();
00371
if (
db.
tempFile != null) {
00372
db.
tempFile.
flush(!checksync(3));
00373 }
00374 }
00375
00376 void reallyClose() throws IOException {
00377
try {
00378
if (
logSync != null) {
00379
logSync.
close();
00380 }
00381 } finally {
00382
logSync = null;
00383
if (
bfo != null) {
00384
try {
00385
bfo.close();
00386 } finally {
00387
bfo = null;
00388 }
00389 }
00390 }
00391 }
00392
00393 void reallyRollbackTransaction(
Transaction tr)
throws Exception {
00394
00395
if (
Trace.bit(18)) {
00396
Debug.println(
"reallyRollbackTransaction(" + tr +
")");
00397 }
00398
00399
long t = tr.getTransactionId();
00400
LogEntry e =
logger.
getLastOp(t);
00401
try {
00402
while (e != null) {
00403
00404
if (e.
getTransactionId() == t) {
00405
switch (e.
getCode()) {
00406
case LogEntry.STEP:
00407
if (e.
getRedoState() ==
LogEntry.DONE) {
00408
try {
00409 e.
undo(tr,
db);
00410 }
catch (Throwable th) {
00411
00412
Debug.println(
"Exception in rollback transaction");
00413
Debug.print(th);
00414
00415 }
00416
logger.
setRedoState(e,
LogEntry.
UNDONE);
00417 }
00418
break;
00419
case LogEntry.BEGIN_TRANSACTION:
00420 e = null;
00421
break;
00422
default:
00423
break;
00424 }
00425 }
00426 e = (e == null || e.
getPrev() < 0) ? null :
logger.
getPrevOp(e);
00427 }
00428 } finally {
00429
rowIdMap = null;
00430 }
00431 }
00432
00433 void reallyRollbackStatement(
Transaction tr,
int s)
throws Exception {
00434
long t = tr.getTransactionId();
00435
LogEntry e =
logger.
getLastOp(t);
00436
rowIdMap = null;
00437
try {
00438
while (e != null) {
00439
if (e.
getStatementId() == s) {
00440
switch (e.
getCode()) {
00441
case LogEntry.STEP:
00442
if (e.
getRedoState() ==
LogEntry.DONE) {
00443
try {
00444 e.
undo(tr,
db);
00445 }
catch (Throwable th) {
00446
00447
Debug.println(
"Exception in statement rollback");
00448
Debug.print(th);
00449
00450 }
00451
logger.
setRedoState(e,
LogEntry.
UNDONE);
00452 }
00453
break;
00454
case LogEntry.BEGIN_STATEMENT:
00455
00456
00457
return;
00458
default:
00459
break;
00460 }
00461 }
00462 e =
logger.
getPrevOp(e);
00463 }
00464 } finally {
00465
rowIdMap = null;
00466 }
00467 }
00468
00469 LogEntry scanLog(LongMap t)
throws IOException {
00470
LogEntry op =
logger.
getFirstOp();
00471
LogEntry last = op;
00472
for (; op != null; last = op, op =
logger.
getNextOp()) {
00473
LogEntry e = op;
00474
if (e != null && e.
getCode() ==
LogEntry.COMMIT) {
00475
00476 t.put(e.
getTransactionId(),
"");
00477 }
00478 }
00479
return last;
00480 }
00481
00482 void reallyRestart() throws Exception {
00483
00484
if (
Trace.bit(18)) {
00485
Debug.println(
toString() +
".reallyRestart()");
00486 }
00487
00488
db.
getTempFile(
false);
00489
Transaction t =
db.
makeTransaction(
false);
00490 LongMap map =
new LongMap(32);
00491
LogEntry last = scanLog(map);
00492
int q = 0;
00493
int checkpointPosition =
logger.
getCheckpoint();
00494
int endPosition =
logger.
getEnd();
00495
LogEntry op = last;
00496
recovering =
true;
00497
try {
00498
for (; op != null; op =
logger.
getPrevOp(op)) {
00499
LogEntry e = op;
00500
if (e != null && e.
getCode() ==
LogEntry.STEP &&
00501 e.
getPosition() < checkpointPosition &&
00502 map.get(e.
getTransactionId()) == null) {
00503
if (e.
getRedoState() ==
LogEntry.DONE) {
00504
00505
if (
Trace.bit(18)) {
00506
Debug.println(
"UNDO[" + e +
"]");
00507 }
00508
00509
if (q++ == 0) {
00510
Debug.println(
"Undoing in-progress transactions...");
00511 }
00512 e.
undo(t,
db);
00513 }
00514 }
00515 }
00516
rowIdMap = null;
00517
00518
int p = 0;
00519
for (op =
logger.
getFirstOp(); op != null; op =
logger.
getNextOp()) {
00520
LogEntry e = op;
00521
if (e.
getPosition() >= endPosition)
break;
00522
if (e != null && map.get(e.
getTransactionId()) != null) {
00523
if (e.
getCode() ==
LogEntry.STEP) {
00524
if (e.
getRedoState() ==
LogEntry.DONE) {
00525
if (p++ == 0) {
00526
Debug.println(
"Restoring committed transactions: " + map);
00527 }
00528
00529
if (
Trace.bit(18)) {
00530
Debug.println(
"REDO[" + e +
"]");
00531 }
00532
00533 e.
redo(t,
db);
00534 }
00535 }
00536 }
00537 }
00538
rowIdMap = null;
00539
00540
if (p > 0 || q > 0) {
00541
Debug.println(
"Recovery complete: " +
00542 p +
" redos, " +
00543 q +
" undos");
00544 }
00545
logger.
reset();
00546
logger.
sync();
00547
if (p > 0 || q > 0) {
00548
checkpoint();
00549 }
00550 } finally {
00551
recovering =
false;
00552 }
00553 }
00554
00555 long lastCheckpoint = System.currentTimeMillis();
00556
00557 void maybeCheckpoint() throws IOException {
00558
long now = System.currentTimeMillis();
00559
boolean idle =
logger.
getActiveTransactionCount() == 0;
00560
if (idle)
rowIdMap = null;
00561
long interval = idle ?
minSyncInterval :
maxSyncInterval;
00562
if (now -
lastCheckpoint >= interval) {
00563
00564
if (
Trace.bit(25)) {
00565
Debug.println(
"[" +
entryCount +
BlockStore.rw() +
00566
"] interval " + (now - lastCheckpoint) +
00567
" ms," + (idle ?
" IDLE" :
"") +
00568
" checkpoint now");
00569 }
00570
00571
00572
reallyCheckpoint();
00573
00574
00575
if (
Trace.bit(25)) {
00576
Debug.println(
"checkpoint done");
00577 }
00578
00579 }
00580 }
00581
00582 void reallyCheckpoint() throws IOException {
00583
try {
00584
db.
flushRoot();
00585
dbFile.
flush(!checksync(4));
00586
logger.
checkpoint();
00587
00588
int numTrans =
logger.
getActiveTransactionCount();
00589
boolean truncate =
pendingBegins == 0 && numTrans == 0;
00590
if (truncate) {
00591
logger.
reset();
00592 }
00593
logger.
sync();
00594
db.
checkpoint(truncate, !checksync(6));
00595
db.
checkpointHandler(
logger.
getActiveTransactions());
00596
dbFile.
clearModified();
00597 } finally {
00598
lastCheckpoint = System.currentTimeMillis();
00599
rowIdMap = null;
00600 }
00601
00602
if (
Trace.bit(21)) {
00603
Debug.println(
"AFTER Log1.reallyCheckpoint: [" +
00604
logger.
getActiveTransactionCount() +
"]");
00605 }
00606
if (
false) {
00607
long sum = 0;
00608
long blk =
dbFile.
getBlockSize();
00609
for (
long x = 0; x <
dbFile.
getSize(); x += blk) {
00610
Block b =
dbFile.
getBlock(x / blk);
00611
for (
int ix = 0; ix < blk; ix += 8) {
00612 sum += b.
readLong(ix);
00613 }
00614 b.
decrRefCount();
00615 }
00616
Debug.println(
"CHECKPOINT: CHECKSUM(" +
dbFile.
getSize() +
") bytes = " +
00617 sum);
00618 }
00619
00620 }
00621
00622
00623 int entryCount = 0;
00624
00625
00626 public void reallyAddEntry(
LogEntry entry)
throws IOException {
00627
00628
entryCount++;
00629
if (
Trace.bit(16)) {
00630
Debug.println(
toString() +
".reallyAddEntry(" + entry +
")");
00631 }
00632
00633
try {
00634
logger.
put(entry);
00635
if (entry.getCode() ==
LogEntry.BEGIN_TRANSACTION) {
00636
pendingBegins--;
00637 }
00638 }
catch (IOException ex) {
00639
if (ex.toString().indexOf(
"full") > 0) {
00640
abortOldestTransaction(entry);
00641
logger.
put(entry);
00642 }
else {
00643
throw ex;
00644 }
00645 }
00646 }
00647
00648 private void sortEntry(
long tId, List save, List discard,
LogEntry e) {
00649
if (e.
getTransactionId() == tId) {
00650 discard.add(e);
00651 }
else {
00652 save.add(e);
00653 }
00654 }
00655
00656 private final void abortOldestTransaction(
LogEntry entry)
00657
throws IOException
00658 {
00659
long tId =
logger.
getOldestTransaction();
00660
Transaction t =
db.
findTransaction(tId);
00661
if (t == null) {
00662
Debug.println(
"Log full, will reset log");
00663
logger.
reset();
00664
00665
00666 }
else {
00667 ArrayList save =
new ArrayList();
00668
Debug.println(
"Log full, will abort " + t);
00669
try {
00670
00671
00672
00673 ArrayList discard =
new ArrayList();
00674
LogEntry e;
00675
while ((e = (
LogEntry)
channel.poll(0)) != null) {
00676 sortEntry(tId, save, discard, e);
00677 }
00678 sortEntry(tId, save, discard, entry);
00679
Debug.println(
"discarding " + discard.size() +
00680
" completed log entries");
00681
for (
int i = discard.size() - 1; i >= 0; i--) {
00682 e = (
LogEntry)discard.get(i);
00683
try {
00684 e.
undo(t,
db);
00685 }
catch (Throwable th) {
00686
00687
Debug.println(
"Error during abort oldest");
00688
Debug.print(th);
00689
00690 }
00691 }
00692 reallyRollbackTransaction(t);
00693 }
catch (IOException ex1) {
00694
throw ex1;
00695 }
catch (Exception ex2) {
00696
00697
Debug.print(ex2);
00698
00699
throw new DatafileException(ex2);
00700 }
00701
TransactionObserver obs = t.
getObserver();
00702
if (obs != null) {
00703 obs.
abort(t);
00704 }
00705
reallyCheckpoint();
00706
00707
00708
00709
Debug.println(
"handling " + save.size() +
" saved log entries");
00710
for (
int i = 0; i < save.size(); i++) {
00711
LogEntry e = (
LogEntry)save.get(i);
00712
try {
00713 e.
handle(
this);
00714 }
catch (Throwable th) {
00715
Debug.print(th);
00716 }
00717 }
00718 }
00719 }
00720
00721
00722
00723
00724
00725
00726 public void put(
LogEntry h)
throws IOException {
00727
while (
true) {
00728
try {
00729
channel.put(h);
00730 }
catch (InterruptedException ex) {
00731
continue;
00732 }
00733
return;
00734 }
00735 }
00736
00737
00738
00739
00740 public static class Flush extends LogEntry {
00741 public Flush() { super(FLUSH); }
00742 public void handle(
Log log)
throws IOException {
00743 ((
Log1)log).reallyFlush();
00744 }
00745 }
00746
00747
00748
00749
00750 static Flush opFlush =
new Flush();
00751
00752
00753
00754
00755 public static class Checkpoint extends LogEntry {
00756 public Checkpoint() { super(CHECKPOINT); }
00757 public void handle(
Log log)
throws IOException {
00758 ((
Log1)log).reallyCheckpoint();
00759 }
00760 }
00761 static Checkpoint opCheckpoint =
new Checkpoint();
00762
00763
00764
00765
00766 public static class Close extends LogEntry {
00767 public Close() { super(CLOSE); }
00768 public void handle(
Log log)
throws IOException {
00769 ((
Log1)log).reallyClose();
00770 }
00771 }
00772
00773
00774
00775
00776 static Close opClose =
new Close();
00777
00778
00779
00780
00781 public class Rollback extends LogEntry {
00782 Transaction
t;
00783 public Rollback(Transaction t) {
00784 super(t.getTransactionId(), ROLLBACK);
00785
this.t = t;
00786 }
00787 public Rollback(Transaction t0,
int s) {
00788 super(t0.getTransactionId(), s, ROLLBACK);
00789
this.t = t0;
00790 }
00791 public void handle(
Log log)
throws Exception {
00792
if (stmtId == -1) {
00793 reallyRollbackTransaction(
t);
00794 }
else {
00795 reallyRollbackStatement(
t, stmtId);
00796 }
00797 }
00798 }
00799
00800
00801
00802
00803 public class Sync extends LogEntry {
00804 Latch
latch;
00805 public Sync(Latch latch) {
00806 super(SYNC);
00807
this.latch = latch;
00808 }
00809 public void handle(
Log log)
throws Exception {
00810
latch.release();
00811 }
00812 }
00813
00814
00815
00816
00817
00818 class LogSync extends Thread {
00819 boolean closeMe =
false;
00820 Log1 log = null;
00821 LogSync(
Log1 log) { super(
"Log Sync");
this.log = log; }
00822
00823 public void close() {
00824
closeMe =
true;
00825 }
00826
00827 public void run() {
00828
try {
00829
while (!
closeMe) {
00830 Object obj = channel.poll(500);
00831
if (obj != null) {
00832
00833
00834
synchronized (fileLock) {
00835
while (obj != null) {
00836
try {
00837
00838
if (
Trace.bit(17)) {
00839
Debug.println(
"PRE [" + obj +
"].handle()");
00840 }
00841
00842 ((
LogEntry)obj).handle(
log);
00843
00844
if (
Trace.bit(15)) {
00845
Debug.println(
"POST [" + obj +
"].handle()");
00846 }
00847
00848 }
catch (IOException ex) {
00849
Debug.println(
"LogSync: Got exception in [" + obj +
"].handle()");
00850
Debug.print(ex);
00851 }
catch (Throwable t) {
00852
Debug.println(
"LogSync: Got exception in [" + obj +
"].handle()");
00853
Debug.print(t);
00854 }
00855 obj = channel.poll(0);
00856 }
00857
if (!
closeMe) {
00858
log.
maybeCheckpoint();
00859 }
00860 }
00861 }
00862 }
00863
log = null;
00864
if (logger != null) logger.
close();
00865 }
catch (InterruptedException ex) {
00866
Debug.print(ex);
00867 }
catch (Throwable t) {
00868
Debug.print(t);
00869 } finally {
00870
00871
00872
00873 closeLatch.release();
00874 }
00875 }
00876
00877 }
00878
00879
00880
00881
00882
00883
00884 public boolean isLogging() {
return true; }
00885
00886
00887
00888
00889 public boolean inRecovery() {
00890
return recovering;
00891 }
00892
00893
00894 int filepos = 0;
00895
00896
00897
00898
00899
00900 byte[]
sav = null;
00901 public void saveBlock(
long b)
throws IOException {
00902
if (
sav == null) {
00903
sav =
new byte[
blockSize + 8];
00904 }
00905
ByteUtil.putLong(
sav, 0, b);
00906
dbFile.
store.
read(b,
sav, 8);
00907
if (
bfo == null)
resetBlocks();
00908
bfo.write(
sav, 0,
sav.length);
00909
bfoActive =
true;
00910
00911
if (
Trace.bit(19))
Debug.println(
"saveBlock(" + b +
", " +
Block.signature(
sav, 8,
blockSize) +
" @ " +
filepos +
")");
00912
filepos += sav.length;
00913
00914
if (checksync(7)) {
00915
try {
00916
bfo.getFD().sync();
00917 }
catch (Throwable t) {
00918 } finally {
00919
bfoActive =
false;
00920 }
00921 }
00922 }
00923
00924
00925
00926
00927 public void restoreBlocks() throws IOException {
00928
00929
if (
Trace.bit(19)) {
00930
Debug.println(
db.
toString() +
00931
".restoreBlocks(): size = " +
dbFile.
getSize());
00932 }
00933
00934 File f =
new File(
db.
getScratchDir(),
"before-images");
00935
int siz =
blockSize + 8;
00936
if (f.exists() && f.length() >= siz) {
00937 RandomAccessFile bf =
new RandomAccessFile(f,
"r");
00938
try {
00939 byte[] buf =
new byte[siz];
00940
long pos = bf.length() - siz;
00941
while (pos >= 0) {
00942 bf.seek(pos);
00943 bf.read(buf);
00944
long blk =
ByteUtil.getLong(buf, 0);
00945
00946
if (
Trace.bit(19)) {
00947
Debug.println(
db.
toString() +
" [RESTORE " + blk +
" @ " + pos +
"]");
00948 }
00949
00950
dbFile.
restoreBlock(blk, buf, 8);
00951 pos -= siz;
00952 }
00953 } finally {
00954 bf.close();
00955 }
00956 }
00957
00958
if (
Trace.bit(19)) {
00959
Debug.println(
db.
toString() +
00960
".restoreBlocks(): size = " +
dbFile.
getSize());
00961 }
00962
if (
false) {
00963
long sum = 0;
00964
long blk =
dbFile.
getBlockSize();
00965
for (
long x = 0; x <
dbFile.
getSize(); x += blk) {
00966
Block b =
dbFile.
getBlock(x / blk);
00967
for (
int ix = 0; ix < blk; ix += 8) {
00968 sum += b.
readLong(ix);
00969 }
00970 b.
decrRefCount();
00971 }
00972
Debug.println(
"RECOVER: CHECKSUM(" +
dbFile.
getSize() +
") bytes = " +
00973 sum);
00974 }
00975
00976 }
00977
00978
00979
00980
00981 public void resetBlocks() throws IOException {
00982
if (
bfo != null) {
00983
try {
00984
bfo.close();
00985 }
catch (Throwable t) {
00986 } finally {
00987
bfo = null;
00988 }
00989 }
00990 File b =
new File(
db.
getScratchDir(),
"before-images");
00991
bfo =
new FileOutputStream(b);
00992
bfoActive =
false;
00993
00994
if (
Trace.bit(19))
Debug.println(
db.
toString() +
".Log1.resetBlocks() @ " +
filepos +
", dbFile.size = " +
dbFile.
getSize());
00995
filepos = 0;
00996
00997 }
00998
00999
01000 public String
toString() {
01001 String s = getClass().getName();
01002
int x = s.lastIndexOf(
'.');
01003
if (x >= 0) s = s.substring(x+1);
01004
return s;
01005 }
01006
01007 }
01008