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.DBPhysicalConstants; import com.neocoretechs.bigsack.io.IoInterface; import com.neocoretechs.bigsack.io.pooled.Datablock; /** * This is a cluster parallel computation component of a tablespace wide request. * We forego the cyclicbarrier in favor of a countdownlatch that waits for responses from the * available masters, after they have received the results from each cluster node. * Copyright (C) NeoCoreTechs 2014 * @author jg * */ public final class GetNextFreeBlocksRequest extends AbstractClusterWork implements CompletionLatchInterface, Serializable { private static final long serialVersionUID = 4504873855639883545L; private long nextFreeBlock = 0L; private transient IoInterface ioUnit; private Datablock d = new Datablock(DBPhysicalConstants.DATASIZE); private int tablespace; private transient CountDownLatch barrierCount; public GetNextFreeBlocksRequest(){} public GetNextFreeBlocksRequest(CountDownLatch barrierCount) { this.barrierCount = barrierCount; } @Override public void process() throws IOException { getNextFreeBlocks(); barrierCount.countDown(); } /** * Set the next free block position from reverse scan of blocks * next free will be set to -1 if there are no free blocks * @exception IOException if seek or size fails */ private void getNextFreeBlocks() throws IOException { long endBlock = 0L; long endBl = ioUnit.Fsize(); nextFreeBlock = -1L; // assume there are none while (endBl > endBlock) { ioUnit.Fseek(endBl - (long) DBPhysicalConstants.DBLOCKSIZ); d.read(ioUnit); if (d.getPrevblk() == -1L && d.getNextblk() == -1L && d.getBytesused() == 0 && d.getBytesinuse() == 0) { endBl -= (long) DBPhysicalConstants.DBLOCKSIZ; continue; } else { // this is it nextFreeBlock = ioUnit.Ftell();// the read position at the end of the block that is used, the new block break; } } } @Override public long getLongReturn() { return nextFreeBlock; } @Override public Object getObjectReturn() { return new Long(nextFreeBlock); } /** * 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) { this.ioUnit = ioi; } /** * This method also set by queueRequest */ @Override public void setTablespace(int tablespace) { this.tablespace = tablespace; } public String toString() { return getUUID()+",tablespace:"+tablespace+":GetNextFreeBlocksRequest:"+nextFreeBlock; } /** * The latch will be extracted by the UDPMaster and when a response comes back it will be tripped */ @Override public CountDownLatch getCountDownLatch() { return barrierCount; } @Override public void setCountDownLatch(CountDownLatch cdl) { barrierCount = cdl; } @Override public void setLongReturn(long val) { nextFreeBlock = val; } @Override public void setObjectReturn(Object o) { nextFreeBlock = (Long) o; } @Override public CyclicBarrier getCyclicBarrier() { return null; } @Override public void setCyclicBarrier(CyclicBarrier cb) { } }