@Test(expected = StoreAccessException.class) public void testConditionalRemoveThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") OperationsCodec<Long, String> codec = mock(OperationsCodec.class); @SuppressWarnings("unchecked") EternalChainResolver<Long, String> chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore<Long, String> store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.remove(1L, "one"); }
@Override public ValueHolder<V> computeIfAbsentAndFault(K key, Function<? super K, ? extends V> mappingFunction) throws StoreAccessException { return computeIfAbsent(key, mappingFunction); }
protected ClusteredStore(Configuration<K, V> config, OperationsCodec<K, V> codec, ChainResolver<K, V> resolver, TimeSource timeSource) { super(config); this.chainCompactionLimit = Integer.getInteger(CHAIN_COMPACTION_THRESHOLD_PROP, DEFAULT_CHAIN_COMPACTION_THRESHOLD); this.codec = codec; this.resolver = resolver; this.timeSource = timeSource; this.getObserver = createObserver("get", StoreOperationOutcomes.GetOutcome.class, true); this.putObserver = createObserver("put", StoreOperationOutcomes.PutOutcome.class, true); this.removeObserver = createObserver("remove", StoreOperationOutcomes.RemoveOutcome.class, true); this.putIfAbsentObserver = createObserver("putIfAbsent", StoreOperationOutcomes.PutIfAbsentOutcome.class, true); this.conditionalRemoveObserver = createObserver("conditionalRemove", StoreOperationOutcomes.ConditionalRemoveOutcome.class, true); this.replaceObserver = createObserver("replace", StoreOperationOutcomes.ReplaceOutcome.class, true); this.conditionalReplaceObserver = createObserver("conditionalReplace", StoreOperationOutcomes.ConditionalReplaceOutcome.class, true); this.getAndFaultObserver = createObserver("getAndFault", AuthoritativeTierOperationOutcomes.GetAndFaultOutcome.class, true); this.evictionObserver = createObserver("eviction", StoreOperationOutcomes.EvictionOutcome.class, false); }
/** * The assumption is that this method will be invoked only by cache.putAll and cache.removeAll methods. */ @Override public Map<K, ValueHolder<V>> bulkCompute(final Set<? extends K> keys, final Function<Iterable<? extends Map.Entry<? extends K, ? extends V>>, Iterable<? extends Map.Entry<? extends K, ? extends V>>> remappingFunction) throws StoreAccessException { Map<K, ValueHolder<V>> valueHolderMap = new HashMap<>(); if(remappingFunction instanceof Ehcache.PutAllFunction) { Ehcache.PutAllFunction<K, V> putAllFunction = (Ehcache.PutAllFunction<K, V>)remappingFunction; Map<K, V> entriesToRemap = putAllFunction.getEntriesToRemap(); for(Map.Entry<K, V> entry: entriesToRemap.entrySet()) { PutStatus putStatus = silentPut(entry.getKey(), entry.getValue()); if(putStatus == PutStatus.PUT) { putAllFunction.getActualPutCount().incrementAndGet(); valueHolderMap.put(entry.getKey(), new ClusteredValueHolder<>(entry.getValue())); } } } else if(remappingFunction instanceof Ehcache.RemoveAllFunction) { Ehcache.RemoveAllFunction<K, V> removeAllFunction = (Ehcache.RemoveAllFunction<K, V>)remappingFunction; for (K key : keys) { boolean removed = silentRemove(key); if(removed) { removeAllFunction.getActualRemoveCount().incrementAndGet(); } } } else { throw new UnsupportedOperationException("This bulkCompute method is not yet capable of handling generic computation functions"); } return valueHolderMap; }
@Test(expected = StoreAccessException.class) public void testClearThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") OperationsCodec<Long, String> codec = mock(OperationsCodec.class); @SuppressWarnings("unchecked") EternalChainResolver<Long, String> chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); doThrow(new RuntimeException()).when(serverStoreProxy).clear(); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore<Long, String> store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.clear(); }
@Test(expected = StoreAccessException.class) public void testConditionalReplaceThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") OperationsCodec<Long, String> codec = mock(OperationsCodec.class); @SuppressWarnings("unchecked") EternalChainResolver<Long, String> chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore<Long, String> store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.replace(1L, "one", "another one"); }
@Test(expected = StoreAccessException.class) public void testGetThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") OperationsCodec<Long, String> codec = mock(OperationsCodec.class); @SuppressWarnings("unchecked") EternalChainResolver<Long, String> chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore<Long, String> store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.get(1L); }
protected PutStatus silentPut(final K key, final V value) throws StoreAccessException { try { PutOperation<K, V> operation = new PutOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); storeProxy.append(extractedKey, payload); return PutStatus.PUT; } catch (Exception re) { throw handleException(re); } }
@Test(expected = StoreAccessException.class) public void testPutIfAbsentThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") OperationsCodec<Long, String> codec = mock(OperationsCodec.class); @SuppressWarnings("unchecked") EternalChainResolver<Long, String> chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore<Long, String> store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.putIfAbsent(1L, "one", b -> {}); }
TimeSource timeSource = mock(TimeSource.class); ClusteredStore<Long, String> store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); store.putIfAbsent(1L, "one", b -> {}); verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); store.replace(1L, "one"); verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); store.replace(1L, "one"); verify(proxy).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); } finally {
@Override public boolean containsKey(final K key) throws StoreAccessException { try { return getInternal(key) != null; } catch (TimeoutException e) { return false; } }
@Test(expected = StoreAccessException.class) public void testContainsKeyThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") OperationsCodec<Long, String> codec = mock(OperationsCodec.class); @SuppressWarnings("unchecked") EternalChainResolver<Long, String> chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore<Long, String> store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.containsKey(1L); }
@Test @SuppressWarnings("unchecked") public void testPutTimeout() throws Exception { ServerStoreProxy proxy = mock(ServerStoreProxy.class); OperationsCodec<Long, String> codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); doThrow(TimeoutException.class).when(proxy).append(anyLong(), isNull()); ClusteredStore<Long, String> store = new ClusteredStore<>(config, codec, null, proxy, timeSource); assertTimeoutOccurred(() -> store.put(1L, "one")); }
protected <K, V> ClusteredStore<K, V> createStore(Configuration<K, V> storeConfig, OperationsCodec<K, V> codec, ChainResolver<K, V> resolver, TimeSource timeSource, boolean useLoaderInAtomics, Object[] serviceConfigs) { return new ClusteredStore<>(storeConfig, codec, resolver, timeSource); }
@Test public void testBulkComputeRemoveAll() throws Exception { store.put(1L, "one"); store.put(2L, "two"); store.put(3L, "three"); Ehcache.RemoveAllFunction<Long, String> removeAllFunction = new Ehcache.RemoveAllFunction<>(); Map<Long, Store.ValueHolder<String>> valueHolderMap = store.bulkCompute(new HashSet<>(Arrays.asList(1L, 2L, 4L)), removeAllFunction); assertThat(valueHolderMap.get(1L), nullValue()); assertThat(store.get(1L), nullValue()); assertThat(valueHolderMap.get(2L), nullValue()); assertThat(store.get(2L), nullValue()); assertThat(valueHolderMap.get(4L), nullValue()); assertThat(store.get(4L), nullValue()); validateStats(store, EnumSet.noneOf(StoreOperationOutcomes.RemoveOutcome.class)); }
@Test public void testBulkComputeIfAbsentGetAll() throws Exception { store.put(1L, "one"); store.put(2L, "two"); Ehcache.GetAllFunction<Long, String> getAllAllFunction = new Ehcache.GetAllFunction<>(); Map<Long, Store.ValueHolder<String>> valueHolderMap = store.bulkComputeIfAbsent(new HashSet<>(Arrays.asList(1L, 2L)), getAllAllFunction); assertThat(valueHolderMap.get(1L).get(), is("one")); assertThat(store.get(1L).get(), is("one")); assertThat(valueHolderMap.get(2L).get(), is("two")); assertThat(store.get(2L).get(), is("two")); }
@Override public boolean remove(final K key) throws StoreAccessException { removeObserver.begin(); if(silentRemove(key)) { removeObserver.end(StoreOperationOutcomes.RemoveOutcome.REMOVED); return true; } else { removeObserver.end(StoreOperationOutcomes.RemoveOutcome.MISS); return false; } }
@Override public PutStatus put(final K key, final V value) throws StoreAccessException { putObserver.begin(); PutStatus status = silentPut(key, value); switch (status) { case PUT: putObserver.end(StoreOperationOutcomes.PutOutcome.PUT); break; case NOOP: putObserver.end(StoreOperationOutcomes.PutOutcome.NOOP); break; default: throw new AssertionError("Invalid put status: " + status); } return status; }
@Test(expected = UnsupportedOperationException.class) public void testBulkComputeIfAbsentThrowsForGenericFunction() throws Exception { @SuppressWarnings("unchecked") Function<Iterable<? extends Long>, Iterable<? extends Map.Entry<? extends Long, ? extends String>>> mappingFunction = mock(Function.class); store.bulkComputeIfAbsent(new HashSet<>(Arrays.asList(1L, 2L)), mappingFunction); }
@Test(expected = UnsupportedOperationException.class) public void testBulkComputeThrowsForGenericFunction() throws Exception { @SuppressWarnings("unchecked") Function<Iterable<? extends Map.Entry<? extends Long, ? extends String>>, Iterable<? extends Map.Entry<? extends Long, ? extends String>>> remappingFunction = mock(Function.class); store.bulkCompute(new HashSet<>(Arrays.asList(1L, 2L)), remappingFunction); }