/*
* 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.log.logrecord;
import org.apache.log4j.Logger;
import org.chaidb.db.Db;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.helper.ByteTool;
import org.chaidb.db.index.btree.bufmgr.PageBufferManager;
import org.chaidb.db.log.LogManager;
import org.chaidb.db.log.LogRecord;
import org.chaidb.db.log.Lsn;
import org.chaidb.db.transaction.Transaction;
import java.util.Date;
/*
* This is the standard log operation for commit.
* Note that we are using an int32_t for the timestamp. This means that
* in 2039 we will need to deprecate this log record and create one that
* either changes the Epoch or has a 64-bit offset.
*/
public class TxnRegopLogRecord extends LogRecord {
private static final Logger logger = Logger.getLogger(TxnRegopLogRecord.class);
private static PageBufferManager bpm = PageBufferManager.getInstance();
private byte opcode;
private long timeStamp;
static int TXN_REGOP_OPCODE_SIZE = 1; //1 bytes
static int TXN_REGOP_TIMESTAMP_SIZE = 8; //8 bytes
//===>>> Constant identifiers for opcode <<<<<=====
//public static int OPERATION_TXN_BEGIN = 1 ; /* begin a transaction */
//public static int OPERATION_TXN_COMMIT= 2; /* commit a transaction */
//public static int OPERATION_TXN_ABORT = 3 ; /* abort a transaction */
/**
* Default Constructor
*/
public TxnRegopLogRecord() {
super();
super.setType(LOG_TXN_REGOP);
}
/**
* Constructor
*
* @param newOpcode
* @param newTimeStamp
*/
public TxnRegopLogRecord(int newOpcode, long newTimeStamp) {
super();
this.opcode = (byte) newOpcode;
this.timeStamp = newTimeStamp;
super.setType(LOG_TXN_REGOP);
}
/**
* Constructor
*
* @param newOpcode
* @param newTimeStamp
* @param newTxnId
*/
public TxnRegopLogRecord(int newOpcode, long newTimeStamp, int newTxnId) {
super();
this.opcode = (byte) newOpcode;
this.timeStamp = newTimeStamp;
super.setType(LOG_TXN_REGOP);
super.setTxnId(newTxnId);
}
/**
* Cretate a TxnRegopLogRecord object
*
* @param newOpcode
* @param newTimeStamp
*/
public static TxnRegopLogRecord create(int newOpcode, long newTimeStamp) {
TxnRegopLogRecord newObj = new TxnRegopLogRecord();
newObj.setOpcode((byte) newOpcode);
newObj.setTimeStamp(newTimeStamp);
newObj.setType(LOG_TXN_REGOP);
return newObj;
}
/**
* set new opcode to current TxnRegopLogRecord Object
*
* @param newOpcode
*/
private void setOpcode(byte newOpcode) {
this.opcode = newOpcode;
}
/**
* set new timeStamp to current TxnRegopLogRecord Object
*
* @param newTimeStamp
*/
private void setTimeStamp(long newTimeStamp) {
this.timeStamp = newTimeStamp;
}
/**
* get opcode of current TxnRegopLogRecord Object
*
* @return int opcode
*/
public byte getOpcode() {
return opcode;
}
/**
* get timeStamp of current TxnRegopLogRecord Object
*
* @return long timeStamp
*/
public long getTimeStamp() {
return timeStamp;
}
/**
* just for compatible
*/
public String getBTreeFileName() {
return null;
}
/**
* user interface to add a log record and put it to buffer pool
*/
public Lsn log(int flag) throws ChaiDBException {
super.log();
LogManager logMgr = Db.getLogManager();
Lsn newLsn;
if (flag == Transaction.TXN_SYNC) {
newLsn = logMgr.put(this, LogManager.LOG_FLUSH);//flush log to log file while commit
} else {
newLsn = logMgr.put(this, LogManager.LOG_DATA);//not flush log to log file,just put it to log buffer
}
return newLsn;
}
/**
* converts a byte array into a log record instance
*/
public boolean read(byte[] bArr, int start) throws ChaiDBException {
/* construct a new LogRecord instance */
super.read(bArr, start);
/* get the values of TxnRegopLogRecord Object */
int step = start + super.getRecordLength();
opcode = bArr[step];
step = step + TXN_REGOP_OPCODE_SIZE;
timeStamp = ByteTool.bytesToLong(bArr, step, msbFirst);
return true;
}
/**
* redo or undo the operation for recovery
*/
public boolean recover(short flag) throws ChaiDBException {
/* added by marriane 2002-1-9 for release btree resource while do
recover's redo operation */
if (flag == LogRecord.REDO) {
bpm.releaseResource(super.getTxnId());
}
return true;
}
/**
* print data and help in debugging log files
*/
public void print() throws ChaiDBException {
//logger.debug("begin: printing the information of TxnRegopLogRecord object......");
super.print();
logger.debug("opcode:" + this.getOpcode());
logger.debug("timeStamp:" + new Date(this.getTimeStamp()).toString());
//logger.debug("end: printing the information of TxnRegopLogRecord object.");
}
/**
* converts a log record instance into a byte array.
* The byte array has the following format:
* ---------------------------------------------------
* | hdr | type | txn | prevLsn | opcode | timeStamp |
* ---------------------------------------------------
* hdr: 8 bytes,the byte array of the header,generated by Hdr.toBytes().
* type: 1 bytes.
* txnId: 4 bytes.
* prevLsn: 8 bytes,the byte array of the header of lsn,generated by Lsn.toBytes().
* <p/>
* opcode: 1 bytes.
* timeStamp: 8 bytes.
*/
public void toBytes(byte[] byteArray, int start) throws ChaiDBException {
super.toBytes(byteArray, start);
int step = start + super.getRecordLength();
byteArray[step] = opcode;
step += TXN_REGOP_OPCODE_SIZE;
ByteTool.longToBytes(byteArray, step, timeStamp);
}
/**
* get current log record type total length
*
* @return int total lenth
*/
public int getRecordLength() {
return super.getRecordLength() + TXN_REGOP_OPCODE_SIZE + TXN_REGOP_TIMESTAMP_SIZE;
}
}