Adapt CacheUtils to identify client LOCAL Regions when collecting (getting) all values from the Region in collectValues(:Region).
Add new isProxyRegion(:Region) method to safely determine if the Region is a PROXY. Add new isRegionWithPool(:Region) method to safely determine if the Region has been configured with a Pool, imply the Region is owned by a client (i.e. ClientCache). Edit Javadoc.
This commit is contained in:
@@ -24,10 +24,12 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.RegionService;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
|
||||
/**
|
||||
@@ -36,9 +38,12 @@ import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.RegionAttributes
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public abstract class CacheUtils {
|
||||
@@ -63,25 +68,72 @@ public abstract class CacheUtils {
|
||||
|
||||
return isClientRegion(region)
|
||||
? clientRegionValues(region)
|
||||
: region.values();
|
||||
|
||||
: localRegionValues(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects values from the given {@literal client} {@link Region}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region Region's} values.
|
||||
* @param region {@link Region} from which to collect values.
|
||||
* @return a {@link Collection} of the {@literal client} {@link Region Region's} values.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #clientRegionValuesFromServer(Region)
|
||||
* @see #localRegionValues(Region)
|
||||
* @see #isProxyRegion(Region)
|
||||
*/
|
||||
private static <T> Collection<T> clientRegionValues(Region<?, T> region) {
|
||||
|
||||
return isProxyRegion(region)
|
||||
? clientRegionValuesFromServer(region)
|
||||
: localRegionValues(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collections all values from the {@literal client} {@link Region} by pulling the values down from the server.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region Region's} values.
|
||||
* @param region {@link Region} from which to collect values.
|
||||
* @return a {@link Collection} containing the values from the {@literal client} {@link Region} on the server.
|
||||
* @see org.apache.geode.cache.Region#keySetOnServer()
|
||||
* @see #getAll(Region, Set)
|
||||
*/
|
||||
private static <T> Collection<T> clientRegionValuesFromServer(Region<?, T> region) {
|
||||
|
||||
Set<?> keys = nullSafeSet(region.keySetOnServer());
|
||||
|
||||
return !keys.isEmpty() ? getAll(keys, region) : Collections.emptySet();
|
||||
return !keys.isEmpty() ? getAll(region, keys) : Collections.emptySet();
|
||||
}
|
||||
|
||||
private static <T> Collection<T> getAll(Set<?> keys, Region<?, T> region) {
|
||||
/**
|
||||
* Gets all values from the given {@link Region} mapped to the specified {@link Set keys}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region Region's} values.
|
||||
* @param region {@link Region} from which to get all values.
|
||||
* @param keys {@link Set} of keys targeting the values to retrieve.
|
||||
* @return a {@link Collection} of the {@link Region Region's} values.
|
||||
* @see org.apache.geode.cache.Region#getAll(Collection)
|
||||
*/
|
||||
private static <T> Collection<T> getAll(Region<?, T> region, Set<?> keys) {
|
||||
return nullSafeMap(region.getAll(keys)).values();
|
||||
// Fallback procedure if region.getAll(keys) is buggered
|
||||
//return keys.stream().map(region::get).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects values from the given {@link Region}, locally.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region Region's} values.
|
||||
* @param region {@link Region} from which to collect values.
|
||||
* @return a {@link Collection} of the {@link Region Region's} values.
|
||||
* @see org.apache.geode.cache.Region#values()
|
||||
*/
|
||||
private static <T> Collection<T> localRegionValues(Region<?, T> region) {
|
||||
return region.values();
|
||||
}
|
||||
|
||||
private static boolean hasText(String value) {
|
||||
return !(value == null || value.trim().isEmpty());
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
|
||||
private static <K, V> Map<K, V> nullSafeMap(Map<K, V> map) {
|
||||
@@ -125,11 +177,8 @@ public abstract class CacheUtils {
|
||||
*/
|
||||
public static boolean isClientRegion(Region<?, ?> region) {
|
||||
|
||||
return region != null && (isClientCache(region.getRegionService())
|
||||
|| Optional.ofNullable(region.getAttributes())
|
||||
.map(RegionAttributes::getPoolName)
|
||||
.filter(CacheUtils::hasText)
|
||||
.isPresent());
|
||||
return region != null
|
||||
&& (isClientCache(region.getRegionService()) || isRegionWithPool(region));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,4 +217,43 @@ public abstract class CacheUtils {
|
||||
public static boolean isPeerRegion(Region<?, ?> region) {
|
||||
return region != null && !isClientRegion(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe method to determine whether the given {@link Region} is a [client] {@literal PROXY} {@link Region}.
|
||||
*
|
||||
* The {@link Region} is a {@literal PROXY} if the {@link DataPolicy} is {@link DataPolicy#EMPTY}
|
||||
* or the {@link Region} has a configured {@link Pool}.
|
||||
*
|
||||
* @param region {@link Region} to evaluate.
|
||||
* @return a boolean value to determine whether the {@link Region} is a [client] {@literal PROXY} {@link Region}.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #isRegionWithPool(Region)
|
||||
*/
|
||||
public static boolean isProxyRegion(Region<?, ?> region) {
|
||||
|
||||
return region != null
|
||||
&& region.getAttributes() != null
|
||||
&& (DataPolicy.EMPTY.equals(region.getAttributes().getDataPolicy())
|
||||
|| isRegionWithPool(region));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe method to determine whether the given {@link Region} was configured with a {@link Pool}.
|
||||
*
|
||||
* A {@link Region} configured with a {@link Pool} (by {@link String name} specified in the {@link RegionAttributes})
|
||||
* is a strong indicator that the {@link Region} is a {@literal client} {@link Region}.
|
||||
*
|
||||
* @param region {@link Region} to evaluate.
|
||||
* @return a boolean to determine whether the given {@link Region} was configured with a {@link Pool}.
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
public static boolean isRegionWithPool(Region<?, ?> region) {
|
||||
|
||||
return Optional.ofNullable(region)
|
||||
.map(Region::getAttributes)
|
||||
.map(RegionAttributes::getPoolName)
|
||||
.filter(CacheUtils::hasText)
|
||||
.isPresent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
package org.springframework.geode.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
@@ -34,6 +36,7 @@ import java.util.TreeSet;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
@@ -63,6 +66,8 @@ public class CacheUtilsUnitTests {
|
||||
|
||||
Region<Object, Object> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
Set<?> keySetOnServer = new TreeSet<>(Arrays.asList(1, 2, 3));
|
||||
@@ -73,17 +78,23 @@ public class CacheUtilsUnitTests {
|
||||
keysValues.put(2, "two");
|
||||
keysValues.put(3, "three");
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(keySetOnServer).when(mockRegion).keySetOnServer();
|
||||
doReturn(keysValues).when(mockRegion).getAll(eq(keySetOnServer));
|
||||
doReturn(DataPolicy.EMPTY).when(mockRegionAttributes).getDataPolicy();
|
||||
|
||||
assertThat(CacheUtils.collectValues(mockRegion)).containsExactlyInAnyOrder(keysValues.values().toArray());
|
||||
|
||||
verify(mockRegion, times(2)).getAttributes();
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(1)).keySetOnServer();
|
||||
verify(mockRegion, times(1)).getAll(eq(keySetOnServer));
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
verify(mockRegion, never()).values();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, never()).getPoolName();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,24 +102,33 @@ public class CacheUtilsUnitTests {
|
||||
|
||||
Region<Object, Object> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
Set<Object> keySetOnServer = new TreeSet<>(Arrays.asList(1, 2));
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(keySetOnServer).when(mockRegion).keySetOnServer();
|
||||
doReturn(null).when(mockRegion).getAll(eq(keySetOnServer));
|
||||
doReturn(DataPolicy.NORMAL).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn("Car").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
Collection<Object> values = CacheUtils.collectValues(mockRegion);
|
||||
|
||||
assertThat(values).isNotNull();
|
||||
assertThat(values).isEmpty();
|
||||
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(1)).keySetOnServer();
|
||||
verify(mockRegion, times(1)).getAll(eq(keySetOnServer));
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
verify(mockRegion, never()).values();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -116,20 +136,30 @@ public class CacheUtilsUnitTests {
|
||||
|
||||
Region<Object, Object> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(null).when(mockRegion).keySetOnServer();
|
||||
doReturn(DataPolicy.PARTITION).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn("Dead").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
Collection<Object> values = CacheUtils.collectValues(mockRegion);
|
||||
|
||||
assertThat(values).isNotNull();
|
||||
assertThat(values).isEmpty();
|
||||
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(1)).keySetOnServer();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
verify(mockRegion, never()).getAll(any());
|
||||
verify(mockRegion, never()).values();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -148,6 +178,36 @@ public class CacheUtilsUnitTests {
|
||||
verify(mockRegion, times(1)).values();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectValuesFromLocalClientRegion() {
|
||||
|
||||
Region<?, String> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, String> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(DataPolicy.NORMAL).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn(" ").when(mockRegionAttributes).getPoolName();
|
||||
doReturn(Arrays.asList("one", "two")).when(mockRegion).values();
|
||||
|
||||
Collection<String> values = CacheUtils.collectValues(mockRegion);
|
||||
|
||||
assertThat(values).isNotNull();
|
||||
assertThat(values).containsExactly("one", "two");
|
||||
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegion, times(1)).values();
|
||||
verify(mockRegion, never()).keySetOnServer();
|
||||
verify(mockRegion, never()).getAll(any());
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectValuesFromPeerRegion() {
|
||||
|
||||
@@ -370,4 +430,135 @@ public class CacheUtilsUnitTests {
|
||||
public void isPeerRegionWithNull() {
|
||||
assertThat(CacheUtils.isPeerRegion(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithProxyRegionBasedOnDataPolicy() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(DataPolicy.EMPTY).when(mockRegionAttributes).getDataPolicy();
|
||||
|
||||
assertThat(CacheUtils.isProxyRegion(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(2)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, never()).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithProxyRegionBasedOnPoolConfiguration() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(DataPolicy.NORMAL).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn("TestPool").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isProxyRegion(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithNonProxyRegion() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(DataPolicy.NORMAL).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn(" ").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isProxyRegion(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithRegionHavingNoAttributesIsNullSafe() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
assertThat(CacheUtils.isProxyRegion(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithNullRegionIsNullSafe() {
|
||||
assertThat(CacheUtils.isProxyRegion(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolWithPooledRegion() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn("Swimming").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isRegionWithPool(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingRegionHavingNoAttributesIsNullSafe() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
assertThat(CacheUtils.isRegionWithPool(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingNullRegionIsNullSafe() {
|
||||
assertThat(CacheUtils.isRegionWithPool(null)).isFalse();
|
||||
}
|
||||
|
||||
private void testIsRegionWithPoolUsingRegionWithInvalidPoolNameReturnsFalse(String poolName) {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(poolName).when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isRegionWithPool(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingRegionConfiguredWithBlankPoolName() {
|
||||
testIsRegionWithPoolUsingRegionWithInvalidPoolNameReturnsFalse(" ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingRegionConfiguredWithEmptyPoolName() {
|
||||
testIsRegionWithPoolUsingRegionWithInvalidPoolNameReturnsFalse("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingRegionConfiguredWithNullPoolName() {
|
||||
testIsRegionWithPoolUsingRegionWithInvalidPoolNameReturnsFalse(null);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user