/*
* Copyright (C) 2006 http://www.chaidb.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
package org.chaidb.db.transaction;
import org.apache.log4j.Logger;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.exception.ErrorCode;
import org.chaidb.db.index.btree.bufmgr.PageBufferManager;
import org.chaidb.db.log.Lsn;
import org.chaidb.db.log.logrecord.TxnCkpLogRecord;
import org.chaidb.db.log.logrecord.TxnFuzzyCkpLogRecord;
import java.util.Date;
/**
* @author Ramon Liu
* Date: 2005-7-24
* Time: 16:57:06
*/
public class Checkpoint {
private static final Logger logger = Logger.getLogger(Checkpoint.class);
private TransactionManager txnManager;
/* The checkpoint run mode or policy by tuning the below parameters.
* The kbyte kilobytes of log data have been written since the last checkpoint.
* The min minutes have passed since the last checkpoint.
* The flags parameter MUST be set one of the following values:
* TransactionManager.DB_PERIOD OR TransactionManager.DB_FORCE
*/
private int flags;
public Checkpoint(TransactionManager txnManager, int flags) {
this.txnManager = txnManager;
this.flags = flags;
}
/**
* Internal routine for doing fuzzy checkpoint.
* steps:
* 1.find smallest begin_lsn of all active txns
* 2.add fuzzy checkpoint log record
* 3.flush btrees
*/
public void doCheckpoint(boolean sync) throws ChaiDBException {
Lsn lastCkp = null;
Lsn ckpLsn = null;
Lsn smallestLsn = txnManager.getSmallestLsnOfAllActiveTxn();
if (!sync && !txnManager.getLogManager().needCheckpoint()) {
txnManager.setTimeCkp(System.currentTimeMillis());
logger.info("Checkpoint thread found there is no new log from " + "the time of last checkpoint. Current checkpoint " + "process will abort.");
return;
}
/* add fuzzy checkpoint log ,and while log(),logManager will flush
the log buffer to disk.*/
lastCkp = txnManager.getLastCkp();
try {
if (flags == TransactionManager.DB_SHUTDOWN) {
ckpLsn = new TxnFuzzyCkpLogRecord(lastCkp, new Date().getTime(), TxnCkpLogRecord.SHUTDOWN_CHECKPOINT, smallestLsn).log();
} else {
ckpLsn = new TxnFuzzyCkpLogRecord(lastCkp, new Date().getTime(), TxnCkpLogRecord.FUZZY_CHECKPOINT, smallestLsn).log();
}
} catch (ChaiDBException e) {
logger.error(e);
String details = "Log failed at LSN [" + new Integer(ckpLsn.getFileId()).toString() + " " + new Integer(ckpLsn.getOffset()).toString() + "].";
throw new ChaiDBException(ErrorCode.CHECKPOINT_FAILURE, details);
}
//System.out.println("begin : get lock in checkpoint ");
/* lock LogManger not to put new log while dumping btree */
// LockManager lockManager = txnManager.getLockManager();
// int ilockerId = lockManager.id();
// Lock lock = null;
// lock = lockManager.get(ilockerId, lockManager.LOCK_WAITING,
// lockManager.OBJECT_OBJECT,
// txnManager.getLogManager().getSyncObject(),
// lockManager.LOCK_WRITE);
try {
// synchronized (BufferedPage.getInstance()) {
//flush log buffer to disk.
txnManager.getLogManager().flush();
//Flush btree buffer to disk.
PageBufferManager bpm = PageBufferManager.getInstance();
bpm.dump(sync);
//because dump() may generate new log records, so that
//flush log again.
txnManager.getLogManager().flush();
//Just recount the checkpoint bytes.
txnManager.getLogManager().initChkptBytes();
txnManager.setLastCkp(ckpLsn);
txnManager.setTimeCkp(System.currentTimeMillis());
// }
} finally {
// txnManager.getLogManager().closeLogFile();
}
}
}