From 38a134857401f80dd16785e61831092ccd4499de Mon Sep 17 00:00:00 2001 From: achmelo <37397715+achmelo@users.noreply.github.com> Date: Wed, 9 Mar 2022 14:46:19 +0100 Subject: [PATCH] fix: update data model for infinispan (#2156) * update data model for infinispan Signed-off-by: achmelo * client cert for profiling Signed-off-by: achmelo * storage tests Signed-off-by: achmelo * fix code smells Signed-off-by: achmelo --- .../infinispan/storage/InfinispanStorage.java | 49 +++++----- .../storage/InfinispanStorageTest.java | 93 +++++++++++-------- config/profiling/run-profiling.sh | 2 +- 3 files changed, 82 insertions(+), 62 deletions(-) diff --git a/caching-service/src/main/java/org/zowe/apiml/caching/service/infinispan/storage/InfinispanStorage.java b/caching-service/src/main/java/org/zowe/apiml/caching/service/infinispan/storage/InfinispanStorage.java index 4854673001..1823d0b6e7 100644 --- a/caching-service/src/main/java/org/zowe/apiml/caching/service/infinispan/storage/InfinispanStorage.java +++ b/caching-service/src/main/java/org/zowe/apiml/caching/service/infinispan/storage/InfinispanStorage.java @@ -10,7 +10,6 @@ package org.zowe.apiml.caching.service.infinispan.storage; import lombok.extern.slf4j.Slf4j; -import org.infinispan.Cache; import org.zowe.apiml.caching.model.KeyValue; import org.zowe.apiml.caching.service.Messages; import org.zowe.apiml.caching.service.Storage; @@ -18,37 +17,37 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentMap; @Slf4j public class InfinispanStorage implements Storage { - private final Cache> cache; + private final ConcurrentMap cache; - public InfinispanStorage(Cache> cache) { + public InfinispanStorage(ConcurrentMap cache) { this.cache = cache; } @Override public KeyValue create(String serviceId, KeyValue toCreate) { + toCreate.setServiceId(serviceId); log.info("Writing record: {}|{}|{}", serviceId, toCreate.getKey(), toCreate.getValue()); - Map serviceCache = cache.computeIfAbsent(serviceId, k -> new HashMap<>()); + KeyValue serviceCache = cache.putIfAbsent(serviceId + toCreate.getKey(), toCreate); - if (serviceCache.containsKey(toCreate.getKey())) { + if (serviceCache != null) { throw new StorageException(Messages.DUPLICATE_KEY.getKey(), Messages.DUPLICATE_KEY.getStatus(), toCreate.getKey()); } - KeyValue entry = serviceCache.put(toCreate.getKey(), toCreate); - cache.put(serviceId, serviceCache); - return entry; + return null; } @Override public KeyValue read(String serviceId, String key) { log.info("Reading record for service {} under key {}", serviceId, key); - Map serviceCache = cache.get(serviceId); - if (serviceCache != null && serviceCache.containsKey(key)) { - return serviceCache.get(key); + KeyValue serviceCache = cache.get(serviceId + key); + if (serviceCache != null) { + return serviceCache; } else { throw new StorageException(Messages.KEY_NOT_IN_CACHE.getKey(), Messages.KEY_NOT_IN_CACHE.getStatus(), key, serviceId); } @@ -56,13 +55,12 @@ public KeyValue read(String serviceId, String key) { @Override public KeyValue update(String serviceId, KeyValue toUpdate) { + toUpdate.setServiceId(serviceId); log.info("Updating record for service {} under key {}", serviceId, toUpdate); - Map serviceCache = cache.get(serviceId); - if (serviceCache == null || !serviceCache.containsKey(toUpdate.getKey())) { + KeyValue serviceCache = cache.put(serviceId + toUpdate.getKey(), toUpdate); + if (serviceCache == null) { throw new StorageException(Messages.KEY_NOT_IN_CACHE.getKey(), Messages.KEY_NOT_IN_CACHE.getStatus(), toUpdate.getKey(), serviceId); } - serviceCache.put(toUpdate.getKey(), toUpdate); - cache.put(serviceId, serviceCache); return toUpdate; } @@ -70,11 +68,8 @@ public KeyValue update(String serviceId, KeyValue toUpdate) { @Override public KeyValue delete(String serviceId, String toDelete) { log.info("Removing record for service {} under key {}", serviceId, toDelete); - Map serviceCache = cache.get(serviceId); - KeyValue entry; - if (serviceCache.containsKey(toDelete)) { - entry = serviceCache.remove(toDelete); - cache.put(serviceId, serviceCache); + KeyValue entry = cache.remove(serviceId + toDelete); + if (entry != null) { return entry; } else { throw new StorageException(Messages.KEY_NOT_IN_CACHE.getKey(), Messages.KEY_NOT_IN_CACHE.getStatus(), toDelete, serviceId); @@ -84,12 +79,22 @@ public KeyValue delete(String serviceId, String toDelete) { @Override public Map readForService(String serviceId) { log.info("Reading all records for service {} ", serviceId); - return cache.get(serviceId); + Map result = new HashMap<>(); + cache.forEach((key, value) -> { + if (serviceId.equals(value.getServiceId())) { + result.put(value.getKey(), value); + } + }); + return result; } @Override public void deleteForService(String serviceId) { log.info("Removing all records for service {} ", serviceId); - cache.remove(serviceId); + cache.forEach((key, value) -> { + if (value.getServiceId().equals(serviceId)) { + cache.remove(key); + } + }); } } diff --git a/caching-service/src/test/java/org/zowe/apiml/caching/service/infinispan/storage/InfinispanStorageTest.java b/caching-service/src/test/java/org/zowe/apiml/caching/service/infinispan/storage/InfinispanStorageTest.java index e3a949600b..48035b3444 100644 --- a/caching-service/src/test/java/org/zowe/apiml/caching/service/infinispan/storage/InfinispanStorageTest.java +++ b/caching-service/src/test/java/org/zowe/apiml/caching/service/infinispan/storage/InfinispanStorageTest.java @@ -16,8 +16,8 @@ import org.zowe.apiml.caching.model.KeyValue; import org.zowe.apiml.caching.service.StorageException; -import java.util.HashMap; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -26,7 +26,7 @@ class InfinispanStorageTest { public static final KeyValue TO_CREATE = new KeyValue("key1", "val1"); public static final KeyValue TO_UPDATE = new KeyValue("key1", "val2"); - Cache> cache; + Cache cache; InfinispanStorage storage; String serviceId1 = "service1"; @@ -39,86 +39,101 @@ void setup() { @Nested class WhenEntryDoesntExist { - Map serviceStore; + KeyValue keyValue; @BeforeEach void createEmptyStore() { - serviceStore = new HashMap<>(); - } - - @Test - void whenCreate_thenCacheIsUpdated() { - when(cache.computeIfAbsent(any(), any())).thenReturn(serviceStore); - storage.create(serviceId1, TO_CREATE); - verify(cache, times(1)).put(serviceId1, serviceStore); + keyValue = null; } @Test void whenRead_thenExceptionIsThrown() { String key = TO_CREATE.getKey(); - when(cache.get(serviceId1)).thenReturn(serviceStore); + when(cache.get(serviceId1)).thenReturn(keyValue); assertThrows(StorageException.class, () -> storage.read(serviceId1, key)); } @Test - void whenDelete_thenExceptionIsThrown() { + void whenUpdate_thenExceptionIsThrown() { + KeyValue entry = new KeyValue("key", "value"); + when(cache.get(serviceId1)).thenReturn(keyValue); + assertThrows(StorageException.class, () -> storage.update(serviceId1, entry)); + } - String key = TO_CREATE.getKey(); - when(cache.get(serviceId1)).thenReturn(serviceStore); - assertThrows(StorageException.class, () -> storage.delete(serviceId1, key)); - verify(cache, times(0)).put(serviceId1, serviceStore); + @Test + void whenAddNew_returnNull() { + keyValue = new KeyValue("key", "value"); + assertNull(storage.create(serviceId1, keyValue)); } @Test - void whenUpdate_thenCacheIsUpdated() { + void whenDelete_thenExceptionIsThrown() { - when(cache.get(serviceId1)).thenReturn(serviceStore); - assertThrows(StorageException.class, () -> storage.update(serviceId1, TO_UPDATE)); - verify(cache, times(0)).put(serviceId1, serviceStore); + String key = TO_CREATE.getKey(); + when(cache.remove(serviceId1 + key)).thenReturn(null); + assertThrows(StorageException.class, () -> storage.delete(serviceId1, key)); } + } @Nested class WhenEntryExists { - Map serviceStore; + KeyValue keyValue; @BeforeEach void createStoreWithEntry() { - serviceStore = new HashMap<>(); - serviceStore.put(TO_CREATE.getKey(), TO_CREATE); + keyValue = TO_CREATE; } @Test - void whenCreate_thenExceptionIsThrown() { - when(cache.computeIfAbsent(any(), any())).thenReturn(serviceStore); + void exceptionIsThrown() { + when(cache.putIfAbsent(any(), any())).thenReturn(keyValue); assertThrows(StorageException.class, () -> storage.create(serviceId1, TO_CREATE)); } @Test - void whenRead_thenEntryIsReturned() { - when(cache.get(serviceId1)).thenReturn(serviceStore); + void entryIsReturned() { + when(cache.get(serviceId1 + TO_CREATE.getKey())).thenReturn(TO_CREATE); KeyValue result = storage.read(serviceId1, TO_CREATE.getKey()); assertEquals(TO_CREATE.getValue(), result.getValue()); } @Test - void whenUpdate_thenCacheIsUpdated() { + void cacheIsUpdated() { - when(cache.get(serviceId1)).thenReturn(serviceStore); + when(cache.put(serviceId1 + TO_UPDATE.getKey(), TO_UPDATE)).thenReturn(TO_UPDATE); storage.update(serviceId1, TO_UPDATE); - verify(cache, times(1)).put(serviceId1, serviceStore); - assertEquals("val2", serviceStore.get(TO_CREATE.getKey()).getValue()); + verify(cache, times(1)).put(serviceId1 + TO_UPDATE.getKey(), TO_UPDATE); + assertEquals("val2", TO_UPDATE.getValue()); } @Test - void whenDelete_thenCacheIsUpdated() { + void itemIsDeleted() { + ConcurrentMap cache = new ConcurrentHashMap<>(); + InfinispanStorage storage = new InfinispanStorage(cache); + assertNull(storage.create(serviceId1, TO_CREATE)); + assertEquals(TO_CREATE, storage.delete(serviceId1, TO_CREATE.getKey())); + } - when(cache.get(serviceId1)).thenReturn(serviceStore); - KeyValue result = storage.delete(serviceId1, TO_CREATE.getKey()); - verify(cache, times(1)).put(serviceId1, serviceStore); - assertEquals(TO_CREATE.getValue(), result.getValue()); - assertNull(serviceStore.get(TO_CREATE.getKey())); + @Test + void returnAll() { + ConcurrentMap cache = new ConcurrentHashMap<>(); + InfinispanStorage storage = new InfinispanStorage(cache); + storage.create(serviceId1, new KeyValue("key", "value")); + storage.create(serviceId1, new KeyValue("key2", "value2")); + assertEquals(2, storage.readForService(serviceId1).size()); + } + + @Test + void removeAll() { + ConcurrentMap cache = new ConcurrentHashMap<>(); + InfinispanStorage storage = new InfinispanStorage(cache); + storage.create(serviceId1, new KeyValue("key", "value")); + storage.create(serviceId1, new KeyValue("key2", "value2")); + assertEquals(2, storage.readForService(serviceId1).size()); + storage.deleteForService(serviceId1); + assertEquals(0, storage.readForService(serviceId1).size()); } } diff --git a/config/profiling/run-profiling.sh b/config/profiling/run-profiling.sh index 3bd4389289..e1856ad72c 100755 --- a/config/profiling/run-profiling.sh +++ b/config/profiling/run-profiling.sh @@ -76,4 +76,4 @@ then fi fi -jmeter -Jhost=$host -Jport=$port -Jthreads=$threads -Jdataset=$dataset -Jjmeter.reportgenerator.overall_granularity=1000 -n -t caching-profiling-parametrized.jmx -l $dir/result -e -o $dir/test-results -j $dir/result.log +jmeter -D javax.net.ssl.keyStore=../../keystore/client_cert/client-certs.p12 -D javax.net.ssl.keyStorePassword=password -Jhost=$host -Jport=$port -Jthreads=$threads -Jdataset=$dataset -Jjmeter.reportgenerator.overall_granularity=1000 -n -t caching-profiling-parametrized.jmx -l $dir/result -e -o $dir/test-results -j $dir/result.log