@Override public boolean equals(Object o) { if (o instanceof Chunk) { return getMemoryAddress() == ((Chunk) o).getMemoryAddress(); } return false; }
@Override public int hashCode() { long value = this.getMemoryAddress(); return (int)(value ^ (value >>> 32)); }
@Override public int compareTo(Chunk o) { int result = Integer.signum(getSize() - o.getSize()); if (result == 0) { // For the same sized chunks we really don't care about their order // but we need compareTo to only return 0 if the two chunks are identical result = Long.signum(getMemoryAddress() - o.getMemoryAddress()); } return result; }
public void readyForFree() { UnsafeMemoryChunk.writeAbsoluteIntVolatile(getMemoryAddress()+REF_COUNT_OFFSET, 0); } public void readyForAllocation(ChunkType chunkType) {
public void readyForAllocation(ChunkType chunkType) { if (!UnsafeMemoryChunk.writeAbsoluteIntVolatile(getMemoryAddress()+REF_COUNT_OFFSET, 0, MAGIC_NUMBER|chunkType.getSrcType())) { throw new IllegalStateException("Expected 0 but found " + Integer.toHexString(UnsafeMemoryChunk.readAbsoluteIntVolatile(getMemoryAddress()+REF_COUNT_OFFSET))); } } /**
/** * Validates that the fill pattern for this chunk has not been disturbed. This method * assumes the TINY_MULTIPLE is 8 bytes. * @throws IllegalStateException when the pattern has been violated. */ public void validateFill() { assert SimpleMemoryAllocatorImpl.TINY_MULTIPLE == 8; long startAddress = getMemoryAddress() + MIN_CHUNK_SIZE; int size = getSize() - MIN_CHUNK_SIZE; for(int i = 0;i < size;i += SimpleMemoryAllocatorImpl.TINY_MULTIPLE) { if(UnsafeMemoryChunk.readAbsoluteLong(startAddress + i) != FILL_PATTERN) { throw new IllegalStateException("Fill pattern violated for chunk " + getMemoryAddress() + " with size " + getSize()); } } }
private static long objectToAddress(@Unretained Object v) { if (v instanceof Chunk) return ((Chunk) v).getMemoryAddress(); if (v instanceof DataAsAddress) return ((DataAsAddress) v).getEncodedAddress(); if (v == null) return NULL_ADDRESS; if (v == Token.TOMBSTONE) return TOMBSTONE_ADDRESS; if (v == Token.INVALID) return INVALID_ADDRESS; if (v == Token.LOCAL_INVALID) return LOCAL_INVALID_ADDRESS; if (v == Token.DESTROYED) return DESTROYED_ADDRESS; if (v == Token.REMOVED_PHASE1) return REMOVED_PHASE1_ADDRESS; if (v == Token.REMOVED_PHASE2) return REMOVED_PHASE2_ADDRESS; if (v == Token.END_OF_STREAM) return END_OF_STREAM_ADDRESS; if (v == Token.NOT_AVAILABLE) return NOT_AVAILABLE_ADDRESS; throw new IllegalStateException("Can not convert " + v + " to an off heap address."); }
protected String toStringForOffHeapByteSource() { return super.toString() + ":<dataSize=" + getDataSize() + " refCount=" + getRefCount() + " addr=" + Long.toHexString(getMemoryAddress()) + ">"; }
@Override public ChunkType getChunkType() { return SimpleMemoryAllocatorImpl.getAllocator().getChunkFactory().getChunkTypeForAddress(getMemoryAddress()); } public static int getSrcTypeOrdinal(long memAddr) {
private void collectFreeHugeChunks(List<SyncChunkStack> l) { Chunk c = this.hugeChunkSet.pollFirst(); SyncChunkStack result = null; while (c != null) { if (result == null) { result = new SyncChunkStack(); l.add(result); } result.offer(c.getMemoryAddress()); c = this.hugeChunkSet.pollFirst(); } }
@Override public MemoryChunk allocate(int size, ChunkType chunkType) { //System.out.println("allocating " + size); Chunk result = this.freeList.allocate(size, chunkType); //("allocated off heap object of size " + size + " @" + Long.toHexString(result.getMemoryAddress()), true); if (ReferenceCountHelper.trackReferenceCounts()) { ReferenceCountHelper.refCountChanged(result.getMemoryAddress(), false, 1); } return result; }
protected Chunk(long memoryAddress, int chunkSize, ChunkType chunkType) { SimpleMemoryAllocatorImpl.validateAddressAndSize(memoryAddress, chunkSize); this.memoryAddress = memoryAddress; setSize(chunkSize); UnsafeMemoryChunk.writeAbsoluteIntVolatile(getMemoryAddress()+REF_COUNT_OFFSET, MAGIC_NUMBER|chunkType.getSrcType()); } public void readyForFree() {
result.validateFill(); if (chunkType.getSrcType() != Chunk.getSrcType(result.getMemoryAddress())) { result = this.ma.chunkFactory.newChunk(result.getMemoryAddress(), chunkType);
free(result.getMemoryAddress(), false); result = this.ma.chunkFactory.newChunk(fragment.getMemoryAddress()+oldOffset, chunkSize, chunkType); allocSize -= chunkSize;
@Override public StoredObject allocateAndInitialize(byte[] v, boolean isSerialized, boolean isCompressed, ChunkType chunkType) { long addr = OffHeapRegionEntryHelper.encodeDataAsAddress(v, isSerialized, isCompressed); if (addr != 0L) { return new DataAsAddress(addr); } if (chunkType == null) { chunkType = GemFireChunk.TYPE; } Chunk result = this.freeList.allocate(v.length, chunkType); //debugLog("allocated off heap object of size " + v.length + " @" + Long.toHexString(result.getMemoryAddress()), true); //debugLog("allocated off heap object of size " + v.length + " @" + Long.toHexString(result.getMemoryAddress()) + "chunkSize=" + result.getSize() + " isSerialized=" + isSerialized + " v=" + Arrays.toString(v), true); if (ReferenceCountHelper.trackReferenceCounts()) { ReferenceCountHelper.refCountChanged(result.getMemoryAddress(), false, 1); } assert result.getChunkType() == chunkType: "chunkType=" + chunkType + " getChunkType()=" + result.getChunkType(); result.setSerializedValue(v); result.setSerialized(isSerialized); result.setCompressed(isCompressed); return result; }