package org.wonderdb.freeblock; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.jboss.netty.buffer.ChannelBuffer; import org.wonderdb.block.BlockManager; import org.wonderdb.block.IndexBranchBlock; import org.wonderdb.cache.impl.CacheEntryPinner; import org.wonderdb.cache.impl.CacheHandler; import org.wonderdb.cache.impl.SecondaryCacheHandlerFactory; import org.wonderdb.cache.impl.SecondaryCacheResourceProvider; import org.wonderdb.cache.impl.SecondaryCacheResourceProviderFactory; import org.wonderdb.file.StorageUtils; import org.wonderdb.seralizers.block.SerializedBlockImpl; import org.wonderdb.serialize.SerializerManager; import org.wonderdb.serialize.block.BlockSerilizer; import org.wonderdb.storage.FileBlockManager; import org.wonderdb.txnlogger.TransactionId; import org.wonderdb.types.BlockPtr; import org.wonderdb.types.ColumnSerializerMetadata; import org.wonderdb.types.SingleBlockPtr; import org.wonderdb.types.record.IndexRecord; import org.wonderdb.types.record.Record; class FreeBlockMgrNew { private static SecondaryCacheResourceProvider secondaryResourceProvider = SecondaryCacheResourceProviderFactory.getInstance().getResourceProvider(); private static CacheHandler<BlockPtr, ChannelBuffer> secondaryCacheHandler = SecondaryCacheHandlerFactory.getInstance().getCacheHandler(); byte fileId; int freePosnsSize = 0; int lowWatermark; int highWatermark; AtomicBoolean backendSyncRunning = new AtomicBoolean(false); IndexBranchBlock currentBlock = null; List<BlockPtr> freePtrList = new ArrayList<BlockPtr>(); FreeBlockMgrNew(byte fileId, int lowWatermarkMultiplier, int highWatermarkMultiplier) { // Set<Object> pinnedBlocks = new HashSet<>(); // try { // this.fileId = fileId; // BlockPtr ptr = new SingleBlockPtr(fileId, 0); // CacheEntryPinner.getInstance().pin(ptr, pinnedBlocks); // SerializedBlockImpl sb = (SerializedBlockImpl) secondaryCacheHandler.get(ptr); // if (sb == null) { // sb = (SerializedBlockImpl) InflightFileReader.getInstance().getBlock(ptr); // secondaryCacheHandler.addIfAbsent(sb); // } // currentBlock = new IndexBranchBlock(ptr); // initialize(sb, lowWatermarkMultiplier, highWatermarkMultiplier); // } finally { // CacheEntryPinner.getInstance().unpin(pinnedBlocks, pinnedBlocks); // } } public FreeBlockMgrNew(byte fileId, TransactionId txnId, int lowWatermarkMultiplier, int highWatermarkMultiplier) { // Set<Object> pinnedBlocks = new HashSet<>(); // SerializedBlockImpl sb = null; // BlockPtr ptr = new SingleBlockPtr(fileId, 0); // this.fileId = fileId; // try { // CacheEntryPinner.getInstance().pin(ptr, pinnedBlocks); // sb = (SerializedBlockImpl) secondaryResourceProvider.getResource(ptr, StorageUtils.getInstance().getSmallestBlockCount(ptr)); // currentBlock = new IndexBranchBlock(ptr); // BlockSerilizer.getInstance().serialize(currentBlock, new ColumnSerializerMetadata(SerializerManager.BLOCK_PTR), txnId); // secondaryCacheHandler.addIfAbsent(sb); // initialize(sb, lowWatermarkMultiplier, highWatermarkMultiplier); // } finally { // LogManager.getInstance().logBlock(txnId, sb); // CacheEntryPinner.getInstance().unpin(ptr, pinnedBlocks); // } } // private void initialize(SerializedBlockImpl sb, int lowWatermarkMultiplier, int highWatermarkMultiplier) { // int size = sb.getData().capacity(); // freePosnsSize = size/10 - 2; // lowWatermark = freePosnsSize * lowWatermarkMultiplier; // highWatermark = freePosnsSize * highWatermarkMultiplier; // } public synchronized void returnBlock(BlockPtr ptr) { freePtrList.add(ptr); if (freePtrList.size() >= highWatermark && !backendSyncRunning.get()) { FreeBlockFactory.getInstance().triggerWrite(this); } } public synchronized long getFreePosn() { // BlockPtr ptr = null; // if (freePtrList.size() > 0) { // ptr = freePtrList.get(freePtrList.size()-1); // } // if (ptr != null && ptr.getBlockPosn() >= 0) { // return ptr.getBlockPosn(); // } // // if (freePtrList.size() <= lowWatermark && !backendSyncRunning.get()) { // FreeBlockFactory.getInstance().triggerRead(this); // } long posn = FileBlockManager.getInstance().getNextBlock(fileId); return posn; } public void read() { if (!backendSyncRunning.compareAndSet(false, true)) { return; } Set<Object> pinnedBlocks = new HashSet<Object>(); SerializedBlockImpl sb = null; try { if (!currentBlock.getData().isEmpty()) { CacheEntryPinner.getInstance().pin(currentBlock.getPtr(), pinnedBlocks); sb = (SerializedBlockImpl) secondaryCacheHandler.get(currentBlock.getPtr()); if (sb == null) { sb = (SerializedBlockImpl) secondaryResourceProvider.getResource(currentBlock.getPtr(), StorageUtils.getInstance().getSmallestBlockCount(currentBlock.getPtr())); secondaryCacheHandler.addIfAbsent(sb); } } else { currentBlock = moveToNonEmptyBlock(pinnedBlocks); } if (!currentBlock.getData().isEmpty()) { synchronized (this) { List<Record> list = currentBlock.getData(); for (int i = 0; i < list.size(); i++) { IndexRecord record = (IndexRecord) list.get(i); BlockPtr p = (BlockPtr) record.getColumn(); freePtrList.add(p); } list.clear(); } BlockSerilizer.getInstance().serialize(currentBlock, new ColumnSerializerMetadata(SerializerManager.BLOCK_PTR), null); } } finally { CacheEntryPinner.getInstance().unpin(pinnedBlocks, pinnedBlocks); backendSyncRunning.set(false); } } private IndexBranchBlock moveToNonEmptyBlock(Set<Object> pinnedBlocks) { BlockPtr ptr = null; CacheEntryPinner.getInstance().pin(currentBlock.getPtr(), pinnedBlocks); if (!currentBlock.getData().isEmpty()) { return currentBlock; } ptr = new SingleBlockPtr(fileId, 0); while (ptr != null) { SerializedBlockImpl sb = getSerializedBlock(ptr, pinnedBlocks); currentBlock = new IndexBranchBlock(sb.getPtr()); if (currentBlock.getData().isEmpty()) { ptr = currentBlock.getNext(); } } return currentBlock; } private void addPtrList(IndexBranchBlock block, List<BlockPtr> list) { IndexRecord record = null; for (int i = 0; i < list.size(); i++) { BlockPtr ptr = list.get(i); record = new IndexRecord(); record.setColumn(ptr); } block.getData().add(record); } public void write() { Set<Object> pinnedBlocks = new HashSet<Object>(); if (!backendSyncRunning.compareAndSet(false, true)) { return; } List<BlockPtr> writeList = new ArrayList<BlockPtr>(); for (int i = 0; i < freePosnsSize; i++) { writeList.add(freePtrList.get(0)); } try { CacheEntryPinner.getInstance().pin(currentBlock.getPtr(), pinnedBlocks); if (!currentBlock.getData().isEmpty()) { long l = getFreePosn(); BlockPtr p = new SingleBlockPtr(fileId, l); CacheEntryPinner.getInstance().pin(p, pinnedBlocks); IndexBranchBlock block = (IndexBranchBlock) BlockManager.getInstance().createBranchBlock(p, pinnedBlocks); currentBlock.setNext(p); BlockSerilizer.getInstance().serialize(currentBlock, new ColumnSerializerMetadata(SerializerManager.BLOCK_PTR), null); currentBlock = block; } addPtrList(currentBlock, freePtrList); BlockSerilizer.getInstance().serialize(currentBlock, new ColumnSerializerMetadata(SerializerManager.BLOCK_PTR), null); } finally { CacheEntryPinner.getInstance().unpin(pinnedBlocks, pinnedBlocks); backendSyncRunning.set(false); } } // private SerializedBlockImpl getFreeResource(BlockPtr ptr, Set<Object> pinnedBlocks) { // SerializedBlockImpl sb = (SerializedBlockImpl) secondaryCacheHandler.get(ptr, pinnedBlocks); // if (sb == null) { // sb = (SerializedBlockImpl) secondaryResourceProvider.getResource(ptr, StorageUtils.getInstance().getSmallestBlockCount(ptr)); // secondaryCacheHandler.addIfAbsent(sb, pinnedBlocks); // } // return sb; // } private SerializedBlockImpl getSerializedBlock(BlockPtr ptr, Set<Object> pinnedBlocks) { BlockManager.getInstance().getBlock(ptr, new ColumnSerializerMetadata(SerializerManager.BLOCK_PTR), pinnedBlocks); SerializedBlockImpl sbCurrentBlock = (SerializedBlockImpl) secondaryCacheHandler.get(ptr); return sbCurrentBlock; } // // private class FreeBlock { // BlockPtr nextPtr = null; // BlockPtr currentPtr = null; // List<BlockPtr> ptrList = new ArrayList<>(); // // FreeBlock(SerializedBlockImpl sb) { // ChannelBuffer buffer = sb.getData(); // buffer.clear(); // buffer.writerIndex(buffer.capacity()); // while (buffer.readable()) { // int size = buffer.readInt(); // for (int i = 0; i < size; i++) { // long p = buffer.readLong(); // BlockPtr ptr = new SingleBlockPtr(fileId, p); // ptrList.add(ptr); // } // long p = buffer.readLong(); // if (p >= 0) { // nextPtr = new SingleBlockPtr(fileId, p); // } // } // } // // FreeBlock(BlockPtr currentPtr, BlockPtr nextPtr, List<BlockPtr> ptrList) { // this.nextPtr = nextPtr; // this.ptrList = ptrList; // } // // private void serialize(SerializedBlockImpl sb) { // ChannelBuffer buffer = sb.getData(); // buffer.clear(); // // for (int i = 0; i < ptrList.size(); i++) { // buffer.writeLong(ptrList.get(i).getBlockPosn()); // } // long p = nextPtr == null ? -1 : nextPtr.getBlockPosn(); // buffer.writeLong(p); // } // // BlockPtr getNextPtr() { // return nextPtr; // } // // List<BlockPtr> getPtrList() { // return ptrList; // } // // void setNextPtr(BlockPtr p) { // nextPtr = p; // } // // void setPtrList(List<BlockPtr> list) { // this.ptrList = list; // } // } }