* 2.do undo to checkpoint in V3.0
* V3.1 should be compatible to V3.0
*/
protected boolean undo() throws ChaiDBException {
this.status = UNDO_STAGE;
Lsn cursorLsn = null;
LogRecord cursorLogRecord = null;
int countCkp = 0; //checkpoint count number
//Gets the lastest lsn in lsn.idb file.
cursorLsn = txnManager.getLogManager().getLastLsnInFlush();
boolean isEnd = false;
Lsn smallestLsn = null;
while (!isEnd) {
try {
cursorLogRecord = txnManager.getLogManager().get(cursorLsn);
} catch (ChaiDBException e) {
logger.error(e);
throw e;
}
/* according to different log type to do different handling */
switch (cursorLogRecord.getType()) {
case LogRecord.LOG_TXN_CHILD:
break;
case LogRecord.LOG_TXN_CHECKPOINT://V3.0 standard checkpoint consistent state
countCkp++;
if (countCkp == 1) {
this.txnManager.setLastCkp(cursorLsn);
} else if (countCkp == 2) {
isEnd = true;
}
break;
case LogRecord.LOG_TXN_FUZZY_CHECKPOINT://V3.1 fuzzy checkpoint
countCkp++;
if (countCkp == 1) {
this.txnManager.setLastCkp(cursorLsn);
} else if (countCkp == 2) {
TxnFuzzyCkpLogRecord fuzzyCkpLog = (TxnFuzzyCkpLogRecord) cursorLogRecord;
/* V3.1, if no active txn while doing fuzzy checkpoint,
smallestLsn is equals to current checkpoint log lsn,if
has active txns,it's euqals to smallest first_lsn of all
active txns. */
smallestLsn = fuzzyCkpLog.getSmallestLsn();
}
break;
default:
//Adding TxnRegopLogRecord to redostack,and do its redo function for release txn resource of btree.
if (cursorLogRecord.getType() == LogRecord.LOG_TXN_REGOP) {
Integer txnid = new Integer(cursorLogRecord.getTxnId());
redoTable.put(txnid, txnid);
}
boolean doUNDO = false;
if (!redoTable.containsKey(new Integer(cursorLogRecord.getTxnId()))) {
doUNDO = true;
}
if (cursorLogRecord.getType() == LogRecord.LOG_DELETE_FILES) {
if (!redoTable.containsKey(new Integer(cursorLogRecord.getTxnId()))) {
Integer txnid = new Integer(cursorLogRecord.getTxnId());
redoTable.put(txnid, txnid);
}
doUNDO = false;
}
if (doUNDO) {
try {
cursorLogRecord.recover(LogRecord.UNDO);
} catch (ChaiDBException ie11) {
logger.error(ie11);
continue;
}
} else { //push into redo stack
redoStack.push(cursorLogRecord);
if (redoStack.size() == STACK_MAXSIZE) {
logger.info("Stack change. " + redoStack.size());
saveStack(cursorLsn);
logger.info(", New=" + redoStack.size() + " Stack" + (++stacks));
}
}
}//switch
if (cursorLsn.getOffset() == LogManager.FIRSTREC_PREVOFFSET || //current lsn is the first lsn of all log files
(smallestLsn != null && cursorLsn.compare(smallestLsn) == 0)//current lsn is equal to smallest lsn
) {
isEnd = true;
}
cursorLsn = new Lsn(cursorLsn.getFileId(), cursorLogRecord.getHeader().getPrevOffset());
}//while
if (countCkp == 0) {
this.txnManager.setLastCkp(new Lsn(LogManager.FIRSTREC_LSN));
}
return true;
}