package com.neocoretechs.bigsack.io;
import java.io.IOException;
import java.io.Serializable;
import com.neocoretechs.arieslogger.core.LogInstance;
import com.neocoretechs.arieslogger.core.impl.CompensationBlock;
import com.neocoretechs.arieslogger.logrecords.Compensation;
import com.neocoretechs.arieslogger.logrecords.Loggable;
import com.neocoretechs.arieslogger.logrecords.Undoable;
import com.neocoretechs.bigsack.Props;
import com.neocoretechs.bigsack.io.pooled.BlockAccessIndex;
import com.neocoretechs.bigsack.io.pooled.GlobalDBIO;
import com.neocoretechs.bigsack.io.pooled.ObjectDBIO;
/**
* Writes out a log record to the log stream, and call its applyChange method to
apply the change to the rawStore.
<BR>Any optional data the applyChange method needs is first written to the log
stream using operation.writeOptionalData, then whatever is written to
the log stream is passed back to the operation for the applyChange method.
* @author jg
*
*/
public final class UndoableBlock implements Undoable, Serializable {
private static final long serialVersionUID = 3823704109110419908L;
private BlockAccessIndex blkV1,blkV2; // utility blocks
public UndoableBlock(BlockAccessIndex tblk, BlockAccessIndex blk) {
blkV1 = tblk;
blkV2 = blk;
}
public BlockAccessIndex getBlkV1() {
return blkV1;
}
public BlockAccessIndex getBlkV2() {
return blkV2;
}
/**
* When writing out a log record to the log stream, logger will call its applyChange method to
apply the change to the rawStore.
Any optional data the applyChange method needs is first written to the log
stream using operation.writeOptionalData, then whatever is written to
the log stream is passed back to the operation for the applyChange method.
*/
@Override
public void applyChange(ObjectDBIO xact, LogInstance instance, Object in) throws IOException {
if( Props.DEBUG ) {
System.out.println("UndoableBlock.applyChange: instance:"+instance+" raw store"+blkV2.getBlockNum()+","+blkV2.getBlk());
}
blkV2.getBlk().setPageLSN(instance.getValueAsLong());
//xact.FseekAndWrite(blkV2.getBlockNum(), blkV2.getBlk()); // sets incore false
int tblsp = GlobalDBIO.getTablespace(blkV2.getBlockNum());
long blkn = GlobalDBIO.getBlock(blkV2.getBlockNum());
//synchronized(xact.getIOManager().getDirectIO(tblsp)) {
// xact.getIOManager().getDirectIO(tblsp).Fseek(blkn);
// blkV2.getBlk().write(xact.getIOManager().getDirectIO(tblsp));
//}
xact.getIOManager().writeDirect(tblsp, blkn, blkV2.getBlk());
// deallocate
blkV2.decrementAccesses();
}
@Override
public byte[] getPreparedLog() throws IOException {
return null;
}
/**
* <P> The sequence of events in recovery redo of a Loggable operation is:
<NL>
<LI> Get the loggable operation. If loggable.needsRedo is false, then
no need to redo this operation.
<LI> If loggable.needsRedo is true, all the resources necessary for
applying the applyChange is acquired in needsRedo.
<LI> If the loggable is actually a compensation operation, then the
logging system will find the undoable operation that needs to be
undone, call compensation.setUndoOp with the undoable operation.
<LI> The recovery system then calls loggable.applyChange, which re-applies the
loggable operation, or re-applies the compensation operation
<LI> The recovery system then calls loggable.releaseResource.
*/
@Override
public boolean needsRedo(ObjectDBIO xact) throws IOException {
return true;
}
@Override
public void releaseResource(ObjectDBIO xact) {
}
@Override
public int group() {
return Loggable.BI_LOG;
}
@Override
public Compensation generateUndo(ObjectDBIO xact) throws IOException {
return new CompensationBlock();
}
public String toString() {
return "Undoable block version 1:"+blkV1+" version 2:"+blkV2;
}
}