You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2021/03/29 17:19:33 UTC
[geode] branch develop updated: GEODE-6143: Remove PowerMock from
offheap tests (#6179)
This is an automated email from the ASF dual-hosted git repository.
klund pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 47c3b96 GEODE-6143: Remove PowerMock from offheap tests (#6179)
47c3b96 is described below
commit 47c3b96f46cd36a23724e47a13a7f352574dd773
Author: Kirk Lund <kl...@apache.org>
AuthorDate: Mon Mar 29 10:18:33 2021 -0700
GEODE-6143: Remove PowerMock from offheap tests (#6179)
* Clean-up offheap code and tests
* Extract OffHeapClearRequired from OffHeapStoredObject
* Extract ReferenceCounter from OffHeapStoredObject
* Move remaining static methods to bottom of OffHeapStoredObject
* Extract non-static delegate OffHeapRegionEntryHelperInstance from
OffHeapRegionEntryHelper
* Extract non-static delegate ReferenceCounterInstance from
ReferenceCounter
* Remove PowerMock from offheap tests
* Remove PowerMock from Geode build files
* Rename OffHeapRegionEntryHelperInstanceTest
* Rename ReferenceCountHelperImplTest
---
.../src/test/resources/expected-pom.xml | 26 +-
.../gradle/plugins/DependencyConstraints.groovy | 6 -
geode-core/build.gradle | 6 -
.../internal/cache/AbstractBucketRegionQueue.java | 6 +-
.../geode/internal/cache/AbstractRegionMap.java | 4 +-
.../geode/internal/cache/BucketRegionQueue.java | 6 +-
.../cache/wan/serial/SerialGatewaySenderQueue.java | 6 +-
.../geode/internal/offheap/FreeListManager.java | 2 +-
.../internal/offheap/OffHeapClearRequired.java | 34 +
.../internal/offheap/OffHeapRegionEntryHelper.java | 342 +----
....java => OffHeapRegionEntryHelperInstance.java} | 328 ++---
.../internal/offheap/OffHeapStoredObject.java | 178 +--
.../internal/offheap/ReferenceCountHelper.java | 64 +-
.../internal/offheap/ReferenceCountHelperImpl.java | 173 +--
.../geode/internal/offheap/ReferenceCounter.java | 50 +
.../internal/offheap/ReferenceCounterInstance.java | 118 ++
.../concurrent/CustomEntryConcurrentHashMap.java | 6 +-
.../internal/offheap/FreeListManagerTest.java | 60 +-
.../OffHeapRegionEntryHelperInstanceTest.java | 907 ++++++++++++++
.../offheap/OffHeapRegionEntryHelperJUnitTest.java | 926 --------------
.../offheap/ReferenceCountHelperImplTest.java | 1320 ++++++++++----------
.../offheap/ReferenceCountHelperJUnitTest.java | 205 ---
.../ParallelGatewaySenderOperationsDUnitTest.java | 4 +-
23 files changed, 2200 insertions(+), 2577 deletions(-)
diff --git a/boms/geode-all-bom/src/test/resources/expected-pom.xml b/boms/geode-all-bom/src/test/resources/expected-pom.xml
index 83987b1..6f650cc 100644
--- a/boms/geode-all-bom/src/test/resources/expected-pom.xml
+++ b/boms/geode-all-bom/src/test/resources/expected-pom.xml
@@ -698,24 +698,6 @@
<scope>compile</scope>
</dependency>
<dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-api-mockito2</artifactId>
- <version>2.0.9</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-core</artifactId>
- <version>2.0.9</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-junit4</artifactId>
- <version>2.0.9</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>3.141.59</version>
@@ -825,25 +807,25 @@
</dependency>
<dependency>
<groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
+ <artifactId>spring-test</artifactId>
<version>5.3.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
+ <artifactId>spring-tx</artifactId>
<version>5.3.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
+ <artifactId>spring-web</artifactId>
<version>5.3.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
+ <artifactId>spring-webmvc</artifactId>
<version>5.3.5</version>
<scope>compile</scope>
</dependency>
diff --git a/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy b/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
index a059ef8..515e003 100644
--- a/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
+++ b/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
@@ -232,12 +232,6 @@ class DependencyConstraints implements Plugin<Project> {
entry('hamcrest')
}
- dependencySet(group: 'org.powermock', version: '2.0.9') {
- entry('powermock-api-mockito2')
- entry('powermock-core')
- entry('powermock-module-junit4')
- }
-
dependencySet(group: 'org.seleniumhq.selenium', version: '3.141.59') {
entry('selenium-api')
entry('selenium-chrome-driver')
diff --git a/geode-core/build.gradle b/geode-core/build.gradle
index 78380fe..5292150 100755
--- a/geode-core/build.gradle
+++ b/geode-core/build.gradle
@@ -333,9 +333,6 @@ dependencies {
testImplementation('org.assertj:assertj-core')
testImplementation('org.mockito:mockito-core')
testImplementation('com.pholser:junit-quickcheck-core')
- testImplementation('org.powermock:powermock-core')
- testImplementation('org.powermock:powermock-module-junit4')
- testImplementation('org.powermock:powermock-api-mockito2')
testImplementation('pl.pragmatists:JUnitParams')
testImplementation('com.tngtech.archunit:archunit-junit4')
testImplementation(project(path: ':geode-core', configuration: 'raOutput'))
@@ -357,9 +354,6 @@ dependencies {
integrationTestImplementation(project(':geode-concurrency-test'))
integrationTestImplementation('org.apache.bcel:bcel')
integrationTestImplementation('org.apache.logging.log4j:log4j-core')
- integrationTestImplementation('org.powermock:powermock-core')
- integrationTestImplementation('org.powermock:powermock-module-junit4')
- integrationTestImplementation('org.powermock:powermock-api-mockito2')
integrationTestImplementation('pl.pragmatists:JUnitParams')
integrationTestImplementation('com.tngtech.archunit:archunit-junit4')
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractBucketRegionQueue.java b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractBucketRegionQueue.java
index 0813eab..bce5b07 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractBucketRegionQueue.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractBucketRegionQueue.java
@@ -39,7 +39,7 @@ import org.apache.geode.internal.cache.wan.AbstractGatewaySenderEventProcessor;
import org.apache.geode.internal.cache.wan.GatewaySenderEventImpl;
import org.apache.geode.internal.cache.wan.GatewaySenderStats;
import org.apache.geode.internal.cache.wan.parallel.ConcurrentParallelGatewaySenderQueue;
-import org.apache.geode.internal.offheap.OffHeapRegionEntryHelper;
+import org.apache.geode.internal.offheap.OffHeapClearRequired;
import org.apache.geode.internal.statistics.StatisticsClock;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.util.internal.GeodeGlossary;
@@ -401,7 +401,7 @@ public abstract class AbstractBucketRegionQueue extends BucketRegion {
@Override
public void closeEntries() {
- OffHeapRegionEntryHelper.doWithOffHeapClear(new Runnable() {
+ OffHeapClearRequired.doWithOffHeapClear(new Runnable() {
@Override
public void run() {
AbstractBucketRegionQueue.super.closeEntries();
@@ -414,7 +414,7 @@ public abstract class AbstractBucketRegionQueue extends BucketRegion {
@Override
public Set<VersionSource> clearEntries(final RegionVersionVector rvv) {
final AtomicReference<Set<VersionSource>> result = new AtomicReference<Set<VersionSource>>();
- OffHeapRegionEntryHelper.doWithOffHeapClear(new Runnable() {
+ OffHeapClearRequired.doWithOffHeapClear(new Runnable() {
@Override
public void run() {
result.set(AbstractBucketRegionQueue.super.clearEntries(rvv));
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
index 9a0d8b6..1993b85 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
@@ -63,8 +63,8 @@ import org.apache.geode.internal.cache.versions.VersionStamp;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.internal.cache.wan.GatewaySenderEventImpl;
import org.apache.geode.internal.logging.log4j.LogMarker;
+import org.apache.geode.internal.offheap.OffHeapClearRequired;
import org.apache.geode.internal.offheap.OffHeapHelper;
-import org.apache.geode.internal.offheap.OffHeapRegionEntryHelper;
import org.apache.geode.internal.offheap.StoredObject;
import org.apache.geode.internal.offheap.annotations.Released;
import org.apache.geode.internal.offheap.annotations.Retained;
@@ -433,7 +433,7 @@ public abstract class AbstractRegionMap extends BaseRegionMap
boolean tombstone = re.isTombstone();
// note: it.remove() did not reliably remove the entry so we use remove(K,V) here
if (getEntryMap().remove(re.getKey(), re)) {
- if (OffHeapRegionEntryHelper.doesClearNeedToCheckForOffHeap()) {
+ if (OffHeapClearRequired.doesClearNeedToCheckForOffHeap()) {
GatewaySenderEventImpl.release(re.getValue()); // OFFHEAP _getValue ok
}
// If this is an overflow only region, we need to free the entry on
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegionQueue.java b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegionQueue.java
index a4e11fd..859de57 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegionQueue.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegionQueue.java
@@ -47,7 +47,7 @@ import org.apache.geode.internal.cache.wan.InternalGatewayQueueEvent;
import org.apache.geode.internal.cache.wan.parallel.BucketRegionQueueUnavailableException;
import org.apache.geode.internal.cache.wan.parallel.ConcurrentParallelGatewaySenderQueue;
import org.apache.geode.internal.concurrent.Atomics;
-import org.apache.geode.internal.offheap.OffHeapRegionEntryHelper;
+import org.apache.geode.internal.offheap.OffHeapClearRequired;
import org.apache.geode.internal.offheap.annotations.Released;
import org.apache.geode.internal.statistics.StatisticsClock;
import org.apache.geode.logging.internal.log4j.api.LogService;
@@ -209,7 +209,7 @@ public class BucketRegionQueue extends AbstractBucketRegionQueue {
@Override
public void closeEntries() {
- OffHeapRegionEntryHelper.doWithOffHeapClear(new Runnable() {
+ OffHeapClearRequired.doWithOffHeapClear(new Runnable() {
@Override
public void run() {
BucketRegionQueue.super.closeEntries();
@@ -222,7 +222,7 @@ public class BucketRegionQueue extends AbstractBucketRegionQueue {
@Override
public Set<VersionSource> clearEntries(final RegionVersionVector rvv) {
final AtomicReference<Set<VersionSource>> result = new AtomicReference<Set<VersionSource>>();
- OffHeapRegionEntryHelper.doWithOffHeapClear(new Runnable() {
+ OffHeapClearRequired.doWithOffHeapClear(new Runnable() {
@Override
public void run() {
result.set(BucketRegionQueue.super.clearEntries(rvv));
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/wan/serial/SerialGatewaySenderQueue.java b/geode-core/src/main/java/org/apache/geode/internal/cache/wan/serial/SerialGatewaySenderQueue.java
index a50caca..89537e6 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/wan/serial/SerialGatewaySenderQueue.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/wan/serial/SerialGatewaySenderQueue.java
@@ -75,7 +75,7 @@ import org.apache.geode.internal.cache.wan.AbstractGatewaySender;
import org.apache.geode.internal.cache.wan.GatewaySenderEventImpl;
import org.apache.geode.internal.cache.wan.GatewaySenderStats;
import org.apache.geode.internal.cache.wan.InternalGatewayQueueEvent;
-import org.apache.geode.internal.offheap.OffHeapRegionEntryHelper;
+import org.apache.geode.internal.offheap.OffHeapClearRequired;
import org.apache.geode.internal.statistics.StatisticsClock;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.management.ManagementService;
@@ -1385,7 +1385,7 @@ public class SerialGatewaySenderQueue implements RegionQueue {
@Override
public void closeEntries() {
- OffHeapRegionEntryHelper.doWithOffHeapClear(new Runnable() {
+ OffHeapClearRequired.doWithOffHeapClear(new Runnable() {
@Override
public void run() {
SerialGatewaySenderQueueMetaRegion.super.closeEntries();
@@ -1396,7 +1396,7 @@ public class SerialGatewaySenderQueue implements RegionQueue {
@Override
public Set<VersionSource> clearEntries(final RegionVersionVector rvv) {
final AtomicReference<Set<VersionSource>> result = new AtomicReference<Set<VersionSource>>();
- OffHeapRegionEntryHelper.doWithOffHeapClear(new Runnable() {
+ OffHeapClearRequired.doWithOffHeapClear(new Runnable() {
@Override
public void run() {
result.set(SerialGatewaySenderQueueMetaRegion.super.clearEntries(rvv));
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/FreeListManager.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/FreeListManager.java
index 9e1f445..21b14d3 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/offheap/FreeListManager.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/FreeListManager.java
@@ -75,7 +75,7 @@ public class FreeListManager {
addr = f.getAddress() + f.getSize();
} else {
int curChunkSize = OffHeapStoredObject.getSize(addr);
- int refCount = OffHeapStoredObject.getRefCount(addr);
+ int refCount = ReferenceCounter.getRefCount(addr);
if (refCount > 0) {
result.add(new OffHeapStoredObject(addr));
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapClearRequired.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapClearRequired.java
new file mode 100644
index 0000000..b6d8c4d
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapClearRequired.java
@@ -0,0 +1,34 @@
+/*
+ * 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 org.apache.geode.internal.offheap;
+
+public class OffHeapClearRequired {
+
+ private static final ThreadLocal<Object> clearNeedsToCheckForOffHeap =
+ new ThreadLocal<>();
+
+ public static boolean doesClearNeedToCheckForOffHeap() {
+ return clearNeedsToCheckForOffHeap.get() != null;
+ }
+
+ public static void doWithOffHeapClear(Runnable r) {
+ clearNeedsToCheckForOffHeap.set(Boolean.TRUE);
+ try {
+ r.run();
+ } finally {
+ clearNeedsToCheckForOffHeap.remove();
+ }
+ }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelper.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelper.java
index 0d10311..01f68f6 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelper.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelper.java
@@ -15,17 +15,12 @@
package org.apache.geode.internal.offheap;
import org.apache.geode.annotations.Immutable;
-import org.apache.geode.internal.cache.CachedDeserializableFactory;
-import org.apache.geode.internal.cache.DiskId;
-import org.apache.geode.internal.cache.EntryEventImpl;
import org.apache.geode.internal.cache.RegionEntryContext;
import org.apache.geode.internal.cache.Token;
-import org.apache.geode.internal.cache.entries.DiskEntry;
import org.apache.geode.internal.cache.entries.OffHeapRegionEntry;
import org.apache.geode.internal.offheap.annotations.Released;
import org.apache.geode.internal.offheap.annotations.Retained;
import org.apache.geode.internal.offheap.annotations.Unretained;
-import org.apache.geode.internal.serialization.DSCODE;
/**
* The class just has static methods that operate on instances of {@link OffHeapRegionEntry}. It
@@ -36,44 +31,18 @@ import org.apache.geode.internal.serialization.DSCODE;
*/
public class OffHeapRegionEntryHelper {
- protected static final long NULL_ADDRESS = 0L << 1;
- protected static final long INVALID_ADDRESS = 1L << 1;
- protected static final long LOCAL_INVALID_ADDRESS = 2L << 1;
- protected static final long DESTROYED_ADDRESS = 3L << 1;
- protected static final long REMOVED_PHASE1_ADDRESS = 4L << 1;
- protected static final long REMOVED_PHASE2_ADDRESS = 5L << 1;
- protected static final long END_OF_STREAM_ADDRESS = 6L << 1;
- protected static final long NOT_AVAILABLE_ADDRESS = 7L << 1;
- protected static final long TOMBSTONE_ADDRESS = 8L << 1;
- public static final int MAX_LENGTH_FOR_DATA_AS_ADDRESS = 8;
-
@Immutable
- private static final Token[] addrToObj =
- new Token[] {null, Token.INVALID, Token.LOCAL_INVALID, Token.DESTROYED, Token.REMOVED_PHASE1,
- Token.REMOVED_PHASE2, Token.END_OF_STREAM, Token.NOT_AVAILABLE, Token.TOMBSTONE,};
+ private static final OffHeapRegionEntryHelper INSTANCE = new OffHeapRegionEntryHelper(
+ new OffHeapRegionEntryHelperInstance());
+
+ private final OffHeapRegionEntryHelperInstance delegate;
+
+ private OffHeapRegionEntryHelper(OffHeapRegionEntryHelperInstance delegate) {
+ this.delegate = delegate;
+ }
- private static long objectToAddress(@Unretained Object v) {
- if (v instanceof StoredObject)
- return ((StoredObject) v).getAddress();
- 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.");
+ private static OffHeapRegionEntryHelperInstance delegate() {
+ return INSTANCE.delegate;
}
/**
@@ -89,216 +58,48 @@ public class OffHeapRegionEntryHelper {
@Retained
public static Object addressToObject(@Released @Retained long ohAddress, boolean decompress,
RegionEntryContext context) {
- if (isOffHeap(ohAddress)) {
- @Unretained
- OffHeapStoredObject chunk = new OffHeapStoredObject(ohAddress);
- @Unretained
- Object result = chunk;
- if (decompress && chunk.isCompressed()) {
- try {
- // to fix bug 47982 need to:
- byte[] decompressedBytes = chunk.getDecompressedBytes(context);
- if (chunk.isSerialized()) {
- // return a VMCachedDeserializable with the decompressed serialized bytes since chunk is
- // serialized
- result = CachedDeserializableFactory.create(decompressedBytes, context.getCache());
- } else {
- // return a byte[] since chunk is not serialized
- result = decompressedBytes;
- }
- } finally {
- // decompress is only true when this method is called by _getValueRetain.
- // In that case the caller has already retained ohAddress because it thought
- // we would return it. But we have unwrapped it and are returning the decompressed
- // results.
- // So we need to release the chunk here.
- chunk.release();
- }
- }
- return result;
- } else if ((ohAddress & ENCODED_BIT) != 0) {
- TinyStoredObject daa = new TinyStoredObject(ohAddress);
- Object result = daa;
- if (decompress && daa.isCompressed()) {
- byte[] decompressedBytes = daa.getDecompressedBytes(context);
- if (daa.isSerialized()) {
- // return a VMCachedDeserializable with the decompressed serialized bytes since daa is
- // serialized
- result = CachedDeserializableFactory.create(decompressedBytes, context.getCache());
- } else {
- // return a byte[] since daa is not serialized
- result = decompressedBytes;
- }
- }
- return result;
- } else {
- return addrToObj[(int) ohAddress >> 1];
- }
+ return delegate().addressToObject(ohAddress, decompress, context);
}
public static int getSerializedLength(TinyStoredObject dataAsAddress) {
- final long ohAddress = dataAsAddress.getAddress();
-
- if ((ohAddress & ENCODED_BIT) != 0) {
- boolean isLong = (ohAddress & LONG_BIT) != 0;
- if (isLong) {
- return 9;
- } else {
- return (int) ((ohAddress & SIZE_MASK) >> SIZE_SHIFT);
- }
- } else {
- return 0;
- }
- }
-
- /*
- * This method is optimized for cases where if the caller wants to convert address to a Token
- * compared to addressToObject which would deserialize the value.
- */
- private static Token addressToToken(long ohAddress) {
- if (isOffHeap(ohAddress) || (ohAddress & ENCODED_BIT) != 0) {
- return Token.NOT_A_TOKEN;
- } else {
- return addrToObj[(int) ohAddress >> 1];
- }
- }
-
- private static void releaseAddress(@Released long ohAddress) {
- if (isOffHeap(ohAddress)) {
- OffHeapStoredObject.release(ohAddress);
- }
+ return delegate().getSerializedLength(dataAsAddress);
}
/**
* The address in 're' will be @Released.
*/
public static void releaseEntry(@Released OffHeapRegionEntry re) {
- if (re instanceof DiskEntry) {
- DiskId did = ((DiskEntry) re).getDiskId();
- if (did != null && did.isPendingAsync()) {
- synchronized (did) {
- // This may not be needed so remove this call if it causes problems.
- // We no longer need this entry to be written to disk so unschedule it
- // before we change its value to REMOVED_PHASE2.
- did.setPendingAsync(false);
- setValue(re, Token.REMOVED_PHASE2);
- return;
- }
- }
- }
- setValue(re, Token.REMOVED_PHASE2);
+ delegate().releaseEntry(re);
}
public static void releaseEntry(@Unretained OffHeapRegionEntry re,
@Released StoredObject expectedValue) {
- long oldAddress = objectToAddress(expectedValue);
- final long newAddress = objectToAddress(Token.REMOVED_PHASE2);
- if (re.setAddress(oldAddress, newAddress)) {
- releaseAddress(oldAddress);
- } /*
- * else { if (!calledSetValue || re.getAddress() != newAddress) { expectedValue.release(); } }
- */
+ delegate().releaseEntry(re, expectedValue);
}
/**
- * This bit is set to indicate that this address has data encoded in it.
- */
- private static final long ENCODED_BIT = 1L;
- /**
- * This bit is set to indicate that the encoded data is serialized.
- */
- static final long SERIALIZED_BIT = 2L;
- /**
- * This bit is set to indicate that the encoded data is compressed.
- */
- static final long COMPRESSED_BIT = 4L;
- /**
- * This bit is set to indicate that the encoded data is a long whose value fits in 7 bytes.
- */
- private static final long LONG_BIT = 8L;
- /**
- * size is in the range 0..7 so we only need 3 bits.
- */
- private static final long SIZE_MASK = 0x70L;
- /**
- * number of bits to shift the size by.
- */
- private static final int SIZE_SHIFT = 4;
- // the msb of this byte is currently unused
-
- /**
* Returns 0 if the data could not be encoded as an address.
*/
- public static long encodeDataAsAddress(byte[] v, boolean isSerialized, boolean isCompressed) {
- if (v.length < MAX_LENGTH_FOR_DATA_AS_ADDRESS) {
- long result = 0L;
- for (int i = 0; i < v.length; i++) {
- result |= v[i] & 0x00ff;
- result <<= 8;
- }
- result |= (v.length << SIZE_SHIFT) | ENCODED_BIT;
- if (isSerialized) {
- result |= SERIALIZED_BIT;
- }
- if (isCompressed) {
- result |= COMPRESSED_BIT;
- }
- return result;
- } else if (isSerialized && !isCompressed) {
- // Check for some special types that take more than 7 bytes to serialize
- // but that might be able to be inlined with less than 8 bytes.
- if (v[0] == DSCODE.LONG.toByte()) {
- // A long is currently always serialized as 8 bytes (9 if you include the dscode).
- // But many long values will actually be small enough for is to encode in 7 bytes.
- if ((v[1] == 0 && (v[2] & 0x80) == 0) || (v[1] == -1 && (v[2] & 0x80) != 0)) {
- // The long can be encoded as 7 bytes since the most signification byte
- // is simply an extension of the sign byte on the second most signification byte.
- long result = 0L;
- for (int i = 2; i < v.length; i++) {
- result |= v[i] & 0x00ff;
- result <<= 8;
- }
- result |= (7 << SIZE_SHIFT) | LONG_BIT | SERIALIZED_BIT | ENCODED_BIT;
- return result;
- }
- }
- }
- return 0L;
+ static long encodeDataAsAddress(byte[] v, boolean isSerialized, boolean isCompressed) {
+ return delegate().encodeDataAsAddress(v, isSerialized, isCompressed);
}
static Object decodeAddressToObject(long ohAddress) {
- byte[] bytes = decodeUncompressedAddressToBytes(ohAddress);
-
- boolean isSerialized = (ohAddress & SERIALIZED_BIT) != 0;
- if (isSerialized) {
- return EntryEventImpl.deserialize(bytes);
- } else {
- return bytes;
- }
+ return delegate().decodeAddressToObject(ohAddress);
}
static int decodeAddressToDataSize(long addr) {
- if ((addr & ENCODED_BIT) == 0) {
- throw new AssertionError("Invalid address: " + addr);
- }
- boolean isLong = (addr & LONG_BIT) != 0;
- if (isLong) {
- return 9;
- }
- return (int) ((addr & SIZE_MASK) >> SIZE_SHIFT);
+ return delegate().decodeAddressToDataSize(addr);
}
/**
* Returns the bytes encoded in the given address. Note that compressed addresses are not
* supported by this method.
*
- * @throws UnsupportedOperationException if the address has compressed data
+ * @throws AssertionError if the address has compressed data
*/
static byte[] decodeUncompressedAddressToBytes(long addr) {
- if ((addr & COMPRESSED_BIT) != 0) {
- throw new AssertionError("Did not expect encoded address to be compressed");
- }
- return decodeAddressToRawBytes(addr);
+ return delegate().decodeUncompressedAddressToBytes(addr);
}
/**
@@ -306,32 +107,7 @@ public class OffHeapRegionEntryHelper {
* compressed then the raw bytes are the compressed bytes.
*/
static byte[] decodeAddressToRawBytes(long addr) {
- if ((addr & ENCODED_BIT) == 0) {
- throw new AssertionError("Invalid address: " + addr);
- }
- int size = (int) ((addr & SIZE_MASK) >> SIZE_SHIFT);
- boolean isLong = (addr & LONG_BIT) != 0;
- byte[] bytes;
- if (isLong) {
- bytes = new byte[9];
- bytes[0] = DSCODE.LONG.toByte();
- for (int i = 8; i >= 2; i--) {
- addr >>= 8;
- bytes[i] = (byte) (addr & 0x00ff);
- }
- if ((bytes[2] & 0x80) != 0) {
- bytes[1] = -1;
- } else {
- bytes[1] = 0;
- }
- } else {
- bytes = new byte[size];
- for (int i = size - 1; i >= 0; i--) {
- addr >>= 8;
- bytes[i] = (byte) (addr & 0x00ff);
- }
- }
- return bytes;
+ return delegate().decodeAddressToRawBytes(addr);
}
/**
@@ -339,35 +115,20 @@ public class OffHeapRegionEntryHelper {
* be set to the @Unretained address of 'v'.
*/
public static void setValue(@Released OffHeapRegionEntry re, @Unretained Object v) {
- // setValue is called when synced so I don't need to worry
- // about oldAddress being released by someone else.
- final long newAddress = objectToAddress(v);
- long oldAddress;
- do {
- oldAddress = re.getAddress();
- } while (!re.setAddress(oldAddress, newAddress));
- ReferenceCountHelper.setReferenceCountOwner(re);
- releaseAddress(oldAddress);
- ReferenceCountHelper.setReferenceCountOwner(null);
+ delegate().setValue(re, v);
}
public static Token getValueAsToken(@Unretained OffHeapRegionEntry re) {
- return addressToToken(re.getAddress());
+ return delegate().getValueAsToken(re);
}
@Unretained
public static Object _getValue(@Unretained OffHeapRegionEntry re) {
- return addressToObject(re.getAddress(), false, null); // no context needed so decompress is
- // false
+ return delegate()._getValue(re);
}
public static boolean isOffHeap(long addr) {
- if ((addr & ENCODED_BIT) != 0)
- return false;
- if (addr < 0)
- return true;
- addr >>= 1; // shift right 1 to convert to array index;
- return addr >= addrToObj.length;
+ return delegate().isOffHeap(addr);
}
/**
@@ -381,61 +142,14 @@ public class OffHeapRegionEntryHelper {
@Retained
public static Object _getValueRetain(@Retained @Unretained OffHeapRegionEntry re,
boolean decompress, RegionEntryContext context) {
- int retryCount = 0;
- @Retained
- long addr = re.getAddress();
- while (isOffHeap(addr)) {
- if (OffHeapStoredObject.retain(addr)) {
- @Unretained
- long addr2 = re.getAddress();
- if (addr != addr2) {
- retryCount = 0;
- OffHeapStoredObject.release(addr);
- // spin around and try again.
- addr = addr2;
- } else {
- return addressToObject(addr, decompress, context);
- }
- } else {
- // spin around and try again
- long addr2 = re.getAddress();
- retryCount++;
- if (retryCount > 100) {
- throw new IllegalStateException("retain failed addr=" + addr + " addr2=" + addr
- + " 100 times" + " history=" + ReferenceCountHelper.getFreeRefCountInfo(addr));
- }
- addr = addr2;
- // Since retain returned false our region entry should have a different
- // value in it. However the actual address could be the exact same one
- // because addr was released, then reallocated from the free list and set
- // back into this region entry. See bug 47782
- }
- }
- return addressToObject(addr, decompress, context);
+ return delegate()._getValueRetain(re, decompress, context);
}
-
-
public static boolean isSerialized(long address) {
- return (address & SERIALIZED_BIT) != 0;
+ return delegate().isSerialized(address);
}
public static boolean isCompressed(long address) {
- return (address & COMPRESSED_BIT) != 0;
- }
-
- private static final ThreadLocal<Object> clearNeedsToCheckForOffHeap = new ThreadLocal<Object>();
-
- public static boolean doesClearNeedToCheckForOffHeap() {
- return clearNeedsToCheckForOffHeap.get() != null;
- }
-
- public static void doWithOffHeapClear(Runnable r) {
- clearNeedsToCheckForOffHeap.set(Boolean.TRUE);
- try {
- r.run();
- } finally {
- clearNeedsToCheckForOffHeap.remove();
- }
+ return delegate().isCompressed(address);
}
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelper.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperInstance.java
similarity index 54%
copy from geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelper.java
copy to geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperInstance.java
index 0d10311..26ddfde 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelper.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperInstance.java
@@ -14,7 +14,10 @@
*/
package org.apache.geode.internal.offheap;
+import java.util.function.Function;
+
import org.apache.geode.annotations.Immutable;
+import org.apache.geode.annotations.VisibleForTesting;
import org.apache.geode.internal.cache.CachedDeserializableFactory;
import org.apache.geode.internal.cache.DiskId;
import org.apache.geode.internal.cache.EntryEventImpl;
@@ -34,46 +37,31 @@ import org.apache.geode.internal.serialization.DSCODE;
*
* @since Geode 1.0
*/
-public class OffHeapRegionEntryHelper {
-
- protected static final long NULL_ADDRESS = 0L << 1;
- protected static final long INVALID_ADDRESS = 1L << 1;
- protected static final long LOCAL_INVALID_ADDRESS = 2L << 1;
- protected static final long DESTROYED_ADDRESS = 3L << 1;
- protected static final long REMOVED_PHASE1_ADDRESS = 4L << 1;
- protected static final long REMOVED_PHASE2_ADDRESS = 5L << 1;
- protected static final long END_OF_STREAM_ADDRESS = 6L << 1;
- protected static final long NOT_AVAILABLE_ADDRESS = 7L << 1;
- protected static final long TOMBSTONE_ADDRESS = 8L << 1;
- public static final int MAX_LENGTH_FOR_DATA_AS_ADDRESS = 8;
-
- @Immutable
- private static final Token[] addrToObj =
- new Token[] {null, Token.INVALID, Token.LOCAL_INVALID, Token.DESTROYED, Token.REMOVED_PHASE1,
- Token.REMOVED_PHASE2, Token.END_OF_STREAM, Token.NOT_AVAILABLE, Token.TOMBSTONE,};
-
- private static long objectToAddress(@Unretained Object v) {
- if (v instanceof StoredObject)
- return ((StoredObject) v).getAddress();
- 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.");
+class OffHeapRegionEntryHelperInstance {
+
+ static final long NULL_ADDRESS = 0L;
+ static final long INVALID_ADDRESS = 1L << 1;
+ static final long LOCAL_INVALID_ADDRESS = 2L << 1;
+ static final long DESTROYED_ADDRESS = 3L << 1;
+ static final long REMOVED_PHASE1_ADDRESS = 4L << 1;
+ static final long REMOVED_PHASE2_ADDRESS = 5L << 1;
+ static final long END_OF_STREAM_ADDRESS = 6L << 1;
+ static final long NOT_AVAILABLE_ADDRESS = 7L << 1;
+ static final long TOMBSTONE_ADDRESS = 8L << 1;
+ static final int MAX_LENGTH_FOR_DATA_AS_ADDRESS = 8;
+
+ private final Function<Long, OffHeapStoredObject> offHeapStoredObjectFactory;
+ private final ReferenceCounterInstance referenceCounter;
+
+ OffHeapRegionEntryHelperInstance() {
+ this(OffHeapStoredObject::new, new ReferenceCounterInstance());
+ }
+
+ @VisibleForTesting
+ OffHeapRegionEntryHelperInstance(Function<Long, OffHeapStoredObject> offHeapStoredObjectFactory,
+ ReferenceCounterInstance referenceCounter) {
+ this.offHeapStoredObjectFactory = offHeapStoredObjectFactory;
+ this.referenceCounter = referenceCounter;
}
/**
@@ -87,11 +75,11 @@ public class OffHeapRegionEntryHelper {
*/
@Unretained
@Retained
- public static Object addressToObject(@Released @Retained long ohAddress, boolean decompress,
+ Object addressToObject(@Released @Retained long ohAddress, boolean decompress,
RegionEntryContext context) {
if (isOffHeap(ohAddress)) {
@Unretained
- OffHeapStoredObject chunk = new OffHeapStoredObject(ohAddress);
+ OffHeapStoredObject chunk = offHeapStoredObjectFactory.apply(ohAddress);
@Unretained
Object result = chunk;
if (decompress && chunk.isCompressed()) {
@@ -107,16 +95,17 @@ public class OffHeapRegionEntryHelper {
result = decompressedBytes;
}
} finally {
- // decompress is only true when this method is called by _getValueRetain.
- // In that case the caller has already retained ohAddress because it thought
- // we would return it. But we have unwrapped it and are returning the decompressed
- // results.
- // So we need to release the chunk here.
+ // Decompress is only true when this method is called by _getValueRetain. In that case the
+ // caller has already retained ohAddress because it thought we would return it. But we
+ // have unwrapped it and are returning the decompressed results. So we need to release the
+ // chunk here.
chunk.release();
}
}
return result;
- } else if ((ohAddress & ENCODED_BIT) != 0) {
+ }
+
+ if ((ohAddress & ENCODED_BIT) != 0) {
TinyStoredObject daa = new TinyStoredObject(ohAddress);
Object result = daa;
if (decompress && daa.isCompressed()) {
@@ -131,73 +120,71 @@ public class OffHeapRegionEntryHelper {
}
}
return result;
- } else {
- return addrToObj[(int) ohAddress >> 1];
}
+
+ return TokenAddress.ADDRESS_TO_OBJECT[(int) ohAddress >> 1];
}
- public static int getSerializedLength(TinyStoredObject dataAsAddress) {
+ int getSerializedLength(TinyStoredObject dataAsAddress) {
final long ohAddress = dataAsAddress.getAddress();
if ((ohAddress & ENCODED_BIT) != 0) {
boolean isLong = (ohAddress & LONG_BIT) != 0;
if (isLong) {
return 9;
- } else {
- return (int) ((ohAddress & SIZE_MASK) >> SIZE_SHIFT);
}
- } else {
- return 0;
+ return (int) ((ohAddress & SIZE_MASK) >> SIZE_SHIFT);
}
+
+ return 0;
}
/*
* This method is optimized for cases where if the caller wants to convert address to a Token
* compared to addressToObject which would deserialize the value.
*/
- private static Token addressToToken(long ohAddress) {
+ private Token addressToToken(long ohAddress) {
if (isOffHeap(ohAddress) || (ohAddress & ENCODED_BIT) != 0) {
return Token.NOT_A_TOKEN;
- } else {
- return addrToObj[(int) ohAddress >> 1];
}
+
+ return TokenAddress.ADDRESS_TO_OBJECT[(int) ohAddress >> 1];
}
- private static void releaseAddress(@Released long ohAddress) {
+ private void releaseAddress(@Released long ohAddress) {
if (isOffHeap(ohAddress)) {
- OffHeapStoredObject.release(ohAddress);
+ referenceCounter.release(ohAddress);
}
}
/**
- * The address in 're' will be @Released.
+ * The address in 'regionEntry' will be @Released.
*/
- public static void releaseEntry(@Released OffHeapRegionEntry re) {
- if (re instanceof DiskEntry) {
- DiskId did = ((DiskEntry) re).getDiskId();
- if (did != null && did.isPendingAsync()) {
- synchronized (did) {
+ public void releaseEntry(@Released OffHeapRegionEntry regionEntry) {
+ if (regionEntry instanceof DiskEntry) {
+ DiskId diskId = ((DiskEntry) regionEntry).getDiskId();
+ if (diskId != null && diskId.isPendingAsync()) {
+ synchronized (diskId) {
// This may not be needed so remove this call if it causes problems.
// We no longer need this entry to be written to disk so unschedule it
// before we change its value to REMOVED_PHASE2.
- did.setPendingAsync(false);
- setValue(re, Token.REMOVED_PHASE2);
+ diskId.setPendingAsync(false);
+ setValue(regionEntry, Token.REMOVED_PHASE2);
return;
}
}
}
- setValue(re, Token.REMOVED_PHASE2);
+
+ setValue(regionEntry, Token.REMOVED_PHASE2);
}
- public static void releaseEntry(@Unretained OffHeapRegionEntry re,
+ public void releaseEntry(@Unretained OffHeapRegionEntry regionEntry,
@Released StoredObject expectedValue) {
- long oldAddress = objectToAddress(expectedValue);
- final long newAddress = objectToAddress(Token.REMOVED_PHASE2);
- if (re.setAddress(oldAddress, newAddress)) {
+ long oldAddress = TokenAddress.objectToAddress(expectedValue);
+ final long newAddress = TokenAddress.objectToAddress(Token.REMOVED_PHASE2);
+ if (regionEntry.setAddress(oldAddress, newAddress)) {
releaseAddress(oldAddress);
- } /*
- * else { if (!calledSetValue || re.getAddress() != newAddress) { expectedValue.release(); } }
- */
+ }
}
/**
@@ -229,14 +216,14 @@ public class OffHeapRegionEntryHelper {
/**
* Returns 0 if the data could not be encoded as an address.
*/
- public static long encodeDataAsAddress(byte[] v, boolean isSerialized, boolean isCompressed) {
- if (v.length < MAX_LENGTH_FOR_DATA_AS_ADDRESS) {
+ long encodeDataAsAddress(byte[] bytes, boolean isSerialized, boolean isCompressed) {
+ if (bytes.length < MAX_LENGTH_FOR_DATA_AS_ADDRESS) {
long result = 0L;
- for (int i = 0; i < v.length; i++) {
- result |= v[i] & 0x00ff;
+ for (byte aByte : bytes) {
+ result |= aByte & 0x00ff;
result <<= 8;
}
- result |= (v.length << SIZE_SHIFT) | ENCODED_BIT;
+ result |= bytes.length << SIZE_SHIFT | ENCODED_BIT;
if (isSerialized) {
result |= SERIALIZED_BIT;
}
@@ -244,57 +231,60 @@ public class OffHeapRegionEntryHelper {
result |= COMPRESSED_BIT;
}
return result;
- } else if (isSerialized && !isCompressed) {
- // Check for some special types that take more than 7 bytes to serialize
- // but that might be able to be inlined with less than 8 bytes.
- if (v[0] == DSCODE.LONG.toByte()) {
- // A long is currently always serialized as 8 bytes (9 if you include the dscode).
- // But many long values will actually be small enough for is to encode in 7 bytes.
- if ((v[1] == 0 && (v[2] & 0x80) == 0) || (v[1] == -1 && (v[2] & 0x80) != 0)) {
- // The long can be encoded as 7 bytes since the most signification byte
- // is simply an extension of the sign byte on the second most signification byte.
+ }
+
+ if (isSerialized && !isCompressed) {
+ // Check for some special types that take more than 7 bytes to serialize but that might be
+ // able to be inlined with less than 8 bytes.
+ if (bytes[0] == DSCODE.LONG.toByte()) {
+ // A long is currently always serialized as 8 bytes (9 if you include the dscode). But many
+ // long values will actually be small enough for is to encode in 7 bytes.
+ if (bytes[1] == 0 && (bytes[2] & 0x80) == 0 || bytes[1] == -1 && (bytes[2] & 0x80) != 0) {
+ // The long can be encoded as 7 bytes since the most signification byte is simply an
+ // extension of the sign byte on the second most signification byte.
long result = 0L;
- for (int i = 2; i < v.length; i++) {
- result |= v[i] & 0x00ff;
+ for (int i = 2; i < bytes.length; i++) {
+ result |= bytes[i] & 0x00ff;
result <<= 8;
}
- result |= (7 << SIZE_SHIFT) | LONG_BIT | SERIALIZED_BIT | ENCODED_BIT;
+ result |= 7 << SIZE_SHIFT | LONG_BIT | SERIALIZED_BIT | ENCODED_BIT;
return result;
}
}
}
+
return 0L;
}
- static Object decodeAddressToObject(long ohAddress) {
+ Object decodeAddressToObject(long ohAddress) {
byte[] bytes = decodeUncompressedAddressToBytes(ohAddress);
boolean isSerialized = (ohAddress & SERIALIZED_BIT) != 0;
if (isSerialized) {
return EntryEventImpl.deserialize(bytes);
- } else {
- return bytes;
}
+
+ return bytes;
}
- static int decodeAddressToDataSize(long addr) {
- if ((addr & ENCODED_BIT) == 0) {
- throw new AssertionError("Invalid address: " + addr);
+ int decodeAddressToDataSize(long address) {
+ if ((address & ENCODED_BIT) == 0) {
+ throw new AssertionError("Invalid address: " + address);
}
- boolean isLong = (addr & LONG_BIT) != 0;
+ boolean isLong = (address & LONG_BIT) != 0;
if (isLong) {
return 9;
}
- return (int) ((addr & SIZE_MASK) >> SIZE_SHIFT);
+ return (int) ((address & SIZE_MASK) >> SIZE_SHIFT);
}
/**
* Returns the bytes encoded in the given address. Note that compressed addresses are not
* supported by this method.
*
- * @throws UnsupportedOperationException if the address has compressed data
+ * @throws AssertionError if the address has compressed data
*/
- static byte[] decodeUncompressedAddressToBytes(long addr) {
+ byte[] decodeUncompressedAddressToBytes(long addr) {
if ((addr & COMPRESSED_BIT) != 0) {
throw new AssertionError("Did not expect encoded address to be compressed");
}
@@ -305,13 +295,15 @@ public class OffHeapRegionEntryHelper {
* Returns the "raw" bytes that have been encoded in the given address. Note that if address is
* compressed then the raw bytes are the compressed bytes.
*/
- static byte[] decodeAddressToRawBytes(long addr) {
+ byte[] decodeAddressToRawBytes(long addr) {
if ((addr & ENCODED_BIT) == 0) {
throw new AssertionError("Invalid address: " + addr);
}
+
int size = (int) ((addr & SIZE_MASK) >> SIZE_SHIFT);
boolean isLong = (addr & LONG_BIT) != 0;
byte[] bytes;
+
if (isLong) {
bytes = new byte[9];
bytes[0] = DSCODE.LONG.toByte();
@@ -331,6 +323,7 @@ public class OffHeapRegionEntryHelper {
bytes[i] = (byte) (addr & 0x00ff);
}
}
+
return bytes;
}
@@ -338,36 +331,42 @@ public class OffHeapRegionEntryHelper {
* The previous value at the address in 're' will be @Released and then the address in 're' will
* be set to the @Unretained address of 'v'.
*/
- public static void setValue(@Released OffHeapRegionEntry re, @Unretained Object v) {
+ public void setValue(@Released OffHeapRegionEntry regionEntry, @Unretained Object value) {
// setValue is called when synced so I don't need to worry
// about oldAddress being released by someone else.
- final long newAddress = objectToAddress(v);
+ final long newAddress = TokenAddress.objectToAddress(value);
long oldAddress;
+
do {
- oldAddress = re.getAddress();
- } while (!re.setAddress(oldAddress, newAddress));
- ReferenceCountHelper.setReferenceCountOwner(re);
+ oldAddress = regionEntry.getAddress();
+ } while (!regionEntry.setAddress(oldAddress, newAddress));
+
+ ReferenceCountHelper.setReferenceCountOwner(regionEntry);
releaseAddress(oldAddress);
ReferenceCountHelper.setReferenceCountOwner(null);
}
- public static Token getValueAsToken(@Unretained OffHeapRegionEntry re) {
- return addressToToken(re.getAddress());
+ public Token getValueAsToken(@Unretained OffHeapRegionEntry regionEntry) {
+ return addressToToken(regionEntry.getAddress());
}
@Unretained
- public static Object _getValue(@Unretained OffHeapRegionEntry re) {
- return addressToObject(re.getAddress(), false, null); // no context needed so decompress is
- // false
+ public Object _getValue(@Unretained OffHeapRegionEntry regionEntry) {
+ // no context needed so decompress is false
+ return addressToObject(regionEntry.getAddress(), false, null);
}
- public static boolean isOffHeap(long addr) {
- if ((addr & ENCODED_BIT) != 0)
+ public boolean isOffHeap(long address) {
+ if ((address & ENCODED_BIT) != 0) {
return false;
- if (addr < 0)
+ }
+ if (address < 0) {
return true;
- addr >>= 1; // shift right 1 to convert to array index;
- return addr >= addrToObj.length;
+ }
+
+ // shift right 1 to convert to array index;
+ address >>= 1;
+ return address >= TokenAddress.ADDRESS_TO_OBJECT.length;
}
/**
@@ -379,63 +378,90 @@ public class OffHeapRegionEntryHelper {
* @return possible OFF_HEAP_OBJECT (caller must release)
*/
@Retained
- public static Object _getValueRetain(@Retained @Unretained OffHeapRegionEntry re,
+ public Object _getValueRetain(@Retained @Unretained OffHeapRegionEntry regionEntry,
boolean decompress, RegionEntryContext context) {
int retryCount = 0;
+
@Retained
- long addr = re.getAddress();
- while (isOffHeap(addr)) {
- if (OffHeapStoredObject.retain(addr)) {
+ long address = regionEntry.getAddress();
+
+ while (isOffHeap(address)) {
+ if (referenceCounter.retain(address)) {
@Unretained
- long addr2 = re.getAddress();
- if (addr != addr2) {
+ long address2 = regionEntry.getAddress();
+ if (address != address2) {
retryCount = 0;
- OffHeapStoredObject.release(addr);
+ referenceCounter.release(address);
// spin around and try again.
- addr = addr2;
+ address = address2;
} else {
- return addressToObject(addr, decompress, context);
+ return addressToObject(address, decompress, context);
}
} else {
// spin around and try again
- long addr2 = re.getAddress();
+ long address2 = regionEntry.getAddress();
retryCount++;
if (retryCount > 100) {
- throw new IllegalStateException("retain failed addr=" + addr + " addr2=" + addr
- + " 100 times" + " history=" + ReferenceCountHelper.getFreeRefCountInfo(addr));
+ throw new IllegalStateException("retain failed address=" + address + " addr2=" + address
+ + " 100 times" + " history=" + ReferenceCountHelper.getFreeRefCountInfo(address));
}
- addr = addr2;
- // Since retain returned false our region entry should have a different
- // value in it. However the actual address could be the exact same one
- // because addr was released, then reallocated from the free list and set
- // back into this region entry. See bug 47782
+ address = address2;
+ // Since retain returned false our region entry should have a different value in it. However
+ // the actual address could be the exact same one because address was released, then
+ // reallocated from the free list and set back into this region entry.
}
}
- return addressToObject(addr, decompress, context);
+ return addressToObject(address, decompress, context);
}
-
-
- public static boolean isSerialized(long address) {
+ public boolean isSerialized(long address) {
return (address & SERIALIZED_BIT) != 0;
}
- public static boolean isCompressed(long address) {
+ public boolean isCompressed(long address) {
return (address & COMPRESSED_BIT) != 0;
}
- private static final ThreadLocal<Object> clearNeedsToCheckForOffHeap = new ThreadLocal<Object>();
+ private static class TokenAddress {
- public static boolean doesClearNeedToCheckForOffHeap() {
- return clearNeedsToCheckForOffHeap.get() != null;
- }
+ @Immutable
+ private static final Token[] ADDRESS_TO_OBJECT =
+ new Token[] {null, Token.INVALID, Token.LOCAL_INVALID, Token.DESTROYED,
+ Token.REMOVED_PHASE1,
+ Token.REMOVED_PHASE2, Token.END_OF_STREAM, Token.NOT_AVAILABLE, Token.TOMBSTONE,};
- public static void doWithOffHeapClear(Runnable r) {
- clearNeedsToCheckForOffHeap.set(Boolean.TRUE);
- try {
- r.run();
- } finally {
- clearNeedsToCheckForOffHeap.remove();
+ private static long objectToAddress(@Unretained Object v) {
+ if (v instanceof StoredObject) {
+ return ((StoredObject) v).getAddress();
+ }
+ 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.");
}
}
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapStoredObject.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapStoredObject.java
index b7b1af0..2fa57d7 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapStoredObject.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/OffHeapStoredObject.java
@@ -260,13 +260,6 @@ public class OffHeapStoredObject extends AbstractStoredObject
return getDataSize(this.memoryAddress);
}
- protected static int getDataSize(long memoryAdress) {
- int dataSizeDelta = AddressableMemoryManager.readInt(memoryAdress + REF_COUNT_OFFSET);
- dataSizeDelta &= DATA_SIZE_DELTA_MASK;
- dataSizeDelta >>= DATA_SIZE_SHIFT;
- return getSize(memoryAdress) - dataSizeDelta;
- }
-
protected long getBaseDataAddress() {
return this.memoryAddress + HEADER_SIZE;
}
@@ -370,7 +363,7 @@ public class OffHeapStoredObject extends AbstractStoredObject
@Override
public void release() {
- release(this.memoryAddress);
+ ReferenceCounter.release(this.memoryAddress);
}
@Override
@@ -481,44 +474,12 @@ public class OffHeapStoredObject extends AbstractStoredObject
@Override
public boolean retain() {
- return retain(this.memoryAddress);
+ return ReferenceCounter.retain(this.memoryAddress);
}
@Override
public int getRefCount() {
- return getRefCount(this.memoryAddress);
- }
-
- public static int getSize(long memAddr) {
- MemoryAllocatorImpl.validateAddress(memAddr);
- return AddressableMemoryManager.readInt(memAddr + CHUNK_SIZE_OFFSET);
- }
-
- public static void setSize(long memAddr, int size) {
- MemoryAllocatorImpl.validateAddressAndSize(memAddr, size);
- AddressableMemoryManager.writeInt(memAddr + CHUNK_SIZE_OFFSET, size);
- }
-
- public static long getNext(long memAddr) {
- MemoryAllocatorImpl.validateAddress(memAddr);
- return AddressableMemoryManager.readLong(memAddr + HEADER_SIZE);
- }
-
- public static void setNext(long memAddr, long next) {
- MemoryAllocatorImpl.validateAddress(memAddr);
- AddressableMemoryManager.writeLong(memAddr + HEADER_SIZE, next);
- }
-
- /**
- * Fills the chunk with a repeated byte fill pattern.
- *
- * @param baseAddress the starting address for a {@link OffHeapStoredObject}.
- */
- public static void fill(long baseAddress) {
- long startAddress = baseAddress + MIN_CHUNK_SIZE;
- int size = getSize(baseAddress) - MIN_CHUNK_SIZE;
-
- AddressableMemoryManager.fill(startAddress, size, FILL_BYTE);
+ return ReferenceCounter.getRefCount(this.memoryAddress);
}
/**
@@ -617,98 +578,6 @@ public class OffHeapStoredObject extends AbstractStoredObject
rawBits, rawBits + 1));
}
- public static int getRefCount(long memAddr) {
- return AddressableMemoryManager.readInt(memAddr + REF_COUNT_OFFSET) & REF_COUNT_MASK;
- }
-
- public static boolean retain(long memAddr) {
- MemoryAllocatorImpl.validateAddress(memAddr);
- int uc;
- int rawBits;
- int retryCount = 0;
- do {
- rawBits = AddressableMemoryManager.readIntVolatile(memAddr + REF_COUNT_OFFSET);
- if ((rawBits & MAGIC_MASK) != MAGIC_NUMBER) {
- // same as uc == 0
- // TODO MAGIC_NUMBER rethink its use and interaction with compactor fragments
- return false;
- }
- uc = rawBits & REF_COUNT_MASK;
- if (uc == MAX_REF_COUNT) {
- throw new IllegalStateException(
- "Maximum use count exceeded. rawBits=" + Integer.toHexString(rawBits));
- } else if (uc == 0) {
- return false;
- }
- retryCount++;
- if (retryCount > 1000) {
- throw new IllegalStateException("tried to write " + (rawBits + 1) + " to @"
- + Long.toHexString(memAddr) + " 1,000 times.");
- }
- } while (!AddressableMemoryManager.writeIntVolatile(memAddr + REF_COUNT_OFFSET, rawBits,
- rawBits + 1));
- // debugLog("use inced ref count " + (uc+1) + " @" + Long.toHexString(memAddr), true);
- if (ReferenceCountHelper.trackReferenceCounts()) {
- ReferenceCountHelper.refCountChanged(memAddr, false, uc + 1);
- }
-
- return true;
- }
-
- public static void release(final long memAddr) {
- release(memAddr, null);
- }
-
- static void release(final long memAddr, FreeListManager freeListManager) {
- MemoryAllocatorImpl.validateAddress(memAddr);
- int newCount;
- int rawBits;
- boolean returnToAllocator;
- do {
- returnToAllocator = false;
- rawBits = AddressableMemoryManager.readIntVolatile(memAddr + REF_COUNT_OFFSET);
- if ((rawBits & MAGIC_MASK) != MAGIC_NUMBER) {
- String msg = "It looks like off heap memory @" + Long.toHexString(memAddr)
- + " was already freed. rawBits=" + Integer.toHexString(rawBits) + " history="
- + ReferenceCountHelper.getFreeRefCountInfo(memAddr);
- // debugLog(msg, true);
- throw new IllegalStateException(msg);
- }
- int curCount = rawBits & REF_COUNT_MASK;
- if ((curCount) == 0) {
- // debugLog("too many frees @" + Long.toHexString(memAddr), true);
- throw new IllegalStateException(
- "Memory has already been freed." + " history=" + ReferenceCountHelper
- .getFreeRefCountInfo(memAddr) /* + System.identityHashCode(this) */);
- }
- if (curCount == 1) {
- newCount = 0; // clear the use count, bits, and the delta size since it will be freed.
- returnToAllocator = true;
- } else {
- newCount = rawBits - 1;
- }
- } while (!AddressableMemoryManager.writeIntVolatile(memAddr + REF_COUNT_OFFSET, rawBits,
- newCount));
- // debugLog("free deced ref count " + (newCount&USE_COUNT_MASK) + " @" +
- // Long.toHexString(memAddr), true);
- if (returnToAllocator) {
- if (ReferenceCountHelper.trackReferenceCounts()) {
- if (ReferenceCountHelper.trackFreedReferenceCounts()) {
- ReferenceCountHelper.refCountChanged(memAddr, true, newCount & REF_COUNT_MASK);
- }
- ReferenceCountHelper.freeRefCountInfo(memAddr);
- }
- if (freeListManager == null) {
- freeListManager = MemoryAllocatorImpl.getAllocator().getFreeListManager();
- }
- freeListManager.free(memAddr);
- } else {
- if (ReferenceCountHelper.trackReferenceCounts()) {
- ReferenceCountHelper.refCountChanged(memAddr, true, newCount & REF_COUNT_MASK);
- }
- }
- }
-
@Override
public String toString() {
return super.toString() + ":<dataSize=" + getDataSize() + " refCount=" + getRefCount()
@@ -763,4 +632,45 @@ public class OffHeapStoredObject extends AbstractStoredObject
public boolean hasRefCount() {
return true;
}
+
+ // ---------------------------------- STATICS --------------------------------------
+
+ protected static int getDataSize(long memoryAdress) {
+ int dataSizeDelta = AddressableMemoryManager.readInt(memoryAdress + REF_COUNT_OFFSET);
+ dataSizeDelta &= DATA_SIZE_DELTA_MASK;
+ dataSizeDelta >>= DATA_SIZE_SHIFT;
+ return getSize(memoryAdress) - dataSizeDelta;
+ }
+
+ public static int getSize(long memAddr) {
+ MemoryAllocatorImpl.validateAddress(memAddr);
+ return AddressableMemoryManager.readInt(memAddr + CHUNK_SIZE_OFFSET);
+ }
+
+ public static void setSize(long memAddr, int size) {
+ MemoryAllocatorImpl.validateAddressAndSize(memAddr, size);
+ AddressableMemoryManager.writeInt(memAddr + CHUNK_SIZE_OFFSET, size);
+ }
+
+ public static long getNext(long memAddr) {
+ MemoryAllocatorImpl.validateAddress(memAddr);
+ return AddressableMemoryManager.readLong(memAddr + HEADER_SIZE);
+ }
+
+ public static void setNext(long memAddr, long next) {
+ MemoryAllocatorImpl.validateAddress(memAddr);
+ AddressableMemoryManager.writeLong(memAddr + HEADER_SIZE, next);
+ }
+
+ /**
+ * Fills the chunk with a repeated byte fill pattern.
+ *
+ * @param baseAddress the starting address for a {@link OffHeapStoredObject}.
+ */
+ public static void fill(long baseAddress) {
+ long startAddress = baseAddress + MIN_CHUNK_SIZE;
+ int size = getSize(baseAddress) - MIN_CHUNK_SIZE;
+
+ AddressableMemoryManager.fill(startAddress, size, FILL_BYTE);
+ }
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCountHelper.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCountHelper.java
index 41c845b..62b67ff 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCountHelper.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCountHelper.java
@@ -18,7 +18,7 @@ package org.apache.geode.internal.offheap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.geode.annotations.internal.MakeNotStatic;
+import org.apache.geode.annotations.Immutable;
import org.apache.geode.util.internal.GeodeGlossary;
/**
@@ -28,34 +28,38 @@ import org.apache.geode.util.internal.GeodeGlossary;
*/
public class ReferenceCountHelper {
- public static final String TRACK_OFFHEAP_REFERENCES =
+ private static final String TRACK_OFFHEAP_REFERENCES =
GeodeGlossary.GEMFIRE_PREFIX + "trackOffHeapRefCounts";
- public static final String TRACK_OFFHEAP_FREES =
+ private static final String TRACK_OFFHEAP_FREES =
GeodeGlossary.GEMFIRE_PREFIX + "trackOffHeapFreedRefCounts";
- @MakeNotStatic
- private static final ReferenceCountHelperImpl inst = new ReferenceCountHelperImpl(
- Boolean.getBoolean(TRACK_OFFHEAP_REFERENCES), Boolean.getBoolean(TRACK_OFFHEAP_FREES));
+ @Immutable
+ private static final ReferenceCountHelper INSTANCE = new ReferenceCountHelper(
+ new ReferenceCountHelperImpl(Boolean.getBoolean(TRACK_OFFHEAP_REFERENCES),
+ Boolean.getBoolean(TRACK_OFFHEAP_FREES)));
- /* Do not allow any instances */
- private ReferenceCountHelper() {}
+ private final ReferenceCountHelperImpl delegate;
- static ReferenceCountHelperImpl getInstance() {
- return inst;
+ private ReferenceCountHelper(ReferenceCountHelperImpl delegate) {
+ this.delegate = delegate;
+ }
+
+ private static ReferenceCountHelperImpl delegate() {
+ return INSTANCE.delegate;
}
/**
* Returns true if reference count tracking is enabled.
*/
public static boolean trackReferenceCounts() {
- return getInstance().trackReferenceCounts();
+ return delegate().trackReferenceCounts();
}
/**
* Returns true if free operation tracking is enabled.
*/
- public static boolean trackFreedReferenceCounts() {
- return getInstance().trackFreedReferenceCounts();
+ static boolean trackFreedReferenceCounts() {
+ return delegate().trackFreedReferenceCounts();
}
/**
@@ -64,7 +68,7 @@ public class ReferenceCountHelper {
* responsible for decrementing it. Calling this method is a noop if !trackReferenceCounts.
*/
public static void setReferenceCountOwner(Object owner) {
- getInstance().setReferenceCountOwner(owner);
+ delegate().setReferenceCountOwner(owner);
}
/**
@@ -72,7 +76,7 @@ public class ReferenceCountHelper {
* and returns null if !trackReferenceCounts.
*/
public static Object createReferenceCountOwner() {
- return getInstance().createReferenceCountOwner();
+ return delegate().createReferenceCountOwner();
}
/**
@@ -81,57 +85,57 @@ public class ReferenceCountHelper {
* of this method must also call unskipRefCountTracking after the allocation or free is done.
*/
public static void skipRefCountTracking() {
- getInstance().skipRefCountTracking();
+ delegate().skipRefCountTracking();
}
/**
* Returns true if currently tracking reference counts.
*/
public static boolean isRefCountTracking() {
- return getInstance().isRefCountTracking();
+ return delegate().isRefCountTracking();
}
/**
* Call this method to undo a call to skipRefCountTracking.
*/
public static void unskipRefCountTracking() {
- getInstance().unskipRefCountTracking();
+ delegate().unskipRefCountTracking();
}
/**
* Returns a list of any reference count tracking information for the given Chunk address.
*/
public static List<RefCountChangeInfo> getRefCountInfo(long address) {
- return getInstance().getRefCountInfo(address);
+ return delegate().getRefCountInfo(address);
}
/**
* Used internally to report that a reference count has changed.
*/
- static void refCountChanged(Long address, boolean decRefCount, int rc) {
- getInstance().refCountChanged(address, decRefCount, rc);
+ public static void refCountChanged(Long address, boolean decRefCount, int rc) {
+ delegate().refCountChanged(address, decRefCount, rc);
}
/**
* Called internally when free operations are tracked to record that a free has happened of the
* given address.
*/
- static void freeRefCountInfo(Long address) {
- getInstance().freeRefCountInfo(address);
+ public static void freeRefCountInfo(Long address) {
+ delegate().freeRefCountInfo(address);
}
/**
* Returns the thread local owner
*/
- static Object getReferenceCountOwner() {
- return getInstance().getReferenceCountOwner();
+ public static Object getReferenceCountOwner() {
+ return delegate().getReferenceCountOwner();
}
/**
* Returns the thread local count of the number of times ref count has been updated
*/
- static AtomicInteger getReenterCount() {
- return getInstance().getReenterCount();
+ public static AtomicInteger getReenterCount() {
+ return delegate().getReenterCount();
}
/**
@@ -139,14 +143,14 @@ public class ReferenceCountHelper {
* previous free(s) when an extra one ends up being done and fails.
*/
public static List<RefCountChangeInfo> getFreeRefCountInfo(long address) {
- return getInstance().getFreeRefCountInfo(address);
+ return delegate().getFreeRefCountInfo(address);
}
/**
* Returns a list of any reference count tracking information for the given Chunk address without
* locking.
*/
- static List<RefCountChangeInfo> peekRefCountInfo(long address) {
- return getInstance().peekRefCountInfo(address);
+ public static List<RefCountChangeInfo> peekRefCountInfo(long address) {
+ return delegate().peekRefCountInfo(address);
}
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCountHelperImpl.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCountHelperImpl.java
index 5671077..1214ea2 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCountHelperImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCountHelperImpl.java
@@ -12,64 +12,78 @@
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
-
package org.apache.geode.internal.offheap;
+import static java.util.Collections.emptyList;
+
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
-import org.apache.geode.annotations.internal.MakeNotStatic;
+import org.apache.geode.annotations.Immutable;
import org.apache.geode.internal.cache.RegionEntry;
/**
* All access to this class should be done through the static methods of ReferenceCountHelper.
*/
class ReferenceCountHelperImpl {
- private boolean trackRefCounts;
- private boolean trackFreedRefCounts;
- private ConcurrentMap<Long, List<RefCountChangeInfo>> stacktraces;
- private ConcurrentMap<Long, List<RefCountChangeInfo>> freedStacktraces;
- private ThreadLocal<Object> refCountOwner;
- private ThreadLocal<AtomicInteger> refCountReenterCount;
+
private static final Object SKIP_REF_COUNT_TRACKING = new Object();
- @MakeNotStatic
- private static final List<RefCountChangeInfo> LOCKED = Collections.emptyList();
+
+ @Immutable
+ private static final List<RefCountChangeInfo> LOCKED = emptyList();
+
+ // TODO: ThreadLocals should be static final
+
+ private final ThreadLocal<Object> refCountOwner;
+ private final ThreadLocal<AtomicInteger> refCountReenterCount;
+
+ private final boolean trackRefCounts;
+ private final boolean trackFreedRefCounts;
+ private final ConcurrentMap<Long, List<RefCountChangeInfo>> stacktraces;
+ private final ConcurrentMap<Long, List<RefCountChangeInfo>> freedStacktraces;
+ private final BiConsumer<String, Boolean> debugLogger;
ReferenceCountHelperImpl(boolean trackRefCounts, boolean trackFreedRefCounts) {
+ this(trackRefCounts, trackFreedRefCounts, MemoryAllocatorImpl::debugLog);
+ }
+
+ ReferenceCountHelperImpl(boolean trackRefCounts, boolean trackFreedRefCounts,
+ BiConsumer<String, Boolean> debugLogger) {
this.trackRefCounts = trackRefCounts;
this.trackFreedRefCounts = trackFreedRefCounts;
if (trackRefCounts) {
- stacktraces = new ConcurrentHashMap<Long, List<RefCountChangeInfo>>();
+ stacktraces = new ConcurrentHashMap<>();
if (trackFreedRefCounts) {
- freedStacktraces = new ConcurrentHashMap<Long, List<RefCountChangeInfo>>();
+ freedStacktraces = new ConcurrentHashMap<>();
} else {
freedStacktraces = null;
}
- refCountOwner = new ThreadLocal<Object>();
- refCountReenterCount = new ThreadLocal<AtomicInteger>();
+ refCountOwner = new ThreadLocal<>();
+ refCountReenterCount = new ThreadLocal<>();
} else {
stacktraces = null;
freedStacktraces = null;
refCountOwner = null;
refCountReenterCount = null;
}
+ this.debugLogger = debugLogger;
}
/**
* Returns true if reference count tracking is enabled.
*/
- public boolean trackReferenceCounts() {
+ boolean trackReferenceCounts() {
return trackRefCounts;
}
/**
* Returns true if free operation tracking is enabled.
*/
- public boolean trackFreedReferenceCounts() {
+ boolean trackFreedReferenceCounts() {
return trackFreedRefCounts;
}
@@ -78,28 +92,28 @@ class ReferenceCountHelperImpl {
* could set the particular EntryEventImpl instance that incremented the reference count and is
* responsible for decrementing it. Calling this method is a noop if !trackReferenceCounts.
*/
- public void setReferenceCountOwner(Object owner) {
+ void setReferenceCountOwner(Object owner) {
if (trackReferenceCounts()) {
if (refCountOwner.get() != null) {
- AtomicInteger ai = refCountReenterCount.get();
+ AtomicInteger reenterCount = refCountReenterCount.get();
if (owner != null) {
- ai.incrementAndGet();
+ reenterCount.incrementAndGet();
} else {
- if (ai.decrementAndGet() <= 0) {
+ if (reenterCount.decrementAndGet() <= 0) {
refCountOwner.set(null);
- ai.set(0);
+ reenterCount.set(0);
}
}
} else {
- AtomicInteger ai = refCountReenterCount.get();
- if (ai == null) {
- ai = new AtomicInteger(0);
- refCountReenterCount.set(ai);
+ AtomicInteger reenterCount = refCountReenterCount.get();
+ if (reenterCount == null) {
+ reenterCount = new AtomicInteger(0);
+ refCountReenterCount.set(reenterCount);
}
if (owner != null) {
- ai.set(1);
+ reenterCount.set(1);
} else {
- ai.set(0);
+ reenterCount.set(0);
}
refCountOwner.set(owner);
}
@@ -110,7 +124,7 @@ class ReferenceCountHelperImpl {
* Create, set, and return a generic reference count owner object. Calling this method is a noop
* and returns null if !trackReferenceCounts.
*/
- public Object createReferenceCountOwner() {
+ Object createReferenceCountOwner() {
Object result = null;
if (trackReferenceCounts()) {
result = new Object();
@@ -131,25 +145,28 @@ class ReferenceCountHelperImpl {
/**
* Returns true if currently tracking reference counts.
*/
- public boolean isRefCountTracking() {
- if (!trackReferenceCounts())
+ boolean isRefCountTracking() {
+ if (!trackReferenceCounts()) {
return false;
- return !(getReferenceCountOwner() == SKIP_REF_COUNT_TRACKING);
+ }
+ return getReferenceCountOwner() != SKIP_REF_COUNT_TRACKING;
}
/**
* Call this method to undo a call to skipRefCountTracking.
*/
- public void unskipRefCountTracking() {
+ void unskipRefCountTracking() {
setReferenceCountOwner(null);
}
/**
* Returns a list of any reference count tracking information for the given Chunk address.
*/
- public List<RefCountChangeInfo> getRefCountInfo(long address) {
- if (!trackReferenceCounts())
+ List<RefCountChangeInfo> getRefCountInfo(Long address) {
+ if (!trackReferenceCounts()) {
return null;
+ }
+
List<RefCountChangeInfo> result = stacktraces.get(address);
getReferenceCountInfoTestHook(stacktraces, address);
@@ -160,20 +177,14 @@ class ReferenceCountHelperImpl {
return result;
}
- /*
- * This method is overridden during testing to allow simulation of a concurrent update occurring
- * between stacktraces.get and stacktraces.replace
- */
- protected void getReferenceCountInfoTestHook(
- ConcurrentMap<Long, List<RefCountChangeInfo>> stacktraces, long address) {}
-
/**
* Returns a list of any reference count tracking information for the given Chunk address without
* locking.
*/
- public List<RefCountChangeInfo> peekRefCountInfo(long address) {
- if (!trackReferenceCounts())
+ List<RefCountChangeInfo> peekRefCountInfo(long address) {
+ if (!trackReferenceCounts()) {
return null;
+ }
return stacktraces.get(address);
}
@@ -181,18 +192,21 @@ class ReferenceCountHelperImpl {
* Used internally to report that a reference count has changed.
*/
void refCountChanged(Long address, boolean decRefCount, int rc) {
- if (!trackReferenceCounts())
+ if (!trackReferenceCounts()) {
return;
+ }
+
final Object owner = refCountOwner.get();
if (owner == SKIP_REF_COUNT_TRACKING) {
return;
}
+
List<RefCountChangeInfo> list = stacktraces.get(address);
- if (list == null) {
- List<RefCountChangeInfo> newList = new ArrayList<RefCountChangeInfo>();
+ if (list == null) {
refCountChangedTestHook(address, decRefCount, rc);
+ List<RefCountChangeInfo> newList = new ArrayList<>();
List<RefCountChangeInfo> old = stacktraces.putIfAbsent(address, newList);
if (old == null) {
list = newList;
@@ -200,6 +214,7 @@ class ReferenceCountHelperImpl {
list = old;
}
}
+
if (decRefCount) {
if (owner != null) {
synchronized (list) {
@@ -226,45 +241,42 @@ class ReferenceCountHelperImpl {
}
}
}
+
if (list == LOCKED) {
- MemoryAllocatorImpl.debugLog("refCount " + (decRefCount ? "deced" : "inced")
- + " after orphan detected for @" + Long.toHexString(address), true);
+ String message = "refCount " + (decRefCount ? "deced" : "inced")
+ + " after orphan detected for @" + Long.toHexString(address);
+ debugLogger.accept(message, true);
return;
}
- RefCountChangeInfo info = new RefCountChangeInfo(decRefCount, rc, owner);
+
+ RefCountChangeInfo refCountChangeInfo = new RefCountChangeInfo(decRefCount, rc, owner);
+
synchronized (list) {
- // if (list.size() == 16) {
- // debugLog("dumping @" + Long.toHexString(address) + " history=" + list, false);
- // list.clear();
- // }
- for (RefCountChangeInfo e : list) {
- if (e.isSameCaller(info)) {
+ for (RefCountChangeInfo otherRefCountChangeInfo : list) {
+ if (otherRefCountChangeInfo.isSameCaller(refCountChangeInfo)) {
// No need to add it just increment useCount
- e.incUseCount();
+ otherRefCountChangeInfo.incUseCount();
return;
}
}
- list.add(info);
+ list.add(refCountChangeInfo);
}
}
- /*
- * This method is overridden during testing to allow simulation of a race to be the first to
- * reference a given address
- */
- protected void refCountChangedTestHook(Long address, boolean decRefCount, int rc) {}
-
/**
* Called internally when free operations are tracked to record that a free has happened of the
* given address.
*/
void freeRefCountInfo(Long address) {
- if (!trackReferenceCounts())
+ if (!trackReferenceCounts()) {
return;
+ }
+
List<RefCountChangeInfo> freedInfo = stacktraces.remove(address);
+
if (freedInfo == LOCKED) {
- MemoryAllocatorImpl.debugLog("freed after orphan detected for @" + Long.toHexString(address),
- true);
+ debugLogger.accept("freed after orphan detected for @" + Long.toHexString(address), true);
+
} else if (trackFreedReferenceCounts()) {
if (freedInfo != null) {
freedStacktraces.put(address, freedInfo);
@@ -278,8 +290,9 @@ class ReferenceCountHelperImpl {
* Returns the thread local owner
*/
Object getReferenceCountOwner() {
- if (!trackReferenceCounts())
+ if (!trackReferenceCounts()) {
return null;
+ }
return refCountOwner.get();
}
@@ -287,8 +300,9 @@ class ReferenceCountHelperImpl {
* Returns the thread local count of the number of times ref count has been updated
*/
AtomicInteger getReenterCount() {
- if (!trackReferenceCounts())
+ if (!trackReferenceCounts()) {
return null;
+ }
return refCountReenterCount.get();
}
@@ -296,10 +310,27 @@ class ReferenceCountHelperImpl {
* Returns a list of any free operation tracking information. This is used to describe who did the
* previous free(s) when an extra one ends up being done and fails.
*/
- public List<RefCountChangeInfo> getFreeRefCountInfo(long address) {
- if (!trackReferenceCounts() || !trackFreedReferenceCounts())
+ List<RefCountChangeInfo> getFreeRefCountInfo(long address) {
+ if (!trackReferenceCounts() || !trackFreedReferenceCounts()) {
return null;
+ }
return freedStacktraces.get(address);
}
+ /**
+ * This method is overridden during testing to allow simulation of a concurrent update occurring
+ * between stacktraces.get and stacktraces.replace
+ */
+ void getReferenceCountInfoTestHook(ConcurrentMap<Long, List<RefCountChangeInfo>> stacktraces,
+ long address) {
+ // nothing
+ }
+
+ /**
+ * This method is overridden during testing to allow simulation of a race to be the first to
+ * reference a given address
+ */
+ void refCountChangedTestHook(Long address, boolean decRefCount, int rc) {
+ // nothing
+ }
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCounter.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCounter.java
new file mode 100644
index 0000000..5f3155e
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCounter.java
@@ -0,0 +1,50 @@
+/*
+ * 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 org.apache.geode.internal.offheap;
+
+import org.apache.geode.annotations.Immutable;
+
+class ReferenceCounter {
+
+ @Immutable
+ private static final ReferenceCounter INSTANCE =
+ new ReferenceCounter(new ReferenceCounterInstance());
+
+ private final ReferenceCounterInstance delegate;
+
+ private static ReferenceCounterInstance delegate() {
+ return INSTANCE.delegate;
+ }
+
+ private ReferenceCounter(ReferenceCounterInstance delegate) {
+ this.delegate = delegate;
+ }
+
+ static int getRefCount(long memAddr) {
+ return delegate().getRefCount(memAddr);
+ }
+
+ static boolean retain(long memAddr) {
+ return delegate().retain(memAddr);
+ }
+
+ static void release(final long memAddr) {
+ delegate().release(memAddr);
+ }
+
+ static void release(final long memAddr, FreeListManager freeListManager) {
+ delegate().release(memAddr, freeListManager);
+ }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCounterInstance.java b/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCounterInstance.java
new file mode 100644
index 0000000..663be5f
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/offheap/ReferenceCounterInstance.java
@@ -0,0 +1,118 @@
+/*
+ * 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 org.apache.geode.internal.offheap;
+
+class ReferenceCounterInstance {
+
+ int getRefCount(long address) {
+ return AddressableMemoryManager.readInt(address + OffHeapStoredObject.REF_COUNT_OFFSET)
+ & OffHeapStoredObject.REF_COUNT_MASK;
+ }
+
+ boolean retain(long address) {
+ MemoryAllocatorImpl.validateAddress(address);
+ int usageCount;
+ int rawBits;
+ int retryCount = 0;
+
+ do {
+ rawBits =
+ AddressableMemoryManager.readIntVolatile(address + OffHeapStoredObject.REF_COUNT_OFFSET);
+ if ((rawBits & OffHeapStoredObject.MAGIC_MASK) != OffHeapStoredObject.MAGIC_NUMBER) {
+ return false;
+ }
+ usageCount = rawBits & OffHeapStoredObject.REF_COUNT_MASK;
+ if (usageCount == OffHeapStoredObject.MAX_REF_COUNT) {
+ throw new IllegalStateException(
+ "Maximum use count exceeded. rawBits=" + Integer.toHexString(rawBits));
+ }
+ if (usageCount == 0) {
+ return false;
+ }
+ retryCount++;
+ if (retryCount > 1000) {
+ throw new IllegalStateException("tried to write " + (rawBits + 1) + " to @"
+ + Long.toHexString(address) + " 1,000 times.");
+ }
+ } while (!AddressableMemoryManager
+ .writeIntVolatile(address + OffHeapStoredObject.REF_COUNT_OFFSET, rawBits, rawBits + 1));
+
+ if (ReferenceCountHelper.trackReferenceCounts()) {
+ ReferenceCountHelper.refCountChanged(address, false, usageCount + 1);
+ }
+
+ return true;
+ }
+
+ void release(final long address) {
+ release(address, null);
+ }
+
+ void release(final long address, FreeListManager freeListManager) {
+ MemoryAllocatorImpl.validateAddress(address);
+ int newCount;
+ int rawBits;
+ boolean returnToAllocator;
+
+ do {
+ returnToAllocator = false;
+ rawBits =
+ AddressableMemoryManager.readIntVolatile(address + OffHeapStoredObject.REF_COUNT_OFFSET);
+ if ((rawBits & OffHeapStoredObject.MAGIC_MASK) != OffHeapStoredObject.MAGIC_NUMBER) {
+ String message = "It looks like off heap memory @" + Long.toHexString(address)
+ + " was already freed. rawBits=" + Integer.toHexString(rawBits) + " history="
+ + ReferenceCountHelper.getFreeRefCountInfo(address);
+ // debugLog(msg, true);
+ throw new IllegalStateException(message);
+ }
+
+ int currentCount = rawBits & OffHeapStoredObject.REF_COUNT_MASK;
+ if (currentCount == 0) {
+ throw new IllegalStateException("Memory has already been freed. history="
+ + ReferenceCountHelper.getFreeRefCountInfo(address));
+ }
+
+ if (currentCount == 1) {
+ // clear the use count, bits, and the delta size since it will be freed.
+ newCount = 0;
+ returnToAllocator = true;
+ } else {
+ newCount = rawBits - 1;
+ }
+ } while (!AddressableMemoryManager
+ .writeIntVolatile(address + OffHeapStoredObject.REF_COUNT_OFFSET, rawBits, newCount));
+
+ if (returnToAllocator) {
+ if (ReferenceCountHelper.trackReferenceCounts()) {
+ if (ReferenceCountHelper.trackFreedReferenceCounts()) {
+ ReferenceCountHelper.refCountChanged(address, true,
+ newCount & OffHeapStoredObject.REF_COUNT_MASK);
+ }
+ ReferenceCountHelper.freeRefCountInfo(address);
+ }
+
+ if (freeListManager == null) {
+ freeListManager = MemoryAllocatorImpl.getAllocator().getFreeListManager();
+ }
+
+ freeListManager.free(address);
+ } else {
+ if (ReferenceCountHelper.trackReferenceCounts()) {
+ ReferenceCountHelper.refCountChanged(address, true,
+ newCount & OffHeapStoredObject.REF_COUNT_MASK);
+ }
+ }
+ }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/util/concurrent/CustomEntryConcurrentHashMap.java b/geode-core/src/main/java/org/apache/geode/internal/util/concurrent/CustomEntryConcurrentHashMap.java
index 51fe988..7551661 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/util/concurrent/CustomEntryConcurrentHashMap.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/util/concurrent/CustomEntryConcurrentHashMap.java
@@ -61,7 +61,7 @@ import org.apache.geode.CancelException;
import org.apache.geode.internal.cache.RegionEntry;
import org.apache.geode.internal.cache.entries.OffHeapRegionEntry;
import org.apache.geode.internal.cache.wan.GatewaySenderEventImpl;
-import org.apache.geode.internal.offheap.OffHeapRegionEntryHelper;
+import org.apache.geode.internal.offheap.OffHeapClearRequired;
import org.apache.geode.internal.size.SingleObjectSizer;
import org.apache.geode.internal.util.ArrayUtils;
import org.apache.geode.logging.internal.executors.LoggingThread;
@@ -1020,7 +1020,7 @@ public class CustomEntryConcurrentHashMap<K, V> extends AbstractMap<K, V>
// Geode changes BEGIN
if (clearedEntries == null) {
final boolean checkForGatewaySenderEvent =
- OffHeapRegionEntryHelper.doesClearNeedToCheckForOffHeap();
+ OffHeapClearRequired.doesClearNeedToCheckForOffHeap();
if (checkForGatewaySenderEvent) {
clearedEntries = new ArrayList<HashEntry<?, ?>>();
} else {
@@ -1805,7 +1805,7 @@ public class CustomEntryConcurrentHashMap<K, V> extends AbstractMap<K, V>
if (entries != null) {
final ArrayList<HashEntry<?, ?>> clearedEntries = entries;
Runnable runnable;
- if (OffHeapRegionEntryHelper.doesClearNeedToCheckForOffHeap()) {
+ if (OffHeapClearRequired.doesClearNeedToCheckForOffHeap()) {
runnable = new Runnable() {
@Override
public void run() {
diff --git a/geode-core/src/test/java/org/apache/geode/internal/offheap/FreeListManagerTest.java b/geode-core/src/test/java/org/apache/geode/internal/offheap/FreeListManagerTest.java
index 2d83b39..4c4a6fd 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/offheap/FreeListManagerTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/offheap/FreeListManagerTest.java
@@ -113,7 +113,7 @@ public class FreeListManagerTest {
int tinySize = 10;
OffHeapStoredObject c = this.freeListManager.allocate(tinySize);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
c = this.freeListManager.allocate(tinySize);
validateChunkSizes(c, tinySize);
@@ -125,7 +125,7 @@ public class FreeListManagerTest {
int dataSize = 10;
OffHeapStoredObject c = this.freeListManager.allocate(dataSize);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
this.freeListManager.allocate(dataSize);
// free list will now be empty
c = this.freeListManager.allocate(dataSize);
@@ -149,7 +149,7 @@ public class FreeListManagerTest {
int dataSize = FreeListManager.MAX_TINY + 1;
OffHeapStoredObject c = this.freeListManager.allocate(dataSize);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
this.freeListManager.allocate(dataSize);
// free list will now be empty
c = this.freeListManager.allocate(dataSize);
@@ -163,7 +163,7 @@ public class FreeListManagerTest {
int dataSize = FreeListManager.MAX_TINY + 1 + 1024;
OffHeapStoredObject c = this.freeListManager.allocate(dataSize);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
dataSize = FreeListManager.MAX_TINY + 1;
c = this.freeListManager.allocate(dataSize);
@@ -183,7 +183,7 @@ public class FreeListManagerTest {
int dataSize = 10;
OffHeapStoredObject c = this.freeListManager.allocate(dataSize);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
assertThat(this.freeListManager.getFreeTinyMemory()).isEqualTo(computeExpectedSize(dataSize));
}
@@ -194,12 +194,12 @@ public class FreeListManagerTest {
int dataSize = 10;
OffHeapStoredObject c = this.freeListManager.allocate(dataSize);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
int dataSize2 = 100;
OffHeapStoredObject c2 = this.freeListManager.allocate(dataSize2);
- OffHeapStoredObject.release(c2.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c2.getAddress(), this.freeListManager);
assertThat(this.freeListManager.getFreeTinyMemory())
.isEqualTo(computeExpectedSize(dataSize) + computeExpectedSize(dataSize2));
@@ -218,7 +218,7 @@ public class FreeListManagerTest {
int dataSize = FreeListManager.MAX_TINY + 1 + 1024;
OffHeapStoredObject c = this.freeListManager.allocate(dataSize);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
assertThat(this.freeListManager.getFreeHugeMemory()).isEqualTo(computeExpectedSize(dataSize));
}
@@ -287,7 +287,7 @@ public class FreeListManagerTest {
chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE / 2 - 8));
chunks.add(this.freeListManager.allocate(SMALL_SLAB - 8 + 1));
for (OffHeapStoredObject c : chunks) {
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
}
this.freeListManager.firstDefragmentation = false;
assertThat(this.freeListManager.defragment(DEFAULT_SLAB_SIZE + 1)).isFalse();
@@ -314,7 +314,7 @@ public class FreeListManagerTest {
chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE / 2 - 8));
chunks.add(this.freeListManager.allocate(SMALL_SLAB - 8 + 1));
for (OffHeapStoredObject c : chunks) {
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
}
this.freeListManager.firstDefragmentation = false;
@@ -335,7 +335,7 @@ public class FreeListManagerTest {
chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE / 2 - 8));
this.freeListManager.allocate(SMALL_SLAB - 8 + 1);
for (OffHeapStoredObject c : chunks) {
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
}
this.freeListManager.firstDefragmentation = false;
@@ -355,7 +355,7 @@ public class FreeListManagerTest {
chunks.add(this.freeListManager.allocate(DEFAULT_SLAB_SIZE / 2 - 8));
this.freeListManager.allocate(SMALL_SLAB - 8 + 1);
for (OffHeapStoredObject c : chunks) {
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
}
this.freeListManager.firstDefragmentation = false;
@@ -398,26 +398,26 @@ public class FreeListManagerTest {
OffHeapStoredObject mediumChunk1 = freeListManager.allocate(128 - 8);
OffHeapStoredObject mediumChunk2 = freeListManager.allocate(128 - 8);
- OffHeapStoredObject.release(bigChunk.getAddress(), freeListManager);
+ ReferenceCounter.release(bigChunk.getAddress(), freeListManager);
int s = chunksToFree.size();
for (int i = s / 2; i >= 0; i--) {
OffHeapStoredObject c = chunksToFree.get(i);
- OffHeapStoredObject.release(c.getAddress(), freeListManager);
+ ReferenceCounter.release(c.getAddress(), freeListManager);
}
for (int i = (s / 2) + 1; i < s; i++) {
OffHeapStoredObject c = chunksToFree.get(i);
- OffHeapStoredObject.release(c.getAddress(), freeListManager);
+ ReferenceCounter.release(c.getAddress(), freeListManager);
}
- OffHeapStoredObject.release(c3.getAddress(), freeListManager);
- OffHeapStoredObject.release(c1.getAddress(), freeListManager);
- OffHeapStoredObject.release(c2.getAddress(), freeListManager);
- OffHeapStoredObject.release(c4.getAddress(), freeListManager);
- OffHeapStoredObject.release(mediumChunk1.getAddress(), freeListManager);
- OffHeapStoredObject.release(mediumChunk2.getAddress(), freeListManager);
+ ReferenceCounter.release(c3.getAddress(), freeListManager);
+ ReferenceCounter.release(c1.getAddress(), freeListManager);
+ ReferenceCounter.release(c2.getAddress(), freeListManager);
+ ReferenceCounter.release(c4.getAddress(), freeListManager);
+ ReferenceCounter.release(mediumChunk1.getAddress(), freeListManager);
+ ReferenceCounter.release(mediumChunk2.getAddress(), freeListManager);
this.freeListManager.firstDefragmentation = false;
assertThat(freeListManager.defragment(DEFAULT_SLAB_SIZE - (ALLOCATE_COUNT * 32))).isFalse();
for (int i = 0; i < ((256 * 2) / 96); i++) {
- OffHeapStoredObject.release(chunksToFreeLater.get(i).getAddress(), freeListManager);
+ ReferenceCounter.release(chunksToFreeLater.get(i).getAddress(), freeListManager);
}
assertThat(freeListManager.defragment(DEFAULT_SLAB_SIZE - (ALLOCATE_COUNT * 32))).isTrue();
}
@@ -431,9 +431,9 @@ public class FreeListManagerTest {
OffHeapStoredObject bigChunk3 = freeListManager.allocate(slabSize / 3 - 8);
this.freeListManager.firstDefragmentation = false;
assertThat(freeListManager.defragment(1)).isFalse();
- OffHeapStoredObject.release(bigChunk3.getAddress(), freeListManager);
- OffHeapStoredObject.release(bigChunk2.getAddress(), freeListManager);
- OffHeapStoredObject.release(bigChunk1.getAddress(), freeListManager);
+ ReferenceCounter.release(bigChunk3.getAddress(), freeListManager);
+ ReferenceCounter.release(bigChunk2.getAddress(), freeListManager);
+ ReferenceCounter.release(bigChunk1.getAddress(), freeListManager);
assertThat(freeListManager.defragment(slabSize)).isTrue();
}
@@ -442,7 +442,7 @@ public class FreeListManagerTest {
setUpSingleSlabManager();
Fragment originalFragment = this.freeListManager.getFragmentList().get(0);
OffHeapStoredObject c = freeListManager.allocate(16);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
c = freeListManager.allocate(16);
this.freeListManager.firstDefragmentation = false;
assertThat(this.freeListManager.defragment(1)).isTrue();
@@ -714,7 +714,7 @@ public class FreeListManagerTest {
this.freeListManager = createFreeListManager(ma, new Slab[] {chunk});
OffHeapStoredObject c = this.freeListManager.allocate(24);
OffHeapStoredObject c2 = this.freeListManager.allocate(24);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
List<MemoryBlock> ob = this.freeListManager.getOrderedBlocks();
assertThat(ob).hasSize(3);
@@ -733,7 +733,7 @@ public class FreeListManagerTest {
Slab chunk = new SlabImpl(96);
this.freeListManager = createFreeListManager(ma, new Slab[] {chunk});
OffHeapStoredObject c = this.freeListManager.allocate(24);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
List<MemoryBlock> ob = this.freeListManager.getAllocatedBlocks();
assertThat(ob).hasSize(0);
}
@@ -773,8 +773,8 @@ public class FreeListManagerTest {
this.freeListManager = createFreeListManager(ma, new Slab[] {chunk, chunk2});
OffHeapStoredObject c = this.freeListManager.allocate(24);
OffHeapStoredObject c2 = this.freeListManager.allocate(1024 * 1024);
- OffHeapStoredObject.release(c.getAddress(), this.freeListManager);
- OffHeapStoredObject.release(c2.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c.getAddress(), this.freeListManager);
+ ReferenceCounter.release(c2.getAddress(), this.freeListManager);
Logger lw = mock(Logger.class);
this.freeListManager.logOffHeapState(lw, 1024);
diff --git a/geode-core/src/test/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperInstanceTest.java b/geode-core/src/test/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperInstanceTest.java
new file mode 100644
index 0000000..d32cb8b
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperInstanceTest.java
@@ -0,0 +1,907 @@
+/*
+ * 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 org.apache.geode.internal.offheap;
+
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.COMPRESSED_BIT;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.DESTROYED_ADDRESS;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.END_OF_STREAM_ADDRESS;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.INVALID_ADDRESS;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.LOCAL_INVALID_ADDRESS;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.NOT_AVAILABLE_ADDRESS;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.NULL_ADDRESS;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.REMOVED_PHASE1_ADDRESS;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.REMOVED_PHASE2_ADDRESS;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.SERIALIZED_BIT;
+import static org.apache.geode.internal.offheap.OffHeapRegionEntryHelperInstance.TOMBSTONE_ADDRESS;
+import static org.apache.geode.util.internal.UncheckedUtils.uncheckedCast;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+import java.nio.ByteBuffer;
+import java.util.function.Function;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.compression.Compressor;
+import org.apache.geode.internal.cache.CachePerfStats;
+import org.apache.geode.internal.cache.CachedDeserializable;
+import org.apache.geode.internal.cache.DiskId;
+import org.apache.geode.internal.cache.EntryEventImpl;
+import org.apache.geode.internal.cache.RegionEntryContext;
+import org.apache.geode.internal.cache.Token;
+import org.apache.geode.internal.cache.VMCachedDeserializable;
+import org.apache.geode.internal.cache.entries.DiskEntry;
+import org.apache.geode.internal.cache.entries.OffHeapRegionEntry;
+import org.apache.geode.internal.cache.entries.VersionedStatsDiskRegionEntryOffHeap;
+import org.apache.geode.internal.serialization.DSCODE;
+
+public class OffHeapRegionEntryHelperInstanceTest {
+
+ private static final long VALUE_IS_NOT_ENCODABLE = 0L;
+
+ private MemoryAllocator memoryAllocator;
+ private ReferenceCounterInstance referenceCounter;
+ private OffHeapStoredObject offHeapStoredObject;
+
+ private OffHeapRegionEntryHelperInstance offHeapRegionEntryHelperInstance;
+
+ @Before
+ public void setUp() {
+ OutOfOffHeapMemoryListener listener = mock(OutOfOffHeapMemoryListener.class);
+ OffHeapMemoryStats stats = mock(OffHeapMemoryStats.class);
+ Function<Long, OffHeapStoredObject> offHeapStoredObjectFactory =
+ uncheckedCast(mock(Function.class));
+ offHeapStoredObject = mock(OffHeapStoredObject.class);
+ referenceCounter = mock(ReferenceCounterInstance.class);
+
+ when(offHeapStoredObjectFactory.apply(anyLong()))
+ .thenReturn(offHeapStoredObject);
+
+ memoryAllocator =
+ MemoryAllocatorImpl.create(listener, stats, 1, OffHeapStorage.MIN_SLAB_SIZE,
+ OffHeapStorage.MIN_SLAB_SIZE);
+
+ offHeapRegionEntryHelperInstance =
+ spy(new OffHeapRegionEntryHelperInstance(ohAddress -> offHeapStoredObject,
+ referenceCounter));
+ }
+
+ @After
+ public void tearDown() {
+ MemoryAllocatorImpl.freeOffHeapMemory();
+ }
+
+ @Test
+ public void encodeDataAsAddressShouldReturnZeroIfValueIsGreaterThanSevenBytes() {
+ byte[] valueInBytes =
+ ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(Long.MAX_VALUE).array();
+
+ assertThat(valueInBytes.length)
+ .isGreaterThanOrEqualTo(OffHeapRegionEntryHelperInstance.MAX_LENGTH_FOR_DATA_AS_ADDRESS);
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(valueInBytes, false, false);
+
+ assertThat(encodedAddress)
+ .isEqualTo(VALUE_IS_NOT_ENCODABLE);
+ }
+
+ @Test
+ public void encodeDataAsAddressShouldEncodeLongIfItsSerializedAndIfItsNotTooBig() {
+ byte[] valueInBytes = EntryEventImpl.serialize(0L);
+ boolean isSerialized = true;
+ boolean isCompressed = false;
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(valueInBytes, isSerialized,
+ isCompressed);
+
+ long expectedEncodedAddress = 123L;
+ assertThat(encodedAddress)
+ .isEqualTo(expectedEncodedAddress);
+
+ assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
+ }
+
+ @Test
+ public void encodeDataAsAddressShouldReturnZeroIfValueIsLongAndItIsSerializedAndBig() {
+ byte[] valueInBytes = EntryEventImpl.serialize(Long.MAX_VALUE);
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(valueInBytes, true,
+ false);
+
+ assertThat(encodedAddress)
+ .isEqualTo(VALUE_IS_NOT_ENCODABLE);
+ }
+
+ @Test
+ public void encodeDataAsAddressShouldReturnZeroIfValueIsLargerThanEightBytesAndNotLong() {
+ byte[] someValue = new byte[8];
+ someValue[0] = DSCODE.CLASS.toByte();
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(someValue, true, false);
+
+ assertThat(encodedAddress)
+ .isEqualTo(VALUE_IS_NOT_ENCODABLE);
+ }
+
+ @Test
+ public void encodeDataAsAddressShouldReturnValidAddressIfValueIsLesserThanSevenBytes() {
+ byte[] valueInBytes =
+ ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
+ boolean isSerialized = false;
+ boolean isCompressed = false;
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(valueInBytes, isSerialized,
+ isCompressed);
+
+ long expectedAddress = 549755813697L;
+ assertThat(encodedAddress)
+ .isEqualTo(expectedAddress);
+
+ assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
+ }
+
+ @Test
+ public void encodeDataAsAddressShouldSetSerializedBitIfSerialized() {
+ byte[] valueInBytes = EntryEventImpl.serialize(Integer.MAX_VALUE);
+ boolean isSerialized = true;
+ boolean isCompressed = false;
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(valueInBytes, isSerialized,
+ isCompressed);
+
+ long expectedAddress = 63221918596947L;
+ assertThat(expectedAddress)
+ .isEqualTo(encodedAddress);
+
+ assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
+ }
+
+ @Test
+ public void encodeDataAsAddressShouldSetSerializedBitIfCompressed() {
+ byte[] valueInBytes =
+ ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
+ boolean isSerialized = false;
+ boolean isCompressed = true;
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(valueInBytes, isSerialized,
+ isCompressed);
+
+ long expectedAddress = 549755813701L;
+ assertThat(encodedAddress)
+ .isEqualTo(expectedAddress);
+
+ assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
+ }
+
+ @Test
+ public void encodeDataAsAddressShouldSetBothSerializedAndCompressedBitsIfSerializedAndCompressed() {
+ byte[] valueInBytes = EntryEventImpl.serialize(Integer.MAX_VALUE);
+ boolean isSerialized = true;
+ boolean isCompressed = true;
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(valueInBytes, isSerialized,
+ isCompressed);
+
+ long expectedAddress = 63221918596951L;
+ assertThat(expectedAddress)
+ .isEqualTo(encodedAddress);
+
+ assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
+ }
+
+ @Test
+ public void decodeUncompressedAddressToBytesShouldReturnActualBytes() {
+ long encodedAddress = 549755813697L;
+ int value = Integer.MAX_VALUE;
+
+ byte[] actual =
+ offHeapRegionEntryHelperInstance.decodeUncompressedAddressToBytes(encodedAddress);
+
+ byte[] expectedValue = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(value).array();
+ assertThat(actual)
+ .isEqualTo(expectedValue);
+ }
+
+ @Test
+ public void decodeUncompressedAddressToBytesShouldDecodeLongIfItsSerializedAndIfItsNotTooBig() {
+ byte[] actual = offHeapRegionEntryHelperInstance.decodeUncompressedAddressToBytes(123L);
+
+ byte[] expectedValue = EntryEventImpl.serialize(0L);
+ assertThat(actual)
+ .isEqualTo(expectedValue);
+ }
+
+ @Test
+ public void decodeUncompressedAddressToBytesWithCompressedAddressShouldThrowException() {
+ long encodedAddress = 549755813703L;
+
+ Throwable thrown = catchThrowable(() -> {
+ offHeapRegionEntryHelperInstance.decodeUncompressedAddressToBytes(encodedAddress);
+ });
+
+ assertThat(thrown)
+ .isInstanceOf(AssertionError.class);
+ }
+
+ @Test
+ public void decodeCompressedDataAsAddressToRawBytes() {
+ long encodedAddress = 549755813703L;
+ byte[] expected = new byte[] {127, -1, -1, -1};
+
+ byte[] bytes = offHeapRegionEntryHelperInstance.decodeAddressToRawBytes(encodedAddress);
+
+ assertThat(bytes)
+ .isEqualTo(expected);
+ }
+
+ @Test
+ public void encodedAddressShouldBeDecodableEvenIfValueIsSerialized() {
+ int value = Integer.MAX_VALUE;
+ byte[] serializedValue = EntryEventImpl.serialize(value);
+
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(serializedValue, true, false);
+
+ int actualValue =
+ (int) offHeapRegionEntryHelperInstance.decodeAddressToObject(encodedAddress);
+
+ assertThat(actualValue)
+ .isEqualTo(value);
+ }
+
+ @Test
+ public void encodedAddressShouldBeDecodableEvenIfValueIsUnserialized() {
+ int value = Integer.MAX_VALUE;
+ byte[] unSerializedValue = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(value).array();
+ long encodedAddress =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(unSerializedValue, false, false);
+
+ byte[] actualValue =
+ (byte[]) offHeapRegionEntryHelperInstance.decodeAddressToObject(encodedAddress);
+
+ assertThat(actualValue)
+ .isEqualTo(unSerializedValue);
+ }
+
+ @Test
+ public void isSerializedShouldReturnTrueIfSerialized() {
+ assertThat(offHeapRegionEntryHelperInstance.isSerialized(1000010L)).isTrue();
+ }
+
+ @Test
+ public void isSerializedShouldReturnFalseIfNotSerialized() {
+ assertThat(offHeapRegionEntryHelperInstance.isSerialized(1000000L)).isFalse();
+ }
+
+ @Test
+ public void isCompressedShouldReturnTrueIfCompressed() {
+ assertThat(offHeapRegionEntryHelperInstance.isCompressed(1000100L)).isTrue();
+ }
+
+ @Test
+ public void isCompressedShouldReturnFalseIfNotCompressed() {
+ assertThat(offHeapRegionEntryHelperInstance.isCompressed(1000000L)).isFalse();
+ }
+
+ @Test
+ public void isOffHeapShouldReturnTrueIfAddressIsOnOffHeap() {
+ OffHeapStoredObject value = createChunk(Long.MAX_VALUE);
+
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(value.getAddress())).isTrue();
+ }
+
+ @Test
+ public void isOffHeapShouldReturnFalseIfAddressIsAnEncodedAddress() {
+ byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
+
+ long address = offHeapRegionEntryHelperInstance.encodeDataAsAddress(data, false, false);
+
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(address)).isFalse();
+ }
+
+ @Test
+ public void isOffHeapShouldReturnFalseForAnyTokenAddress() {
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(NULL_ADDRESS)).isFalse();
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(INVALID_ADDRESS)).isFalse();
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(LOCAL_INVALID_ADDRESS)).isFalse();
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(DESTROYED_ADDRESS)).isFalse();
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(REMOVED_PHASE1_ADDRESS)).isFalse();
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(REMOVED_PHASE2_ADDRESS)).isFalse();
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(END_OF_STREAM_ADDRESS)).isFalse();
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(NOT_AVAILABLE_ADDRESS)).isFalse();
+ assertThat(offHeapRegionEntryHelperInstance.isOffHeap(TOMBSTONE_ADDRESS)).isFalse();
+ }
+
+ @Test
+ public void setValueShouldChangeTheRegionEntryAddressToNewAddress() {
+ // mock region entry
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ // some old address
+ long oldAddress = 1L;
+
+ // testing when the newValue is a chunk
+ OffHeapStoredObject newValue = createChunk(Long.MAX_VALUE);
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, newValue.getAddress())).thenReturn(Boolean.TRUE);
+
+ // invoke the method under test
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, newValue);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, newValue.getAddress());
+ // resetting the spy in-order to re-use
+ reset(regionEntry);
+
+ // testing when the newValue is DataAsAddress
+ TinyStoredObject newAddress1 = new TinyStoredObject(2L);
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, newAddress1.getAddress())).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, newAddress1);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, newAddress1.getAddress());
+ reset(regionEntry);
+
+ // Testing when newValue is Token Objects
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, NULL_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, null);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, NULL_ADDRESS);
+ reset(regionEntry);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, INVALID_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.INVALID);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, INVALID_ADDRESS);
+ reset(regionEntry);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, LOCAL_INVALID_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.LOCAL_INVALID);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, LOCAL_INVALID_ADDRESS);
+ reset(regionEntry);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, DESTROYED_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.DESTROYED);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, DESTROYED_ADDRESS);
+ reset(regionEntry);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, REMOVED_PHASE1_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.REMOVED_PHASE1);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, REMOVED_PHASE1_ADDRESS);
+ reset(regionEntry);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, REMOVED_PHASE2_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.REMOVED_PHASE2);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, REMOVED_PHASE2_ADDRESS);
+ reset(regionEntry);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, END_OF_STREAM_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.END_OF_STREAM);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, END_OF_STREAM_ADDRESS);
+ reset(regionEntry);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, NOT_AVAILABLE_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.NOT_AVAILABLE);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, NOT_AVAILABLE_ADDRESS);
+ reset(regionEntry);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, TOMBSTONE_ADDRESS)).thenReturn(true);
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.TOMBSTONE);
+
+ // verify oldAddress is replaced with newAddress
+ verify(regionEntry).setAddress(oldAddress, TOMBSTONE_ADDRESS);
+ }
+
+ @Test
+ public void setValueShouldChangeTheRegionEntryAddressToNewAddressAndReleaseOldValueIfItsOnOffHeap() {
+ OffHeapStoredObject oldValue = createChunk(Long.MAX_VALUE);
+ OffHeapStoredObject newValue = createChunk(Long.MAX_VALUE - 1);
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ // mock Chunk static methods - in-order to verify that release is called
+ doNothing().when(offHeapStoredObject).release();
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress())
+ .thenReturn(oldValue.getAddress());
+ when(regionEntry.setAddress(oldValue.getAddress(), newValue.getAddress()))
+ .thenReturn(Boolean.TRUE);
+
+ // invoke the method under test
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, newValue);
+
+ // verify oldAddress is changed to newAddress
+ verify(regionEntry)
+ .setAddress(oldValue.getAddress(), newValue.getAddress());
+
+ // verify oldAddress is released
+ verify(referenceCounter)
+ .release(oldValue.getAddress());
+ }
+
+ @Test
+ public void setValueShouldChangeTheRegionEntryAddressToNewAddressAndDoesNothingIfOldAddressIsAnEncodedAddress() {
+ byte[] oldData =
+ ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
+ byte[] newData =
+ ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE - 1).array();
+ long oldAddress = offHeapRegionEntryHelperInstance.encodeDataAsAddress(oldData, false, false);
+ StoredObject newAddress = new TinyStoredObject(
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(newData, false, false));
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress())
+ .thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, newAddress.getAddress()))
+ .thenReturn(true);
+
+ // invoke the method under test
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, newAddress);
+
+ // verify oldAddress is changed to newAddress
+ verify(regionEntry)
+ .setAddress(oldAddress, newAddress.getAddress());
+
+ // verify that release is never called as the old address is not on offheap
+ verifyNoInteractions(offHeapStoredObject);
+ }
+
+ @Test
+ public void setValueShouldChangeTheRegionEntryAddressToNewAddressAndDoesNothingIfOldAddressIsATokenAddress() {
+ long oldAddress = REMOVED_PHASE1_ADDRESS;
+ long newAddress = REMOVED_PHASE2_ADDRESS;
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ when(regionEntry.getAddress())
+ .thenReturn(oldAddress);
+ when(regionEntry.setAddress(oldAddress, newAddress))
+ .thenReturn(true);
+
+ // invoke the method under test
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, Token.REMOVED_PHASE2);
+
+ // verify oldAddress is changed to newAddress
+ verify(regionEntry)
+ .setAddress(oldAddress, newAddress);
+ }
+
+ @Test
+ public void setValueShouldThrowIllegalExceptionIfNewValueCannotBeConvertedToAddress() {
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ when(regionEntry.getAddress())
+ .thenReturn(1L);
+
+ // invoke the method under test with some object other than Chunk/DataAsAddress/Token
+ Throwable thrown = catchThrowable(() -> {
+ offHeapRegionEntryHelperInstance.setValue(regionEntry, new Object());
+ });
+
+ assertThat(thrown)
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ public void getValueAsTokenShouldReturnNotATokenIfValueIsOnOffHeap() {
+ OffHeapStoredObject chunk = createChunk(Long.MAX_VALUE);
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ when(regionEntry.getAddress())
+ .thenReturn(chunk.getAddress());
+
+ Token token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+
+ assertThat(token)
+ .isEqualTo(Token.NOT_A_TOKEN);
+ }
+
+ @Test
+ public void getValueAsTokenShouldReturnNotATokenIfValueIsEncoded() {
+ byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
+ long address = offHeapRegionEntryHelperInstance.encodeDataAsAddress(data, false, false);
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ when(regionEntry.getAddress())
+ .thenReturn(address);
+
+ Token token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+
+ assertThat(token)
+ .isEqualTo(Token.NOT_A_TOKEN);
+ }
+
+ @Test
+ public void getValueAsTokenShouldReturnAValidToken() {
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ when(regionEntry.getAddress()).thenReturn(NULL_ADDRESS);
+ Token token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isNull();
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(INVALID_ADDRESS);
+ token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isEqualTo(Token.INVALID);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(LOCAL_INVALID_ADDRESS);
+ token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isEqualTo(Token.LOCAL_INVALID);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(DESTROYED_ADDRESS);
+ token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isEqualTo(Token.DESTROYED);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(REMOVED_PHASE1_ADDRESS);
+ token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isEqualTo(Token.REMOVED_PHASE1);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(REMOVED_PHASE2_ADDRESS);
+ token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isEqualTo(Token.REMOVED_PHASE2);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(END_OF_STREAM_ADDRESS);
+ token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isEqualTo(Token.END_OF_STREAM);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(NOT_AVAILABLE_ADDRESS);
+ token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isEqualTo(Token.NOT_AVAILABLE);
+
+ // mock region entry methods required for test
+ when(regionEntry.getAddress()).thenReturn(TOMBSTONE_ADDRESS);
+ token = offHeapRegionEntryHelperInstance.getValueAsToken(regionEntry);
+ assertThat(token).isEqualTo(Token.TOMBSTONE);
+ }
+
+ @Test
+ public void addressToObjectShouldReturnValueFromChunk() {
+ OffHeapRegionEntryHelperInstance offHeapRegionEntryHelperInstance =
+ new OffHeapRegionEntryHelperInstance();
+ OffHeapStoredObject expected = createChunk(Long.MAX_VALUE);
+
+ Object actual =
+ offHeapRegionEntryHelperInstance.addressToObject(expected.getAddress(), false, null);
+
+ assertThat(actual)
+ .isInstanceOf(OffHeapStoredObject.class)
+ .isEqualTo(expected);
+ }
+
+ @Test
+ public void addressToObjectShouldReturnCachedDeserializableFromChunkIfAskedToDecompress() {
+ byte[] data = EntryEventImpl.serialize(Long.MAX_VALUE);
+ RegionEntryContext regionContext = mock(RegionEntryContext.class);
+ CachePerfStats cacheStats = mock(CachePerfStats.class);
+ Compressor compressor = mock(Compressor.class);
+
+ when(regionContext.getCompressor())
+ .thenReturn(compressor);
+ when(compressor.decompress(data))
+ .thenReturn(data);
+ when(regionContext.getCachePerfStats())
+ .thenReturn(cacheStats);
+ when(cacheStats.startDecompression())
+ .thenReturn(10000L);
+
+ MemoryBlock chunk =
+ (MemoryBlock) memoryAllocator.allocateAndInitialize(data, true, true);
+ offHeapRegionEntryHelperInstance =
+ spy(new OffHeapRegionEntryHelperInstance(OffHeapStoredObject::new, referenceCounter));
+
+ Object actual =
+ offHeapRegionEntryHelperInstance.addressToObject(chunk.getAddress(), true, regionContext);
+
+ assertThat(actual)
+ .isInstanceOf(VMCachedDeserializable.class);
+
+ long actualValue = (long) ((CachedDeserializable) actual).getDeserializedForReading();
+
+ assertThat(actualValue)
+ .isEqualTo(Long.MAX_VALUE);
+ }
+
+ @Test
+ public void addressToObjectShouldReturnDecompressedValueFromChunkIfAskedToDecompress() {
+ byte[] data = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(Long.MAX_VALUE).array();
+ RegionEntryContext regionContext = mock(RegionEntryContext.class);
+ CachePerfStats cacheStats = mock(CachePerfStats.class);
+ Compressor compressor = mock(Compressor.class);
+
+ when(regionContext.getCompressor())
+ .thenReturn(compressor);
+ when(compressor.decompress(data))
+ .thenReturn(data);
+ when(regionContext.getCachePerfStats())
+ .thenReturn(cacheStats);
+ when(cacheStats.startDecompression())
+ .thenReturn(10000L);
+
+ MemoryBlock chunk = (MemoryBlock) memoryAllocator.allocateAndInitialize(data, false, true);
+ offHeapRegionEntryHelperInstance =
+ spy(new OffHeapRegionEntryHelperInstance(OffHeapStoredObject::new, referenceCounter));
+
+ Object actual =
+ offHeapRegionEntryHelperInstance.addressToObject(chunk.getAddress(), true, regionContext);
+
+ assertThat(actual)
+ .isInstanceOf(byte[].class)
+ .isEqualTo(data);
+ }
+
+ @Test
+ public void addressToObjectShouldReturnValueFromDataAsAddress() {
+ byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
+ long address = offHeapRegionEntryHelperInstance.encodeDataAsAddress(data, false, false);
+
+ Object actual = offHeapRegionEntryHelperInstance.addressToObject(address, false, null);
+
+ TinyStoredObject expected = new TinyStoredObject(address);
+
+ assertThat(actual)
+ .isInstanceOf(TinyStoredObject.class)
+ .isEqualTo(expected);
+ }
+
+ @Test
+ public void addressToObjectShouldReturnCachedDeserializableFromSerializedDataAsAddressIfAskedToDecompress() {
+ byte[] data = EntryEventImpl.serialize(Integer.MAX_VALUE);
+ RegionEntryContext regionContext = mock(RegionEntryContext.class);
+ CachePerfStats cacheStats = mock(CachePerfStats.class);
+ Compressor compressor = mock(Compressor.class);
+
+ when(regionContext.getCompressor())
+ .thenReturn(compressor);
+ when(compressor.decompress(data))
+ .thenReturn(data);
+ when(regionContext.getCachePerfStats())
+ .thenReturn(cacheStats);
+ when(cacheStats.startDecompression())
+ .thenReturn(10000L);
+
+ long address =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(data, true, true);
+
+ Object actual = offHeapRegionEntryHelperInstance.addressToObject(address, true, regionContext);
+
+ assertThat(actual)
+ .isInstanceOf(VMCachedDeserializable.class);
+
+ int actualValue = (int) ((CachedDeserializable) actual).getDeserializedForReading();
+
+ assertThat(actualValue)
+ .isEqualTo(Integer.MAX_VALUE);
+ }
+
+ @Test
+ public void addressToObjectShouldReturnDecompressedValueFromDataAsAddressIfAskedToDecompress() {
+ byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
+ RegionEntryContext regionContext = mock(RegionEntryContext.class);
+ CachePerfStats cacheStats = mock(CachePerfStats.class);
+ Compressor compressor = mock(Compressor.class);
+
+ when(regionContext.getCompressor())
+ .thenReturn(compressor);
+ when(compressor.decompress(data))
+ .thenReturn(data);
+ when(regionContext.getCachePerfStats())
+ .thenReturn(cacheStats);
+ when(cacheStats.startDecompression())
+ .thenReturn(10000L);
+
+ long address =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(data, false, true);
+
+ Object actual = offHeapRegionEntryHelperInstance.addressToObject(address, true, regionContext);
+
+ assertThat(actual)
+ .isInstanceOf(byte[].class)
+ .isEqualTo(data);
+ }
+
+ @Test
+ public void addressToObjectShouldReturnToken() {
+ Token token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(NULL_ADDRESS, false, null);
+ assertThat(token).isNull();
+
+ token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(INVALID_ADDRESS, false, null);
+ assertThat(token).isEqualTo(Token.INVALID);
+
+ token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(LOCAL_INVALID_ADDRESS, false, null);
+ assertThat(token).isEqualTo(Token.LOCAL_INVALID);
+
+ token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(DESTROYED_ADDRESS, false, null);
+ assertThat(token).isEqualTo(Token.DESTROYED);
+
+ token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(REMOVED_PHASE1_ADDRESS, false, null);
+ assertThat(token).isEqualTo(Token.REMOVED_PHASE1);
+
+ token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(REMOVED_PHASE2_ADDRESS, false, null);
+ assertThat(token).isEqualTo(Token.REMOVED_PHASE2);
+
+ token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(END_OF_STREAM_ADDRESS, false, null);
+ assertThat(token).isEqualTo(Token.END_OF_STREAM);
+
+ token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(NOT_AVAILABLE_ADDRESS, false, null);
+ assertThat(token).isEqualTo(Token.NOT_AVAILABLE);
+
+ token = (Token) offHeapRegionEntryHelperInstance
+ .addressToObject(TOMBSTONE_ADDRESS, false, null);
+ assertThat(token).isEqualTo(Token.TOMBSTONE);
+ }
+
+ @Test
+ public void getSerializedLengthFromDataAsAddressShouldReturnValidLength() {
+ byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
+ long address =
+ offHeapRegionEntryHelperInstance.encodeDataAsAddress(data, false, true);
+ TinyStoredObject tinyStoredObject = new TinyStoredObject(address);
+
+ int actualLength = offHeapRegionEntryHelperInstance.getSerializedLength(tinyStoredObject);
+
+ assertThat(actualLength)
+ .isEqualTo(data.length);
+ }
+
+ @Test
+ public void getSerializedLengthFromDataAsAddressShouldReturnZeroForNonEncodedAddress() {
+ TinyStoredObject nonEncodedAddress = new TinyStoredObject(100000L);
+
+ int actualLength = offHeapRegionEntryHelperInstance.getSerializedLength(nonEncodedAddress);
+
+ assertThat(actualLength)
+ .isZero();
+ }
+
+ @Test
+ public void releaseEntryShouldSetValueToRemovePhase2() {
+ OffHeapRegionEntry regionEntry = mock(OffHeapRegionEntry.class);
+
+ when(regionEntry.getAddress())
+ .thenReturn(1L);
+ when(regionEntry.setAddress(1L, REMOVED_PHASE2_ADDRESS))
+ .thenReturn(Boolean.TRUE);
+
+ offHeapRegionEntryHelperInstance.releaseEntry(regionEntry);
+
+ verify(offHeapRegionEntryHelperInstance)
+ .setValue(regionEntry, Token.REMOVED_PHASE2);
+ }
+
+ @Test
+ public void releaseEntryShouldSetValueToRemovePhase2AndSetsAsyncToFalseForDiskEntry() {
+ OffHeapRegionEntry regionEntry = mock(VersionedStatsDiskRegionEntryOffHeap.class);
+ DiskId diskId = spy(DiskId.class);
+
+ when(regionEntry.getAddress())
+ .thenReturn(1L);
+ when(regionEntry.setAddress(1L, REMOVED_PHASE2_ADDRESS))
+ .thenReturn(Boolean.TRUE);
+ when(((DiskEntry) regionEntry).getDiskId())
+ .thenReturn(diskId);
+ when(diskId.isPendingAsync())
+ .thenReturn(Boolean.TRUE);
+
+ offHeapRegionEntryHelperInstance.releaseEntry(regionEntry);
+
+ verify(offHeapRegionEntryHelperInstance)
+ .setValue(regionEntry, Token.REMOVED_PHASE2);
+ verify(diskId)
+ .setPendingAsync(Boolean.FALSE);
+ }
+
+ @Test
+ public void doWithOffHeapClearShouldSetTheThreadLocalToTrue() {
+ // verify that threadlocal is not set
+ assertThat(OffHeapClearRequired.doesClearNeedToCheckForOffHeap()).isFalse();
+
+ OffHeapClearRequired.doWithOffHeapClear(() -> {
+ // verify that threadlocal is set when offheap is cleared
+ assertThat(OffHeapClearRequired.doesClearNeedToCheckForOffHeap()).isTrue();
+ });
+
+ // verify that threadlocal is reset after offheap is cleared
+ assertThat(OffHeapClearRequired.doesClearNeedToCheckForOffHeap()).isFalse();
+ }
+
+ private OffHeapStoredObject createChunk(Object value) {
+ byte[] bytes = EntryEventImpl.serialize(value);
+
+ StoredObject chunk = memoryAllocator.allocateAndInitialize(bytes, true, false);
+
+ return (OffHeapStoredObject) chunk;
+ }
+
+ private static void assertSerializedAndCompressedBits(long encodedAddress,
+ boolean shouldSerializedBitBeSet, boolean shouldCompressedBitBeSet) {
+ boolean isSerializedBitSet = (encodedAddress & SERIALIZED_BIT) == SERIALIZED_BIT;
+
+ assertThat(isSerializedBitSet)
+ .isEqualTo(shouldSerializedBitBeSet);
+
+ boolean isCompressedBitSet = (encodedAddress & COMPRESSED_BIT) == COMPRESSED_BIT;
+
+ assertThat(isCompressedBitSet)
+ .isEqualTo(shouldCompressedBitBeSet);
+ }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperJUnitTest.java
deleted file mode 100644
index 3c219ff..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/offheap/OffHeapRegionEntryHelperJUnitTest.java
+++ /dev/null
@@ -1,926 +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 org.apache.geode.internal.offheap;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.nio.ByteBuffer;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import org.apache.geode.compression.Compressor;
-import org.apache.geode.internal.cache.CachePerfStats;
-import org.apache.geode.internal.cache.DiskId;
-import org.apache.geode.internal.cache.EntryEventImpl;
-import org.apache.geode.internal.cache.RegionEntryContext;
-import org.apache.geode.internal.cache.Token;
-import org.apache.geode.internal.cache.VMCachedDeserializable;
-import org.apache.geode.internal.cache.entries.DiskEntry;
-import org.apache.geode.internal.cache.entries.OffHeapRegionEntry;
-import org.apache.geode.internal.cache.entries.VersionedStatsDiskRegionEntryOffHeap;
-import org.apache.geode.internal.serialization.DSCODE;
-
-@RunWith(PowerMockRunner.class)
-@PowerMockIgnore("*.UnitTest")
-@PrepareForTest({OffHeapStoredObject.class, OffHeapRegionEntryHelper.class})
-public class OffHeapRegionEntryHelperJUnitTest {
-
- private static final Long VALUE_IS_NOT_ENCODABLE = 0L;
-
- private MemoryAllocator ma;
-
- @Before
- public void setUp() {
- OutOfOffHeapMemoryListener ooohml = mock(OutOfOffHeapMemoryListener.class);
- OffHeapMemoryStats stats = mock(OffHeapMemoryStats.class);
-
- ma = MemoryAllocatorImpl.create(ooohml, stats, 1, OffHeapStorage.MIN_SLAB_SIZE * 1,
- OffHeapStorage.MIN_SLAB_SIZE);
- }
-
- @After
- public void tearDown() {
- MemoryAllocatorImpl.freeOffHeapMemory();
- }
-
- private OffHeapStoredObject createChunk(Object value) {
- byte[] v = EntryEventImpl.serialize(value);
-
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- OffHeapStoredObject chunk =
- (OffHeapStoredObject) ma.allocateAndInitialize(v, isSerialized, isCompressed);
-
- return chunk;
- }
-
- @Test
- public void encodeDataAsAddressShouldReturnZeroIfValueIsGreaterThanSevenBytes() {
- Long value = Long.MAX_VALUE;
-
- byte[] valueInBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(value).array();
- boolean isSerialized = false;
- boolean isCompressed = false;
-
- assertThat(valueInBytes.length)
- .isGreaterThanOrEqualTo(OffHeapRegionEntryHelper.MAX_LENGTH_FOR_DATA_AS_ADDRESS);
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(valueInBytes, isSerialized, isCompressed);
-
- assertThat(encodedAddress).isEqualTo(VALUE_IS_NOT_ENCODABLE);
- }
-
- @Test
- public void encodeDataAsAddressShouldEncodeLongIfItsSerializedAndIfItsNotTooBig() {
- Long value = 0L;
- long expectedEncodedAddress = 123L;
-
- byte[] valueInBytes = EntryEventImpl.serialize(value);
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(valueInBytes, isSerialized, isCompressed);
-
- assertThat(encodedAddress).isEqualTo(expectedEncodedAddress);
- assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
- }
-
- @Test
- public void encodeDataAsAddressShouldReturnZeroIfValueIsLongAndItIsSerializedAndBig() {
- Long value = Long.MAX_VALUE;
-
- byte[] valueInBytes = EntryEventImpl.serialize(value);
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(valueInBytes, isSerialized, isCompressed);
-
- assertThat(encodedAddress).isEqualTo(VALUE_IS_NOT_ENCODABLE);
- }
-
- @Test
- public void encodeDataAsAddressShouldReturnZeroIfValueIsLargerThanEightBytesAndNotLong() {
- byte[] someValue = new byte[8];
- someValue[0] = DSCODE.CLASS.toByte();
-
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(someValue, isSerialized, isCompressed);
-
- assertThat(encodedAddress).isEqualTo(VALUE_IS_NOT_ENCODABLE);
- }
-
- @Test
- public void encodeDataAsAddressShouldReturnValidAddressIfValueIsLesserThanSevenBytes() {
- long expectedAddress = 549755813697L;
-
- Integer value = Integer.MAX_VALUE;
-
- byte[] valueInBytes = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(value).array();
- boolean isSerialized = false;
- boolean isCompressed = false;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(valueInBytes, isSerialized, isCompressed);
-
- assertThat(encodedAddress).isEqualTo(expectedAddress);
- assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
- }
-
- @Test
- public void encodeDataAsAssressShouldSetSerialziedBitIfSerizliaed() {
- long expectedAddress = 63221918596947L;
-
- Integer value = Integer.MAX_VALUE;
-
- byte[] valueInBytes = EntryEventImpl.serialize(value);
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(valueInBytes, isSerialized, isCompressed);
-
- assertThat(expectedAddress).isEqualTo(encodedAddress);
- assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
- }
-
- @Test
- public void encodeDataAsAssressShouldSetSerialziedBitIfCompressed() {
- long expectedAddress = 549755813701L;
-
- Integer value = Integer.MAX_VALUE;
-
- byte[] valueInBytes = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(value).array();
- boolean isSerialized = false;
- boolean isCompressed = true;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(valueInBytes, isSerialized, isCompressed);
-
- assertThat(encodedAddress).isEqualTo(expectedAddress);
- assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
- }
-
- @Test
- public void encodeDataAsAssressShouldSetBothSerialziedAndCompressedBitsIfSerializedAndCompressed() {
- long expectedAddress = 63221918596951L;
-
- Integer value = Integer.MAX_VALUE;
-
- byte[] valueInBytes = EntryEventImpl.serialize(value);
- boolean isSerialized = true;
- boolean isCompressed = true;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(valueInBytes, isSerialized, isCompressed);
-
- assertThat(expectedAddress).isEqualTo(encodedAddress);
- assertSerializedAndCompressedBits(encodedAddress, isSerialized, isCompressed);
- }
-
- private void assertSerializedAndCompressedBits(long encodedAddress,
- boolean shouldSerializedBitBeSet, boolean shouldCompressedBitBeSet) {
- boolean isSerializedBitSet = (encodedAddress
- & OffHeapRegionEntryHelper.SERIALIZED_BIT) == OffHeapRegionEntryHelper.SERIALIZED_BIT ? true
- : false;
- boolean isCompressedBitSet = (encodedAddress
- & OffHeapRegionEntryHelper.COMPRESSED_BIT) == OffHeapRegionEntryHelper.COMPRESSED_BIT ? true
- : false;
-
- assertThat(isSerializedBitSet).isEqualTo(shouldSerializedBitBeSet);
- assertThat(isCompressedBitSet).isEqualTo(shouldCompressedBitBeSet);
- }
-
- @Test
- public void decodeUncompressedAddressToBytesShouldReturnActualBytes() {
- long encodedAddress = 549755813697L;
- Integer value = Integer.MAX_VALUE;
-
- byte[] actual = OffHeapRegionEntryHelper.decodeUncompressedAddressToBytes(encodedAddress);
- byte[] expectedValue = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(value).array();
-
- assertThat(actual).isEqualTo(expectedValue);
- }
-
- @Test
- public void decodeUncompressedAddressToBytesShouldDecodeLongIfItsSerializedAndIfItsNotTooBig() {
- Long value = 0L;
- long encodedAddress = 123L;
-
- byte[] actual = OffHeapRegionEntryHelper.decodeUncompressedAddressToBytes(encodedAddress);
- byte[] expectedValue = EntryEventImpl.serialize(value);
-
- assertThat(actual).isEqualTo(expectedValue);
- }
-
- @Test(expected = AssertionError.class)
- public void decodeUncompressedAddressToBytesWithCompressedAddressShouldThrowException() {
- long encodedAddress = 549755813703L;
- OffHeapRegionEntryHelper.decodeUncompressedAddressToBytes(encodedAddress);
- }
-
- @Test
- public void decodeCompressedDataAsAddressToRawBytes() {
- long encodedAddress = 549755813703L;
- byte[] expected = new byte[] {127, -1, -1, -1};
-
- byte[] bytes = OffHeapRegionEntryHelper.decodeAddressToRawBytes(encodedAddress);
-
- assertThat(bytes).isEqualTo(expected);
- }
-
- @Test
- public void encodedAddressShouldBeDecodableEvenIfValueIsSerialized() {
- Integer value = Integer.MAX_VALUE;
-
- byte[] serializedValue = EntryEventImpl.serialize(value);
- boolean isSerialized = true;
- boolean isCompressed = false;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(serializedValue, isSerialized, isCompressed);
-
- Integer actualValue = (Integer) OffHeapRegionEntryHelper.decodeAddressToObject(encodedAddress);
-
- assertThat(actualValue).isEqualTo(value);
- }
-
- @Test
- public void encodedAddressShouldBeDecodableEvenIfValueIsUnserialized() {
- Integer value = Integer.MAX_VALUE;
-
- byte[] unSerializedValue = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(value).array();
- boolean isSerialized = false;
- boolean isCompressed = false;
-
- long encodedAddress =
- OffHeapRegionEntryHelper.encodeDataAsAddress(unSerializedValue, isSerialized, isCompressed);
-
- byte[] actualValue = (byte[]) OffHeapRegionEntryHelper.decodeAddressToObject(encodedAddress);
-
- assertThat(actualValue).isEqualTo(unSerializedValue);
- }
-
- @Test
- public void isSerializedShouldReturnTrueIfSerialized() {
- assertThat(OffHeapRegionEntryHelper.isSerialized(1000010L)).isTrue();
- }
-
- @Test
- public void isSerializedShouldReturnFalseIfNotSerialized() {
- assertThat(OffHeapRegionEntryHelper.isSerialized(1000000L)).isFalse();
- }
-
- @Test
- public void isCompressedShouldReturnTrueIfCompressed() {
- assertThat(OffHeapRegionEntryHelper.isCompressed(1000100L)).isTrue();
- }
-
- @Test
- public void isCompressedShouldReturnFalseIfNotCompressed() {
- assertThat(OffHeapRegionEntryHelper.isCompressed(1000000L)).isFalse();
- }
-
- @Test
- public void isOffHeapShouldReturnTrueIfAddressIsOnOffHeap() {
- OffHeapStoredObject value = createChunk(Long.MAX_VALUE);
- assertThat(OffHeapRegionEntryHelper.isOffHeap(value.getAddress())).isTrue();
- }
-
- @Test
- public void isOffHeapShouldReturnFalseIfAddressIsAnEncodedAddress() {
- byte[] data =
- ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt((Integer) Integer.MAX_VALUE).array();
- long address = OffHeapRegionEntryHelper.encodeDataAsAddress(data, false, false);
- assertThat(OffHeapRegionEntryHelper.isOffHeap(address)).isFalse();
- }
-
- @Test
- public void isOffHeapShouldReturnFalseForAnyTokenAddress() {
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.NULL_ADDRESS)).isFalse();
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.INVALID_ADDRESS))
- .isFalse();
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.LOCAL_INVALID_ADDRESS))
- .isFalse();
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.DESTROYED_ADDRESS))
- .isFalse();
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.REMOVED_PHASE1_ADDRESS))
- .isFalse();
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.REMOVED_PHASE2_ADDRESS))
- .isFalse();
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.END_OF_STREAM_ADDRESS))
- .isFalse();
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.NOT_AVAILABLE_ADDRESS))
- .isFalse();
- assertThat(OffHeapRegionEntryHelper.isOffHeap(OffHeapRegionEntryHelper.TOMBSTONE_ADDRESS))
- .isFalse();
- }
-
- @Test
- public void setValueShouldChangeTheRegionEntryAddressToNewAddress() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
-
- // some old address
- long oldAddress = 1L;
-
- // testing when the newValue is a chunk
- OffHeapStoredObject newValue = createChunk(Long.MAX_VALUE);
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, newValue.getAddress())).thenReturn(Boolean.TRUE);
-
- // invoke the method under test
- OffHeapRegionEntryHelper.setValue(re, newValue);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, newValue.getAddress());
- // resetting the spy in-order to re-use
- reset(re);
-
- // testing when the newValue is DataAsAddress
- TinyStoredObject newAddress1 = new TinyStoredObject(2L);
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, newAddress1.getAddress())).thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, newAddress1);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, newAddress1.getAddress());
- reset(re);
-
- // Testing when newValue is Token Objects
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.NULL_ADDRESS)).thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, null);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.NULL_ADDRESS);
- reset(re);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.INVALID_ADDRESS))
- .thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, Token.INVALID);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.INVALID_ADDRESS);
- reset(re);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.LOCAL_INVALID_ADDRESS))
- .thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, Token.LOCAL_INVALID);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.LOCAL_INVALID_ADDRESS);
- reset(re);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.DESTROYED_ADDRESS))
- .thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, Token.DESTROYED);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.DESTROYED_ADDRESS);
- reset(re);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.REMOVED_PHASE1_ADDRESS))
- .thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, Token.REMOVED_PHASE1);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.REMOVED_PHASE1_ADDRESS);
- reset(re);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.REMOVED_PHASE2_ADDRESS))
- .thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, Token.REMOVED_PHASE2);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.REMOVED_PHASE2_ADDRESS);
- reset(re);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.END_OF_STREAM_ADDRESS))
- .thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, Token.END_OF_STREAM);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.END_OF_STREAM_ADDRESS);
- reset(re);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.NOT_AVAILABLE_ADDRESS))
- .thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, Token.NOT_AVAILABLE);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.NOT_AVAILABLE_ADDRESS);
- reset(re);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, OffHeapRegionEntryHelper.TOMBSTONE_ADDRESS))
- .thenReturn(Boolean.TRUE);
- OffHeapRegionEntryHelper.setValue(re, Token.TOMBSTONE);
-
- // verify oldAddress is replaced with newAddress
- verify(re, times(1)).setAddress(oldAddress, OffHeapRegionEntryHelper.TOMBSTONE_ADDRESS);
- reset(re);
- }
-
- @Test
- public void setValueShouldChangeTheRegionEntryAddressToNewAddressAndReleaseOldValueIfItsOnOffHeap() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
-
- OffHeapStoredObject oldValue = createChunk(Long.MAX_VALUE);
- OffHeapStoredObject newValue = createChunk(Long.MAX_VALUE - 1);
-
- // mock Chunk static methods - in-order to verify that release is called
- PowerMockito.spy(OffHeapStoredObject.class);
- PowerMockito.doNothing().when(OffHeapStoredObject.class);
- OffHeapStoredObject.release(oldValue.getAddress());
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldValue.getAddress());
- when(re.setAddress(oldValue.getAddress(), newValue.getAddress())).thenReturn(Boolean.TRUE);
-
- // invoke the method under test
- OffHeapRegionEntryHelper.setValue(re, newValue);
-
- // verify oldAddress is changed to newAddress
- verify(re, times(1)).setAddress(oldValue.getAddress(), newValue.getAddress());
-
- // verify oldAddress is released
- PowerMockito.verifyStatic(OffHeapStoredObject.class);
- OffHeapStoredObject.release(oldValue.getAddress());
- }
-
- @Test
- public void setValueShouldChangeTheRegionEntryAddressToNewAddressAndDoesNothingIfOldAddressIsAnEncodedAddress() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
-
- byte[] oldData =
- ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt((Integer) Integer.MAX_VALUE).array();
- long oldAddress = OffHeapRegionEntryHelper.encodeDataAsAddress(oldData, false, false);
-
- byte[] newData = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE)
- .putInt((Integer) Integer.MAX_VALUE - 1).array();
- TinyStoredObject newAddress =
- new TinyStoredObject(OffHeapRegionEntryHelper.encodeDataAsAddress(newData, false, false));
-
- // mock Chunk static methods - in-order to verify that release is never called
- PowerMockito.spy(OffHeapStoredObject.class);
- PowerMockito.doNothing().when(OffHeapStoredObject.class);
- OffHeapStoredObject.release(oldAddress);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, newAddress.getAddress())).thenReturn(Boolean.TRUE);
-
- // invoke the method under test
- OffHeapRegionEntryHelper.setValue(re, newAddress);
-
- // verify oldAddress is changed to newAddress
- verify(re, times(1)).setAddress(oldAddress, newAddress.getAddress());
-
- // verify that release is never called as the old address is not on offheap
- PowerMockito.verifyStatic(OffHeapStoredObject.class, never());
- OffHeapStoredObject.release(oldAddress);
- }
-
- @Test
- public void setValueShouldChangeTheRegionEntryAddressToNewAddressAndDoesNothingIfOldAddressIsATokenAddress() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
-
- long oldAddress = OffHeapRegionEntryHelper.REMOVED_PHASE1_ADDRESS;
-
- Token newValue = Token.REMOVED_PHASE2;
- long newAddress = OffHeapRegionEntryHelper.REMOVED_PHASE2_ADDRESS;
-
- // mock Chunk static methods - in-order to verify that release is never called
- PowerMockito.spy(OffHeapStoredObject.class);
- PowerMockito.doNothing().when(OffHeapStoredObject.class);
- OffHeapStoredObject.release(oldAddress);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(oldAddress);
- when(re.setAddress(oldAddress, newAddress)).thenReturn(Boolean.TRUE);
-
- // invoke the method under test
- OffHeapRegionEntryHelper.setValue(re, newValue);
-
- // verify oldAddress is changed to newAddress
- verify(re, times(1)).setAddress(oldAddress, newAddress);
-
- // verify that release is never called as the old address is not on offheap
- PowerMockito.verifyStatic(OffHeapStoredObject.class, never());
- OffHeapStoredObject.release(oldAddress);
- }
-
- @Test(expected = IllegalStateException.class)
- public void setValueShouldThrowIllegalExceptionIfNewValueCannotBeConvertedToAddress() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(1L);
-
- // invoke the method under test with some object other than Chunk/DataAsAddress/Token
- OffHeapRegionEntryHelper.setValue(re, new Object());
- }
-
- @Test
- public void getValueAsTokenShouldReturnNotATokenIfValueIsOnOffHeap() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
-
- OffHeapStoredObject chunk = createChunk(Long.MAX_VALUE);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(chunk.getAddress());
- Token token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.NOT_A_TOKEN);
- }
-
- @Test
- public void getValueAsTokenShouldReturnNotATokenIfValueIsEncoded() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
-
- byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
- long address = OffHeapRegionEntryHelper.encodeDataAsAddress(data, false, false);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(address);
- Token token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.NOT_A_TOKEN);
- }
-
- @Test
- public void getValueAsTokenShouldReturnAValidToken() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.NULL_ADDRESS);
- Token token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isNull();
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.INVALID_ADDRESS);
- token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.INVALID);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.LOCAL_INVALID_ADDRESS);
- token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.LOCAL_INVALID);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.DESTROYED_ADDRESS);
- token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.DESTROYED);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.REMOVED_PHASE1_ADDRESS);
- token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.REMOVED_PHASE1);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.REMOVED_PHASE2_ADDRESS);
- token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.REMOVED_PHASE2);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.END_OF_STREAM_ADDRESS);
- token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.END_OF_STREAM);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.NOT_AVAILABLE_ADDRESS);
- token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.NOT_AVAILABLE);
-
- // mock region entry methods required for test
- when(re.getAddress()).thenReturn(OffHeapRegionEntryHelper.TOMBSTONE_ADDRESS);
- token = OffHeapRegionEntryHelper.getValueAsToken(re);
-
- assertThat(token).isEqualTo(Token.TOMBSTONE);
- }
-
- @Test
- public void addressToObjectShouldReturnValueFromChunk() {
- OffHeapStoredObject expected = createChunk(Long.MAX_VALUE);
- Object actual = OffHeapRegionEntryHelper.addressToObject(expected.getAddress(), false, null);
-
- assertThat(actual).isInstanceOf(OffHeapStoredObject.class);
- assertThat(actual).isEqualTo(expected);
- }
-
- @Test
- public void addressToObjectShouldReturnCachedDeserializableFromChunkIfAskedToDecompress() {
- byte[] data = EntryEventImpl.serialize(Long.MAX_VALUE);
- boolean isSerialized = true;
- boolean isCompressed = true;
-
- OffHeapStoredObject chunk =
- (OffHeapStoredObject) ma.allocateAndInitialize(data, isSerialized, isCompressed);
-
- // create the mock context
- RegionEntryContext regionContext = mock(RegionEntryContext.class);
- CachePerfStats cacheStats = mock(CachePerfStats.class);
- Compressor compressor = mock(Compressor.class);
-
- long startTime = 10000L;
-
- // mock required things
- when(regionContext.getCompressor()).thenReturn(compressor);
- when(compressor.decompress(data)).thenReturn(data);
- when(regionContext.getCachePerfStats()).thenReturn(cacheStats);
- when(cacheStats.startDecompression()).thenReturn(startTime);
-
- Object actual =
- OffHeapRegionEntryHelper.addressToObject(chunk.getAddress(), true, regionContext);
-
- assertThat(actual).isInstanceOf(VMCachedDeserializable.class);
-
- Long actualValue = (Long) ((VMCachedDeserializable) actual).getDeserializedForReading();
- assertThat(actualValue).isEqualTo(Long.MAX_VALUE);
- }
-
- @Test
- public void addressToObjectShouldReturnDecompressedValueFromChunkIfAskedToDecompress() {
- byte[] data = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(Long.MAX_VALUE).array();
- boolean isSerialized = false;
- boolean isCompressed = true;
-
- OffHeapStoredObject chunk =
- (OffHeapStoredObject) ma.allocateAndInitialize(data, isSerialized, isCompressed);
-
- // create the mock context
- RegionEntryContext regionContext = mock(RegionEntryContext.class);
- CachePerfStats cacheStats = mock(CachePerfStats.class);
- Compressor compressor = mock(Compressor.class);
-
- long startTime = 10000L;
-
- // mock required things
- when(regionContext.getCompressor()).thenReturn(compressor);
- when(compressor.decompress(data)).thenReturn(data);
- when(regionContext.getCachePerfStats()).thenReturn(cacheStats);
- when(cacheStats.startDecompression()).thenReturn(startTime);
-
- Object actual =
- OffHeapRegionEntryHelper.addressToObject(chunk.getAddress(), true, regionContext);
-
- assertThat(actual).isInstanceOf(byte[].class);
- assertThat(actual).isEqualTo(data);
- }
-
- @Test
- public void addressToObjectShouldReturnValueFromDataAsAddress() {
- byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
- long address = OffHeapRegionEntryHelper.encodeDataAsAddress(data, false, false);
-
- TinyStoredObject expected = new TinyStoredObject(address);
- Object actual = OffHeapRegionEntryHelper.addressToObject(address, false, null);
-
- assertThat(actual).isInstanceOf(TinyStoredObject.class);
- assertThat(actual).isEqualTo(expected);
- }
-
- @Test
- public void addressToObjectShouldReturnCachedDeserializableFromSerializedDataAsAddressIfAskedToDecompress() {
- byte[] data = EntryEventImpl.serialize(Integer.MAX_VALUE);
- boolean isSerialized = true;
- boolean isCompressed = true;
-
- long address = OffHeapRegionEntryHelper.encodeDataAsAddress(data, isSerialized, isCompressed);
-
- // create the mock context
- RegionEntryContext regionContext = mock(RegionEntryContext.class);
- CachePerfStats cacheStats = mock(CachePerfStats.class);
- Compressor compressor = mock(Compressor.class);
-
- long startTime = 10000L;
-
- // mock required things
- when(regionContext.getCompressor()).thenReturn(compressor);
- when(compressor.decompress(data)).thenReturn(data);
- when(regionContext.getCachePerfStats()).thenReturn(cacheStats);
- when(cacheStats.startDecompression()).thenReturn(startTime);
-
- Object actual = OffHeapRegionEntryHelper.addressToObject(address, true, regionContext);
-
- assertThat(actual).isInstanceOf(VMCachedDeserializable.class);
-
- Integer actualValue = (Integer) ((VMCachedDeserializable) actual).getDeserializedForReading();
- assertThat(actualValue).isEqualTo(Integer.MAX_VALUE);
- }
-
- @Test
- public void addressToObjectShouldReturnDecompressedValueFromDataAsAddressIfAskedToDecompress() {
- byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
- boolean isSerialized = false;
- boolean isCompressed = true;
-
- long address = OffHeapRegionEntryHelper.encodeDataAsAddress(data, isSerialized, isCompressed);
-
- // create the mock context
- RegionEntryContext regionContext = mock(RegionEntryContext.class);
- CachePerfStats cacheStats = mock(CachePerfStats.class);
- Compressor compressor = mock(Compressor.class);
-
- long startTime = 10000L;
-
- // mock required things
- when(regionContext.getCompressor()).thenReturn(compressor);
- when(compressor.decompress(data)).thenReturn(data);
- when(regionContext.getCachePerfStats()).thenReturn(cacheStats);
- when(cacheStats.startDecompression()).thenReturn(startTime);
-
- Object actual = OffHeapRegionEntryHelper.addressToObject(address, true, regionContext);
-
- assertThat(actual).isInstanceOf(byte[].class);
- assertThat(actual).isEqualTo(data);
- }
-
- @Test
- public void addressToObjectShouldReturnToken() {
- Token token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.NULL_ADDRESS, false, null);
- assertThat(token).isNull();
-
- token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.INVALID_ADDRESS, false, null);
- assertThat(token).isEqualTo(Token.INVALID);
-
- token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.LOCAL_INVALID_ADDRESS, false, null);
- assertThat(token).isEqualTo(Token.LOCAL_INVALID);
-
- token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.DESTROYED_ADDRESS, false, null);
- assertThat(token).isEqualTo(Token.DESTROYED);
-
- token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.REMOVED_PHASE1_ADDRESS, false, null);
- assertThat(token).isEqualTo(Token.REMOVED_PHASE1);
-
- token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.REMOVED_PHASE2_ADDRESS, false, null);
- assertThat(token).isEqualTo(Token.REMOVED_PHASE2);
-
- token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.END_OF_STREAM_ADDRESS, false, null);
- assertThat(token).isEqualTo(Token.END_OF_STREAM);
-
- token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.NOT_AVAILABLE_ADDRESS, false, null);
- assertThat(token).isEqualTo(Token.NOT_AVAILABLE);
-
- token = (Token) OffHeapRegionEntryHelper
- .addressToObject(OffHeapRegionEntryHelper.TOMBSTONE_ADDRESS, false, null);
- assertThat(token).isEqualTo(Token.TOMBSTONE);
- }
-
- @Test
- public void getSerializedLengthFromDataAsAddressShouldReturnValidLength() {
- byte[] data = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(Integer.MAX_VALUE).array();
- boolean isSerialized = false;
- boolean isCompressed = true;
-
- long address = OffHeapRegionEntryHelper.encodeDataAsAddress(data, isSerialized, isCompressed);
- TinyStoredObject daa = new TinyStoredObject(address);
-
- int actualLength = OffHeapRegionEntryHelper.getSerializedLength(daa);
-
- assertThat(actualLength).isEqualTo(data.length);
- }
-
- @Test
- public void getSerializedLengthFromDataAsAddressShouldReturnZeroForNonEncodedAddress() {
- TinyStoredObject nonEncodedAddress = new TinyStoredObject(100000L);
- int actualLength = OffHeapRegionEntryHelper.getSerializedLength(nonEncodedAddress);
- assertThat(actualLength).isZero();
- }
-
- @Test
- public void releaseEntryShouldSetValueToRemovePhase2() {
- // mock region entry
- OffHeapRegionEntry re = mock(OffHeapRegionEntry.class);
- when(re.getAddress()).thenReturn(1L);
- when(re.setAddress(1L, OffHeapRegionEntryHelper.REMOVED_PHASE2_ADDRESS))
- .thenReturn(Boolean.TRUE);
-
- // mock required methods
- PowerMockito.spy(OffHeapRegionEntryHelper.class);
- PowerMockito.doNothing().when(OffHeapRegionEntryHelper.class);
- OffHeapRegionEntryHelper.setValue(re, Token.REMOVED_PHASE2);
-
- OffHeapRegionEntryHelper.releaseEntry(re);
-
- PowerMockito.verifyStatic(OffHeapRegionEntryHelper.class);
- OffHeapRegionEntryHelper.setValue(re, Token.REMOVED_PHASE2);
- }
-
- @Test
- public void releaseEntryShouldSetValueToRemovePhase2AndSetsAsyncToFalseForDiskEntry() {
- // mock region entry
- OffHeapRegionEntry re = mock(VersionedStatsDiskRegionEntryOffHeap.class);
- when(re.getAddress()).thenReturn(1L);
- when(re.setAddress(1L, OffHeapRegionEntryHelper.REMOVED_PHASE2_ADDRESS))
- .thenReturn(Boolean.TRUE);
-
- DiskId spy = Mockito.spy(DiskId.class);
- when(((DiskEntry) re).getDiskId()).thenReturn(spy);
- when(spy.isPendingAsync()).thenReturn(Boolean.TRUE);
-
- // mock required methods
- PowerMockito.spy(OffHeapRegionEntryHelper.class);
- PowerMockito.doNothing().when(OffHeapRegionEntryHelper.class);
- OffHeapRegionEntryHelper.setValue(re, Token.REMOVED_PHASE2);
-
- OffHeapRegionEntryHelper.releaseEntry(re);
-
- verify(spy, times(1)).setPendingAsync(Boolean.FALSE);
-
- PowerMockito.verifyStatic(OffHeapRegionEntryHelper.class);
- OffHeapRegionEntryHelper.setValue(re, Token.REMOVED_PHASE2);
- }
-
- @Test
- public void doWithOffHeapClearShouldSetTheThreadLocalToTrue() {
- // verify that threadlocal is not set
- assertThat(OffHeapRegionEntryHelper.doesClearNeedToCheckForOffHeap()).isFalse();
-
- OffHeapRegionEntryHelper.doWithOffHeapClear(new Runnable() {
- @Override
- public void run() {
- // verify that threadlocal is set when offheap is cleared
- assertThat(OffHeapRegionEntryHelper.doesClearNeedToCheckForOffHeap()).isTrue();
- }
- });
-
- // verify that threadlocal is reset after offheap is cleared
- assertThat(OffHeapRegionEntryHelper.doesClearNeedToCheckForOffHeap()).isFalse();
- }
-}
diff --git a/geode-core/src/test/java/org/apache/geode/internal/offheap/ReferenceCountHelperImplTest.java b/geode-core/src/test/java/org/apache/geode/internal/offheap/ReferenceCountHelperImplTest.java
index 4ee1356..28d0732 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/offheap/ReferenceCountHelperImplTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/offheap/ReferenceCountHelperImplTest.java
@@ -12,976 +12,966 @@
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
-
package org.apache.geode.internal.offheap;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.geode.util.internal.UncheckedUtils.uncheckedCast;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
-import org.junit.Rule;
+import org.junit.Before;
import org.junit.Test;
-import org.junit.contrib.java.lang.system.SystemOutRule;
-import org.junit.runner.RunWith;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
import org.apache.geode.internal.cache.RegionEntry;
-/*
- * PowerMock used in this test to verify static method MemoryAllocatorImpl.debugLog
- */
-@RunWith(PowerMockRunner.class)
-@PowerMockIgnore({"*.UnitTest"})
-@PrepareForTest({MemoryAllocatorImpl.class})
public class ReferenceCountHelperImplTest {
- ReferenceCountHelperImpl rchi;
+ private BiConsumer<String, Boolean> debugLogger;
- @Rule
- public SystemOutRule sor = new SystemOutRule();
+ @Before
+ public void setUp() {
+ debugLogger = uncheckedCast(mock(BiConsumer.class));
+ }
@Test
public void doTrackReferenceCountsWithTrackRefsTrueAndTrackFreesTrue() {
- rchi = getTrueTrue();
- assertTrue(rchi.trackReferenceCounts());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
+ assertThat(referenceCountHelperImpl.trackReferenceCounts()).isTrue();
}
@Test
public void doTrackReferenceCountsWithTrackRefsTrueAndTrackFreesFalse() {
- rchi = getTrueFalse();
- assertTrue(rchi.trackReferenceCounts());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
+ assertThat(referenceCountHelperImpl.trackReferenceCounts()).isTrue();
}
@Test
public void doTrackReferenceCountsWithTrackRefsFalseAndTrackFreesTrue() {
- rchi = getFalseTrue();
- assertFalse(rchi.trackReferenceCounts());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
+ assertThat(referenceCountHelperImpl.trackReferenceCounts()).isFalse();
}
@Test
public void doTrackReferenceCountsWithTrackRefsFalseAndTrackFreesFalse() {
- rchi = getFalseFalse();
- assertFalse(rchi.trackReferenceCounts());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
+ assertThat(referenceCountHelperImpl.trackReferenceCounts()).isFalse();
}
@Test
public void doTrackFreedReferenceCountsWithTrackRefsTrueAndTrackFreesTrue() {
- rchi = getTrueTrue();
- assertTrue(rchi.trackFreedReferenceCounts());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
+ assertThat(referenceCountHelperImpl.trackFreedReferenceCounts()).isTrue();
}
@Test
public void doTrackFreedReferenceCountsWithTrackRefsTrueAndTrackFreesFalse() {
- rchi = getTrueFalse();
- assertFalse(rchi.trackFreedReferenceCounts());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
+ assertThat(referenceCountHelperImpl.trackFreedReferenceCounts()).isFalse();
}
@Test
public void doTrackFreedReferenceCountsWithTrackRefsFalseAndTrackFreesTrue() {
- rchi = getFalseTrue();
- assertTrue(rchi.trackFreedReferenceCounts());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
+ assertThat(referenceCountHelperImpl.trackFreedReferenceCounts()).isTrue();
}
@Test
public void doTrackFreedReferenceCountsWithTrackRefsFalseAndTrackFreesFalse() {
- rchi = getFalseFalse();
- assertFalse(rchi.trackFreedReferenceCounts());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
+ assertThat(referenceCountHelperImpl.trackFreedReferenceCounts()).isFalse();
}
@Test
public void doSkipRefCountTrackingWithTrackRefsTrueAndTrackFreesTrue() {
- rchi = getTrueTrue();
- Object preOwner = rchi.getReferenceCountOwner();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
- rchi.skipRefCountTracking();
- Object postOwner = rchi.getReferenceCountOwner();
+ Object preOwner = referenceCountHelperImpl.getReferenceCountOwner();
+ referenceCountHelperImpl.skipRefCountTracking();
+ Object postOwner = referenceCountHelperImpl.getReferenceCountOwner();
- assertTrue(postOwner != preOwner); // skip sets owner to SKIP_REF_COUNT_TRACKING
-
- assertFalse(rchi.isRefCountTracking());
+ // skip sets owner to SKIP_REF_COUNT_TRACKING
+ assertThat(postOwner).isNotEqualTo(preOwner);
+ assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- rchi.unskipRefCountTracking();
- postOwner = rchi.getReferenceCountOwner();
- assertEquals(postOwner, preOwner);
+ referenceCountHelperImpl.unskipRefCountTracking();
+ postOwner = referenceCountHelperImpl.getReferenceCountOwner();
- assertTrue(rchi.isRefCountTracking());
+ assertThat(preOwner).isEqualTo(postOwner);
+ assertThat(referenceCountHelperImpl.isRefCountTracking()).isTrue();
}
@Test
public void doSkipRefCountTrackingWithTrackRefsFalseAndTrackFreesTrue() {
- rchi = getFalseTrue();
- Object preOwner = rchi.getReferenceCountOwner();
- assertEquals(null, preOwner); // getReferenceCountOwner returns null if not tracking
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
+ Object preOwner = referenceCountHelperImpl.getReferenceCountOwner();
+ // getReferenceCountOwner returns null if not tracking
+ assertThat(preOwner).isNull();
- rchi.skipRefCountTracking();
- assertFalse(rchi.isRefCountTracking());
+ referenceCountHelperImpl.skipRefCountTracking();
+ assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
- rchi.unskipRefCountTracking();
- assertFalse(rchi.isRefCountTracking()); // system prop not set
+ referenceCountHelperImpl.unskipRefCountTracking();
+ assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse(); // system prop not set
}
@Test
public void doSkipRefCountTrackingWithTrackRefsFalseAndTrackFreesFalse() {
- rchi = getFalseFalse();
- Object preOwner = rchi.getReferenceCountOwner();
- assertEquals(null, preOwner); // getReferenceCountOwner returns null if not tracking
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
+ Object preOwner = referenceCountHelperImpl.getReferenceCountOwner();
+ // getReferenceCountOwner returns null if not tracking
+ assertThat(preOwner).isNull();
- rchi.skipRefCountTracking();
- assertFalse(rchi.isRefCountTracking());
+ referenceCountHelperImpl.skipRefCountTracking();
+ assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
- rchi.unskipRefCountTracking();
- assertFalse(rchi.isRefCountTracking()); // system prop not set
+ referenceCountHelperImpl.unskipRefCountTracking();
+ // system prop not set
+ assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
}
@Test
public void doSkipRefCountTrackingWithTrackRefsTrueAndTrackFreesFalse() {
- rchi = getTrueFalse();
- Object preOwner = rchi.getReferenceCountOwner();
-
- rchi.skipRefCountTracking();
- Object postOwner = rchi.getReferenceCountOwner();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
- assertTrue(postOwner != preOwner); // skip sets owner to SKIP_REF_COUNT_TRACKING
+ Object preOwner = referenceCountHelperImpl.getReferenceCountOwner();
+ referenceCountHelperImpl.skipRefCountTracking();
+ Object postOwner = referenceCountHelperImpl.getReferenceCountOwner();
+ // skip sets owner to SKIP_REF_COUNT_TRACKING
+ assertThat(postOwner).isNotEqualTo(preOwner);
+ assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
- assertFalse(rchi.isRefCountTracking());
-
- rchi.unskipRefCountTracking();
- postOwner = rchi.getReferenceCountOwner();
- assertEquals(postOwner, preOwner);
-
- assertTrue(rchi.isRefCountTracking());
+ referenceCountHelperImpl.unskipRefCountTracking();
+ postOwner = referenceCountHelperImpl.getReferenceCountOwner();
+ assertThat(preOwner).isEqualTo(postOwner);
+ assertThat(referenceCountHelperImpl.isRefCountTracking()).isTrue();
}
@Test
public void doSetReferenceCountOwnerWithTrackRefsTrueAndTrackFreesTrue() {
- rchi = getTrueTrue();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
String owner = null;
- rchi.setReferenceCountOwner(owner);
- AtomicInteger ai = rchi.getReenterCount();
- assertEquals(0, ai.get());
-
- owner = new String("SomeOwner");
- rchi.setReferenceCountOwner(owner);
- ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), owner);
-
- String owner2 = new String("SomeOwner2");
- rchi.setReferenceCountOwner(owner2);
- ai = rchi.getReenterCount();
- assertEquals(2, ai.get());
- assertTrue(rchi.getReferenceCountOwner() != owner2); // stays original owner until cnt = 0
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isZero();
+
+ owner = "SomeOwner";
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
+
+ String owner2 = "SomeOwner2";
+ referenceCountHelperImpl.setReferenceCountOwner(owner2);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isEqualTo(2);
+ // stays original owner until cnt = 0
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNotEqualTo(owner2);
String owner3 = null;
- rchi.setReferenceCountOwner(owner3);
- ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), owner);
+ referenceCountHelperImpl.setReferenceCountOwner(owner3);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
owner = null;
- rchi.setReferenceCountOwner(owner);
- ai = rchi.getReenterCount();
- assertEquals(0, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), null);
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isZero();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
- RegionEntry re = mock(RegionEntry.class);
- rchi.setReferenceCountOwner(re);
- ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), re);
+ RegionEntry regionEntry = mock(RegionEntry.class);
+ referenceCountHelperImpl.setReferenceCountOwner(regionEntry);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
+ assertThat(regionEntry).isEqualTo(referenceCountHelperImpl.getReferenceCountOwner());
Long address = (long) 0x1000;
boolean decRefCount = false;
int rc = 1;
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- RefCountChangeInfo rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, decRefCount, rc);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, decRefCount, rc);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
-
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(0, list.size());
+ referenceCountHelperImpl.refCountChanged(address, decRefCount, rc);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
+ referenceCountHelperImpl.refCountChanged(address, decRefCount, rc);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isEmpty();
}
@Test
public void doSetReferenceCountOwnerWithTrackRefsFalseAndTrackFreesTrue() {
- rchi = getFalseTrue();
- String owner = null;
- rchi.setReferenceCountOwner(owner);
- assertEquals(rchi.getReferenceCountOwner(), owner);
- AtomicInteger ai = rchi.getReenterCount();
- assertEquals(null, ai);
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
+
+ referenceCountHelperImpl.setReferenceCountOwner(null);
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
+
+ AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount).isNull();
}
@Test
public void doSetReferenceCountOwnerWithTrackRefsFalseAndTrackFreesFalse() {
- rchi = getFalseFalse();
- String owner = null;
- rchi.setReferenceCountOwner(owner);
- assertEquals(rchi.getReferenceCountOwner(), owner);
- AtomicInteger ai = rchi.getReenterCount();
- assertEquals(null, ai);
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
+
+ referenceCountHelperImpl.setReferenceCountOwner(null);
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
+
+ AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount).isNull();
}
@Test
public void doSetReferenceCountOwnerWithTrackRefsTrueAndTrackFreesFalse() {
- rchi = getTrueFalse();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
+
String owner = null;
- rchi.setReferenceCountOwner(owner);
- AtomicInteger ai = rchi.getReenterCount();
- assertEquals(0, ai.get());
-
- owner = new String("SomeOwner");
- rchi.setReferenceCountOwner(owner);
- ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), owner);
-
- String owner2 = new String("SomeOwner2");
- rchi.setReferenceCountOwner(owner2);
- ai = rchi.getReenterCount();
- assertEquals(2, ai.get());
- assertTrue(rchi.getReferenceCountOwner() != owner2); // stays original owner until cnt = 0
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isZero();
+
+ owner = "SomeOwner";
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
+
+ String owner2 = "SomeOwner2";
+ referenceCountHelperImpl.setReferenceCountOwner(owner2);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isEqualTo(2);
+ // stays original owner until cnt = 0
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
String owner3 = null;
- rchi.setReferenceCountOwner(owner3);
- ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), owner);
+ referenceCountHelperImpl.setReferenceCountOwner(owner3);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
owner = null;
- rchi.setReferenceCountOwner(owner);
- ai = rchi.getReenterCount();
- assertEquals(0, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), null);
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isZero();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
}
@Test
public void doCreateReferenceCountOwnerWithTrackRefsTrueAndTrackFreesTrue() {
- rchi = getTrueTrue();
- Object owner = rchi.createReferenceCountOwner();
- assertFalse(owner == null);
- AtomicInteger ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
+
+ Object owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNotNull();
+ AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
owner = null;
- rchi.setReferenceCountOwner(owner);
- ai = rchi.getReenterCount();
- assertEquals(0, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), null);
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isZero();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
}
@Test
public void doCreateReferenceCountOwnerWithTrackRefsFalseAndTrackFreesTrue() {
- rchi = getFalseTrue();
- Object owner = rchi.createReferenceCountOwner();
- assertTrue(owner == null);
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
+ Object owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNull();
}
@Test
public void doCreateReferenceCountOwnerWithTrackRefsFalseAndTrackFreesFalse() {
- rchi = getFalseFalse();
- Object owner = rchi.createReferenceCountOwner();
- assertTrue(owner == null);
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
+ Object owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNull();
}
@Test
public void doCreateReferenceCountOwnerWithTrackRefsTrueAndTrackFreesFalse() {
- rchi = getTrueFalse();
- Object owner = rchi.createReferenceCountOwner();
- assertFalse(owner == null);
- AtomicInteger ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
+ Object owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNotNull();
+ AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
owner = null;
- rchi.setReferenceCountOwner(owner);
- ai = rchi.getReenterCount();
- assertEquals(0, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), null);
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isZero();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
}
@Test
public void doRefCountChangedNoOwnerWithTrackRefsTrueAndTrackFreesTrue() {
- rchi = getTrueTrue();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
- rchi.freeRefCountInfo(address); // quick check of free of nonexistent info
+ // quick check of free of nonexistent info
+ referenceCountHelperImpl.freeRefCountInfo(address);
+ Object owner = referenceCountHelperImpl.getReferenceCountOwner();
+ assertThat(owner).isNull();
- Object owner = rchi.getReferenceCountOwner();
- assertTrue(owner == null);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- RefCountChangeInfo rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(2, list.size()); // inc and dec are tracked in different changeinfo objects (?)
- rcci = list.get(1);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
+
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // inc and dec are tracked in different changeinfo objects (?)
+ assertThat(list).hasSize(2);
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(2, list.size());
- rcci = list.get(1);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ refCountChangeInfo = list.get(1);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- list = rchi.peekRefCountInfo(address);
- assertEquals(2, list.size()); // list contains 2 entries from inc/dec done above
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(2);
- List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // no freeRefCountInfo calls yet
+ refCountChangeInfo = list.get(1);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- rchi.freeRefCountInfo(address); // when freed, moved to FreeRefCountInfo list
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // list contains 2 entries from inc/dec done above
+ assertThat(list).hasSize(2);
- List<RefCountChangeInfo> freeInfo2 = rchi.getFreeRefCountInfo(address);
- assertEquals(2, freeInfo2.size()); // the inc/dec info moved to freeRefCountInfo list
+ List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // no freeRefCountInfo calls yet
+ assertThat(freeInfo).isNull();
- list = rchi.getRefCountInfo(address);
- assertEquals(null, list); // the inc/dec ref count list should now be null
+ // when freed, moved to FreeRefCountInfo list
+ referenceCountHelperImpl.freeRefCountInfo(address);
+ List<RefCountChangeInfo> freeInfo2 = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // the inc/dec info moved to freeRefCountInfo list
+ assertThat(freeInfo2).hasSize(2);
+
+ list = referenceCountHelperImpl.getRefCountInfo(address);
+ // the inc/dec ref count list should now be null
+ assertThat(list).isNull();
}
@Test
public void doRefCountChangedNoOwnerWithTrackRefsFalseAndTrackFreesTrue() {
-
- rchi = getFalseTrue();
-
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
-
- Object owner = rchi.getReferenceCountOwner();
- assertTrue(owner == null);
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ Object owner = referenceCountHelperImpl.getReferenceCountOwner();
+ assertThat(owner).isNull();
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // no freeRefCountInfo calls yet
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- rchi.freeRefCountInfo(address); // noop when not tracking
+ List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // no freeRefCountInfo calls yet
+ assertThat(freeInfo).isNull();
- freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // should still be null
+ // noop when not tracking
+ referenceCountHelperImpl.freeRefCountInfo(address);
+ freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // should still be null
+ assertThat(freeInfo).isNull();
}
@Test
public void doRefCountChangedNoOwnerWithTrackRefsFalseAndTrackFreesFalse() {
-
- rchi = getFalseFalse();
-
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
- Object owner = rchi.getReferenceCountOwner();
- assertTrue(owner == null);
+ Object owner = referenceCountHelperImpl.getReferenceCountOwner();
+ assertThat(owner).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
-
- List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // no freeRefCountInfo calls yet
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- rchi.freeRefCountInfo(address); // noop when not tracking
+ List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // no freeRefCountInfo calls yet
+ assertThat(freeInfo).isNull();
- freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // should still be null
+ // noop when not tracking
+ referenceCountHelperImpl.freeRefCountInfo(address);
+ // should still be null
+ freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ assertThat(freeInfo).isNull();
}
@Test
public void doRefCountChangedNoOwnerWithTrackRefsTrueAndTrackFreesFalse() {
- rchi = getTrueFalse();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
- Object owner = rchi.getReferenceCountOwner();
- assertTrue(owner == null);
+ Object owner = referenceCountHelperImpl.getReferenceCountOwner();
+ assertThat(owner).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- RefCountChangeInfo rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(2, list.size()); // inc and dec are tracked in different changeinfo objects (?)
- rcci = list.get(1);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // inc and dec are tracked in different changeinfo objects (?)
+ assertThat(list).hasSize(2);
+ refCountChangeInfo = list.get(1);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(2, list.size());
- rcci = list.get(1);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(2);
+ refCountChangeInfo = list.get(1);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- list = rchi.peekRefCountInfo(address);
- assertEquals(2, list.size()); // list contains 2 entries from inc/dec done above
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // list contains 2 entries from inc/dec done above
+ assertThat(list).hasSize(2);
- List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // no freeRefCountInfo calls yet
+ List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // no freeRefCountInfo calls yet
+ assertThat(freeInfo).isNull();
- rchi.freeRefCountInfo(address); // when freed, moved to FreeRefCountInfo list
+ // when freed, moved to FreeRefCountInfo list
+ referenceCountHelperImpl.freeRefCountInfo(address);
- List<RefCountChangeInfo> freeInfo2 = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo2); // not tracking freed info
+ List<RefCountChangeInfo> freeInfo2 = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // not tracking freed info
+ assertThat(freeInfo2).isNull();
- list = rchi.getRefCountInfo(address);
- assertEquals(null, list); // the inc/dec ref count list should now be null
+ list = referenceCountHelperImpl.getRefCountInfo(address);
+ // the inc/dec ref count list should now be null
+ assertThat(list).isNull();
}
@Test
public void doRefCountChangedWithOwnerWithTrackRefsTrueAndTrackFreesTrue() {
- rchi = getTrueTrue();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
- Object owner = rchi.createReferenceCountOwner();
- assertFalse(owner == null);
+ Object owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNotNull();
- AtomicInteger ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
+ AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
owner = null;
- rchi.setReferenceCountOwner(owner);
- ai = rchi.getReenterCount();
- assertEquals(0, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), null);
-
- owner = rchi.createReferenceCountOwner();
- assertFalse(owner == null);
-
- ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
-
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- RefCountChangeInfo rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
-
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isZero();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size()); // inc and dec are tracked in different changeinfo objects (?)
- rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNotNull();
+
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
+
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
+
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.getRefCountInfo(address);
- assertEquals(0, list.size());
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // inc and dec are tracked in different changeinfo objects (?)
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
+
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.getRefCountInfo(address);
+ assertThat(list).isEmpty();
}
@Test
public void doRefCountChangedWithOwnerWithTrackRefsFalseAndTrackFreesTrue() {
-
- rchi = getFalseTrue();
-
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
- Object owner = rchi.createReferenceCountOwner();
- assertTrue(owner == null);
+ Object owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list); // inc and dec are tracked in different changeinfo objects (?)
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // inc and dec are tracked in different changeinfo objects (?)
+ assertThat(list).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // no freeRefCountInfo calls yet
+ List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // no freeRefCountInfo calls yet
+ assertThat(freeInfo).isNull();
- rchi.freeRefCountInfo(address); // when freed, moved to FreeRefCountInfo list
+ // when freed, moved to FreeRefCountInfo list
+ referenceCountHelperImpl.freeRefCountInfo(address);
- freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // the inc/dec info moved to freeRefCountInfo list
+ freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // the inc/dec info moved to freeRefCountInfo list
+ assertThat(freeInfo).isNull();
}
@Test
public void doRefCountChangedWithOwnerWithTrackRefsFalseAndTrackFreesFalse() {
-
- rchi = getFalseFalse();
-
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
- Object owner = rchi.createReferenceCountOwner();
- assertTrue(owner == null);
+ Object owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list); // inc and dec are tracked in different changeinfo objects (?)
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // inc and dec are tracked in different changeinfo objects (?)
+ assertThat(list).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // no freeRefCountInfo calls yet
+ List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // no freeRefCountInfo calls yet
+ assertThat(freeInfo).isNull();
- rchi.freeRefCountInfo(address); // when freed, moved to FreeRefCountInfo list
+ // when freed, moved to FreeRefCountInfo list
+ referenceCountHelperImpl.freeRefCountInfo(address);
- freeInfo = rchi.getFreeRefCountInfo(address);
- assertEquals(null, freeInfo); // the inc/dec info moved to freeRefCountInfo list
+ freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
+ // the inc/dec info moved to freeRefCountInfo list
+ assertThat(freeInfo).isNull();
}
@Test
public void doRefCountChangedWithOwnerWithTrackRefsTrueAndTrackFreesFalse() {
- rchi = getTrueFalse();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
Long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
- Object owner = rchi.createReferenceCountOwner();
- assertFalse(owner == null);
+ Object owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNotNull();
- AtomicInteger ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
+ AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
owner = null;
- rchi.setReferenceCountOwner(owner);
- ai = rchi.getReenterCount();
- assertEquals(0, ai.get());
- assertEquals(rchi.getReferenceCountOwner(), null);
-
- owner = rchi.createReferenceCountOwner();
- assertFalse(owner == null);
-
- ai = rchi.getReenterCount();
- assertEquals(1, ai.get());
-
- rchi.refCountChanged(address, decRefCount, rc);
- List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- RefCountChangeInfo rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
-
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
-
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size()); // inc and dec are tracked in different changeinfo objects (?)
- rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
-
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(0, list.size());
+ referenceCountHelperImpl.setReferenceCountOwner(owner);
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isZero();
+ assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
+
+ owner = referenceCountHelperImpl.createReferenceCountOwner();
+ assertThat(owner).isNotNull();
+ reenterCount = referenceCountHelperImpl.getReenterCount();
+ assertThat(reenterCount.get()).isOne();
+
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
+
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
+
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // inc and dec are tracked in different changeinfo objects (?)
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
+
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isEmpty();
}
@Test
public void doGetRefCountInfoWithTrackRefsTrueAndTrackFreesTrue() {
- rchi = getTrueTrue();
- long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
-
- List<RefCountChangeInfo> list = null;
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
+ Long address = (long) 0x1000;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- RefCountChangeInfo rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo
- assertEquals(1, info.size());
- rcci = info.get(0);
- assertEquals(1, rcci.getUseCount());
+ // now getRefCountInfo
+ List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
+ assertThat(info).hasSize(1);
+ refCountChangeInfo = info.get(0);
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- list = rchi.peekRefCountInfo(address);
- assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty)
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // getRefCountInfo leaves list LOCKED (i.e. empty)
+ assertThat(list).isEmpty();
}
@Test
- public void doRefCountChangedAfterGetRefCountInfoWithTrackRefsTrueAndTrackFreesTrue()
- throws Exception {
- rchi = getTrueTrue();
- long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
-
- List<RefCountChangeInfo> list = null;
-
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- RefCountChangeInfo rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
-
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
-
- List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo
- assertEquals(1, info.size());
- rcci = info.get(0);
- assertEquals(1, rcci.getUseCount());
-
- list = rchi.peekRefCountInfo(address);
- assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty)
+ public void doRefCountChangedAfterGetRefCountInfoWithTrackRefsTrueAndTrackFreesTrue() {
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
+ Long address = (long) 0x1000;
- sor.mute(); // Mute system out
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- PowerMockito.spy(MemoryAllocatorImpl.class); // Watch the impl for invocation of debugLog
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- rchi.refCountChanged(address, decRefCount, rc); // this line should fail. no inc after getInfo
- // allowed
- PowerMockito.verifyStatic(MemoryAllocatorImpl.class);
- MemoryAllocatorImpl.debugLog("refCount inced after orphan detected for @1000", true);
+ // now getRefCountInfo
+ List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
+ assertThat(info).hasSize(1);
+ refCountChangeInfo = info.get(0);
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- decRefCount = true;
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // getRefCountInfo leaves list LOCKED (i.e. empty)
+ assertThat(list).isEmpty();
- rchi.refCountChanged(address, decRefCount, rc); // this line should fail. no inc after getInfo
- // allowed
- PowerMockito.verifyStatic(MemoryAllocatorImpl.class);
- MemoryAllocatorImpl.debugLog("refCount deced after orphan detected for @1000", true);
+ // this line should fail. no inc after getInfo allowed
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ verify(debugLogger).accept("refCount inced after orphan detected for @1000", true);
- rchi.freeRefCountInfo(address); // this line should fail. no free after getInfo allowed
- PowerMockito.verifyStatic(MemoryAllocatorImpl.class);
- MemoryAllocatorImpl.debugLog("freed after orphan detected for @1000", true);
+ // this line should fail. no inc after getInfo allowed
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ verify(debugLogger).accept("refCount deced after orphan detected for @1000", true);
+ // this line should fail. no free after getInfo allowed
+ referenceCountHelperImpl.freeRefCountInfo(address);
+ verify(debugLogger).accept("freed after orphan detected for @1000", true);
}
@Test
public void doGetRefCountInfoWithTrackRefsFalseAndTrackFreesTrue() {
- rchi = getFalseTrue();
- long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
+ Long address = (long) 0x1000;
- List<RefCountChangeInfo> list = rchi.getRefCountInfo(address);
- assertEquals(null, list);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.getRefCountInfo(address);
+ assertThat(list).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- List<RefCountChangeInfo> info = rchi.getRefCountInfo(address);
- assertEquals(null, info);
+ List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
+ assertThat(info).isNull();
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- rchi.refCountChanged(address, decRefCount, rc); // this will be ignored.
- decRefCount = true;
- rchi.refCountChanged(address, decRefCount, rc); // this will be ignored.
- rchi.freeRefCountInfo(address); // this will be ignored.
+ // TODO: add assertions for the following
+ // this will be ignored.
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ // this will be ignored.
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ // this will be ignored.
+ referenceCountHelperImpl.freeRefCountInfo(address);
}
@Test
public void doGetRefCountInfoWithTrackRefsFalseAndTrackFreesFalse() {
- rchi = getFalseFalse();
- long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
+ Long address = (long) 0x1000;
- List<RefCountChangeInfo> list = rchi.getRefCountInfo(address);
- assertEquals(null, list);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.getRefCountInfo(address);
+ assertThat(list).isNull();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
- List<RefCountChangeInfo> info = rchi.getRefCountInfo(address);
- assertEquals(null, info);
+ List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
+ assertThat(info).isNull();
- list = rchi.peekRefCountInfo(address);
- assertEquals(null, list);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).isNull();
}
@Test
public void doGetRefCountInfoWithTrackRefsTrueAndTrackFreesFalse() {
- rchi = getTrueFalse();
+ ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
long address = (long) 0x1000;
- boolean decRefCount = false;
- int rc = 1;
-
- List<RefCountChangeInfo> list = null;
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- RefCountChangeInfo rcci = list.get(0);
- assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- rchi.refCountChanged(address, decRefCount, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1
- // when adding new entry?
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo
- assertEquals(1, info.size());
- rcci = info.get(0);
- assertEquals(1, rcci.getUseCount());
+ // now getRefCountInfo
+ List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
+ assertThat(info).hasSize(1);
+ refCountChangeInfo = info.get(0);
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- list = rchi.peekRefCountInfo(address);
- assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty)
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // getRefCountInfo leaves list LOCKED (i.e. empty)
+ assertThat(list).isEmpty();
}
- private ReferenceCountHelperImpl getTrueTrue() {
- return new ReferenceCountHelperImpl(true, true);
- }
-
- private ReferenceCountHelperImpl getTrueFalse() {
- return new ReferenceCountHelperImpl(true, false);
- }
-
- private ReferenceCountHelperImpl getFalseTrue() {
- return new ReferenceCountHelperImpl(false, true);
- }
-
- private ReferenceCountHelperImpl getFalseFalse() {
- return new ReferenceCountHelperImpl(false, false);
- }
+ @Test
+ public void doGetRefCountInfoNonRegionEntryConcurrencyTest() {
+ ReferenceCountHelperImpl referenceCountHelperImpl = newHookedReferenceCountHelperImpl();
+ Long address = (long) 0x1000;
- private ReferenceCountHelperImpl getHookedImpl() {
- return new HookedReferenceCountHelperImpl(true, true);
+ // assume test identity
+ referenceCountHelperImpl.setReferenceCountOwner("TestOwner");
+
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // hooked impl simulates a concurrent update, so cnt is > expected
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
+
+ // sets owner to null and resets count
+ referenceCountHelperImpl.setReferenceCountOwner(null);
+ // sets owner to null and resets count // sets owner to null and resets count
+
+ // assume new identity
+ referenceCountHelperImpl.setReferenceCountOwner("TestOwner2");
+
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // list is not null, so hook not used
+ assertThat(refCountChangeInfo.getUseCount()).isEqualTo(2);
+
+ // dec ref count
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // dec adds new list of stack traces
+ assertThat(list).hasSize(2);
+ refCountChangeInfo = list.get(1);
+ // cnt starts at 0 for new entries
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
+
+ // now getRefCountInfo
+ List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
+ // hooked impl added one to list
+ assertThat(info).hasSize(3);
+ refCountChangeInfo = info.get(2);
+ // count starts at 0 for new entries
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
+
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // getRefCountInfo leaves list LOCKED (i.e. empty)
+ assertThat(list).isEmpty();
}
@Test
- public void doGetRefCountInfoNonRegionEntryConcurrencyTest() {
- rchi = getHookedImpl();
- long address = (long) 0x1000;
- int rc = 1;
- RefCountChangeInfo rcci;
-
- List<RefCountChangeInfo> list = null;
+ public void doGetRefCountInfoRegionEntryConcurrencyTest() {
+ ReferenceCountHelperImpl referenceCountHelperImpl = newHookedReferenceCountHelperImpl();
+ Long address = (long) 0x1000;
- rchi.setReferenceCountOwner("TestOwner"); // assume test identity
+ RegionEntry regionEntry1 = mock(RegionEntry.class);
+ // set owner to region entry type
+ referenceCountHelperImpl.setReferenceCountOwner(regionEntry1);
- rchi.refCountChanged(address, false, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // hooked impl simulates a concurrent update, so cnt is >
- // expected
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ RefCountChangeInfo refCountChangeInfo = list.get(0);
+ // hooked impl simulates a concurrent update, so cnt is > expected
+ assertThat(refCountChangeInfo.getUseCount()).isOne();
- rchi.setReferenceCountOwner(null); // sets owner to null and resets count
- rchi.setReferenceCountOwner(null); // sets owner to null and resets count
+ // sets owner to null and resets count
+ referenceCountHelperImpl.setReferenceCountOwner(null);
+ // sets owner to null and resets count
+ referenceCountHelperImpl.setReferenceCountOwner(null);
- rchi.setReferenceCountOwner("TestOwner2"); // assume new identity
+ RegionEntry regionEntry2 = mock(RegionEntry.class);
+ // set owner to region entry type
+ referenceCountHelperImpl.setReferenceCountOwner(regionEntry2);
- rchi.refCountChanged(address, false, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(2, rcci.getUseCount()); // list is not null, so hook not used
+ referenceCountHelperImpl.refCountChanged(address, false, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ assertThat(list).hasSize(1);
+ refCountChangeInfo = list.get(0);
+ // list is not null, so hook not used
+ assertThat(refCountChangeInfo.getUseCount()).isEqualTo(2);
- rchi.refCountChanged(address, true, rc); // dec ref count
- list = rchi.peekRefCountInfo(address);
- assertEquals(2, list.size()); // dec adds new list of stack traces
- rcci = list.get(1);
- assertEquals(0, rcci.getUseCount()); // cnt starts at 0 for new entries
+ // dec ref count
+ referenceCountHelperImpl.refCountChanged(address, true, 1);
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // dec adds new list of stack traces
+ assertThat(list).hasSize(2);
+ refCountChangeInfo = list.get(1);
+ // cnt starts at 0 for new entries
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo
- assertEquals(3, info.size()); // hooked impl added one to list
- rcci = info.get(2);
- assertEquals(0, rcci.getUseCount()); // count starts at 0 for new entries
+ // now getRefCountInfo
+ List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
+ // hooked impl added one to list
+ assertThat(info).hasSize(3);
+ refCountChangeInfo = info.get(2);
+ // count starts at 0 for new entries
+ assertThat(refCountChangeInfo.getUseCount()).isZero();
- list = rchi.peekRefCountInfo(address);
- assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty)
+ list = referenceCountHelperImpl.peekRefCountInfo(address);
+ // getRefCountInfo leaves list LOCKED (i.e. empty)
+ assertThat(list).isEmpty();
}
- @Test
- public void doGetRefCountInfoRegionEntryConcurrencyTest() {
- rchi = getHookedImpl();
- long address = (long) 0x1000;
- int rc = 1;
- RefCountChangeInfo rcci;
-
- List<RefCountChangeInfo> list = null;
-
- RegionEntry re = mock(RegionEntry.class);
- rchi.setReferenceCountOwner(re); // set owner to region entry type
-
- rchi.refCountChanged(address, false, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(1, rcci.getUseCount()); // hooked impl simulates a concurrent update, so cnt is >
- // expected
+ private ReferenceCountHelperImpl newReferenceCountHelperImpl_TrueTrue() {
+ return new ReferenceCountHelperImpl(true, true, debugLogger);
+ }
- rchi.setReferenceCountOwner(null); // sets owner to null and resets count
- rchi.setReferenceCountOwner(null); // sets owner to null and resets count
+ private ReferenceCountHelperImpl newReferenceCountHelperImpl_TrueFalse() {
+ return new ReferenceCountHelperImpl(true, false, debugLogger);
+ }
- RegionEntry re2 = mock(RegionEntry.class);
- rchi.setReferenceCountOwner(re2); // set owner to region entry type
+ private ReferenceCountHelperImpl newReferenceCountHelperImpl_FalseTrue() {
+ return new ReferenceCountHelperImpl(false, true, debugLogger);
+ }
- rchi.refCountChanged(address, false, rc);
- list = rchi.peekRefCountInfo(address);
- assertEquals(1, list.size());
- rcci = list.get(0);
- assertEquals(2, rcci.getUseCount()); // list is not null, so hook not used
+ private ReferenceCountHelperImpl newReferenceCountHelperImpl_FalseFalse() {
+ return new ReferenceCountHelperImpl(false, false, debugLogger);
+ }
- rchi.refCountChanged(address, true, rc); // dec ref count
- list = rchi.peekRefCountInfo(address);
- assertEquals(2, list.size()); // dec adds new list of stack traces
- rcci = list.get(1);
- assertEquals(0, rcci.getUseCount()); // cnt starts at 0 for new entries
+ private ReferenceCountHelperImpl newHookedReferenceCountHelperImpl() {
+ return new HookedReferenceCountHelperImpl(true, true, debugLogger);
+ }
- List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo
- assertEquals(3, info.size()); // hooked impl added one to list
- rcci = info.get(2);
- assertEquals(0, rcci.getUseCount()); // count starts at 0 for new entries
+ private static class HookedReferenceCountHelperImpl extends ReferenceCountHelperImpl {
- list = rchi.peekRefCountInfo(address);
- assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty)
- }
+ private int refCountChangedTestHookCount;
- private class HookedReferenceCountHelperImpl extends ReferenceCountHelperImpl {
- HookedReferenceCountHelperImpl(boolean trackRefCounts, boolean trackFreedRefCounts) {
- super(trackRefCounts, trackFreedRefCounts);
+ private HookedReferenceCountHelperImpl(boolean trackRefCounts, boolean trackFreedRefCounts,
+ BiConsumer<String, Boolean> debugLogger) {
+ super(trackRefCounts, trackFreedRefCounts, debugLogger);
}
- protected int refCountChangedTestHookCount = 0;
-
- /*
+ /**
* Update list of stack traces for address. Hooked SUT should see that the list changed.
*/
@Override
protected void getReferenceCountInfoTestHook(
- ConcurrentMap<Long, List<RefCountChangeInfo>> stacktraces, long address) {
+ ConcurrentMap<Long, List<RefCountChangeInfo>> stackTraces, long address) {
List<RefCountChangeInfo> updatedList =
- new ArrayList<RefCountChangeInfo>(stacktraces.get(address));
- RefCountChangeInfo rcci = new RefCountChangeInfo(false, 0, "TestOwner");
- updatedList.add(rcci);
- stacktraces.put(address, updatedList);
+ new ArrayList<>(stackTraces.get(address));
+ RefCountChangeInfo refCountChangeInfo = new RefCountChangeInfo(false, 0, "TestOwner");
+ updatedList.add(refCountChangeInfo);
+ stackTraces.put(address, updatedList);
}
- /*
+ /**
* Reinvoke refCountChanged to update reference count. Hooked SUT should see that the count has
* changed.
*/
diff --git a/geode-core/src/test/java/org/apache/geode/internal/offheap/ReferenceCountHelperJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/offheap/ReferenceCountHelperJUnitTest.java
deleted file mode 100644
index a7ca6101..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/offheap/ReferenceCountHelperJUnitTest.java
+++ /dev/null
@@ -1,205 +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 org.apache.geode.internal.offheap;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-
-/*
- * This test simply verifies the static class delegates properly to the impl
- *
- * PowerMock used in this test to inject mocked impl into static class The PowerMockRule bootstraps
- * PowerMock without the need for the @RunWith(PowerMockRunner.class) annotation, which was
- * interfering with jacoco
- *
- */
-@RunWith(PowerMockRunner.class)
-@PowerMockIgnore({"*.UnitTest"})
-@PrepareForTest({ReferenceCountHelper.class})
-public class ReferenceCountHelperJUnitTest {
-
- private ReferenceCountHelperImpl prepareInstance() {
- ReferenceCountHelperImpl rchi = mock(ReferenceCountHelperImpl.class);
- PowerMockito.mockStatic(ReferenceCountHelper.class, Mockito.CALLS_REAL_METHODS);
- PowerMockito.when(ReferenceCountHelper.getInstance()).thenReturn(rchi);
- return rchi;
- }
-
- @Test
- public void trackReferenceCountsTrueTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- when(rchi.trackReferenceCounts()).thenReturn(true);
- boolean b = ReferenceCountHelper.trackReferenceCounts();
- assertTrue(b);
- verify(rchi).trackReferenceCounts();
- }
-
- @Test
- public void trackReferenceCountsFalseTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- when(rchi.trackReferenceCounts()).thenReturn(false);
- boolean b = ReferenceCountHelper.trackReferenceCounts();
- assertFalse(b);
- verify(rchi).trackReferenceCounts();
- }
-
- @Test
- public void trackFreedReferenceCountsTrueTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- when(rchi.trackFreedReferenceCounts()).thenReturn(true);
- assertTrue(ReferenceCountHelper.trackFreedReferenceCounts());
- verify(rchi).trackFreedReferenceCounts();
- }
-
- @Test
- public void trackFreedReferenceCountsFalseTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- when(rchi.trackFreedReferenceCounts()).thenReturn(false);
- assertFalse(ReferenceCountHelper.trackFreedReferenceCounts());
- verify(rchi).trackFreedReferenceCounts();
- }
-
- @Test
- public void setReferenceCountOwnerTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- Object theOwner = new Object();
- ReferenceCountHelper.setReferenceCountOwner(theOwner);
- verify(rchi).setReferenceCountOwner(theOwner);
- }
-
- @Test
- public void createReferenceCountOwnerTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- Object expectedResult = new String("createReferenceCountOwner result");
- when(rchi.createReferenceCountOwner()).thenReturn(expectedResult);
- Object s = ReferenceCountHelper.createReferenceCountOwner();
- assertEquals(s, expectedResult);
- verify(rchi).createReferenceCountOwner();
- }
-
- @Test
- public void skipRefCountTrackingTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- ReferenceCountHelper.skipRefCountTracking();
- verify(rchi).skipRefCountTracking();
- }
-
- @Test
- public void isRefCountTrackingTrueTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- when(rchi.isRefCountTracking()).thenReturn(true);
- boolean b = ReferenceCountHelper.isRefCountTracking();
- assertTrue(b);
- verify(rchi).isRefCountTracking();
- }
-
- @Test
- public void isRefCountTrackingFalseTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- when(rchi.isRefCountTracking()).thenReturn(false);
- boolean b = ReferenceCountHelper.isRefCountTracking();
- assertFalse(b);
- verify(rchi).isRefCountTracking();
- }
-
- @Test
- public void unskipRefCountTrackingTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- ReferenceCountHelper.unskipRefCountTracking();
- verify(rchi).unskipRefCountTracking();
- }
-
- @Test
- public void getRefCountInfoTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- List<RefCountChangeInfo> expectedResult = Collections.emptyList();
- when(rchi.getRefCountInfo((long) 1000)).thenReturn(expectedResult);
- List<RefCountChangeInfo> l = ReferenceCountHelper.getRefCountInfo(1000);
- assertEquals(l, expectedResult);
- verify(rchi).getRefCountInfo(1000);
- }
-
- @Test
- public void refCountChangedTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- ReferenceCountHelper.refCountChanged((long) 1000, true, 4);
- verify(rchi).refCountChanged((long) 1000, true, 4);
- }
-
- @Test
- public void freeRefCountInfoTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- ReferenceCountHelper.freeRefCountInfo((long) 1000);
- verify(rchi).freeRefCountInfo((long) 1000);
- }
-
- @Test
- public void getReferenceCountOwnerTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- Object expectedResult = new String("getReferenceCountOwner result");
- when(rchi.getReferenceCountOwner()).thenReturn(expectedResult);
- Object o = ReferenceCountHelper.getReferenceCountOwner();
- assertEquals(o, expectedResult);
- verify(rchi).getReferenceCountOwner();
- }
-
- @Test
- public void getReenterCountTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- AtomicInteger expectedResult = new AtomicInteger(8);
- when(rchi.getReenterCount()).thenReturn(expectedResult);
- AtomicInteger ai = ReferenceCountHelper.getReenterCount();
- assertEquals(ai, expectedResult);
- verify(rchi).getReenterCount();
- }
-
- @Test
- public void getFreeRefCountInfoTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- List<RefCountChangeInfo> expectedResult = Collections.emptyList();
- when(rchi.getFreeRefCountInfo((long) 1000)).thenReturn(expectedResult);
- List<RefCountChangeInfo> l = ReferenceCountHelper.getFreeRefCountInfo(1000);
- assertEquals(l, expectedResult);
- verify(rchi).getFreeRefCountInfo(1000);
- }
-
- @Test
- public void peekRefCountInfoTest() throws Exception {
- ReferenceCountHelperImpl rchi = prepareInstance();
- List<RefCountChangeInfo> expectedResult = Collections.emptyList();
- when(rchi.peekRefCountInfo((long) 1000)).thenReturn(expectedResult);
- List<RefCountChangeInfo> l = ReferenceCountHelper.peekRefCountInfo(1000);
- assertEquals(l, expectedResult);
- verify(rchi).peekRefCountInfo(1000);
- }
-}
diff --git a/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/parallel/ParallelGatewaySenderOperationsDUnitTest.java b/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/parallel/ParallelGatewaySenderOperationsDUnitTest.java
index 3a8a6a1..6b76e6a 100644
--- a/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/parallel/ParallelGatewaySenderOperationsDUnitTest.java
+++ b/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/parallel/ParallelGatewaySenderOperationsDUnitTest.java
@@ -63,7 +63,7 @@ import org.apache.geode.internal.cache.wan.AbstractGatewaySender;
import org.apache.geode.internal.cache.wan.GatewaySenderException;
import org.apache.geode.internal.cache.wan.WANTestBase;
import org.apache.geode.internal.offheap.MemoryAllocatorImpl;
-import org.apache.geode.internal.offheap.OffHeapRegionEntryHelper;
+import org.apache.geode.internal.offheap.OffHeapClearRequired;
import org.apache.geode.test.awaitility.GeodeAwaitility;
import org.apache.geode.test.dunit.AsyncInvocation;
import org.apache.geode.test.dunit.IgnoredException;
@@ -929,7 +929,7 @@ public class ParallelGatewaySenderOperationsDUnitTest extends WANTestBase {
// above.
callables.add(Executors.callable(() -> {
try {
- OffHeapRegionEntryHelper.doWithOffHeapClear(new Runnable() {
+ OffHeapClearRequired.doWithOffHeapClear(new Runnable() {
@Override
public void run() {
// Wait for the cache writer to be invoked to release this countdown latch.