You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2016/02/19 22:51:26 UTC
[3/5] incubator-geode git commit: GEODE-831: unit test FreeListManager
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java
index 12d297b..14bde59 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java
@@ -55,47 +55,20 @@ import com.gemstone.gemfire.internal.offheap.annotations.Unretained;
* @author Kirk Lund
* @since 9.0
*/
-public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
+public class SimpleMemoryAllocatorImpl implements MemoryAllocator {
static final Logger logger = LogService.getLogger();
public static final String FREE_OFF_HEAP_MEMORY_PROPERTY = "gemfire.free-off-heap-memory";
- /**
- * How many extra allocations to do for each actual slab allocation.
- * Is this really a good idea?
- */
- public static final int BATCH_SIZE = Integer.getInteger("gemfire.OFF_HEAP_BATCH_ALLOCATION_SIZE", 1);
- /**
- * Every allocated chunk smaller than TINY_MULTIPLE*TINY_FREE_LIST_COUNT will allocate a chunk of memory that is a multiple of this value.
- * Sizes are always rounded up to the next multiple of this constant
- * so internal fragmentation will be limited to TINY_MULTIPLE-1 bytes per allocation
- * and on average will be TINY_MULTIPLE/2 given a random distribution of size requests.
- * This does not account for the additional internal fragmentation caused by the off-heap header
- * which currently is always 8 bytes.
- */
- public final static int TINY_MULTIPLE = Integer.getInteger("gemfire.OFF_HEAP_ALIGNMENT", 8);
- /**
- * Number of free lists to keep for tiny allocations.
- */
- public final static int TINY_FREE_LIST_COUNT = Integer.getInteger("gemfire.OFF_HEAP_FREE_LIST_COUNT", 16384);
- public final static int MAX_TINY = TINY_MULTIPLE*TINY_FREE_LIST_COUNT;
- /**
- * How many unused bytes are allowed in a huge memory allocation.
- */
- public final static int HUGE_MULTIPLE = 256;
-
- volatile OffHeapMemoryStats stats;
+ private volatile OffHeapMemoryStats stats;
- volatile OutOfOffHeapMemoryListener ooohml;
-
- /** The MemoryChunks that this allocator is managing by allocating smaller chunks of them.
- * The contents of this array never change.
- */
- private final UnsafeMemoryChunk[] slabs;
- private final long totalSlabSize;
- private final int largestSlab;
+ private volatile OutOfOffHeapMemoryListener ooohml;
+ OutOfOffHeapMemoryListener getOutOfOffHeapMemoryListener() {
+ return this.ooohml;
+ }
+
public final FreeListManager freeList;
private MemoryInspector memoryInspector;
@@ -103,7 +76,6 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
private volatile MemoryUsageListener[] memoryUsageListeners = new MemoryUsageListener[0];
private static SimpleMemoryAllocatorImpl singleton = null;
- final ChunkFactory chunkFactory;
public static SimpleMemoryAllocatorImpl getAllocator() {
SimpleMemoryAllocatorImpl result = singleton;
@@ -118,10 +90,9 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
public static MemoryAllocator create(OutOfOffHeapMemoryListener ooohml, OffHeapMemoryStats stats, LogWriter lw,
int slabCount, long offHeapMemorySize, long maxSlabSize) {
return create(ooohml, stats, lw, slabCount, offHeapMemorySize, maxSlabSize,
- null, TINY_MULTIPLE, BATCH_SIZE, TINY_FREE_LIST_COUNT, HUGE_MULTIPLE,
- new UnsafeMemoryChunk.Factory() {
+ null, new AddressableMemoryChunkFactory() {
@Override
- public UnsafeMemoryChunk create(int size) {
+ public AddressableMemoryChunk create(int size) {
return new UnsafeMemoryChunk(size);
}
});
@@ -129,15 +100,14 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
private static SimpleMemoryAllocatorImpl create(OutOfOffHeapMemoryListener ooohml, OffHeapMemoryStats stats, LogWriter lw,
int slabCount, long offHeapMemorySize, long maxSlabSize,
- UnsafeMemoryChunk[] slabs, int tinyMultiple, int batchSize, int tinyFreeListCount, int hugeMultiple,
- UnsafeMemoryChunk.Factory memChunkFactory) {
+ AddressableMemoryChunk[] slabs, AddressableMemoryChunkFactory memChunkFactory) {
SimpleMemoryAllocatorImpl result = singleton;
boolean created = false;
try {
if (result != null) {
result.reuse(ooohml, lw, stats, offHeapMemorySize, slabs);
if (lw != null) {
- lw.config("Reusing " + result.getTotalMemory() + " bytes of off-heap memory. The maximum size of a single off-heap object is " + result.largestSlab + " bytes.");
+ lw.config("Reusing " + result.getTotalMemory() + " bytes of off-heap memory. The maximum size of a single off-heap object is " + result.freeList.getLargestSlabSize() + " bytes.");
}
created = true;
LifecycleListener.invokeAfterReuse(result);
@@ -175,7 +145,7 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
}
}
- result = new SimpleMemoryAllocatorImpl(ooohml, stats, slabs, tinyMultiple, batchSize, tinyFreeListCount, hugeMultiple);
+ result = new SimpleMemoryAllocatorImpl(ooohml, stats, slabs);
singleton = result;
LifecycleListener.invokeAfterCreate(result);
created = true;
@@ -192,19 +162,12 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
}
return result;
}
- // for unit tests
- static SimpleMemoryAllocatorImpl create(OutOfOffHeapMemoryListener ooohml, OffHeapMemoryStats stats, LogWriter lw,
- int slabCount, long offHeapMemorySize, long maxSlabSize, UnsafeMemoryChunk.Factory memChunkFactory) {
+ static SimpleMemoryAllocatorImpl createForUnitTest(OutOfOffHeapMemoryListener ooohml, OffHeapMemoryStats stats, LogWriter lw,
+ int slabCount, long offHeapMemorySize, long maxSlabSize, AddressableMemoryChunkFactory memChunkFactory) {
return create(ooohml, stats, lw, slabCount, offHeapMemorySize, maxSlabSize,
- null, TINY_MULTIPLE, BATCH_SIZE, TINY_FREE_LIST_COUNT, HUGE_MULTIPLE, memChunkFactory);
- }
- // for unit tests
- public static SimpleMemoryAllocatorImpl create(OutOfOffHeapMemoryListener oooml, OffHeapMemoryStats stats, UnsafeMemoryChunk[] slabs) {
- return create(oooml, stats, slabs, TINY_MULTIPLE, BATCH_SIZE, TINY_FREE_LIST_COUNT, HUGE_MULTIPLE);
+ null, memChunkFactory);
}
- // for unit tests
- static SimpleMemoryAllocatorImpl create(OutOfOffHeapMemoryListener oooml, OffHeapMemoryStats stats, UnsafeMemoryChunk[] slabs,
- int tinyMultiple, int batchSize, int tinyFreeListCount, int hugeMultiple) {
+ public static SimpleMemoryAllocatorImpl createForUnitTest(OutOfOffHeapMemoryListener oooml, OffHeapMemoryStats stats, AddressableMemoryChunk[] slabs) {
int slabCount = 0;
long offHeapMemorySize = 0;
long maxSlabSize = 0;
@@ -218,11 +181,11 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
}
}
}
- return create(oooml, stats, null, slabCount, offHeapMemorySize, maxSlabSize, slabs, tinyMultiple, batchSize, tinyFreeListCount, hugeMultiple, null);
+ return create(oooml, stats, null, slabCount, offHeapMemorySize, maxSlabSize, slabs, null);
}
- private void reuse(OutOfOffHeapMemoryListener oooml, LogWriter lw, OffHeapMemoryStats newStats, long offHeapMemorySize, UnsafeMemoryChunk[] slabs) {
+ private void reuse(OutOfOffHeapMemoryListener oooml, LogWriter lw, OffHeapMemoryStats newStats, long offHeapMemorySize, AddressableMemoryChunk[] slabs) {
if (isClosed()) {
throw new IllegalStateException("Can not reuse a closed off-heap memory manager.");
}
@@ -234,83 +197,47 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
lw.warning("Using " + getTotalMemory() + " bytes of existing off-heap memory instead of the requested " + offHeapMemorySize);
}
}
- if (slabs != null) {
- // this will only happen in unit tests
- if (slabs != this.slabs) {
- // If the unit test gave us a different array
- // of slabs then something is wrong because we
- // are trying to reuse the old already allocated
- // array which means that the new one will never
- // be used. Note that this code does not bother
- // comparing the contents of the arrays.
- throw new IllegalStateException("attempted to reuse existing off-heap memory even though new off-heap memory was allocated");
- }
+ if (!this.freeList.okToReuse(slabs)) {
+ throw new IllegalStateException("attempted to reuse existing off-heap memory even though new off-heap memory was allocated");
}
this.ooohml = oooml;
newStats.initialize(this.stats);
this.stats = newStats;
}
- private SimpleMemoryAllocatorImpl(final OutOfOffHeapMemoryListener oooml, final OffHeapMemoryStats stats, final UnsafeMemoryChunk[] slabs,
- int tinyMultiple, int batchSize, int tinyFreeListCount, int hugeMultiple) {
+ private SimpleMemoryAllocatorImpl(final OutOfOffHeapMemoryListener oooml, final OffHeapMemoryStats stats, final AddressableMemoryChunk[] slabs) {
if (oooml == null) {
throw new IllegalArgumentException("OutOfOffHeapMemoryListener is null");
}
- if (tinyMultiple <= 0 || (tinyMultiple & 3) != 0) {
- throw new IllegalStateException("gemfire.OFF_HEAP_ALIGNMENT must be a multiple of 8.");
- }
- if (tinyMultiple > 256) {
- // this restriction exists because of the dataSize field in the object header.
- throw new IllegalStateException("gemfire.OFF_HEAP_ALIGNMENT must be <= 256 and a multiple of 8.");
- }
- if (batchSize <= 0) {
- throw new IllegalStateException("gemfire.OFF_HEAP_BATCH_ALLOCATION_SIZE must be >= 1.");
- }
- if (tinyFreeListCount <= 0) {
- throw new IllegalStateException("gemfire.OFF_HEAP_FREE_LIST_COUNT must be >= 1.");
- }
- if (hugeMultiple > 256 || hugeMultiple < 0) {
- // this restriction exists because of the dataSize field in the object header.
- throw new IllegalStateException("HUGE_MULTIPLE must be >= 0 and <= 256 but it was " + hugeMultiple);
- }
this.ooohml = oooml;
this.stats = stats;
- this.slabs = slabs;
- this.chunkFactory = new GemFireChunkFactory();
-
+
//OSProcess.printStacks(0, InternalDistributedSystem.getAnyInstance().getLogWriter(), false);
this.stats.setFragments(slabs.length);
- largestSlab = slabs[0].getSize();
- this.stats.setLargestFragment(largestSlab);
- long total = 0;
- for (int i=0; i < slabs.length; i++) {
- //debugLog("slab"+i + " @" + Long.toHexString(slabs[i].getMemoryAddress()), false);
- //UnsafeMemoryChunk.clearAbsolute(slabs[i].getMemoryAddress(), slabs[i].getSize()); // HACK to see what this does to bug 47883
- total += slabs[i].getSize();
- }
- totalSlabSize = total;
- this.stats.incMaxMemory(this.totalSlabSize);
- this.stats.incFreeMemory(this.totalSlabSize);
+ this.stats.setLargestFragment(slabs[0].getSize());
- this.freeList = new FreeListManager(this);
+ this.freeList = new FreeListManager(this, slabs);
this.memoryInspector = new MemoryInspectorImpl(this.freeList);
+
+ this.stats.incMaxMemory(this.freeList.getTotalMemory());
+ this.stats.incFreeMemory(this.freeList.getTotalMemory());
}
- public List<Chunk> getLostChunks() {
- List<Chunk> liveChunks = this.freeList.getLiveChunks();
- List<Chunk> regionChunks = getRegionLiveChunks();
- Set<Chunk> liveChunksSet = new HashSet<>(liveChunks);
- Set<Chunk> regionChunksSet = new HashSet<>(regionChunks);
+ public List<ObjectChunk> getLostChunks() {
+ List<ObjectChunk> liveChunks = this.freeList.getLiveChunks();
+ List<ObjectChunk> regionChunks = getRegionLiveChunks();
+ Set<ObjectChunk> liveChunksSet = new HashSet<>(liveChunks);
+ Set<ObjectChunk> regionChunksSet = new HashSet<>(regionChunks);
liveChunksSet.removeAll(regionChunksSet);
- return new ArrayList<Chunk>(liveChunksSet);
+ return new ArrayList<ObjectChunk>(liveChunksSet);
}
/**
* Returns a possibly empty list that contains all the Chunks used by regions.
*/
- private List<Chunk> getRegionLiveChunks() {
- ArrayList<Chunk> result = new ArrayList<Chunk>();
+ private List<ObjectChunk> getRegionLiveChunks() {
+ ArrayList<ObjectChunk> result = new ArrayList<ObjectChunk>();
RegionService gfc = GemFireCacheImpl.getInstance();
if (gfc != null) {
Iterator<Region<?,?>> rootIt = gfc.rootRegions().iterator();
@@ -326,7 +253,7 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
return result;
}
- private void getRegionLiveChunks(Region<?,?> r, List<Chunk> result) {
+ private void getRegionLiveChunks(Region<?,?> r, List<ObjectChunk> result) {
if (r.getAttributes().getOffHeap()) {
if (r instanceof PartitionedRegion) {
@@ -350,7 +277,7 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
}
- private void basicGetRegionLiveChunks(LocalRegion r, List<Chunk> result) {
+ private void basicGetRegionLiveChunks(LocalRegion r, List<ObjectChunk> result) {
for (Object key : r.keySet()) {
RegionEntry re = ((LocalRegion) r).getRegionEntry(key);
if (re != null) {
@@ -359,24 +286,34 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
*/
@Unretained(OffHeapIdentifier.GATEWAY_SENDER_EVENT_IMPL_VALUE)
Object value = re._getValue();
- if (value instanceof Chunk) {
- result.add((Chunk) value);
+ if (value instanceof ObjectChunk) {
+ result.add((ObjectChunk) value);
}
}
}
}
- @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);
+ private ObjectChunk allocateChunk(int size) {
+ ObjectChunk result = this.freeList.allocate(size);
+ int resultSize = result.getSize();
+ stats.incObjects(1);
+ stats.incUsedMemory(resultSize);
+ stats.incFreeMemory(-resultSize);
+ notifyListeners();
if (ReferenceCountHelper.trackReferenceCounts()) {
ReferenceCountHelper.refCountChanged(result.getMemoryAddress(), false, 1);
}
return result;
}
+ @Override
+ public MemoryChunk allocate(int size) {
+ //System.out.println("allocating " + size);
+ ObjectChunk result = allocateChunk(size);
+ //("allocated off heap object of size " + size + " @" + Long.toHexString(result.getMemoryAddress()), true);
+ return result;
+ }
+
public static void debugLog(String msg, boolean logStack) {
if (logStack) {
logger.info(msg, new RuntimeException(msg));
@@ -386,22 +323,14 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
}
@Override
- public StoredObject allocateAndInitialize(byte[] v, boolean isSerialized, boolean isCompressed, ChunkType chunkType) {
+ public StoredObject allocateAndInitialize(byte[] v, boolean isSerialized, boolean isCompressed) {
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);
+ ObjectChunk result = allocateChunk(v.length);
//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);
@@ -420,7 +349,7 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
@Override
public long getTotalMemory() {
- return totalSlabSize;
+ return this.freeList.getTotalMemory();
}
@Override
@@ -445,7 +374,7 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
private void realClose() {
// Removing this memory immediately can lead to a SEGV. See 47885.
if (setClosed()) {
- freeSlabs(this.slabs);
+ this.freeList.freeSlabs();
this.stats.close();
singleton = null;
}
@@ -464,45 +393,21 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
}
- private static void freeSlabs(final UnsafeMemoryChunk[] slabs) {
- //debugLog("called freeSlabs", false);
- for (int i=0; i < slabs.length; i++) {
- slabs[i].release();
- }
- }
-
- void freeChunk(long addr) {
- this.freeList.free(addr);
- }
-
- protected UnsafeMemoryChunk[] getSlabs() {
- return this.slabs;
+ FreeListManager getFreeListManager() {
+ return this.freeList;
}
/**
* Return the slabId of the slab that contains the given addr.
*/
int findSlab(long addr) {
- for (int i=0; i < this.slabs.length; i++) {
- UnsafeMemoryChunk slab = this.slabs[i];
- long slabAddr = slab.getMemoryAddress();
- if (addr >= slabAddr) {
- if (addr < slabAddr + slab.getSize()) {
- return i;
- }
- }
- }
- throw new IllegalStateException("could not find a slab for addr " + addr);
+ return this.freeList.findSlab(addr);
}
public OffHeapMemoryStats getStats() {
return this.stats;
}
- public ChunkFactory getChunkFactory() {
- return this.chunkFactory;
- }
-
@Override
public void addMemoryUsageListener(final MemoryUsageListener listener) {
synchronized (this.memoryUsageListeners) {
@@ -558,12 +463,8 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
SimpleMemoryAllocatorImpl ma = SimpleMemoryAllocatorImpl.singleton;
if (ma != null) {
sb.append(". Valid addresses must be in one of the following ranges: ");
- for (int i=0; i < ma.slabs.length; i++) {
- long startAddr = ma.slabs[i].getMemoryAddress();
- long endAddr = startAddr + ma.slabs[i].getSize();
- sb.append("[").append(Long.toString(startAddr, 16)).append("..").append(Long.toString(endAddr, 16)).append("] ");
- }
- }
+ ma.freeList.getSlabDescriptions(sb);
+ }
throw new IllegalStateException(sb.toString());
}
if (addr >= 0 && addr < 1024) {
@@ -576,28 +477,19 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
if (doExpensiveValidation) {
SimpleMemoryAllocatorImpl ma = SimpleMemoryAllocatorImpl.singleton;
if (ma != null) {
- for (int i=0; i < ma.slabs.length; i++) {
- if (ma.slabs[i].getMemoryAddress() <= addr && addr < (ma.slabs[i].getMemoryAddress() + ma.slabs[i].getSize())) {
- // validate addr + size is within the same slab
- if (size != -1) { // skip this check if size is -1
- if (!(ma.slabs[i].getMemoryAddress() <= (addr+size-1) && (addr+size-1) < (ma.slabs[i].getMemoryAddress() + ma.slabs[i].getSize()))) {
- throw new IllegalStateException(" address 0x" + Long.toString(addr+size-1, 16) + " does not address the original slab memory");
- }
- }
- return;
- }
+ if (!ma.freeList.validateAddressAndSizeWithinSlab(addr, size)) {
+ throw new IllegalStateException(" address 0x" + Long.toString(addr, 16) + " does not address the original slab memory");
}
- throw new IllegalStateException(" address 0x" + Long.toString(addr, 16) + " does not address the original slab memory");
}
}
}
public synchronized List<MemoryBlock> getOrphans() {
- List<Chunk> liveChunks = this.freeList.getLiveChunks();
- List<Chunk> regionChunks = getRegionLiveChunks();
+ List<ObjectChunk> liveChunks = this.freeList.getLiveChunks();
+ List<ObjectChunk> regionChunks = getRegionLiveChunks();
liveChunks.removeAll(regionChunks);
List<MemoryBlock> orphans = new ArrayList<MemoryBlock>();
- for (Chunk chunk: liveChunks) {
+ for (ObjectChunk chunk: liveChunks) {
orphans.add(new MemoryBlockNode(this, chunk));
}
Collections.sort(orphans,
@@ -615,11 +507,5 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator {
public MemoryInspector getMemoryInspector() {
return this.memoryInspector;
}
-
- /*
- * Set this to "true" to perform data integrity checks on allocated and reused Chunks. This may clobber
- * performance so turn on only when necessary.
- */
- final boolean validateMemoryWithFill = Boolean.getBoolean("gemfire.validateOffHeapWithFill");
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SyncChunkStack.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SyncChunkStack.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SyncChunkStack.java
index 7ba28a2..99fd96f 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SyncChunkStack.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SyncChunkStack.java
@@ -42,7 +42,7 @@ public class SyncChunkStack {
assert e != 0;
SimpleMemoryAllocatorImpl.validateAddress(e);
synchronized (this) {
- Chunk.setNext(e, this.topAddr);
+ ObjectChunk.setNext(e, this.topAddr);
this.topAddr = e;
}
}
@@ -51,7 +51,7 @@ public class SyncChunkStack {
synchronized (this) {
result = this.topAddr;
if (result != 0L) {
- this.topAddr = Chunk.getNext(result);
+ this.topAddr = ObjectChunk.getNext(result);
}
}
return result;
@@ -85,8 +85,8 @@ public class SyncChunkStack {
concurrentModDetected = false;
addr = headAddr;
while (addr != 0L) {
- int curSize = Chunk.getSize(addr);
- addr = Chunk.getNext(addr);
+ int curSize = ObjectChunk.getSize(addr);
+ addr = ObjectChunk.getNext(addr);
testHookDoConcurrentModification();
long curHead = this.topAddr;
if (curHead != headAddr) {
@@ -113,8 +113,8 @@ public class SyncChunkStack {
result = 0;
addr = headAddr;
while (addr != 0L) {
- result += Chunk.getSize(addr);
- addr = Chunk.getNext(addr);
+ result += ObjectChunk.getSize(addr);
+ addr = ObjectChunk.getNext(addr);
testHookDoConcurrentModification();
long curHead = this.topAddr;
if (curHead != headAddr) {
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/UnsafeMemoryChunk.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/UnsafeMemoryChunk.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/UnsafeMemoryChunk.java
index ed1c843..aebc459 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/UnsafeMemoryChunk.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/UnsafeMemoryChunk.java
@@ -25,7 +25,7 @@ import com.gemstone.gemfire.pdx.internal.unsafe.UnsafeWrapper;
*
* @since 9.0
*/
-public class UnsafeMemoryChunk implements MemoryChunk {
+public class UnsafeMemoryChunk implements AddressableMemoryChunk {
private static final UnsafeWrapper unsafe;
private static final int ARRAY_BYTE_BASE_OFFSET;
private static String reason;
@@ -70,6 +70,10 @@ public class UnsafeMemoryChunk implements MemoryChunk {
return (int)this.size;
}
+ /* (non-Javadoc)
+ * @see com.gemstone.gemfire.internal.offheap.AddressableMemoryChunk#getMemoryAddress()
+ */
+ @Override
public long getMemoryAddress() {
return this.data;
}
@@ -210,14 +214,4 @@ public class UnsafeMemoryChunk implements MemoryChunk {
sb.append("}");
return sb.toString();
}
-
- /**
- * Used to create UnsafeMemoryChunk instances.
- */
- public interface Factory {
- /** Create and return an UnsafeMemoryChunk.
- * @throws OutOfMemoryError if the create fails
- */
- public UnsafeMemoryChunk create(int size);
- }
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ByteBufferInputStream.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ByteBufferInputStream.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ByteBufferInputStream.java
index 8a7d351..cfc05f2 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ByteBufferInputStream.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ByteBufferInputStream.java
@@ -31,7 +31,7 @@ import java.nio.ByteOrder;
import com.gemstone.gemfire.internal.ByteBufferWriter;
import com.gemstone.gemfire.internal.HeapDataOutputStream;
-import com.gemstone.gemfire.internal.offheap.Chunk;
+import com.gemstone.gemfire.internal.offheap.ObjectChunk;
import com.gemstone.gemfire.internal.offheap.UnsafeMemoryChunk;
/**
@@ -109,7 +109,7 @@ public class ByteBufferInputStream extends InputStream implements DataInput, jav
public static ByteSource create(ByteBuffer bb) {
return new ByteBufferByteSource(bb);
}
- public static ByteSource create(Chunk chunk) {
+ public static ByteSource create(ObjectChunk chunk) {
// Since I found a way to create a DirectByteBuffer (using reflection) from a Chunk
// we might not even need the ByteSource abstraction any more.
// But it is possible that createByteBuffer will not work on a different jdk so keep it for now.
@@ -323,9 +323,9 @@ public class ByteBufferInputStream extends InputStream implements DataInput, jav
public static class OffHeapByteSource implements ByteSource {
private int position;
private int limit;
- private final Chunk chunk;
+ private final ObjectChunk chunk;
- public OffHeapByteSource(Chunk c) {
+ public OffHeapByteSource(ObjectChunk c) {
this.chunk = c;
this.position = 0;
this.limit = capacity();
@@ -724,7 +724,7 @@ public class ByteBufferInputStream extends InputStream implements DataInput, jav
this.buffer = copy.buffer.duplicate();
}
- public ByteBufferInputStream(Chunk blob) {
+ public ByteBufferInputStream(ObjectChunk blob) {
this.buffer = ByteSourceFactory.create(blob);
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ImmutableByteBufferInputStream.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ImmutableByteBufferInputStream.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ImmutableByteBufferInputStream.java
index 52f332f..d632158 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ImmutableByteBufferInputStream.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/tcp/ImmutableByteBufferInputStream.java
@@ -18,7 +18,7 @@ package com.gemstone.gemfire.internal.tcp;
import java.nio.ByteBuffer;
-import com.gemstone.gemfire.internal.offheap.Chunk;
+import com.gemstone.gemfire.internal.offheap.ObjectChunk;
/**
* You should only create an instance of this class if the bytes this buffer reads
@@ -67,7 +67,7 @@ public class ImmutableByteBufferInputStream extends ByteBufferInputStream {
// for serialization
}
- public ImmutableByteBufferInputStream(Chunk blob) {
+ public ImmutableByteBufferInputStream(ObjectChunk blob) {
super(blob);
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/BlobHelper.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/BlobHelper.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/BlobHelper.java
index 7a4840e..40015a4 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/BlobHelper.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/BlobHelper.java
@@ -27,7 +27,7 @@ import com.gemstone.gemfire.internal.DSCODE;
import com.gemstone.gemfire.internal.HeapDataOutputStream;
import com.gemstone.gemfire.internal.Version;
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
-import com.gemstone.gemfire.internal.offheap.Chunk;
+import com.gemstone.gemfire.internal.offheap.ObjectChunk;
import com.gemstone.gemfire.internal.offheap.annotations.Unretained;
import com.gemstone.gemfire.pdx.internal.PdxInputStream;
@@ -140,7 +140,7 @@ public class BlobHelper {
* If a PdxInstance is returned then it will refer to Chunk's off-heap memory
* with an unretained reference.
*/
- public static @Unretained Object deserializeOffHeapBlob(Chunk blob) throws IOException, ClassNotFoundException {
+ public static @Unretained Object deserializeOffHeapBlob(ObjectChunk blob) throws IOException, ClassNotFoundException {
Object result;
final long start = startDeserialization();
// For both top level and nested pdxs we just want a reference to this off-heap blob.
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/main/java/com/gemstone/gemfire/pdx/internal/PdxInputStream.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/pdx/internal/PdxInputStream.java b/gemfire-core/src/main/java/com/gemstone/gemfire/pdx/internal/PdxInputStream.java
index 85e078d..4a5a9df 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/pdx/internal/PdxInputStream.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/pdx/internal/PdxInputStream.java
@@ -26,7 +26,7 @@ import java.util.Date;
import com.gemstone.gemfire.DataSerializer;
import com.gemstone.gemfire.InternalGemFireException;
import com.gemstone.gemfire.pdx.PdxSerializationException;
-import com.gemstone.gemfire.internal.offheap.Chunk;
+import com.gemstone.gemfire.internal.offheap.ObjectChunk;
import com.gemstone.gemfire.internal.tcp.ByteBufferInputStream;
import com.gemstone.gemfire.internal.tcp.ImmutableByteBufferInputStream;
@@ -76,7 +76,7 @@ public class PdxInputStream extends ImmutableByteBufferInputStream {
// for serialization
}
- public PdxInputStream(Chunk blob) {
+ public PdxInputStream(ObjectChunk blob) {
super(blob);
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
index 0606387..b69f82e 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
@@ -29,7 +29,7 @@ import org.junit.experimental.categories.Category;
import com.gemstone.gemfire.internal.cache.DiskEntry.Helper.ChunkValueWrapper;
import com.gemstone.gemfire.internal.cache.DiskEntry.Helper.Flushable;
-import com.gemstone.gemfire.internal.offheap.Chunk;
+import com.gemstone.gemfire.internal.offheap.ObjectChunk;
import com.gemstone.gemfire.internal.offheap.NullOffHeapMemoryStats;
import com.gemstone.gemfire.internal.offheap.NullOutOfOffHeapMemoryListener;
import com.gemstone.gemfire.internal.offheap.SimpleMemoryAllocatorImpl;
@@ -40,13 +40,13 @@ import com.gemstone.gemfire.test.junit.categories.UnitTest;
public class ChunkValueWrapperJUnitTest {
private static ChunkValueWrapper createChunkValueWrapper(byte[] bytes, boolean isSerialized) {
- Chunk c = (Chunk)SimpleMemoryAllocatorImpl.getAllocator().allocateAndInitialize(bytes, isSerialized, false, null);
+ ObjectChunk c = (ObjectChunk)SimpleMemoryAllocatorImpl.getAllocator().allocateAndInitialize(bytes, isSerialized, false);
return new ChunkValueWrapper(c);
}
@Before
public void setUp() throws Exception {
- SimpleMemoryAllocatorImpl.create(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
+ SimpleMemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
}
@After
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/OldValueImporterTestBase.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/OldValueImporterTestBase.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/OldValueImporterTestBase.java
index f7d0714..690b55a 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/OldValueImporterTestBase.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/OldValueImporterTestBase.java
@@ -26,7 +26,7 @@ import org.junit.Test;
import com.gemstone.gemfire.internal.HeapDataOutputStream;
import com.gemstone.gemfire.internal.cache.EntryEventImpl.OldValueImporter;
-import com.gemstone.gemfire.internal.offheap.Chunk;
+import com.gemstone.gemfire.internal.offheap.ObjectChunk;
import com.gemstone.gemfire.internal.offheap.DataAsAddress;
import com.gemstone.gemfire.internal.offheap.NullOffHeapMemoryStats;
import com.gemstone.gemfire.internal.offheap.NullOutOfOffHeapMemoryListener;
@@ -110,10 +110,10 @@ public abstract class OldValueImporterTestBase {
// off-heap DataAsAddress byte array
{
SimpleMemoryAllocatorImpl sma =
- SimpleMemoryAllocatorImpl.create(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
+ SimpleMemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
try {
byte[] baValue = new byte[] {1,2};
- DataAsAddress baValueSO = (DataAsAddress) sma.allocateAndInitialize(baValue, false, false, null);
+ DataAsAddress baValueSO = (DataAsAddress) sma.allocateAndInitialize(baValue, false, false);
OldValueImporter omsg = createImporter();
omsg.importOldObject(baValueSO, false);
hdos = new HeapDataOutputStream(bytes);
@@ -127,10 +127,10 @@ public abstract class OldValueImporterTestBase {
// off-heap Chunk byte array
{
SimpleMemoryAllocatorImpl sma =
- SimpleMemoryAllocatorImpl.create(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
+ SimpleMemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
try {
byte[] baValue = new byte[] {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
- Chunk baValueSO = (Chunk) sma.allocateAndInitialize(baValue, false, false, null);
+ ObjectChunk baValueSO = (ObjectChunk) sma.allocateAndInitialize(baValue, false, false);
OldValueImporter omsg = createImporter();
omsg.importOldObject(baValueSO, false);
hdos = new HeapDataOutputStream(bytes);
@@ -144,11 +144,11 @@ public abstract class OldValueImporterTestBase {
// off-heap DataAsAddress String
{
SimpleMemoryAllocatorImpl sma =
- SimpleMemoryAllocatorImpl.create(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
+ SimpleMemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
try {
String baValue = "12";
byte[] baValueBlob = BlobHelper.serializeToBlob(baValue);
- DataAsAddress baValueSO = (DataAsAddress) sma.allocateAndInitialize(baValueBlob, true, false, null);
+ DataAsAddress baValueSO = (DataAsAddress) sma.allocateAndInitialize(baValueBlob, true, false);
OldValueImporter omsg = createImporter();
omsg.importOldObject(baValueSO, true);
hdos = new HeapDataOutputStream(bytes);
@@ -162,11 +162,11 @@ public abstract class OldValueImporterTestBase {
// off-heap Chunk String
{
SimpleMemoryAllocatorImpl sma =
- SimpleMemoryAllocatorImpl.create(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
+ SimpleMemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), new UnsafeMemoryChunk[]{new UnsafeMemoryChunk(1024*1024)});
try {
String baValue = "12345678";
byte[] baValueBlob = BlobHelper.serializeToBlob(baValue);
- Chunk baValueSO = (Chunk) sma.allocateAndInitialize(baValueBlob, true, false, null);
+ ObjectChunk baValueSO = (ObjectChunk) sma.allocateAndInitialize(baValueBlob, true, false);
OldValueImporter omsg = createImporter();
omsg.importOldObject(baValueSO, true);
hdos = new HeapDataOutputStream(bytes);
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/ChunkWithHeapFormJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/ChunkWithHeapFormJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/ChunkWithHeapFormJUnitTest.java
deleted file mode 100644
index bc32367..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/ChunkWithHeapFormJUnitTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.gemstone.gemfire.internal.offheap;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertSame;
-
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import com.gemstone.gemfire.test.junit.categories.UnitTest;
-
-@Category(UnitTest.class)
-public class ChunkWithHeapFormJUnitTest extends GemFireChunkJUnitTest {
-
- @Test
- public void getRawBytesShouldReturnCachedHeapForm() {
- GemFireChunk chunk = createValueAsUnserializedStoredObject(getValue());
-
- byte[] valueInBytes = getValueAsByteArray();
- ChunkWithHeapForm heapForm = new ChunkWithHeapForm(chunk, valueInBytes);
-
- assertNotNull(heapForm);
-
- assertSame(valueInBytes, heapForm.getRawBytes());
- }
-
- @Test
- public void getChunkWithoutHeapFormShouldReturnGemFireChunk() {
- GemFireChunk chunk = createValueAsSerializedStoredObject(getValue());
-
- byte[] valueInBytes = getValueAsByteArray();
- ChunkWithHeapForm heapForm = new ChunkWithHeapForm(chunk, valueInBytes);
-
- Chunk chunkWithOutHeapForm = heapForm.getChunkWithoutHeapForm();
-
- assertNotNull(chunkWithOutHeapForm);
- assertEquals(GemFireChunk.class, chunkWithOutHeapForm.getClass());
-
- assertEquals(chunk, heapForm.getChunkWithoutHeapForm());
-
- assertEquals(chunk.getMemoryAddress(), chunkWithOutHeapForm.getMemoryAddress());
- assertArrayEquals(chunk.getRawBytes(), chunkWithOutHeapForm.getRawBytes());
- assertNotSame(valueInBytes, chunkWithOutHeapForm.getRawBytes());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FragmentJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FragmentJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FragmentJUnitTest.java
index ccc6b67..54eac9e 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FragmentJUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FragmentJUnitTest.java
@@ -18,7 +18,6 @@
package com.gemstone.gemfire.internal.offheap;
import static org.junit.Assert.*;
-import static org.mockito.Mockito.mock;
import static org.hamcrest.CoreMatchers.*;
import java.util.Arrays;
@@ -33,19 +32,12 @@ import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException;
-import com.gemstone.gemfire.LogWriter;
import com.gemstone.gemfire.test.junit.categories.UnitTest;
@Category(UnitTest.class)
public class FragmentJUnitTest {
- private SimpleMemoryAllocatorImpl ma;
- private OutOfOffHeapMemoryListener ooohml;
- private OffHeapMemoryStats stats;
- private LogWriter lw;
- private UnsafeMemoryChunk.Factory umcFactory;
private UnsafeMemoryChunk[] slabs;
- private int numSlabs;
static {
ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
@@ -68,30 +60,18 @@ public class FragmentJUnitTest {
@Before
public void setUp() throws Exception {
- ooohml = mock(OutOfOffHeapMemoryListener.class);
- stats = mock(OffHeapMemoryStats.class);
- lw = mock(LogWriter.class);
-
- numSlabs = 2;
- umcFactory = new UnsafeMemoryChunk.Factory(){
- @Override
- public UnsafeMemoryChunk create(int size) {
- return new UnsafeMemoryChunk(size);
- }
- };
- slabs = allocateMemorySlabs();
+ UnsafeMemoryChunk slab1 = new UnsafeMemoryChunk((int)OffHeapStorage.MIN_SLAB_SIZE);
+ UnsafeMemoryChunk slab2 = new UnsafeMemoryChunk((int)OffHeapStorage.MIN_SLAB_SIZE);
+ slabs = new UnsafeMemoryChunk[]{slab1, slab2};
}
@After
public void tearDown() throws Exception {
- SimpleMemoryAllocatorImpl.freeOffHeapMemory();
+ for (int i=0; i < slabs.length; i++) {
+ slabs[i].release();
+ }
}
- private UnsafeMemoryChunk[] allocateMemorySlabs() {
- ma = SimpleMemoryAllocatorImpl.create(ooohml, stats, lw, numSlabs, OffHeapStorage.MIN_SLAB_SIZE * numSlabs, OffHeapStorage.MIN_SLAB_SIZE, umcFactory);
- return ma.getSlabs();
- }
-
@Test
public void fragmentConstructorThrowsExceptionForNon8ByteAlignedAddress() {
@@ -147,7 +127,6 @@ public class FragmentJUnitTest {
@Test
public void getStateIsAlwaysStateUNUSED() {
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
softly.assertThat(fragment.getState()).isEqualTo(MemoryBlock.State.UNUSED);
fragment.allocate(fragment.getFreeIndex(), fragment.getFreeIndex() + 256);
@@ -156,7 +135,6 @@ public class FragmentJUnitTest {
@Test
public void getFreeListIdIsAlwaysMinus1() {
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
softly.assertThat(fragment.getFreeListId()).isEqualTo(-1);
fragment.allocate(fragment.getFreeIndex(), fragment.getFreeIndex() + 256);
@@ -165,7 +143,6 @@ public class FragmentJUnitTest {
@Test
public void getRefCountIsAlwaysZero() {
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
softly.assertThat(fragment.getRefCount()).isEqualTo(0);
fragment.allocate(fragment.getFreeIndex(), fragment.getFreeIndex() + 256);
@@ -174,7 +151,6 @@ public class FragmentJUnitTest {
@Test
public void getDataTypeIsAlwaysNA() {
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
softly.assertThat(fragment.getDataType()).isEqualTo("N/A");
fragment.allocate(fragment.getFreeIndex(), fragment.getFreeIndex() + 256);
@@ -183,7 +159,6 @@ public class FragmentJUnitTest {
@Test
public void isSerializedIsAlwaysFalse() {
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
softly.assertThat(fragment.isSerialized()).isEqualTo(false);
fragment.allocate(fragment.getFreeIndex(), fragment.getFreeIndex() + 256);
@@ -192,7 +167,6 @@ public class FragmentJUnitTest {
@Test
public void isCompressedIsAlwaysFalse() {
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
softly.assertThat(fragment.isCompressed()).isEqualTo(false);
fragment.allocate(fragment.getFreeIndex(), fragment.getFreeIndex() + 256);
@@ -201,7 +175,6 @@ public class FragmentJUnitTest {
@Test
public void getDataValueIsAlwaysNull() {
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
softly.assertThat(fragment.getDataValue()).isNull();
fragment.allocate(fragment.getFreeIndex(), fragment.getFreeIndex() + 256);
@@ -209,17 +182,7 @@ public class FragmentJUnitTest {
}
@Test
- public void getChunkTypeIsAlwaysNull() {
- slabs = allocateMemorySlabs();
- Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
- softly.assertThat(fragment.getChunkType()).isNull();
- fragment.allocate(fragment.getFreeIndex(), fragment.getFreeIndex() + 256);
- softly.assertThat(fragment.getChunkType()).isNull();
- }
-
- @Test
public void fragmentEqualsComparesMemoryBlockAddresses() {
- slabs = allocateMemorySlabs();
Fragment fragment0 = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
Fragment sameFragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
Fragment fragment1 = new Fragment(slabs[1].getMemoryAddress(), slabs[1].getSize());
@@ -229,14 +192,12 @@ public class FragmentJUnitTest {
@Test
public void fragmentEqualsIsFalseForNonFragmentObjects() {
- slabs = allocateMemorySlabs();
Fragment fragment0 = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
assertThat(fragment0.equals(slabs[0]), is(false));
}
@Test
public void fragmentHashCodeIsHashCodeOfItsMemoryAddress() {
- slabs = allocateMemorySlabs();
Fragment fragment0 = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
Fragment fragment1 = new Fragment(slabs[1].getMemoryAddress(), slabs[1].getSize());
Long fragmentAddress = fragment0.getMemoryAddress();
@@ -246,12 +207,11 @@ public class FragmentJUnitTest {
@Test
public void fragmentFillSetsAllBytesToTheSameConstantValue() {
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
Long fragmentAddress = fragment.getMemoryAddress();
byte[] bytes = new byte[(int)OffHeapStorage.MIN_SLAB_SIZE];
byte[] expectedBytes = new byte[(int)OffHeapStorage.MIN_SLAB_SIZE];
- Arrays.fill(expectedBytes, Chunk.FILL_BYTE);;
+ Arrays.fill(expectedBytes, ObjectChunk.FILL_BYTE);;
fragment.fill();
UnsafeMemoryChunk.readAbsoluteBytes(fragmentAddress, bytes, 0, (int)OffHeapStorage.MIN_SLAB_SIZE);
assertThat(bytes, is(equalTo(expectedBytes)));
@@ -261,7 +221,6 @@ public class FragmentJUnitTest {
public void getNextBlockThrowsExceptionForFragment() {
expectedException.expect(UnsupportedOperationException.class);
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
fragment.getNextBlock();
fail("getNextBlock failed to throw UnsupportedOperationException");
@@ -271,7 +230,6 @@ public class FragmentJUnitTest {
public void getSlabIdThrowsExceptionForFragment() {
expectedException.expect(UnsupportedOperationException.class);
- slabs = allocateMemorySlabs();
Fragment fragment = new Fragment(slabs[0].getMemoryAddress(), slabs[0].getSize());
fragment.getSlabId();
fail("getSlabId failed to throw UnsupportedOperationException");
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListManagerTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListManagerTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListManagerTest.java
new file mode 100644
index 0000000..64032cc
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListManagerTest.java
@@ -0,0 +1,797 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gemstone.gemfire.internal.offheap;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+import static com.googlecode.catchexception.CatchException.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.LogWriter;
+import com.gemstone.gemfire.OutOfOffHeapMemoryException;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class FreeListManagerTest {
+ static {
+ ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
+ }
+
+ private final int DEFAULT_SLAB_SIZE = 1024*1024*5;
+ private final SimpleMemoryAllocatorImpl ma = mock(SimpleMemoryAllocatorImpl.class);
+ private final OffHeapMemoryStats stats = mock(OffHeapMemoryStats.class);
+ private TestableFreeListManager freeListManager;
+
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ when(ma.getStats()).thenReturn(stats);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (this.freeListManager != null) {
+ this.freeListManager.freeSlabs();
+ }
+ }
+
+ private static TestableFreeListManager createFreeListManager(SimpleMemoryAllocatorImpl ma, AddressableMemoryChunk[] slabs) {
+ return new TestableFreeListManager(ma, slabs);
+ }
+
+ private void setUpSingleSlabManager() {
+ setUpSingleSlabManager(DEFAULT_SLAB_SIZE);
+ }
+ private void setUpSingleSlabManager(int slabSize) {
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(slabSize);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {slab});
+ }
+
+ @Test
+ public void usedMemoryIsZeroOnDefault() {
+ setUpSingleSlabManager();
+ assertThat(this.freeListManager.getUsedMemory()).isZero();
+ }
+
+ @Test
+ public void freeMemoryIsSlabSizeOnDefault() {
+ setUpSingleSlabManager();
+ assertThat(this.freeListManager.getFreeMemory()).isEqualTo(DEFAULT_SLAB_SIZE);
+ }
+
+ @Test
+ public void totalMemoryIsSlabSizeOnDefault() {
+ setUpSingleSlabManager();
+ assertThat(this.freeListManager.getTotalMemory()).isEqualTo(DEFAULT_SLAB_SIZE);
+ }
+
+ @Test
+ public void allocateTinyChunkHasCorrectSize() {
+ setUpSingleSlabManager();
+ int tinySize = 10;
+
+ ObjectChunk c = this.freeListManager.allocate(tinySize);
+
+ validateChunkSizes(c, tinySize);
+ }
+
+ private void validateChunkSizes(ObjectChunk c, int dataSize) {
+ assertThat(c).isNotNull();
+ assertThat(c.getDataSize()).isEqualTo(dataSize);
+ assertThat(c.getSize()).isEqualTo(computeExpectedSize(dataSize));
+ }
+
+ @Test
+ public void allocateTinyChunkFromFreeListHasCorrectSize() {
+ setUpSingleSlabManager();
+ int tinySize = 10;
+
+ ObjectChunk c = this.freeListManager.allocate(tinySize);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ c = this.freeListManager.allocate(tinySize);
+
+ validateChunkSizes(c, tinySize);
+ }
+
+ @Test
+ public void allocateTinyChunkFromEmptyFreeListHasCorrectSize() {
+ setUpSingleSlabManager();
+ int dataSize = 10;
+
+ ObjectChunk c = this.freeListManager.allocate(dataSize);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ this.freeListManager.allocate(dataSize);
+ // free list will now be empty
+ c = this.freeListManager.allocate(dataSize);
+
+ validateChunkSizes(c, dataSize);
+ }
+
+ @Test
+ public void allocateHugeChunkHasCorrectSize() {
+ setUpSingleSlabManager();
+ int hugeSize = FreeListManager.MAX_TINY+1;
+
+ ObjectChunk c = this.freeListManager.allocate(hugeSize);
+
+ validateChunkSizes(c, hugeSize);
+ }
+
+ @Test
+ public void allocateHugeChunkFromEmptyFreeListHasCorrectSize() {
+ setUpSingleSlabManager();
+ int dataSize = FreeListManager.MAX_TINY+1;
+
+ ObjectChunk c = this.freeListManager.allocate(dataSize);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ this.freeListManager.allocate(dataSize);
+ // free list will now be empty
+ c = this.freeListManager.allocate(dataSize);
+
+ validateChunkSizes(c, dataSize);
+ }
+
+ @Test
+ public void allocateHugeChunkFromFragmentWithItemInFreeListHasCorrectSize() {
+ setUpSingleSlabManager();
+ int dataSize = FreeListManager.MAX_TINY+1+1024;
+
+ ObjectChunk c = this.freeListManager.allocate(dataSize);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ dataSize = FreeListManager.MAX_TINY+1;
+ c = this.freeListManager.allocate(dataSize);
+
+ validateChunkSizes(c, dataSize);
+ }
+ @Test
+ public void freeTinyMemoryDefault() {
+ setUpSingleSlabManager();
+
+ assertThat(this.freeListManager.getFreeTinyMemory()).isZero();
+ }
+ @Test
+ public void freeTinyMemoryEqualToChunkSize() {
+ setUpSingleSlabManager();
+ int dataSize = 10;
+
+ ObjectChunk c = this.freeListManager.allocate(dataSize);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+
+ assertThat(this.freeListManager.getFreeTinyMemory()).isEqualTo(computeExpectedSize(dataSize));
+ }
+
+ @Test
+ public void freeTinyMemoryWithTwoTinyFreeListsEqualToChunkSize() {
+ setUpSingleSlabManager();
+ int dataSize = 10;
+
+ ObjectChunk c = this.freeListManager.allocate(dataSize);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+
+ int dataSize2 = 100;
+
+ ObjectChunk c2 = this.freeListManager.allocate(dataSize2);
+ ObjectChunk.release(c2.getMemoryAddress(), this.freeListManager);
+
+ assertThat(this.freeListManager.getFreeTinyMemory()).isEqualTo(computeExpectedSize(dataSize)+computeExpectedSize(dataSize2));
+ }
+
+ @Test
+ public void freeHugeMemoryDefault() {
+ setUpSingleSlabManager();
+
+ assertThat(this.freeListManager.getFreeHugeMemory()).isZero();
+ }
+ @Test
+ public void freeHugeMemoryEqualToChunkSize() {
+ setUpSingleSlabManager();
+ int dataSize = FreeListManager.MAX_TINY+1+1024;
+
+ ObjectChunk c = this.freeListManager.allocate(dataSize);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+
+ assertThat(this.freeListManager.getFreeHugeMemory()).isEqualTo(computeExpectedSize(dataSize));
+ }
+
+ @Test
+ public void freeFragmentMemoryDefault() {
+ setUpSingleSlabManager();
+
+ assertThat(this.freeListManager.getFreeFragmentMemory()).isEqualTo(DEFAULT_SLAB_SIZE);
+ }
+
+ @Test
+ public void freeFragmentMemorySomeOfFragmentAllocated() {
+ setUpSingleSlabManager();
+ ObjectChunk c = this.freeListManager.allocate(DEFAULT_SLAB_SIZE/4-8);
+
+ assertThat(this.freeListManager.getFreeFragmentMemory()).isEqualTo((DEFAULT_SLAB_SIZE/4)*3);
+ }
+
+ @Test
+ public void freeFragmentMemoryMostOfFragmentAllocated() {
+ setUpSingleSlabManager();
+ ObjectChunk c = this.freeListManager.allocate(DEFAULT_SLAB_SIZE-8-8);
+
+ assertThat(this.freeListManager.getFreeFragmentMemory()).isZero();
+ }
+
+ private int computeExpectedSize(int dataSize) {
+ return ((dataSize + ObjectChunk.OFF_HEAP_HEADER_SIZE + 7) / 8) * 8;
+ }
+
+ @Test(expected = AssertionError.class)
+ public void allocateZeroThrowsAssertion() {
+ setUpSingleSlabManager();
+ this.freeListManager.allocate(0);
+ }
+
+ @Test
+ public void allocateFromMultipleSlabs() {
+ int SMALL_SLAB = 16;
+ int MEDIUM_SLAB = 128;
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(DEFAULT_SLAB_SIZE);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(MEDIUM_SLAB),
+ slab});
+ this.freeListManager.allocate(SMALL_SLAB-8+1);
+ this.freeListManager.allocate(DEFAULT_SLAB_SIZE-8);
+ this.freeListManager.allocate(SMALL_SLAB-8+1);
+ assertThat(this.freeListManager.getFreeMemory()).isEqualTo(SMALL_SLAB*2+MEDIUM_SLAB-((SMALL_SLAB+8)*2));
+ assertThat(this.freeListManager.getUsedMemory()).isEqualTo(DEFAULT_SLAB_SIZE+(SMALL_SLAB+8)*2);
+ assertThat(this.freeListManager.getTotalMemory()).isEqualTo(DEFAULT_SLAB_SIZE+MEDIUM_SLAB+SMALL_SLAB*2);
+ }
+
+ @Test
+ public void compactWithLargeChunkSizeReturnsFalse() {
+ int SMALL_SLAB = 16;
+ int MEDIUM_SLAB = 128;
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(DEFAULT_SLAB_SIZE);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(MEDIUM_SLAB),
+ slab});
+ ArrayList<ObjectChunk> chunks = new ArrayList<>();
+ chunks.add(this.freeListManager.allocate(SMALL_SLAB-8+1));
+ chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE/2-8));
+ chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE/2-8));
+ chunks.add(this.freeListManager.allocate(SMALL_SLAB-8+1));
+ for (ObjectChunk c: chunks) {
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ }
+ this.freeListManager.firstCompact = false;
+ assertThat(this.freeListManager.compact(DEFAULT_SLAB_SIZE+1)).isFalse();
+ }
+
+ @Test
+ public void compactWithChunkSizeOfMaxSlabReturnsTrue() {
+ int SMALL_SLAB = 16;
+ int MEDIUM_SLAB = 128;
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(DEFAULT_SLAB_SIZE);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(MEDIUM_SLAB),
+ slab});
+ ArrayList<ObjectChunk> chunks = new ArrayList<>();
+ chunks.add(this.freeListManager.allocate(SMALL_SLAB-8+1));
+ chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE/2-8));
+ chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE/2-8));
+ chunks.add(this.freeListManager.allocate(SMALL_SLAB-8+1));
+ for (ObjectChunk c: chunks) {
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ }
+
+ assertThat(this.freeListManager.compact(DEFAULT_SLAB_SIZE)).isTrue();
+ //assertThat(this.freeListManager.getFragmentList()).hasSize(4); // TODO intermittently fails because Fragments may be merged
+ }
+
+ @Test
+ public void compactWithLiveChunks() {
+ int SMALL_SLAB = 16;
+ int MEDIUM_SLAB = 128;
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(DEFAULT_SLAB_SIZE);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(MEDIUM_SLAB),
+ slab});
+ ArrayList<ObjectChunk> chunks = new ArrayList<>();
+ chunks.add(this.freeListManager.allocate(SMALL_SLAB-8+1));
+ this.freeListManager.allocate(DEFAULT_SLAB_SIZE/2-8);
+ chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE/2-8));
+ this.freeListManager.allocate(SMALL_SLAB-8+1);
+ for (ObjectChunk c: chunks) {
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ }
+
+ assertThat(this.freeListManager.compact(DEFAULT_SLAB_SIZE/2)).isTrue();
+ }
+
+ @Test
+ public void compactAfterAllocatingAll() {
+ setUpSingleSlabManager();
+ ObjectChunk c = freeListManager.allocate(DEFAULT_SLAB_SIZE-8);
+ this.freeListManager.firstCompact = false;
+ assertThat(this.freeListManager.compact(1)).isFalse();
+ // call compact twice for extra code coverage
+ assertThat(this.freeListManager.compact(1)).isFalse();
+ assertThat(this.freeListManager.getFragmentList()).isEmpty();
+ }
+
+ @Test
+ public void afterAllocatingAllOneSizeCompactToAllocateDifferentSize() {
+ setUpSingleSlabManager();
+ ArrayList<ObjectChunk> chunksToFree = new ArrayList<>();
+ ArrayList<ObjectChunk> chunksToFreeLater = new ArrayList<>();
+ int ALLOCATE_COUNT = 1000;
+ ObjectChunk bigChunk = freeListManager.allocate(DEFAULT_SLAB_SIZE-8-(ALLOCATE_COUNT*32)-256-256);
+ for (int i=0; i < ALLOCATE_COUNT; i++) {
+ ObjectChunk c = freeListManager.allocate(24);
+ if (i%3 != 2) {
+ chunksToFree.add(c);
+ } else {
+ chunksToFreeLater.add(c);
+ }
+ }
+ ObjectChunk c1 = freeListManager.allocate(64-8);
+ ObjectChunk c2 = freeListManager.allocate(64-8);
+ ObjectChunk c3 = freeListManager.allocate(64-8);
+ ObjectChunk c4 = freeListManager.allocate(64-8);
+
+ ObjectChunk mediumChunk1 = freeListManager.allocate(128-8);
+ ObjectChunk mediumChunk2 = freeListManager.allocate(128-8);
+
+ ObjectChunk.release(bigChunk.getMemoryAddress(), freeListManager);
+ int s = chunksToFree.size();
+ for (int i=s/2; i >=0; i--) {
+ ObjectChunk c = chunksToFree.get(i);
+ ObjectChunk.release(c.getMemoryAddress(), freeListManager);
+ }
+ for (int i=(s/2)+1; i < s; i++) {
+ ObjectChunk c = chunksToFree.get(i);
+ ObjectChunk.release(c.getMemoryAddress(), freeListManager);
+ }
+ ObjectChunk.release(c3.getMemoryAddress(), freeListManager);
+ ObjectChunk.release(c1.getMemoryAddress(), freeListManager);
+ ObjectChunk.release(c2.getMemoryAddress(), freeListManager);
+ ObjectChunk.release(c4.getMemoryAddress(), freeListManager);
+ ObjectChunk.release(mediumChunk1.getMemoryAddress(), freeListManager);
+ ObjectChunk.release(mediumChunk2.getMemoryAddress(), freeListManager);
+ this.freeListManager.firstCompact = false;
+ assertThat(freeListManager.compact(DEFAULT_SLAB_SIZE-(ALLOCATE_COUNT*32))).isFalse();
+ for (int i=0; i < ((256*2)/96); i++) {
+ ObjectChunk.release(chunksToFreeLater.get(i).getMemoryAddress(), freeListManager);
+ }
+ assertThat(freeListManager.compact(DEFAULT_SLAB_SIZE-(ALLOCATE_COUNT*32))).isTrue();
+ }
+
+ @Test
+ public void afterAllocatingAndFreeingCompact() {
+ int slabSize = 1024*3;
+ setUpSingleSlabManager(slabSize);
+ ObjectChunk bigChunk1 = freeListManager.allocate(slabSize/3-8);
+ ObjectChunk bigChunk2 = freeListManager.allocate(slabSize/3-8);
+ ObjectChunk bigChunk3 = freeListManager.allocate(slabSize/3-8);
+ this.freeListManager.firstCompact = false;
+ assertThat(freeListManager.compact(1)).isFalse();
+ ObjectChunk.release(bigChunk3.getMemoryAddress(), freeListManager);
+ ObjectChunk.release(bigChunk2.getMemoryAddress(), freeListManager);
+ ObjectChunk.release(bigChunk1.getMemoryAddress(), freeListManager);
+ assertThat(freeListManager.compact(slabSize)).isTrue();
+ }
+
+ @Test
+ public void compactWithEmptyTinyFreeList() {
+ setUpSingleSlabManager();
+ Fragment originalFragment = this.freeListManager.getFragmentList().get(0);
+ ObjectChunk c = freeListManager.allocate(16);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ c = freeListManager.allocate(16);
+ this.freeListManager.firstCompact = false;
+ assertThat(this.freeListManager.compact(1)).isTrue();
+ assertThat(this.freeListManager.getFragmentList()).hasSize(1);
+ Fragment compactedFragment = this.freeListManager.getFragmentList().get(0);
+ assertThat(compactedFragment.getSize()).isEqualTo(originalFragment.getSize()-(16+8));
+ assertThat(compactedFragment.getMemoryAddress()).isEqualTo(originalFragment.getMemoryAddress()+(16+8));
+ }
+
+ @Test
+ public void allocationsThatLeaveLessThanMinChunkSizeFreeInAFragment() {
+ int SMALL_SLAB = 16;
+ int MEDIUM_SLAB = 128;
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(DEFAULT_SLAB_SIZE);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(SMALL_SLAB),
+ new UnsafeMemoryChunk(MEDIUM_SLAB),
+ slab});
+ this.freeListManager.allocate(DEFAULT_SLAB_SIZE-8-(ObjectChunk.MIN_CHUNK_SIZE-1));
+ this.freeListManager.allocate(MEDIUM_SLAB-8-(ObjectChunk.MIN_CHUNK_SIZE-1));
+
+ assertThat(this.freeListManager.compact(SMALL_SLAB)).isTrue();
+ }
+ @Test
+ public void maxAllocationUsesAllMemory() {
+ setUpSingleSlabManager();
+
+ this.freeListManager.allocate(DEFAULT_SLAB_SIZE-8);
+
+ assertThat(this.freeListManager.getFreeMemory()).isZero();
+ assertThat(this.freeListManager.getUsedMemory()).isEqualTo(DEFAULT_SLAB_SIZE);
+ }
+
+
+ @Test
+ public void overMaxAllocationFails() {
+ setUpSingleSlabManager();
+ OutOfOffHeapMemoryListener ooohml = mock(OutOfOffHeapMemoryListener.class);
+ when(this.ma.getOutOfOffHeapMemoryListener()).thenReturn(ooohml);
+
+ catchException(this.freeListManager).allocate(DEFAULT_SLAB_SIZE-7);
+
+ verify(ooohml).outOfOffHeapMemory(caughtException());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void allocateNegativeThrowsAssertion() {
+ setUpSingleSlabManager();
+ this.freeListManager.allocate(-123);
+ }
+
+ @Test
+ public void hugeMultipleLessThanZeroIsIllegal() {
+ try {
+ FreeListManager.verifyHugeMultiple(-1);
+ fail("expected IllegalStateException");
+ } catch (IllegalStateException expected) {
+ assertThat(expected.getMessage()).contains("HUGE_MULTIPLE must be >= 0 and <= " + FreeListManager.HUGE_MULTIPLE + " but it was -1");
+ }
+ }
+ @Test
+ public void hugeMultipleGreaterThan256IsIllegal() {
+ try {
+ FreeListManager.verifyHugeMultiple(257);
+ fail("expected IllegalStateException");
+ } catch (IllegalStateException expected) {
+ assertThat(expected.getMessage()).contains("HUGE_MULTIPLE must be >= 0 and <= 256 but it was 257");
+ }
+ }
+ @Test
+ public void hugeMultipleof256IsLegal() {
+ FreeListManager.verifyHugeMultiple(256);
+ }
+
+ @Test
+ public void offHeapFreeListCountLessThanZeroIsIllegal() {
+ try {
+ FreeListManager.verifyOffHeapFreeListCount(-1);
+ fail("expected IllegalStateException");
+ } catch (IllegalStateException expected) {
+ assertThat(expected.getMessage()).contains("gemfire.OFF_HEAP_FREE_LIST_COUNT must be >= 1.");
+ }
+ }
+ @Test
+ public void offHeapFreeListCountOfZeroIsIllegal() {
+ try {
+ FreeListManager.verifyOffHeapFreeListCount(0);
+ fail("expected IllegalStateException");
+ } catch (IllegalStateException expected) {
+ assertThat(expected.getMessage()).contains("gemfire.OFF_HEAP_FREE_LIST_COUNT must be >= 1.");
+ }
+ }
+ @Test
+ public void offHeapFreeListCountOfOneIsLegal() {
+ FreeListManager.verifyOffHeapFreeListCount(1);
+ }
+ @Test
+ public void offHeapAlignmentLessThanZeroIsIllegal() {
+ try {
+ FreeListManager.verifyOffHeapAlignment(-1);
+ fail("expected IllegalStateException");
+ } catch (IllegalStateException expected) {
+ assertThat(expected.getMessage()).contains("gemfire.OFF_HEAP_ALIGNMENT must be a multiple of 8");
+ }
+ }
+ @Test
+ public void offHeapAlignmentNotAMultipleOf8IsIllegal() {
+ try {
+ FreeListManager.verifyOffHeapAlignment(9);
+ fail("expected IllegalStateException");
+ } catch (IllegalStateException expected) {
+ assertThat(expected.getMessage()).contains("gemfire.OFF_HEAP_ALIGNMENT must be a multiple of 8");
+ }
+ }
+ @Test
+ public void offHeapAlignmentGreaterThan256IsIllegal() {
+ try {
+ FreeListManager.verifyOffHeapAlignment(256+8);
+ fail("expected IllegalStateException");
+ } catch (IllegalStateException expected) {
+ assertThat(expected.getMessage()).contains("gemfire.OFF_HEAP_ALIGNMENT must be <= 256");
+ }
+ }
+ @Test
+ public void offHeapAlignmentOf256IsLegal() {
+ FreeListManager.verifyOffHeapAlignment(256);
+ }
+
+ @Test
+ public void okToReuseNull() {
+ setUpSingleSlabManager();
+ assertThat(this.freeListManager.okToReuse(null)).isTrue();
+ }
+
+ @Test
+ public void okToReuseSameSlabs() {
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(DEFAULT_SLAB_SIZE);
+ UnsafeMemoryChunk[] slabs = new UnsafeMemoryChunk[] {slab};
+ this.freeListManager = createFreeListManager(ma, slabs);
+ assertThat(this.freeListManager.okToReuse(slabs)).isTrue();
+ }
+ @Test
+ public void notOkToReuseDifferentSlabs() {
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(DEFAULT_SLAB_SIZE);
+ UnsafeMemoryChunk[] slabs = new UnsafeMemoryChunk[] {slab};
+ this.freeListManager = createFreeListManager(ma, slabs);
+ UnsafeMemoryChunk[] slabs2 = new UnsafeMemoryChunk[] {slab};
+ assertThat(this.freeListManager.okToReuse(slabs2)).isFalse();
+ }
+ @Test
+ public void firstSlabAlwaysLargest() {
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {
+ new UnsafeMemoryChunk(10),
+ new UnsafeMemoryChunk(100)});
+ assertThat(this.freeListManager.getLargestSlabSize()).isEqualTo(10);
+ }
+
+ @Test
+ public void findSlab() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(10);
+ long address = chunk.getMemoryAddress();
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ assertThat(this.freeListManager.findSlab(address)).isEqualTo(0);
+ assertThat(this.freeListManager.findSlab(address+9)).isEqualTo(0);
+ catchException(this.freeListManager).findSlab(address-1);
+ assertThat((Exception)caughtException())
+ .isExactlyInstanceOf(IllegalStateException.class)
+ .hasMessage("could not find a slab for addr " + (address-1));
+ catchException(this.freeListManager).findSlab(address+10);
+ assertThat((Exception)caughtException())
+ .isExactlyInstanceOf(IllegalStateException.class)
+ .hasMessage("could not find a slab for addr " + (address+10));
+ }
+
+ @Test
+ public void findSecondSlab() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(10);
+ long address = chunk.getMemoryAddress();
+ UnsafeMemoryChunk slab = new UnsafeMemoryChunk(DEFAULT_SLAB_SIZE);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {slab, chunk});
+ assertThat(this.freeListManager.findSlab(address)).isEqualTo(1);
+ assertThat(this.freeListManager.findSlab(address+9)).isEqualTo(1);
+ catchException(this.freeListManager).findSlab(address-1);
+ assertThat((Exception)caughtException())
+ .isExactlyInstanceOf(IllegalStateException.class)
+ .hasMessage("could not find a slab for addr " + (address-1));
+ catchException(this.freeListManager).findSlab(address+10);
+ assertThat((Exception)caughtException())
+ .isExactlyInstanceOf(IllegalStateException.class)
+ .hasMessage("could not find a slab for addr " + (address+10));
+ }
+
+ @Test
+ public void validateAddressWithinSlab() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(10);
+ long address = chunk.getMemoryAddress();
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ assertThat(this.freeListManager.validateAddressAndSizeWithinSlab(address, -1)).isTrue();
+ assertThat(this.freeListManager.validateAddressAndSizeWithinSlab(address+9, -1)).isTrue();
+ assertThat(this.freeListManager.validateAddressAndSizeWithinSlab(address-1, -1)).isFalse();
+ assertThat(this.freeListManager.validateAddressAndSizeWithinSlab(address+10, -1)).isFalse();
+ }
+
+ @Test
+ public void validateAddressAndSizeWithinSlab() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(10);
+ long address = chunk.getMemoryAddress();
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ assertThat(this.freeListManager.validateAddressAndSizeWithinSlab(address, 1)).isTrue();
+ assertThat(this.freeListManager.validateAddressAndSizeWithinSlab(address, 10)).isTrue();
+ catchException(this.freeListManager).validateAddressAndSizeWithinSlab(address, 0);
+ assertThat((Exception)caughtException())
+ .isExactlyInstanceOf(IllegalStateException.class)
+ .hasMessage(" address 0x" + Long.toString(address+0-1, 16) + " does not address the original slab memory");
+ catchException(this.freeListManager).validateAddressAndSizeWithinSlab(address, 11);
+ assertThat((Exception)caughtException())
+ .isExactlyInstanceOf(IllegalStateException.class)
+ .hasMessage(" address 0x" + Long.toString(address+11-1, 16) + " does not address the original slab memory");
+ }
+
+ @Test
+ public void descriptionOfOneSlab() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(10);
+ long address = chunk.getMemoryAddress();
+ long endAddress = address+10;
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ StringBuilder sb = new StringBuilder();
+ this.freeListManager.getSlabDescriptions(sb);
+ assertThat(sb.toString()).isEqualTo("[" + Long.toString(address, 16) + ".." + Long.toString(endAddress, 16) + "] ");
+ }
+
+ @Test
+ public void orderBlocksContainsFragment() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(10);
+ long address = chunk.getMemoryAddress();
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ List<MemoryBlock> ob = this.freeListManager.getOrderedBlocks();
+ assertThat(ob).hasSize(1);
+ assertThat(ob.get(0).getMemoryAddress()).isEqualTo(address);
+ assertThat(ob.get(0).getBlockSize()).isEqualTo(10);
+ }
+
+ @Test
+ public void orderBlocksContainsTinyFree() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(96);
+ long address = chunk.getMemoryAddress();
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ ObjectChunk c = this.freeListManager.allocate(24);
+ ObjectChunk c2 = this.freeListManager.allocate(24);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+
+ List<MemoryBlock> ob = this.freeListManager.getOrderedBlocks();
+ assertThat(ob).hasSize(3);
+ }
+
+ @Test
+ public void allocatedBlocksEmptyIfNoAllocations() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(10);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ List<MemoryBlock> ob = this.freeListManager.getAllocatedBlocks();
+ assertThat(ob).hasSize(0);
+ }
+
+ @Test
+ public void allocatedBlocksEmptyAfterFree() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(96);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ ObjectChunk c = this.freeListManager.allocate(24);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ List<MemoryBlock> ob = this.freeListManager.getAllocatedBlocks();
+ assertThat(ob).hasSize(0);
+ }
+
+ @Test
+ public void allocatedBlocksHasAllocatedChunk() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(96);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ ObjectChunk c = this.freeListManager.allocate(24);
+ List<MemoryBlock> ob = this.freeListManager.getAllocatedBlocks();
+ assertThat(ob).hasSize(1);
+ assertThat(ob.get(0).getMemoryAddress()).isEqualTo(c.getMemoryAddress());
+ }
+
+ @Test
+ public void allocatedBlocksHasBothAllocatedChunks() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(96);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ ObjectChunk c = this.freeListManager.allocate(24);
+ ObjectChunk c2 = this.freeListManager.allocate(33);
+ List<MemoryBlock> ob = this.freeListManager.getAllocatedBlocks();
+ assertThat(ob).hasSize(2);
+ }
+
+ @Test
+ public void allocateFromFragmentWithBadIndexesReturnsNull() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(96);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk});
+ assertThat(this.freeListManager.allocateFromFragment(-1, 32)).isNull();
+ assertThat(this.freeListManager.allocateFromFragment(1, 32)).isNull();
+ }
+
+ @Test
+ public void testLogging() {
+ UnsafeMemoryChunk chunk = new UnsafeMemoryChunk(32);
+ UnsafeMemoryChunk chunk2 = new UnsafeMemoryChunk(1024*1024*5);
+ this.freeListManager = createFreeListManager(ma, new UnsafeMemoryChunk[] {chunk, chunk2});
+ ObjectChunk c = this.freeListManager.allocate(24);
+ ObjectChunk c2 = this.freeListManager.allocate(1024*1024);
+ ObjectChunk.release(c.getMemoryAddress(), this.freeListManager);
+ ObjectChunk.release(c2.getMemoryAddress(), this.freeListManager);
+
+ LogWriter lw = mock(LogWriter.class);
+ this.freeListManager.logOffHeapState(lw, 1024);
+ }
+ /**
+ * Just like Fragment except that the first time allocate is called
+ * it returns false indicating that the allocate failed.
+ * In a real system this would only happen if a concurrent allocate
+ * happened. This allows better code coverage.
+ */
+ private static class TestableFragment extends Fragment {
+ private boolean allocateCalled = false;
+ public TestableFragment(long addr, int size) {
+ super(addr, size);
+ }
+ @Override
+ public boolean allocate(int oldOffset, int newOffset) {
+ if (!allocateCalled) {
+ allocateCalled = true;
+ return false;
+ }
+ return super.allocate(oldOffset, newOffset);
+ }
+ }
+ private static class TestableFreeListManager extends FreeListManager {
+ private boolean firstTime = true;
+
+ @Override
+ protected Fragment createFragment(long addr, int size) {
+ return new TestableFragment(addr, size);
+ }
+
+ @Override
+ protected SyncChunkStack createFreeListForEmptySlot(AtomicReferenceArray<SyncChunkStack> freeLists, int idx) {
+ if (this.firstTime) {
+ this.firstTime = false;
+ SyncChunkStack clq = super.createFreeListForEmptySlot(freeLists, idx);
+ if (!freeLists.compareAndSet(idx, null, clq)) {
+ fail("this should never happen. Indicates a concurrent modification");
+ }
+ }
+ return super.createFreeListForEmptySlot(freeLists, idx);
+ }
+
+ public boolean firstCompact = true;
+ @Override
+ protected void afterCompactCountFetched() {
+ if (this.firstCompact) {
+ this.firstCompact = false;
+ // Force compact into thinking a concurrent compaction happened.
+ this.compactCount.incrementAndGet();
+ }
+ }
+
+ public TestableFreeListManager(SimpleMemoryAllocatorImpl ma, AddressableMemoryChunk[] slabs) {
+ super(ma, slabs);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListOffHeapRegionJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListOffHeapRegionJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListOffHeapRegionJUnitTest.java
index 93f2039..6790f6a 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListOffHeapRegionJUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/FreeListOffHeapRegionJUnitTest.java
@@ -40,7 +40,7 @@ public class FreeListOffHeapRegionJUnitTest extends OffHeapRegionBase {
@Override
public int perObjectOverhead() {
- return Chunk.OFF_HEAP_HEADER_SIZE;
+ return ObjectChunk.OFF_HEAP_HEADER_SIZE;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9899940b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/GemFireChunkFactoryJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/GemFireChunkFactoryJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/GemFireChunkFactoryJUnitTest.java
deleted file mode 100644
index d12b823..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/GemFireChunkFactoryJUnitTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.gemstone.gemfire.internal.offheap;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import com.gemstone.gemfire.LogWriter;
-import com.gemstone.gemfire.internal.cache.EntryEventImpl;
-import com.gemstone.gemfire.test.junit.categories.UnitTest;
-
-@Category(UnitTest.class)
-public class GemFireChunkFactoryJUnitTest {
-
- private MemoryAllocator ma;
-
- @Before
- public void setUp() {
- OutOfOffHeapMemoryListener ooohml = mock(OutOfOffHeapMemoryListener.class);
- OffHeapMemoryStats stats = mock(OffHeapMemoryStats.class);
- LogWriter lw = mock(LogWriter.class);
-
- ma = SimpleMemoryAllocatorImpl.create(ooohml, stats, lw, 1, OffHeapStorage.MIN_SLAB_SIZE * 1, OffHeapStorage.MIN_SLAB_SIZE);
- }
-
- @After
- public void tearDown() {
- SimpleMemoryAllocatorImpl.freeOffHeapMemory();
- }
-
- private GemFireChunk createChunk(Object value) {
- byte[] v = EntryEventImpl.serialize(value);
-
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- GemFireChunk chunk = (GemFireChunk) ma.allocateAndInitialize(v, isSerialized, isCompressed, GemFireChunk.TYPE);
-
- return chunk;
- }
-
- @Test
- public void factoryShouldCreateNewChunkWithGivenAddress() {
- GemFireChunk chunk = createChunk(Long.MAX_VALUE);
-
- ChunkFactory factory = new GemFireChunkFactory();
- Chunk newChunk = factory.newChunk(chunk.getMemoryAddress());
-
- assertNotNull(newChunk);
- assertEquals(GemFireChunk.class, newChunk.getClass());
-
- assertThat(newChunk.getMemoryAddress()).isEqualTo(chunk.getMemoryAddress());
-
- chunk.release();
- }
-
- @Test
- public void factoryShouldCreateNewChunkWithGivenAddressAndType() {
- GemFireChunk chunk = createChunk(Long.MAX_VALUE);
-
- ChunkFactory factory = new GemFireChunkFactory();
- Chunk newChunk = factory.newChunk(chunk.getMemoryAddress(), GemFireChunk.TYPE);
-
- assertNotNull(newChunk);
- assertEquals(GemFireChunk.class, newChunk.getClass());
-
- assertThat(newChunk.getMemoryAddress()).isEqualTo(chunk.getMemoryAddress());
- assertThat(newChunk.getChunkType()).isEqualTo(GemFireChunk.TYPE);
-
- chunk.release();
- }
-
- @Test
- public void shouldGetChunkTypeFromAddress() {
- byte[] v = EntryEventImpl.serialize(Long.MAX_VALUE);
-
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- GemFireChunk chunk = (GemFireChunk) ma.allocateAndInitialize(v, isSerialized, isCompressed, GemFireChunk.TYPE);
-
- ChunkFactory factory = new GemFireChunkFactory();
- ChunkType actualType = factory.getChunkTypeForAddress(chunk.getMemoryAddress());
-
- assertEquals(GemFireChunk.TYPE, actualType);
-
- chunk.release();
- }
-
- @Test
- public void shouldGetChunkTypeFromRawBits() {
- byte[] v = EntryEventImpl.serialize(Long.MAX_VALUE);
-
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- GemFireChunk chunk = (GemFireChunk) ma.allocateAndInitialize(v, isSerialized, isCompressed, GemFireChunk.TYPE);
-
- int rawBits = UnsafeMemoryChunk.readAbsoluteIntVolatile(chunk.getMemoryAddress() + 4 /* REF_COUNT_OFFSET */);
-
- ChunkFactory factory = new GemFireChunkFactory();
- ChunkType actualType = factory.getChunkTypeForRawBits(rawBits);
- assertEquals(GemFireChunk.TYPE, actualType);
-
- chunk.release();
- }
-}