/*
* 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.recover;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.helper.FileUtil;
import org.chaidb.db.log.LogRecord;
import org.chaidb.db.log.RecordFactory;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.LinkedList;
public class RedoList {
LinkedHashMap txnList = new LinkedHashMap(16, (float) 0.75, true);
LinkedList lastTxnList;
long logCount;
public RedoList() {
File dir = new File(PositiveRecovery.DR_TMP_DIR);
if (dir.exists() && dir.isDirectory()) {
FileUtil.removeFileOrDirectory(dir);
}
dir.mkdirs();
}
/**
* Create a txn entry for the log, then push it to the entry
*
* @param log
* @throws ChaiDBException
*/
public void add(LogRecord log) throws ChaiDBException {
int txnId = log.getTxnId();
TransactionLog txnLog = new TransactionLog(txnId);
txnList.put(new Integer(txnId), txnLog);
push(log);
logCount++;
}
/**
* push a log to corresponding txn entry, if the entry does not exist, aborts the log.
*
* @param log
* @return the logrecord which is put to stack successfully, or <tt>null</tt>
* if the txn doesn't exist in stack.
* @throws ChaiDBException
*/
public LogRecord push(LogRecord log) throws ChaiDBException {
int txnId = log.getTxnId();
TransactionLog txnLog = (TransactionLog) txnList.get(new Integer(txnId));
if (txnLog != null) {
byte[] data = new byte[log.getRecordLength()];
log.toBytes(data, 0);
txnLog.push(data);
// txnList.remove(txnLog);
// txnList.push(new Integer(txnId), txnLog);
} else {
return null;
}
logCount++;
return log;
}
/**
* Pop a log from stack
*
* @return the logrecord which on the top of the stack
* @throws ChaiDBException
*/
public LogRecord pop() throws ChaiDBException {
if (lastTxnList == null) {
TransactionLog[] arrList = new TransactionLog[txnList.size()];
arrList = (TransactionLog[]) txnList.values().toArray(arrList);
lastTxnList = new LinkedList();
for (int i = arrList.length - 1; i >= 0; i--) {
lastTxnList.add(arrList[i]);
}
}
while (lastTxnList.size() > 0) {
TransactionLog transactionLog = (TransactionLog) lastTxnList.getFirst();
byte[] data = transactionLog.pop();
if (data != null) {
LogRecord log = RecordFactory.createRecord(data, 0);
if (log != null) {
logCount++;
return log;
}
}
lastTxnList.removeFirst();
}
return null;
}
/**
* Pack the txn stack to a file.
*
* @param txnId
* @return <tt>true</tt> if the pack the txn stack successfully, or
* <tt>false</tt> if the txn doesn't exist in stack.
*/
public boolean pack(int txnId) {
TransactionLog txnLog = (TransactionLog) txnList.get(new Integer(txnId));
if (txnLog != null) {
txnLog.pack();
return true;
}
return false;
}
/**
* Clean the temp directory.
*
* @return true if successfully, or false if not.
*/
public boolean clean() {
//clean up
return FileUtil.removeFileOrDirectory(new File(PositiveRecovery.DR_TMP_DIR));
}
public long getLogCount() {
return logCount;
}
}