package org.wonderdb.serialize; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.jboss.netty.buffer.ChannelBuffer; import org.wonderdb.cache.impl.CacheEntryPinner; import org.wonderdb.helper.LazyExtendedSpaceProvider; import org.wonderdb.types.BlockPtr; import org.wonderdb.types.ColumnHeader; import org.wonderdb.types.ColumnSerializerMetadata; //import org.wonderdb.types.ColumnSerializerMetadata; import org.wonderdb.types.DBType; import org.wonderdb.types.Extended; import org.wonderdb.types.ExtendedColumn; import org.wonderdb.types.IndexRecordMetadata; import org.wonderdb.types.NullType; import org.wonderdb.types.TypeMetadata; public class ColumnSerializer { public static ColumnSerializer instance = new ColumnSerializer(); private ColumnSerializer() { } static public ColumnSerializer getInstance() { return instance; } public DBType readMinimum(ChannelBuffer buffer, TypeMetadata meta) { ColumnHeader header = ColumnHeaderSerializer.getInstance().getHeader(buffer); if (header.isNull()) { return NullType.getInstance(); } DBType retVal = null; if (header.isExtended()) { BlockPtr ptr = (BlockPtr) Serializer.getInstance().getObject(SerializerManager.BLOCK_PTR, buffer, meta); List<BlockPtr> extendedPtrs = new ArrayList<BlockPtr>(); extendedPtrs.add(ptr); retVal = new ExtendedColumn(null, extendedPtrs); } else { int type = -1; if (meta instanceof ColumnSerializerMetadata){ type = ((ColumnSerializerMetadata) meta).getColumnId(); } else if (meta instanceof IndexRecordMetadata) { type = SerializerManager.INDEX_TYPE; } retVal = Serializer.getInstance().getObject(type, buffer, meta); } return retVal; } public void readFull(DBType column, TypeMetadata meta) { ChannelBuffer buf = null; Set<Object> pinnedBlocks = new HashSet<Object>(); try { if (column instanceof Extended) { buf = LazyExtendedSpaceProvider.getInstance().provideSpaceToRead(((Extended) column).getPtrList(), pinnedBlocks); } else { throw new RuntimeException("readFull should not be required for non extended columns"); } int type = -1; if (meta instanceof ColumnSerializerMetadata){ type = ((ColumnSerializerMetadata) meta).getColumnId(); } else if (meta instanceof IndexRecordMetadata) { type = SerializerManager.INDEX_TYPE; } DBType dt = Serializer.getInstance().getObject(type, buf, meta); ((ExtendedColumn) column).setValue(dt); } finally { CacheEntryPinner.getInstance().unpin(pinnedBlocks, pinnedBlocks); } } public void serializeExtended(byte fileId, ExtendedColumn column, int blockSize, TypeMetadata meta, Set<Object> pinnedBlocks) { int type = -1; if (meta instanceof ColumnSerializerMetadata){ type = ((ColumnSerializerMetadata) meta).getColumnId(); } else if (meta instanceof IndexRecordMetadata) { type = SerializerManager.INDEX_TYPE; } int size = 1+ Serializer.getInstance().getObjectSize(type, column.getValue(meta), meta); int blocksRequired = getExtraBlocksRequired(size, blockSize); List<BlockPtr> list = column instanceof ExtendedColumn ? ((ExtendedColumn) column).getPtrList() : new ArrayList<BlockPtr>(); ChannelBuffer buf = LazyExtendedSpaceProvider.getInstance().provideSpaceToWrite(fileId, list, blocksRequired, pinnedBlocks); ColumnHeader header = new ColumnHeader(); if (column.getValue(meta) == NullType.getInstance()) { header.setNull(true); } // ColumnHeaderSerializer.getInstance().serialize(header, buf); Serializer.getInstance().serialize(type, column.getValue(meta), buf, meta); } public void serializeMinimum(DBType column, ChannelBuffer buffer, TypeMetadata meta) { ColumnHeader header = new ColumnHeader(); header.setExtended(column instanceof Extended); header.setNull(column == NullType.getInstance()); ColumnHeaderSerializer.getInstance().serialize(header, buffer); int type = -1; if (meta instanceof ColumnSerializerMetadata){ type = ((ColumnSerializerMetadata) meta).getColumnId(); } else if (meta instanceof IndexRecordMetadata) { type = SerializerManager.INDEX_TYPE; } if (column instanceof Extended) { Serializer.getInstance().serialize(SerializerManager.BLOCK_PTR, ((Extended) column).getPtrList().get(0), buffer, meta); } else { Serializer.getInstance().serialize(type, column, buffer, meta); } } public int getObjectRealSize(DBType column, TypeMetadata meta) { int type = -1; if (meta instanceof ColumnSerializerMetadata){ type = ((ColumnSerializerMetadata) meta).getColumnId(); } else if (meta instanceof IndexRecordMetadata) { type = SerializerManager.INDEX_TYPE; } return 1+ Serializer.getInstance().getObjectSize(type, column, meta); } public int getObjectBlockSize(DBType column, TypeMetadata meta) { if (column instanceof Extended) { return 9+1; } return getObjectRealSize(column, meta); } private int getExtraBlocksRequired(int requiredSize, int maxSize) { int mSize = maxSize -10; int retSize = requiredSize/mSize; int balance = requiredSize%mSize; return balance > 0 ? retSize + 1 : retSize; } public DBType getObject(int type, ChannelBuffer buffer, TypeMetadata meta) { return readMinimum(buffer, meta); } public void serialize(DBType object, ChannelBuffer buffer, TypeMetadata meta) { serializeMinimum(object, buffer, meta); } public int getObjectSize(DBType object, TypeMetadata meta) { int type = -1; if (meta instanceof ColumnSerializerMetadata){ type = ((ColumnSerializerMetadata) meta).getColumnId(); } else if (meta instanceof IndexRecordMetadata) { type = SerializerManager.INDEX_TYPE; } return 1 + (object instanceof Extended ? 9 : Serializer.getInstance().getObjectSize(type, object, meta)); } }