package com.neocoretechs.bigsack.io.request.cluster;
import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import com.neocoretechs.bigsack.io.IoInterface;
import com.neocoretechs.bigsack.io.RecoveryLogManager;
import com.neocoretechs.bigsack.io.pooled.MappedBlockBuffer;
import com.neocoretechs.bigsack.io.request.iomanager.CommitBufferFlushRequest;
/**
* A special case of request the does not propagate outward to workers but instead is
* used to serialize commit/rollback etc. on the request queue. The overridden method
* of AbstractClusterWork 'doPropagate' is set false to prevent this request from
* traveling outward to nodes. The commit is two stage, with the first local
* operation happening which pushes out blocks from resident buffer polls to nodes.
* In the second stage a request si sent to the nodes, causing the buffers to be persisted.
* In lieu of waiting for a synchronization or waiting for the queue to empty, queue this
* type of special request to assure completion. We use countdown latches to control synchronization.
* These latches are not serializable so we maintain them separately at the nodes.
* This is an intent parallel computation component of a tablespace wide request.
* We are using a CyclicBarrier set up with the number of tablespaces and after each thread
* does a commit it will await the barrier synch.
* Once released from barrier synch a countdown latch is decreased which activates the
* IO manager countdown latch waiter when count reaches 0, thereby releasing the thread
* to proceed. The commit request is a proxy to send the commit request to the block pools. Rather than
* wait for a semaphore or other synchronization, we are queuing a request to run when appropriate to achieve
* serial computation
* Copyright (C) NeoCoreTechs 2014
* @author jg
*
*/
public final class CommitRequest extends AbstractClusterWork implements CompletionLatchInterface, Serializable {
private static final long serialVersionUID = 1L;
private transient MappedBlockBuffer blockManager;
private transient CyclicBarrier barrierSynch;
private int tablespace;
private transient CountDownLatch barrierCount;
private transient RecoveryLogManager recoveryLog;
private transient IoInterface ioManager;
/**
* We re use the barriers, they are cyclic, so they are stored as fields
* in the blockManager and passed here
* @param blockBuffer
* @param barrierSynch
* @param barrierCount
*/
public CommitRequest(MappedBlockBuffer blockBuffer, RecoveryLogManager rlog, CyclicBarrier barrierSynch, CountDownLatch barrierCount) {
this.blockManager = blockBuffer;
this.recoveryLog = rlog;
this.barrierSynch = barrierSynch;
this.barrierCount = barrierCount;
}
@Override
public void process() throws IOException {
CommitBufferFlushRequest cbfr = new CommitBufferFlushRequest(blockManager, recoveryLog, barrierCount, barrierSynch);
cbfr.setIoInterface(ioManager);
blockManager.queueRequest(cbfr);
}
@Override
public long getLongReturn() {
return -1L;
}
@Override
public Object getObjectReturn() {
return new Long(-1L);
}
/**
* This method is called by queueRequest to set the proper tablespace from IOManager
* It is the default way to set the active IO unit
*/
@Override
public void setIoInterface(IoInterface ioi) {
ioManager = ioi;
}
@Override
public void setTablespace(int tablespace) {
this.tablespace = tablespace;
}
public String toString() {
return "Commit Request for tablespace "+tablespace;
}
@Override
public CountDownLatch getCountDownLatch() {
return barrierCount;
}
@Override
public void setCountDownLatch(CountDownLatch cdl) {
this.barrierCount = cdl;
}
@Override
public void setLongReturn(long val) {
}
@Override
public void setObjectReturn(Object o) {
}
@Override
public CyclicBarrier getCyclicBarrier() {
return barrierSynch;
}
@Override
public void setCyclicBarrier(CyclicBarrier cb) {
barrierSynch = cb;
}
@Override
public boolean doPropagate() { return false; }
}