private int readElementLength(long element) { // The most significant bit (MSB) of element length is used to signify whether an element is explicitly allocated // (msb clear) or part of a contiguous chain (msb set). Clear the msb when returning length. return Integer.MAX_VALUE & storage.readInt(element + ELEMENT_HEADER_LENGTH_OFFSET); }
@Override public long getAllocatedMemory() { return storage.getAllocatedMemory(); }
@Override public void free(Page page) { delegatePageSource.free(page); }
private long writeElement(long address, ByteBuffer element) { storage.writeLong(address + ELEMENT_HEADER_SEQUENCE_OFFSET, nextSequenceNumber++); storage.writeInt(address + ELEMENT_HEADER_LENGTH_OFFSET, element.remaining()); storage.writeBuffer(address + ELEMENT_HEADER_SIZE, element.duplicate()); return address; }
private ByteBuffer readKeyBuffer(long encoding) { int keyLength = readKeySize(encoding); int elemLength = readElementLength(encoding + this.totalChainHeaderSize); return storage.readBuffer(encoding + this.totalChainHeaderSize + ELEMENT_HEADER_SIZE + elemLength, keyLength); }
protected OffHeapChainStorageEngine(PageSource source, Portability<? super K> keyPortability, int minPageSize, int maxPageSize, boolean thief, boolean victim, final ByteBuffer emptyExtendedChainHeader) { this.storage = new OffHeapStorageArea(PointerSize.LONG, new StorageOwner(), source, minPageSize, maxPageSize, thief, victim); this.keyPortability = keyPortability; this.extendedChainHeaderSize = emptyExtendedChainHeader.remaining(); this.emptyExtendedChainHeader = emptyExtendedChainHeader; this.totalChainHeaderSize = CHAIN_HEADER_SIZE + this.extendedChainHeaderSize; }
@Override public boolean shrink() { return storage.shrink(); }
@Override public long getOccupiedMemory() { return storage.getOccupiedMemory(); }
@Override public void destroy() { storage.destroy(); }
@Override public void clear() { storage.clear(); }
@Override public void setLong(int offset, long value) { if (offset < 0 || offset >= extendedChainHeaderSize) { throw new IllegalArgumentException("Offset not within bounds 0 >= " + offset + " < " + extendedChainHeaderSize); } else { storage.writeLong(toExtensionAddress(chainAddress) + offset, value); } }
private long findHead(long address) { while (!isHead(address)) { address = storage.readLong(address + ELEMENT_HEADER_NEXT_OFFSET); } return address; }
@Override public Page allocate(int size, boolean thief, boolean victim, OffHeapStorageArea owner) { return delegatePageSource.allocate(size, thief, victim, owner); }
public long getAllocatedSize() { return delegatePageSource.getAllocatedSizeUnSync(); }
@Override public int readKeyHash(long encoding) { return storage.readInt(encoding + CHAIN_HEADER_KEY_HASH_OFFSET); }
protected ByteBuffer getExtensionHeader(long chainAddress) { checkExtensionHeaderExists(); return storage.readBuffer(toExtensionAddress(chainAddress), extendedChainHeaderSize); }
private ExtendedOffHeapChainStorageEngine(PageSource source, Portability<? super K> keyPortability, int minPageSize, int maxPageSize, boolean thief, boolean victim, PageSource cachePageSource) { super(source, keyPortability, minPageSize, maxPageSize, thief, victim, EMPTY_HEADER_NODE); this.extendedArea = new OffHeapStorageArea(PointerSize.LONG, new ExtendedEngineOwner(), cachePageSource, minPageSize, maxPageSize, thief, victim); this.chainAddresses = new HashSet<>(); }
@Override public long getDataSize() { return storage.getAllocatedMemory(); }
private boolean isHead(long address) { return storage.readInt(address + CHAIN_HEADER_KEY_LENGTH_OFFSET) < 0; }
private int readKeySize(long encoding) { return Integer.MAX_VALUE & storage.readInt(encoding + CHAIN_HEADER_KEY_LENGTH_OFFSET); }