package org.wonderdb.helper;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.wonderdb.cache.Cacheable;
import org.wonderdb.cache.impl.CacheEntryPinner;
import org.wonderdb.cache.impl.CacheHandler;
import org.wonderdb.cache.impl.InflightFileReader;
import org.wonderdb.cache.impl.PrimaryCacheResourceProvider;
import org.wonderdb.cache.impl.PrimaryCacheResourceProviderFactory;
import org.wonderdb.cache.impl.SecondaryCacheHandlerFactory;
import org.wonderdb.core.collection.ExtendedUtils;
import org.wonderdb.file.StorageUtils;
import org.wonderdb.freeblock.FreeBlockFactory;
import org.wonderdb.serialize.DefaultSerializer;
import org.wonderdb.serialize.Serializer;
import org.wonderdb.serialize.SerializerManager;
import org.wonderdb.types.BlockPtr;
public class LazyExtendedSpaceProvider {
private static CacheHandler<BlockPtr, ChannelBuffer> secondaryCacheHandler = SecondaryCacheHandlerFactory.getInstance().getCacheHandler();
// private static SecondaryCacheResourceProvider cacheResourceProvider = SecondaryCacheResourceProviderFactory.getInstance().getResourceProvider();
PrimaryCacheResourceProvider primaryResourceProvider = PrimaryCacheResourceProviderFactory.getInstance().getResourceProvider();
private static LazyExtendedSpaceProvider instance = new LazyExtendedSpaceProvider();
private LazyExtendedSpaceProvider() {
}
public static LazyExtendedSpaceProvider getInstance() {
return instance;
}
public ChannelBuffer provideSpaceToRead(List<BlockPtr> extendedPtrs, Set<Object> pinnedBlocks) {
BlockPtr currentPtr = extendedPtrs.get(0);
Cacheable<BlockPtr, ChannelBuffer> currentBlock = null;
List<ChannelBuffer> list = new ArrayList<ChannelBuffer>();
while (true) {
if (currentPtr == null) {
break;
}
CacheEntryPinner.getInstance().pin(currentPtr, pinnedBlocks);
currentBlock = secondaryCacheHandler.get(currentPtr);
if (currentBlock == null) {
currentBlock = InflightFileReader.getInstance().getBlock(currentPtr);
}
primaryResourceProvider.getResource(currentPtr, StorageUtils.getInstance().getSmallestBlockCount(currentPtr));
ChannelBuffer b = currentBlock.getData();
b.writerIndex(b.capacity());
currentPtr = (BlockPtr) Serializer.getInstance().getObject(SerializerManager.BLOCK_PTR, b, null);
if (currentPtr != null) {
extendedPtrs.add(currentPtr);
}
ChannelBuffer buffer = b.slice(10, b.capacity()-10);
buffer.clear();
buffer.writerIndex(buffer.capacity());
list.add(buffer);
}
ChannelBuffer[] bufer = new ChannelBuffer[list.size()];
ChannelBuffer buf = ChannelBuffers.wrappedBuffer(list.toArray(bufer));
buf.clear();
buf.writerIndex(buf.capacity());
return buf;
}
public ChannelBuffer provideSpaceToWrite(byte fileId, List<BlockPtr> list, int requiredBlocks, Set<Object> pinnedBlocks) {
List<ChannelBuffer> buffers = new ArrayList<ChannelBuffer>();
Cacheable<BlockPtr, ChannelBuffer> block = null;
while (list.size() > requiredBlocks) {
BlockPtr p = list.remove(list.size()-1);
CacheEntryPinner.getInstance().pin(p, pinnedBlocks);
secondaryCacheHandler.remove(p);
primaryResourceProvider.returnResource(p);
FreeBlockFactory.getInstance().returnBlock(p);
}
while (requiredBlocks > list.size()) {
List<BlockPtr> l = ExtendedUtils.getInstance().extend(fileId, pinnedBlocks);
BlockPtr p = l.get(l.size()-1);
BlockPtr prevPtr = list.get(list.size()-1);
if (p.getBlockPosn() < prevPtr.getBlockPosn()) {
int x = 0;
x=20;
}
CacheEntryPinner.getInstance().pin(prevPtr, pinnedBlocks);
block = secondaryCacheHandler.get(prevPtr);
ChannelBuffer buf = block.getData();
buf.clear();
Serializer.getInstance().serialize(SerializerManager.BLOCK_PTR, p, buf, null);
list.add(p);
}
BlockPtr p = list.get(list.size()-1);
CacheEntryPinner.getInstance().pin(p, pinnedBlocks);
block = secondaryCacheHandler.get(p);
ChannelBuffer buf = block.getData();
buf.clear();
Serializer.getInstance().serialize(SerializerManager.BLOCK_PTR, DefaultSerializer.NULL_BLKPTR, buf, null);
for (int i = 0; i < list.size(); i++) {
CacheEntryPinner.getInstance().pin(list.get(i), pinnedBlocks);
block = secondaryCacheHandler.get(list.get(i));
block.getData().clear();
ChannelBuffer b = block.getData().slice(10, block.getData().capacity()-10);
b.clear();
b.writerIndex(b.capacity());
buffers.add(b);
}
if (requiredBlocks > 0) {
ChannelBuffer[] b = new ChannelBuffer[buffers.size()];
ChannelBuffer bufer = ChannelBuffers.wrappedBuffer(buffers.toArray(b));
bufer.clear();
return bufer;
}
return null;
}
}