package org.wonderdb.serialize.block; import java.util.ArrayList; import java.util.List; import org.jboss.netty.buffer.ChannelBuffer; import org.wonderdb.block.Block; import org.wonderdb.block.IndexBranchBlock; import org.wonderdb.block.IndexLeafBlock; import org.wonderdb.block.ListBlock; import org.wonderdb.cache.impl.CacheHandler; import org.wonderdb.cache.impl.SecondaryCacheHandlerFactory; import org.wonderdb.seralizers.block.SerializedBlockImpl; import org.wonderdb.serialize.Serializer; import org.wonderdb.serialize.SerializerManager; import org.wonderdb.serialize.record.ObjectRecordSerializer; import org.wonderdb.serialize.record.RecordSerializer; import org.wonderdb.serialize.record.TableRecordSerializer; import org.wonderdb.txnlogger.LogManager; import org.wonderdb.txnlogger.TransactionId; import org.wonderdb.types.BlockPtr; import org.wonderdb.types.ColumnSerializerMetadata; import org.wonderdb.types.RecordId; import org.wonderdb.types.TableRecordMetadata; import org.wonderdb.types.TypeMetadata; import org.wonderdb.types.record.ExtendedTableRecord; import org.wonderdb.types.record.ListRecord; import org.wonderdb.types.record.ObjectRecord; import org.wonderdb.types.record.Record; import org.wonderdb.types.record.TableRecord; public class BlockSerilizer { private static CacheHandler<BlockPtr, ChannelBuffer> secondaryCacheHandler = SecondaryCacheHandlerFactory.getInstance().getCacheHandler(); private static final int BLOCK_HEADER = SerializedBlockImpl.HEADER_SIZE + 1 /* block header */ + (1 + Long.SIZE/8) /* prev pointer */ + (1 + Long.SIZE/8) /* next pointer */ + Integer.SIZE/8 /* reserved */ + Integer.SIZE/8 /* record list size */; public static final int INDEX_BLOCK_HEADER = BLOCK_HEADER + (1 + Long.SIZE/8) /* parent pointer */; public static final int LIST_BLOCK_HEADER = BLOCK_HEADER + Integer.SIZE/8 /* max posn */; private static BlockSerilizer instance = new BlockSerilizer(); private BlockSerilizer() { } public static BlockSerilizer getInstance() { return instance; } public void serialize(Block block, TypeMetadata meta, TransactionId id) { SerializedBlockImpl serializedBlock = (SerializedBlockImpl) secondaryCacheHandler.get(block.getPtr()); serializedBlock.setLastAccessTime(block.getLastAccessTime()); ChannelBuffer buffer = serializedBlock.getData(); buffer.clear(); BlockHeader header = getBlockHeader(block); BlockHeaderSerializer.getInstance().serialize(header, buffer); Serializer.getInstance().serialize(SerializerManager.BLOCK_PTR, block.getNext(), buffer, null); Serializer.getInstance().serialize(SerializerManager.BLOCK_PTR, block.getPrev(), buffer, null); buffer.writeInt(0); //reserved if (header.isIndexBlock() || header.isIndexBranchBlock()) { // Serializer.getInstance().serialize(SerializerManager.BLOCK_PTR, block.getParent(), buffer, meta); Serializer.getInstance().serialize(SerializerManager.BLOCK_PTR, null, buffer, meta); } else { int maxPosn = ((ListBlock) block).getMaxPosn(); buffer.writeInt(maxPosn); } List<Record> list = block.getData(); buffer.writeInt(list.size()); for (int i = 0; i < list.size(); i++) { TypeMetadata newMeta = meta; Record record = list.get(i); if (record instanceof ListRecord) { RecordId recordId = ((ListRecord) record).getRecordId(); buffer.writeInt(recordId.getPosn()); } RecordSerializer.getInstance().serializeMinimum(record, buffer, newMeta); } secondaryCacheHandler.changed(block.getPtr()); LogManager.getInstance().logBlock(id, serializedBlock); } public Block getBlock(SerializedBlockImpl serializedBlock, TypeMetadata meta) { BlockPtr ptr = serializedBlock.getPtr(); ChannelBuffer buffer = serializedBlock.getData(); BlockHeader header = BlockHeaderSerializer.getInstance().getHeader(buffer); BlockPtr nextPtr = (BlockPtr) Serializer.getInstance().getObject(SerializerManager.BLOCK_PTR, buffer, meta); BlockPtr prevPtr = (BlockPtr) Serializer.getInstance().getObject(SerializerManager.BLOCK_PTR, buffer, meta); int reserved = buffer.readInt(); BlockPtr parentPtr = null; TypeMetadata newMeta = meta; Block block = null; int maxPosn = -1; if (header.isIndexBlock() || header.isIndexBranchBlock()) { parentPtr = (BlockPtr) Serializer.getInstance().getObject(SerializerManager.BLOCK_PTR, buffer, meta); } else { maxPosn = buffer.readInt(); } if (header.isIndexBranchBlock()) { block = new IndexBranchBlock(ptr); block.setParent(parentPtr); } else if (header.isIndexBlock()) { block = new IndexLeafBlock(ptr); block.setParent(parentPtr); } else { block = new ListBlock(ptr); ((ListBlock) block).setMaxPosn(maxPosn); } block.setNext(nextPtr); block.setPrev(prevPtr); block.setLastAccessTime(System.currentTimeMillis()); int size = buffer.readInt(); List<Record> list = new ArrayList<Record>(size); block.setData(list); for (int i = 0; i < size; i++) { Record record = null; if (header.isIndexBranchBlock()) { newMeta = new ColumnSerializerMetadata(SerializerManager.BLOCK_PTR); record = ObjectRecordSerializer.getInstance().readMinimum(header, buffer, newMeta); } else if (header.isIndexBlock()) { record = ObjectRecordSerializer.getInstance().readMinimum(header, buffer, meta); } else if (meta instanceof TableRecordMetadata){ int posn = buffer.readInt(); record = TableRecordSerializer.getInstance().readMinimum(buffer, meta); ((ListRecord) record).setRecordId(new RecordId(ptr, posn)); } else { int posn = buffer.readInt(); record = ObjectRecordSerializer.getInstance().readMinimum(header, buffer, meta); ((ListRecord) record).setRecordId(new RecordId(ptr, posn)); } list.add(record); } return block; } public int getBlockSize(Block block, TypeMetadata meta) { int size = 0; if (block instanceof ListBlock) { size = size + LIST_BLOCK_HEADER; } else { size = size + INDEX_BLOCK_HEADER; } List<Record> list = block.getData(); for (int i = 0; i < list.size(); i++) { Record record = list.get(i); if (record instanceof ExtendedTableRecord) { size = size + 9; } else if (record instanceof ObjectRecord) { size = size + ObjectRecordSerializer.getInstance().getObjectSize(record, meta); } else if (record instanceof TableRecord) { size = size + TableRecordSerializer.getInstance().getObjectSize(record, meta); } } return size; } private BlockHeader getBlockHeader(Block block) { BlockHeader header = new BlockHeader(); if (block instanceof IndexBranchBlock) { header.setIndexBranchBlock(true); } if (block instanceof IndexLeafBlock) { header.setIndexBlock(true); } return header; } }