private Boolean removeKeyValue(EntryView.ReadWriteEntryView<K, Collection<V>> entryView) { return entryView.find().map(values -> { if (values.contains(value)) { Collection<V> newValues = new HashSet<>(); newValues.addAll(values); newValues.remove(value); if (newValues.isEmpty()) { // If the collection is empty after remove, remove the key entryView.remove(); } else { entryView.set(newValues); } return newValues.size() < values.size(); } else { return Boolean.FALSE; } } ).orElse(Boolean.FALSE); }
@Override public Void apply(EntryView.ReadWriteEntryView<Object, Object> view) { if (trace) { log.tracef("Applying %s to %s", this, view.find().orElse(null)); view.set(this, region.getExpiringMetaParam()); return null; Object oldValue = view.find().orElse(null); Object oldVersion = null; long oldTimestamp = Long.MIN_VALUE; view.set(value instanceof CacheEntry ? value : this); view.set(new VersionedEntry(null, null, timestamp), region.getExpiringMetaParam()); } else { int compareResult = versionComparator.compare(version, oldVersion); view.set(this, region.getExpiringMetaParam()); } else if (compareResult > 0) { view.set(value instanceof CacheEntry ? value : this);
rw.eval(key, view -> view.set(view.get() + "+2")).join(); assertEquals("v1+2", backup.get(key)); rw.evalMany(Util.asSet(keys), view -> view.set(view.get() + "+3")) .forEach(ret -> assertEquals(null, ret)); for (Object key : keys) { rw.evalMany(Util.asSet(keys), view -> view.find().orElse("none")) .forEach(ret -> assertEquals("none", ret)); for (Object key : keys) { rw.eval(keys[0], "v4", MarshallableFunctions.setValueReturnPrevOrNull()).join(); rw.evalMany(Util.asSet(keys[1], keys[2]), view -> view.find().orElse("none")) .forEach(ret -> assertEquals("none", ret)); tm.commit();
@Override public Boolean apply(EntryView.ReadWriteEntryView<ClusteredLockKey, ClusteredLockValue> entryView) { if (trace) { log.tracef("Lock[%s] unlock request by reqId [%s] requestors %s", entryView.key().getName(), requestId, requestors); ClusteredLockValue lockValue = entryView.find().orElseThrow(() -> log.lockDeleted()); log.tracef("Lock[%s] Already free. State[RELEASED], reqId [%s], owner [%s]", entryView.key().getName(), lockValue.getRequestId(), lockValue.getOwner()); log.tracef("Lock[%s] Unlocked by reqId [%s] requestors %s", entryView.key().getName(), requestId, requestors); entryView.set(ClusteredLockValue.INITIAL_STATE); return Boolean.TRUE; entryView.key().getName(), requestId, requestors,
try { rw1.eval(new UserType<>(1, "key"), view -> { assertFalse(view.find().isPresent()); view.set(new UserType<>(1, "value")); return null; }); rw2.eval(new UserType<>(2, "key"), view -> { UserType<String> value = view.find().orElseThrow(() -> new AssertionError()); assertEquals(2, value.type); assertEquals("value", value.instance); view.set(new UserType<>(2, "value2")); return null; });
public void testUnsupportedCommands() { Cache<String, String> cache0 = cache(0); assertTrue(cache0.isEmpty()); try { cache0.compute("test.proto", (k, v) -> "import \"missing.proto\";"); } catch (Exception e) { assertTrue(e instanceof CacheException); assertTrue(e.getMessage().contains("ISPN028014")); } assertTrue(cache0.isEmpty()); try { FunctionalMap.ReadWriteMap<String, String> rwMap = ReadWriteMapImpl.create(FunctionalMapImpl.create(cache0.getAdvancedCache())); rwMap.eval("test.proto", "val", (value, view) -> { view.set(value); return "ret"; }).join(); } catch (CompletionException e) { assertTrue(e.getCause() instanceof CacheException); assertTrue(e.getCause().getMessage().contains("ISPN028014")); } assertTrue(cache0.isEmpty()); assertNoTransactionsAndLocks(); }
@Override public Void apply(EntryView.ReadWriteEntryView<Object, Object> view) { Object storedValue = view.find().orElse(null); if (value == null) { if (storedValue != null && !(storedValue instanceof Tombstone)) { // We have to keep Tombstone, because otherwise putFromLoad could insert a stale entry // (after it has been already updated and *then* evicted) view.set(new Tombstone(ZERO, timestamp), region.getExpiringMetaParam()); } // otherwise it's eviction } else if (storedValue instanceof Tombstone) { Tombstone tombstone = (Tombstone) storedValue; if (tombstone.getLastTimestamp() < timestamp) { view.set(value); } } else if (storedValue == null) { // async putFromLoads shouldn't cross the invalidation timestamp if (region.getLastRegionInvalidation() < timestamp) { view.set(value); } } else { // Don't do anything locally. This could be the async remote write, though, when local // value has been already updated: let it propagate to remote nodes, too view.set(storedValue, view.findMetaParam(MetaParam.MetaLifespan.class).get()); } return null; }
@Override public Boolean apply(EntryView.ReadWriteEntryView<ClusteredLockKey, ClusteredLockValue> entryView) { ClusteredLockValue lock = entryView.find().orElseThrow(() -> log.lockDeleted()); if (trace) { log.tracef("LOCK[%s] lock request by reqId %s requestor %s", entryView.key().getName(), requestId, requestor); } if (lock.getState() == ClusteredLockState.RELEASED) { entryView.set(new ClusteredLockValue(requestId, requestor, ClusteredLockState.ACQUIRED)); if (trace) { log.tracef("LOCK[%s] lock acquired by %s %s", entryView.key().getName(), requestId, requestor); } return Boolean.TRUE; } else if (lock.getState() == ClusteredLockState.ACQUIRED && lock.getRequestId().equals(requestId) && lock.getOwner().equals(requestor)) { log.tracef("LOCK[%s] lock already acquired by %s %s", entryView.key().getName(), requestId, requestor); return Boolean.TRUE; } if (trace) { log.tracef("LOCK[%s] lock not available, owned by %s %s", entryView.key().getName(), lock.getRequestId(), lock.getOwner()); } return Boolean.FALSE; }
/** * Read-write allows for replace operations to happen based on version * comparison, and update version information if replace is versions are * equals. * * This is the kind of advance operation that Hot Rod prototocol requires * but the current Infinispan API is unable to offer without offering * atomicity at the level of the function that compares the version * information. */ <K> void doReadWriteForConditionalParamBasedReplace(Supplier<K> keySupplier, ReadWriteMap<K, String> map1, ReadWriteMap<K, String> map2) { replaceWithVersion(keySupplier, map1, map2, 100, rw -> { assertEquals("uno", rw.get()); assertEquals(Optional.of(new MetaEntryVersion(new NumericVersion(200))), rw.findMetaParam(MetaEntryVersion.class)); } ); replaceWithVersion(keySupplier, map1, map2, 900, rw -> { assertEquals(Optional.of("one"), rw.find()); assertEquals(Optional.of(new MetaEntryVersion(new NumericVersion(100))), rw.findMetaParam(MetaEntryVersion.class)); }); }
@Override public Void apply(EntryView.ReadWriteEntryView<Object, Object> view) { Object storedValue = view.find().orElse(null); if (storedValue instanceof Tombstone) { // Note that the update has to keep tombstone even if the transaction was unsuccessful; // before write we have removed the value and we have to protect the entry against stale putFromLoads Tombstone tombstone = (Tombstone) storedValue; Object result = tombstone.applyUpdate(uuid, timestamp, this.value); if (result instanceof Tombstone) { view.set(result, region.getExpiringMetaParam()); } else { view.set(result); } } // Else: this is an async future update, and it's timestamp may be vastly outdated // We need to first execute the async update and then local one, because if we're on the primary // owner the local future update would fail the async one. // TODO: There is some discrepancy with TombstoneUpdate handling which does not fail the update return null; }
@Override protected Object perform(TestWriteOperation op, AdvancedCache<Object, Object> cache0, String key) { try { return super.perform(op, cache0, key); } catch (IllegalArgumentException e) { switch (op) { case REPLACE_META_FUNCTIONAL: return FunctionalTestUtils.await(rw(cache0).eval(key, "v1", (v, rw) -> { return rw.findMetaParam(MetaEntryVersion.class) .filter(ver -> ver.get().compareTo(new NumericVersion(1)) == EQUAL) .map(ver -> { rw.set(v, new MetaEntryVersion(new NumericVersion(2))); return true; }).orElse(false); })); default: throw new AssertionError("Unknown operation: " + op); } } }
@Override public Optional<BucketConfiguration> getConfiguration(K key) { try { SerializableFunction<EntryView.ReadWriteEntryView<K, GridBucketState>, GridBucketState> findFunction = (SerializableFunction<EntryView.ReadWriteEntryView<K, GridBucketState>, GridBucketState>) entry -> entry.find().orElse(null); GridBucketState state = readWriteMap.eval(key, findFunction).get(); if (state == null) { return Optional.empty(); } else { return Optional.of(state.getConfiguration()); } } catch (InterruptedException | ExecutionException e) { throw new CacheException(e); } }
private byte advanceToRollback(EntryView.ReadWriteEntryView<CacheXid, TxState> view) { TxState state = view.get(); Status prevState = state.getStatus(); //we can rollback if the transaction is running or prepared switch (prevState) { case ACTIVE: case PREPARED: case PREPARING: view.set(state.setStatus(MARK_ROLLBACK, true, timeService)); case MARK_ROLLBACK: return OK.value; default: //any other status, we return it to the caller to decide what to do. return prevState.value; } }
@Override public Optional<BucketConfiguration> getConfiguration(K key) { try { SerializableFunction<EntryView.ReadWriteEntryView<K, GridBucketState>, GridBucketState> findFunction = (SerializableFunction<EntryView.ReadWriteEntryView<K, GridBucketState>, GridBucketState>) entry -> entry.find().orElse(null); GridBucketState state = readWriteMap.eval(key, findFunction).get(); if (state == null) { return Optional.empty(); } else { return Optional.of(state.getConfiguration()); } } catch (InterruptedException | ExecutionException e) { throw new CacheException(e); } }
@Override public Byte apply(EntryView.ReadWriteEntryView<CacheXid, TxState> view) { if (view.find().isPresent()) { TxState state = view.get(); switch (state.getStatus()) { case ACTIVE: view.set(state.markPreparing(modifications, timeService)); case PREPARING: return OK.value; default: return state.getStatus().value; } } else { return NO_TRANSACTION.value; } }