package com.ctriposs.sdb.table; import java.io.IOException; import java.nio.ByteBuffer; /** * Memory mapped file entry implementation * * @author bulldog * */ public class MMFMapEntryImpl implements IMapEntry { private int index; private ByteBuffer dataMappedByteBuffer; private ByteBuffer indexMappedByteBuffer; public MMFMapEntryImpl(int index, ByteBuffer indexMappedByteBuffer, ByteBuffer dataMappedByteBuffer) { this.index = index; this.dataMappedByteBuffer = dataMappedByteBuffer; this.indexMappedByteBuffer = indexMappedByteBuffer; } int getKeyLength() { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_KEY_LENGTH_OFFSET; return this.indexMappedByteBuffer.getInt(offsetInIndexFile); } int getValueLength() { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_VALUE_LENGTH_OFFSET; return this.indexMappedByteBuffer.getInt(offsetInIndexFile); } long getItemOffsetInDataFile() { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index; return this.indexMappedByteBuffer.getLong(offsetInIndexFile); } @Override public int getIndex() { return index; } @Override public byte[] getKey() throws IOException { int itemOffsetInDataFile = (int)this.getItemOffsetInDataFile(); int keyLength = this.getKeyLength(); byte[] result = new byte[keyLength]; for(int i = 0; i < keyLength; i++) { result[i] = this.dataMappedByteBuffer.get(i + itemOffsetInDataFile); } return result; } @Override public byte[] getValue() throws IOException { int itemOffsetInDataFile = (int)this.getItemOffsetInDataFile(); int keyLength = this.getKeyLength(); itemOffsetInDataFile += keyLength; int valueLength = this.getValueLength(); byte[] result = new byte[valueLength]; for(int i = 0; i < valueLength; i++) { result[i] = this.dataMappedByteBuffer.get(i + itemOffsetInDataFile); } return result; } @Override public int getKeyHash() throws IOException { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_KEY_HASH_CODE_OFFSET; int hashCode = this.indexMappedByteBuffer.getInt(offsetInIndexFile); return hashCode; } @Override public long getTimeToLive() throws IOException { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_TIME_TO_LIVE_OFFSET; return this.indexMappedByteBuffer.getLong(offsetInIndexFile); } @Override public long getCreatedTime() throws IOException { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_CREATED_TIME_OFFSET; return this.indexMappedByteBuffer.getLong(offsetInIndexFile); } @Override public boolean isDeleted() throws IOException { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_STATUS; byte status = this.indexMappedByteBuffer.get(offsetInIndexFile); return (status & ( 1 << 1)) != 0; } @Override public boolean isCompressed() throws IOException { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_STATUS; byte status = this.indexMappedByteBuffer.get(offsetInIndexFile); return (status & ( 1 << 2)) != 0; } @Override public void markDeleted() throws IOException { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_STATUS; byte status = this.indexMappedByteBuffer.get(offsetInIndexFile); status = (byte) (status | 1 << 1); this.indexMappedByteBuffer.put((int)offsetInIndexFile, status); } @Override public boolean isInUse() throws IOException { int offsetInIndexFile = AbstractMapTable.INDEX_ITEM_LENGTH * index + IMapEntry.INDEX_ITEM_STATUS; byte status = this.indexMappedByteBuffer.get(offsetInIndexFile); return (status & 1) != 0; } @Override public boolean isExpired() throws IOException { long ttl = this.getTimeToLive(); if (ttl > 0) { if (System.currentTimeMillis() - this.getCreatedTime() > ttl) return true; } return false; } }