writeFuture1.thenCompose(r -> readOnlyMap.eval("key1", EntryView.ReadEntryView::get)); CompletableFuture<String> readFuture2 = writeFuture2.thenCompose(r -> readOnlyMap.eval("key2", EntryView.ReadEntryView::get)); readOnlyMap.evalMany(data.keySet(), readOnlyView -> readOnlyView); System.out.printf("Updated entries: %n"); entryViews.forEach(view -> System.out.printf("%s%n", view));
@Override public void close() { try { readOnly.close(); } catch (Exception e) { throw new AssertionError(e); } }
@Override public boolean containsValue(Object value) { return readOnly.entries().anyMatch(ro -> ro.get().equals(value)); }
writeFuture1.thenCompose(r -> readOnlyMap.eval("key1", ReadEntryView::get)); CompletableFuture<String> readFuture2 = writeFuture2.thenCompose(r -> readOnlyMap.eval("key2", ReadEntryView::get)); readOnlyMap.evalMany(data.keySet(), readOnlyView -> readOnlyView); printf("Updated entries: %n"); entryViews.forEach(view -> printf("%s%n", view));
wo.eval(KEY, MarshallableFunctions.removeConsumer()).join(); assertNull(cache.putIfAbsent(KEY, "y")); assertEquals("y", ro.eval(KEY, MarshallableFunctions.returnReadOnlyFindOrNull()).join()); tm.commit();
private <K> void doUpdateSubsetAndReturnPrevs(Supplier<K> keySupplier, ReadOnlyMap<K, String> map1, WriteOnlyMap<K, String> map2, ReadWriteMap<K, String> map3) { K key1 = keySupplier.get(), key2 = keySupplier.get(), key3 = keySupplier.get(); Map<K, String> data = new HashMap<>(); data.put(key1, "one"); data.put(key2, "two"); data.put(key3, "three"); await(map2.evalMany(data, setValueConsumer())); Traversable<String> currentValues = map1.evalMany(data.keySet(), returnReadOnlyFindOrNull()); List<String> collectedValues = currentValues.collect(ArrayList::new, ArrayList::add, ArrayList::addAll); Collections.sort(collectedValues); List<String> dataValues = new ArrayList<>(data.values()); Collections.sort(dataValues); assertEquals(collectedValues, dataValues); Map<K, String> newData = new HashMap<>(); newData.put(key1, "bat"); newData.put(key2, "bi"); newData.put(key3, "hiru"); Traversable<String> prevTraversable = map3.evalMany(newData, setValueReturnPrevOrNull()); List<String> collectedPrev = prevTraversable.collect(ArrayList::new, ArrayList::add, ArrayList::addAll); Collections.sort(collectedPrev); assertEquals(dataValues, collectedPrev); Traversable<String> updatedValues = map1.evalMany(data.keySet(), returnReadOnlyFindOrNull()); List<String> collectedUpdates = updatedValues.collect(ArrayList::new, ArrayList::add, ArrayList::addAll); Collections.sort(collectedUpdates); List<String> newDataValues = new ArrayList<>(newData.values()); Collections.sort(newDataValues); assertEquals(newDataValues, collectedUpdates); }
@Override public Iterator<Entry<K, V>> iterator() { Traversable<Entry<K, V>> t = readOnly.entries().map(rw -> new Entry<K, V>() { @Override public K getKey() { return rw.key(); } @Override public V getValue() { return rw.get(); } @Override public <T> T unwrap(Class<T> clazz) { return null; } // In Java 8, default remove() implementation is unsupported, but // adding support for it would be relatively trivial if following // similar solution to the one in ConcurrentMapDecorator }); return Traversables.asIterator(t); }
/** * Write-only allows for non-capturing values to be written along with metadata, * and read-only allows for both values and metadata to be retrieved. */ private <K> void doWriteValueAndReadValueAndMetadata(Supplier<K> keySupplier, ReadOnlyMap<K, String> map1, WriteOnlyMap<K, String> map2) { K key = keySupplier.get(); await( map2.eval(key, "one", SetValueAndConstantLifespan.getInstance()).thenCompose(r -> map1.eval(key, identity()).thenAccept(ro -> { assertNull(r); assertEquals(Optional.of("one"), ro.find()); assertEquals("one", ro.get()); assertEquals(Optional.of(new MetaLifespan(100000)), ro.findMetaParam(MetaLifespan.class)); } ) ) ); }
/** * Write-only allows for constant, non-capturing, values to be written, * and read-only allows for those values to be retrieved. */ private <K> void doWriteConstantAndReadGetsValue(Supplier<K> keySupplier, ReadOnlyMap<K, String> map1, WriteOnlyMap<K, String> map2) { K key = keySupplier.get(); await( map2.eval(key, SetStringConstant.INSTANCE).thenCompose(r -> map1.eval(key, returnReadOnlyFindOrNull()).thenAccept(v -> { assertNull(r); assertEquals("one", v); } ) ) ); }
private <K> void testReadOnMissingValues(K[] keys, FunctionalMap.ReadOnlyMap<K, String> ro, ReadMethod method) throws Exception { tm.begin(); for (K key : keys) { Assert.assertEquals(ro.eval(key, view -> view.find().isPresent()).join(), Boolean.FALSE); } tm.commit(); tm.begin(); for (K key : keys) { expectExceptionNonStrict(CompletionException.class, CacheException.class, NoSuchElementException.class, () -> method.eval(key, ro, EntryView.ReadEntryView::get)); // The first exception should cause the whole transaction to fail assertEquals(Status.STATUS_MARKED_ROLLBACK, tm.getStatus()); tm.rollback(); break; } if (tm.getStatus() == Status.STATUS_ACTIVE) { tm.commit(); } }
@Test(dataProvider = "owningModeAndReadWrites") public void testWriteModsInTxContext(boolean isOwner, WriteMethod method) throws Exception { Object KEY = getKey(isOwner, DIST); cache(0, DIST).put(KEY, "a"); tm.begin(); assertEquals("a", cache(0, DIST).put(KEY, "b")); // read-write operation should execute locally instead assertEquals("b", method.eval(KEY, null, rw, EntryView.ReadEntryView::get, (e, prev) -> e.set(prev + "c"), getClass())); // make sure that the operation was executed in context assertEquals("bc", ro.eval(KEY, MarshallableFunctions.returnReadOnlyFindOrNull()).join()); tm.commit(); }
@Override public V get(Object key) { return await(readOnly.eval(toK(key), returnReadOnlyFindOrNull())); }
@Override public boolean containsKey(K key) { return await(readOnly.eval(key, returnReadOnlyFindIsPresent())); }
@Override public int size() { return (int) readOnly.keys().count(); }
@Override public String getName() { return readOnly.getName(); }
@Override public boolean isClosed() { return readOnly.getStatus().isTerminated(); }
@Override public Collection<V> values() { return readOnly.entries().collect(ArrayList::new, (l, v) -> l.add(v.get()), ArrayList::addAll); }
@Override public boolean isEmpty() { return !readOnly.keys().findAny().isPresent(); }
@Override protected void workerLogic(Cache<Integer, Integer> cache, Set<Integer> threadKeys, int iteration) { FunctionalMap.ReadOnlyMap<Integer, Integer> ro = ReadOnlyMapImpl.create(FunctionalMapImpl.create(cache.getAdvancedCache())); List<CompletableFuture> futures = new ArrayList(threadKeys.size()); for (Integer key : threadKeys) { futures.add(ro.eval(key, (view -> view.get() + 1)).thenAccept(value -> assertEquals(Integer.valueOf(key + 1), value))); } futures.stream().forEach(f -> f.join()); } }
@Override public Set<Entry<K, V>> entrySet() { return readOnly.entries().collect(HashSet::new, (s, ro) -> s.add(new FunctionalMapEntry<>(ro, writeOnly)), HashSet::addAll); }