diff --git a/commons/src/main/java/org/infinispan/commons/marshall/Ids.java b/commons/src/main/java/org/infinispan/commons/marshall/Ids.java index 2af2a3649d4f..ce4a56535179 100644 --- a/commons/src/main/java/org/infinispan/commons/marshall/Ids.java +++ b/commons/src/main/java/org/infinispan/commons/marshall/Ids.java @@ -22,5 +22,6 @@ public interface Ids { // Functional lambdas int LAMBDA_CONSTANT = 158; int LAMBDA_SET_VALUE_IF_EQUALS_RETURN_BOOLEAN = 159; + int LAMBDA_WITH_METAS = 160; } diff --git a/commons/src/main/java/org/infinispan/commons/marshall/MarshallableLambdaExternalizers.java b/commons/src/main/java/org/infinispan/commons/marshall/MarshallableLambdaExternalizers.java index 0e7af1dbffb7..b0c79573b8da 100644 --- a/commons/src/main/java/org/infinispan/commons/marshall/MarshallableLambdaExternalizers.java +++ b/commons/src/main/java/org/infinispan/commons/marshall/MarshallableLambdaExternalizers.java @@ -1,5 +1,6 @@ package org.infinispan.commons.marshall; +import org.infinispan.commons.api.functional.MetaParam; import org.infinispan.commons.util.Util; import org.jboss.marshalling.util.IdentityIntMap; @@ -12,31 +13,31 @@ public class MarshallableLambdaExternalizers { + private static final short VALUE_MATCH_ALWAYS = 0x1000; + private static final short VALUE_MATCH_EXPECTED = 0x2000; + private static final short VALUE_MATCH_EXPECTED_OR_NEW = 0x3000; + private static final short VALUE_MATCH_NON_NULL = 0x4000; + private static final short VALUE_MATCH_NEVER = 0x5000; + + private static final int VALUE_MATCH_MASK = 0xF000; + + private static final int SET_VALUE_RETURN_PREV_OR_NULL = 1 | VALUE_MATCH_ALWAYS; + private static final int SET_VALUE_RETURN_VIEW = 2 | VALUE_MATCH_ALWAYS; + private static final int SET_VALUE_IF_ABSENT_RETURN_PREV_OR_NULL = 3 | VALUE_MATCH_EXPECTED; + private static final int SET_VALUE_IF_ABSENT_RETURN_BOOLEAN = 4 | VALUE_MATCH_EXPECTED; + private static final int SET_VALUE_IF_PRESENT_RETURN_PREV_OR_NULL = 5 | VALUE_MATCH_NON_NULL; + private static final int SET_VALUE_IF_PRESENT_RETURN_BOOLEAN = 6 | VALUE_MATCH_NON_NULL; + private static final int REMOVE_RETURN_PREV_OR_NULL = 7 | VALUE_MATCH_ALWAYS; + private static final int REMOVE_RETURN_BOOLEAN = 8 | VALUE_MATCH_ALWAYS; + private static final int REMOVE_IF_VALUE_EQUALS_RETURN_BOOLEAN = 9 | VALUE_MATCH_EXPECTED; + private static final int SET_VALUE_CONSUMER = 10 | VALUE_MATCH_ALWAYS; + private static final int REMOVE_CONSUMER = 11 | VALUE_MATCH_ALWAYS; + private static final int RETURN_READ_WRITE_FIND = 12 | VALUE_MATCH_ALWAYS; + private static final int RETURN_READ_WRITE_GET = 13 | VALUE_MATCH_ALWAYS; + private static final int RETURN_READ_WRITE_VIEW = 14 | VALUE_MATCH_ALWAYS; + public static final class ConstantLambdaExternalizer implements LambdaExternalizer { - private static final short VALUE_MATCH_ALWAYS = 0x1000; - private static final short VALUE_MATCH_EXPECTED = 0x2000; - private static final short VALUE_MATCH_EXPECTED_OR_NEW = 0x3000; - private static final short VALUE_MATCH_NON_NULL = 0x4000; - private static final short VALUE_MATCH_NEVER = 0x5000; - - private static final int VALUE_MATCH_MASK = 0xF000; - - private static final int SET_VALUE_RETURN_PREV_OR_NULL = 1 | VALUE_MATCH_ALWAYS; - private static final int SET_VALUE_RETURN_VIEW = 2 | VALUE_MATCH_ALWAYS; - private static final int SET_VALUE_IF_ABSENT_RETURN_PREV_OR_NULL = 3 | VALUE_MATCH_EXPECTED; - private static final int SET_VALUE_IF_ABSENT_RETURN_BOOLEAN = 4 | VALUE_MATCH_EXPECTED; - private static final int SET_VALUE_IF_PRESENT_RETURN_PREV_OR_NULL = 5 | VALUE_MATCH_NON_NULL; - private static final int SET_VALUE_IF_PRESENT_RETURN_BOOLEAN = 6 | VALUE_MATCH_NON_NULL; - private static final int REMOVE_RETURN_PREV_OR_NULL = 7 | VALUE_MATCH_ALWAYS; - private static final int REMOVE_RETURN_BOOLEAN = 8 | VALUE_MATCH_ALWAYS; - private static final int REMOVE_IF_VALUE_EQUALS_RETURN_BOOLEAN = 9 | VALUE_MATCH_EXPECTED; - private static final int SET_VALUE_CONSUMER = 10 | VALUE_MATCH_ALWAYS; - private static final int REMOVE_CONSUMER = 11 | VALUE_MATCH_ALWAYS; - private static final int RETURN_READ_WRITE_FIND = 12 | VALUE_MATCH_ALWAYS; - private static final int RETURN_READ_WRITE_GET = 13 | VALUE_MATCH_ALWAYS; - private static final int RETURN_READ_WRITE_VIEW = 14 | VALUE_MATCH_ALWAYS; - - private final IdentityIntMap> numbers = new IdentityIntMap<>(12); + private final IdentityIntMap> numbers = new IdentityIntMap<>(16); public ConstantLambdaExternalizer() { numbers.put(setValueReturnPrevOrNull().getClass(), SET_VALUE_RETURN_PREV_OR_NULL); @@ -119,16 +120,100 @@ public Object readObject(ObjectInput input) throws IOException { } } + public static final class LambdaWithMetasExternalizer implements LambdaExternalizer { + private final IdentityIntMap> numbers = new IdentityIntMap<>(8); + + public LambdaWithMetasExternalizer() { + numbers.put(SetValueMetasReturnPrevOrNull.class, SET_VALUE_RETURN_PREV_OR_NULL); + numbers.put(SetValueMetasReturnView.class, SET_VALUE_RETURN_VIEW); + numbers.put(SetValueMetasIfAbsentReturnPrevOrNull.class, SET_VALUE_IF_ABSENT_RETURN_PREV_OR_NULL); + numbers.put(SetValueMetasIfAbsentReturnBoolean.class, SET_VALUE_IF_ABSENT_RETURN_BOOLEAN); + numbers.put(SetValueMetasIfPresentReturnPrevOrNull.class, SET_VALUE_IF_PRESENT_RETURN_PREV_OR_NULL); + numbers.put(SetValueMetasIfPresentReturnBoolean.class, SET_VALUE_IF_PRESENT_RETURN_BOOLEAN); + numbers.put(SetValueMetas.class, SET_VALUE_CONSUMER); + } + + @Override + public ValueMatcherMode valueMatcher(Object o) { + // TODO: Code duplication + int i = numbers.get(o.getClass(), -1); + if (i > 0) { + int valueMatcherId = ((i & VALUE_MATCH_MASK) >> 12) - 1; + return ValueMatcherMode.values()[valueMatcherId]; + } + + return ValueMatcherMode.MATCH_ALWAYS; + } + + @Override + public Set> getTypeClasses() { + return Util.>asSet( + SetValueMetasReturnPrevOrNull.class, + SetValueMetasReturnView.class, + SetValueMetasIfAbsentReturnPrevOrNull.class, + SetValueMetasIfAbsentReturnBoolean.class, + SetValueMetasIfPresentReturnPrevOrNull.class, + SetValueMetasIfPresentReturnBoolean.class, + SetValueMetas.class + ); + } + + @Override + public Integer getId() { + return Ids.LAMBDA_WITH_METAS; + } + + @Override + public void writeObject(ObjectOutput oo, LambdaWithMetas o) throws IOException { + int id = numbers.get(o.getClass(), -1); + oo.writeShort(id); + writeMetas(oo, o); + } + + @Override + public LambdaWithMetas readObject(ObjectInput input) throws IOException, ClassNotFoundException { + short id = input.readShort(); + MetaParam.Writable[] metas = readMetas(input); + switch (id) { + case SET_VALUE_RETURN_PREV_OR_NULL: return new SetValueMetasReturnPrevOrNull<>(metas); + case SET_VALUE_IF_ABSENT_RETURN_PREV_OR_NULL: return new SetValueMetasIfAbsentReturnPrevOrNull<>(metas); + case SET_VALUE_IF_ABSENT_RETURN_BOOLEAN: return new SetValueMetasIfAbsentReturnBoolean<>(metas); + case SET_VALUE_RETURN_VIEW: return new SetValueMetasReturnView<>(metas); + case SET_VALUE_IF_PRESENT_RETURN_PREV_OR_NULL: return new SetValueMetasIfPresentReturnPrevOrNull<>(metas); + case SET_VALUE_IF_PRESENT_RETURN_BOOLEAN: return new SetValueMetasIfPresentReturnBoolean<>(metas); + case SET_VALUE_CONSUMER: return new SetValueMetas<>(metas); + default: + throw new IllegalStateException("Unknown lambda and meta parameters with ID: " + id); + } + } + } + + static MetaParam.Writable[] readMetas(ObjectInput input) throws IOException, ClassNotFoundException { + int len = input.readInt(); + MetaParam.Writable[] metas = new MetaParam.Writable[len]; + for(int i = 0; i < len; i++) + metas[i] = (MetaParam.Writable) input.readObject(); + return metas; + } + + private static void writeMetas(ObjectOutput oo, LambdaWithMetas o) throws IOException { + oo.writeInt(o.metas().length); + for (MetaParam.Writable meta : o.metas()) + oo.writeObject(meta); + } + public static final class SetValueIfEqualsReturnBooleanExternalizer implements LambdaExternalizer { public void writeObject(ObjectOutput oo, SetValueIfEqualsReturnBoolean o) throws IOException { oo.writeObject(o.oldValue); + writeMetas(oo, o); } public SetValueIfEqualsReturnBoolean readObject(ObjectInput input) throws IOException, ClassNotFoundException { Object oldValue = input.readObject(); - return new SetValueIfEqualsReturnBoolean<>(oldValue); + MetaParam.Writable[] metas = readMetas(input); + return new SetValueIfEqualsReturnBoolean<>(oldValue, metas); } @Override diff --git a/commons/src/main/java/org/infinispan/commons/marshall/MarshallableLambdas.java b/commons/src/main/java/org/infinispan/commons/marshall/MarshallableLambdas.java index ef5def40ffd7..6e63a59ce3f7 100644 --- a/commons/src/main/java/org/infinispan/commons/marshall/MarshallableLambdas.java +++ b/commons/src/main/java/org/infinispan/commons/marshall/MarshallableLambdas.java @@ -2,6 +2,7 @@ import org.infinispan.commons.api.functional.EntryView.ReadWriteEntryView; import org.infinispan.commons.api.functional.EntryView.WriteEntryView; +import org.infinispan.commons.api.functional.MetaParam; import java.util.Optional; import java.util.function.BiConsumer; @@ -15,28 +16,52 @@ public static BiFunction, V> setValueReturnPr return SetValueReturnPrevOrNull.getInstance(); } + public static BiFunction, V> setValueMetasReturnPrevOrNull(MetaParam.Writable... metas) { + return new SetValueMetasReturnPrevOrNull<>(metas); + } + public static BiFunction, ReadWriteEntryView> setValueReturnView() { return SetValueReturnView.getInstance(); } + public static BiFunction, ReadWriteEntryView> setValueMetasReturnView(MetaParam.Writable... metas) { + return new SetValueMetasReturnView<>(metas); + } + public static BiFunction, V> setValueIfAbsentReturnPrevOrNull() { return SetValueIfAbsentReturnPrevOrNull.getInstance(); } + public static BiFunction, V> setValueMetasIfAbsentReturnPrevOrNull(MetaParam.Writable... metas) { + return new SetValueMetasIfAbsentReturnPrevOrNull<>(metas); + } + public static BiFunction, Boolean> setValueIfAbsentReturnBoolean() { return SetValueIfAbsentReturnBoolean.getInstance(); } + public static BiFunction, Boolean> setValueMetasIfAbsentReturnBoolean(MetaParam.Writable... metas) { + return new SetValueMetasIfAbsentReturnBoolean<>(metas); + } + public static BiFunction, V> setValueIfPresentReturnPrevOrNull() { return SetValueIfPresentReturnPrevOrNull.getInstance(); } + public static BiFunction, V> setValueMetasIfPresentReturnPrevOrNull(MetaParam.Writable... metas) { + return new SetValueMetasIfPresentReturnPrevOrNull<>(metas); + } + public static BiFunction, Boolean> setValueIfPresentReturnBoolean() { return SetValueIfPresentReturnBoolean.getInstance(); } - public static BiFunction, Boolean> setValueIfEqualsReturnBoolean(V oldValue) { - return new SetValueIfEqualsReturnBoolean<>(oldValue); + public static BiFunction, Boolean> setValueMetasIfPresentReturnBoolean(MetaParam.Writable... metas) { + return new SetValueMetasIfPresentReturnBoolean<>(metas); + } + + public static BiFunction, Boolean> setValueIfEqualsReturnBoolean(V oldValue, MetaParam.Writable... metas) { + return new SetValueIfEqualsReturnBoolean<>(oldValue, metas); } public static Function, V> removeReturnPrevOrNull() { @@ -55,6 +80,10 @@ public static BiConsumer> setValueConsumer() { return SetValue.getInstance(); } + public static BiConsumer> setValueMetasConsumer(MetaParam.Writable... metas) { + return new SetValueMetas<>(metas); + } + public static Consumer> removeConsumer() { return Remove.getInstance(); } @@ -71,129 +100,288 @@ public static Function, ReadWriteEntryView return ReturnReadWriteView.getInstance(); } - private static final class SetValueReturnPrevOrNull + private static abstract class AbstractSetValueReturnPrevOrNull implements BiFunction, V> { + final MetaParam.Writable[] metas; + + protected AbstractSetValueReturnPrevOrNull(MetaParam.Writable[] metas) { + this.metas = metas; + } + @Override public V apply(V v, ReadWriteEntryView rw) { V prev = rw.find().orElse(null); - rw.set(v); + rw.set(v, metas); return prev; } + } - private static final SetValueReturnPrevOrNull INSTANCE = new SetValueReturnPrevOrNull<>(); + private static final class SetValueReturnPrevOrNull extends AbstractSetValueReturnPrevOrNull { + protected SetValueReturnPrevOrNull(MetaParam.Writable[] metas) { + super(metas); + } + + private static final SetValueReturnPrevOrNull INSTANCE = + new SetValueReturnPrevOrNull<>(new MetaParam.Writable[0]); @SuppressWarnings("unchecked") private static BiFunction, V> getInstance() { return SetValueReturnPrevOrNull.INSTANCE; } } - private static final class SetValueReturnView + interface LambdaWithMetas { + MetaParam.Writable[] metas(); + } + + static final class SetValueMetasReturnPrevOrNull + extends AbstractSetValueReturnPrevOrNull implements LambdaWithMetas { + SetValueMetasReturnPrevOrNull(MetaParam.Writable[] metas) { + super(metas); + } + + @Override + public MetaParam.Writable[] metas() { + return metas; + } + } + + private static abstract class AbstractSetValueReturnView implements BiFunction, ReadWriteEntryView> { + final MetaParam.Writable[] metas; + + protected AbstractSetValueReturnView(MetaParam.Writable[] metas) { + this.metas = metas; + } + @Override public ReadWriteEntryView apply(V v, ReadWriteEntryView rw) { rw.set(v); return rw; } + } - private static final SetValueReturnView INSTANCE = new SetValueReturnView<>(); + private static final class SetValueReturnView extends AbstractSetValueReturnView { + protected SetValueReturnView(MetaParam.Writable[] metas) { + super(metas); + } + + private static final SetValueReturnView INSTANCE = new SetValueReturnView<>(new MetaParam.Writable[]{}); @SuppressWarnings("unchecked") private static BiFunction, ReadWriteEntryView> getInstance() { return SetValueReturnView.INSTANCE; } } - private static final class SetValueIfAbsentReturnPrevOrNull + static final class SetValueMetasReturnView extends AbstractSetValueReturnView implements LambdaWithMetas { + protected SetValueMetasReturnView(MetaParam.Writable[] metas) { + super(metas); + } + + @Override + public MetaParam.Writable[] metas() { + return metas; + } + } + + private static abstract class AbstractSetValueIfAbsentReturnPrevOrNull implements BiFunction, V> { + final MetaParam.Writable[] metas; + + protected AbstractSetValueIfAbsentReturnPrevOrNull(MetaParam.Writable[] metas) { + this.metas = metas; + } + @Override public V apply(V v, ReadWriteEntryView rw) { Optional opt = rw.find(); V prev = opt.orElse(null); if (!opt.isPresent()) - rw.set(v); + rw.set(v, metas); return prev; } + } + + private static final class SetValueIfAbsentReturnPrevOrNull + extends AbstractSetValueIfAbsentReturnPrevOrNull { + protected SetValueIfAbsentReturnPrevOrNull(MetaParam.Writable[] metas) { + super(metas); + } private static final SetValueIfAbsentReturnPrevOrNull INSTANCE = - new SetValueIfAbsentReturnPrevOrNull<>(); + new SetValueIfAbsentReturnPrevOrNull<>(new MetaParam.Writable[]{}); @SuppressWarnings("unchecked") private static BiFunction, V> getInstance() { return SetValueIfAbsentReturnPrevOrNull.INSTANCE; } } - private static final class SetValueIfAbsentReturnBoolean + static final class SetValueMetasIfAbsentReturnPrevOrNull + extends AbstractSetValueIfAbsentReturnPrevOrNull implements LambdaWithMetas { + protected SetValueMetasIfAbsentReturnPrevOrNull(MetaParam.Writable[] metas) { + super(metas); + } + + @Override + public MetaParam.Writable[] metas() { + return metas; + } + } + + private static abstract class AbstractSetValueIfAbsentReturnBoolean implements BiFunction, Boolean> { + final MetaParam.Writable[] metas; + + private AbstractSetValueIfAbsentReturnBoolean(MetaParam.Writable[] metas) { + this.metas = metas; + } + @Override public Boolean apply(V v, ReadWriteEntryView rw) { Optional opt = rw.find(); boolean success = !opt.isPresent(); - if (success) rw.set(v); + if (success) rw.set(v, metas); return success; } + } + + private static final class SetValueIfAbsentReturnBoolean + extends AbstractSetValueIfAbsentReturnBoolean { + private SetValueIfAbsentReturnBoolean(MetaParam.Writable[] metas) { + super(metas); + } private static final SetValueIfAbsentReturnBoolean INSTANCE = - new SetValueIfAbsentReturnBoolean<>(); + new SetValueIfAbsentReturnBoolean<>(new MetaParam.Writable[]{}); @SuppressWarnings("unchecked") private static BiFunction, Boolean> getInstance() { return SetValueIfAbsentReturnBoolean.INSTANCE; } } - private static final class SetValueIfPresentReturnPrevOrNull + static final class SetValueMetasIfAbsentReturnBoolean + extends AbstractSetValueIfAbsentReturnBoolean implements LambdaWithMetas { + SetValueMetasIfAbsentReturnBoolean(MetaParam.Writable[] metas) { + super(metas); + } + + @Override + public MetaParam.Writable[] metas() { + return metas; + } + } + + private static abstract class AbstractSetValueIfPresentReturnPrevOrNull implements BiFunction, V> { + final MetaParam.Writable[] metas; + + protected AbstractSetValueIfPresentReturnPrevOrNull(MetaParam.Writable[] metas) { + this.metas = metas; + } + @Override public V apply(V v, ReadWriteEntryView rw) { return rw.find().map(prev -> { - rw.set(v); + rw.set(v, metas); return prev; }).orElse(null); } + } + + private static final class SetValueIfPresentReturnPrevOrNull + extends AbstractSetValueIfPresentReturnPrevOrNull { + protected SetValueIfPresentReturnPrevOrNull(MetaParam.Writable[] metas) { + super(metas); + } private static final SetValueIfPresentReturnPrevOrNull INSTANCE = - new SetValueIfPresentReturnPrevOrNull<>(); + new SetValueIfPresentReturnPrevOrNull<>(new MetaParam.Writable[]{}); @SuppressWarnings("unchecked") private static BiFunction, V> getInstance() { return SetValueIfPresentReturnPrevOrNull.INSTANCE; } } - private static final class SetValueIfPresentReturnBoolean + static final class SetValueMetasIfPresentReturnPrevOrNull + extends AbstractSetValueIfPresentReturnPrevOrNull implements LambdaWithMetas { + protected SetValueMetasIfPresentReturnPrevOrNull(MetaParam.Writable[] metas) { + super(metas); + } + + @Override + public MetaParam.Writable[] metas() { + return metas; + } + } + + private static abstract class AbstractSetValueIfPresentReturnBoolean implements BiFunction, Boolean> { + final MetaParam.Writable[] metas; + + private AbstractSetValueIfPresentReturnBoolean(MetaParam.Writable[] metas) { + this.metas = metas; + } + @Override public Boolean apply(V v, ReadWriteEntryView rw) { return rw.find().map(prev -> { - rw.set(v); + rw.set(v, metas); return true; }).orElse(false); } + } + + private static final class SetValueIfPresentReturnBoolean + extends AbstractSetValueIfPresentReturnBoolean { + private SetValueIfPresentReturnBoolean(MetaParam.Writable[] metas) { + super(metas); + } private static final SetValueIfPresentReturnBoolean INSTANCE = - new SetValueIfPresentReturnBoolean<>(); + new SetValueIfPresentReturnBoolean<>(new MetaParam.Writable[]{}); @SuppressWarnings("unchecked") private static BiFunction, Boolean> getInstance() { return SetValueIfPresentReturnBoolean.INSTANCE; } } + static final class SetValueMetasIfPresentReturnBoolean + extends AbstractSetValueIfPresentReturnBoolean implements LambdaWithMetas { + SetValueMetasIfPresentReturnBoolean(MetaParam.Writable[] metas) { + super(metas); + } + + @Override + public MetaParam.Writable[] metas() { + return metas; + } + } + static final class SetValueIfEqualsReturnBoolean - implements BiFunction, Boolean> { + implements BiFunction, Boolean>, LambdaWithMetas { final V oldValue; + final MetaParam.Writable[] metas; - public SetValueIfEqualsReturnBoolean(V oldValue) { + public SetValueIfEqualsReturnBoolean(V oldValue, MetaParam.Writable[] metas) { this.oldValue = oldValue; + this.metas = metas; } @Override public Boolean apply(V v, ReadWriteEntryView rw) { return rw.find().map(prev -> { if (prev.equals(oldValue)) { - rw.set(v); + rw.set(v, metas); return true; } return false; }).orElse(false); } + + @Override + public MetaParam.Writable[] metas() { + return metas; + } } private static final class RemoveReturnPrevOrNull @@ -250,19 +438,42 @@ private static BiFunction, Boolean> getInstan } } - private static final class SetValue implements BiConsumer> { + private static abstract class AbstractSetValue implements BiConsumer> { + final MetaParam.Writable[] metas; + + protected AbstractSetValue(MetaParam.Writable[] metas) { + this.metas = metas; + } + @Override public void accept(V v, WriteEntryView wo) { - wo.set(v); + wo.set(v, metas); + } + } + + private static final class SetValue extends AbstractSetValue { + protected SetValue(MetaParam.Writable[] metas) { + super(metas); } - private static final SetValue INSTANCE = new SetValue<>(); + private static final SetValue INSTANCE = new SetValue<>(new MetaParam.Writable[0]); @SuppressWarnings("unchecked") private static BiConsumer> getInstance() { return SetValue.INSTANCE; } } + static final class SetValueMetas extends AbstractSetValue implements LambdaWithMetas { + SetValueMetas(MetaParam.Writable[] metas) { + super(metas); + } + + @Override + public MetaParam.Writable[] metas() { + return metas; + } + } + private static final class Remove implements Consumer> { @Override public void accept(WriteEntryView wo) { diff --git a/core/src/main/java/org/infinispan/marshall/core/ExternalizerTable.java b/core/src/main/java/org/infinispan/marshall/core/ExternalizerTable.java index 1b2b5ed637c1..6447fef4946d 100644 --- a/core/src/main/java/org/infinispan/marshall/core/ExternalizerTable.java +++ b/core/src/main/java/org/infinispan/marshall/core/ExternalizerTable.java @@ -379,6 +379,7 @@ private void loadInternalMarshallables() { addInternalExternalizer(new EntryViews.ReadWriteSnapshotViewExternalizer()); addInternalExternalizer(new MarshallableLambdaExternalizers.ConstantLambdaExternalizer()); + addInternalExternalizer(new MarshallableLambdaExternalizers.LambdaWithMetasExternalizer()); addInternalExternalizer(new MarshallableLambdaExternalizers.SetValueIfEqualsReturnBooleanExternalizer()); } diff --git a/core/src/test/java/org/infinispan/expiry/ExpiryTest.java b/core/src/test/java/org/infinispan/expiry/ExpiryTest.java index 1d2469dd5f71..98575864bd4f 100644 --- a/core/src/test/java/org/infinispan/expiry/ExpiryTest.java +++ b/core/src/test/java/org/infinispan/expiry/ExpiryTest.java @@ -51,7 +51,7 @@ public void tearDown() { } public void testLifespanExpiryInPut() throws InterruptedException { - Cache cache = cm.getCache(); + Cache cache = getCache(); long lifespan = EXPIRATION_TIMEOUT; cache.put("k", "v", lifespan, MILLISECONDS); @@ -68,8 +68,12 @@ public void testLifespanExpiryInPut() throws InterruptedException { assert cache.get("k") == null; } + protected Cache getCache() { + return cm.getCache(); + } + public void testIdleExpiryInPut() throws InterruptedException { - Cache cache = cm.getCache(); + Cache cache = getCache(); long idleTime = IDLE_TIMEOUT; cache.put("k", "v", -1, MILLISECONDS, idleTime, MILLISECONDS); @@ -87,7 +91,7 @@ public void testIdleExpiryInPut() throws InterruptedException { } public void testLifespanExpiryInPutAll() throws InterruptedException { - Cache cache = cm.getCache(); + Cache cache = getCache(); final long lifespan = EXPIRATION_TIMEOUT; Map m = new HashMap(); m.put("k1", "v"); @@ -104,7 +108,7 @@ public void testLifespanExpiryInPutAll() throws InterruptedException { } public void testIdleExpiryInPutAll() throws InterruptedException { - Cache cache = cm.getCache(); + Cache cache = getCache(); final long idleTime = EXPIRATION_TIMEOUT; Map m = new HashMap(); m.put("k1", "v"); @@ -120,7 +124,7 @@ public void testIdleExpiryInPutAll() throws InterruptedException { } public void testLifespanExpiryInPutIfAbsent() throws InterruptedException { - Cache cache = cm.getCache(); + Cache cache = getCache(); final long lifespan = EXPIRATION_TIMEOUT; assert cache.putIfAbsent("k", "v", lifespan, MILLISECONDS) == null; long partial = lifespan / 10; @@ -136,7 +140,7 @@ public void testLifespanExpiryInPutIfAbsent() throws InterruptedException { } public void testIdleExpiryInPutIfAbsent() throws InterruptedException { - Cache cache = cm.getCache(); + Cache cache = getCache(); long idleTime = EXPIRATION_TIMEOUT; assertNull(cache.putIfAbsent("k", "v", -1, MILLISECONDS, idleTime, MILLISECONDS)); assertEquals("v", cache.get("k")); @@ -150,7 +154,7 @@ public void testIdleExpiryInPutIfAbsent() throws InterruptedException { } public void testLifespanExpiryInReplace() throws InterruptedException { - Cache cache = cm.getCache(); + Cache cache = getCache(); final long lifespan = EXPIRATION_TIMEOUT; assertNull(cache.get("k")); assertNull(cache.replace("k", "v", lifespan, MILLISECONDS)); @@ -174,7 +178,7 @@ public void testLifespanExpiryInReplace() throws InterruptedException { } public void testIdleExpiryInReplace() throws InterruptedException { - Cache cache = cm.getCache(); + Cache cache = getCache(); long idleTime = EXPIRATION_TIMEOUT; assertNull(cache.get("k")); assertNull(cache.replace("k", "v", -1, MILLISECONDS, idleTime, MILLISECONDS)); diff --git a/core/src/test/java/org/infinispan/functional/decorators/FunctionalAdvancedCache.java b/core/src/test/java/org/infinispan/functional/decorators/FunctionalAdvancedCache.java index 8961b040b513..cde8457f0d80 100644 --- a/core/src/test/java/org/infinispan/functional/decorators/FunctionalAdvancedCache.java +++ b/core/src/test/java/org/infinispan/functional/decorators/FunctionalAdvancedCache.java @@ -5,6 +5,14 @@ import org.infinispan.CacheSet; import org.infinispan.atomic.Delta; import org.infinispan.batch.BatchContainer; +import org.infinispan.commons.api.functional.FunctionalMap; +import org.infinispan.commons.api.functional.FunctionalMap.ReadWriteMap; +import org.infinispan.commons.api.functional.FunctionalMap.WriteOnlyMap; +import org.infinispan.commons.api.functional.MetaParam; +import org.infinispan.commons.api.functional.MetaParam.MetaLifespan; +import org.infinispan.commons.api.functional.MetaParam.MetaMaxIdle; +import org.infinispan.commons.api.functional.Param; +import org.infinispan.commons.api.functional.Param.FutureMode; import org.infinispan.commons.util.concurrent.NotifyingFuture; import org.infinispan.configuration.cache.Configuration; import org.infinispan.container.DataContainer; @@ -17,6 +25,9 @@ import org.infinispan.factories.ComponentRegistry; import org.infinispan.filter.KeyFilter; import org.infinispan.filter.KeyValueFilter; +import org.infinispan.functional.impl.FunctionalMapImpl; +import org.infinispan.functional.impl.ReadWriteMapImpl; +import org.infinispan.functional.impl.WriteOnlyMapImpl; import org.infinispan.interceptors.base.CommandInterceptor; import org.infinispan.iteration.EntryIterable; import org.infinispan.lifecycle.ComponentStatus; @@ -36,17 +47,31 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import static org.infinispan.commons.marshall.MarshallableLambdas.*; + public final class FunctionalAdvancedCache implements AdvancedCache { - final ConcurrentMap map; final AdvancedCache cache; + final ConcurrentMap map; + final ReadWriteMap rw; + final ReadWriteMap rwCompleted; + final WriteOnlyMap wo; + final WriteOnlyMap woCompleted; + private FunctionalAdvancedCache(ConcurrentMap map, AdvancedCache cache) { this.map = map; this.cache = cache; + FunctionalMapImpl fmap = FunctionalMapImpl.create(cache); + this.rw = ReadWriteMapImpl.create(fmap); + this.wo = WriteOnlyMapImpl.create(fmap); + this.woCompleted = wo.withParams(FutureMode.COMPLETED); + this.rwCompleted = rw.withParams(FutureMode.COMPLETED); } public static AdvancedCache create(AdvancedCache cache) { @@ -90,6 +115,79 @@ public boolean remove(Object key, Object value) { return map.remove(key, value); } + @Override + public V put(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, lifespanUnit); + final MetaMaxIdle metaMaxIdle = createMetaMaxIdle(maxIdleTime, maxIdleTimeUnit); + return await(rwCompleted.eval(key, value, setValueMetasReturnPrevOrNull(metaLifespan, metaMaxIdle))); + } + + @Override + public void putAll(Map map, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, lifespanUnit); + final MetaMaxIdle metaMaxIdle = createMetaMaxIdle(maxIdleTime, maxIdleTimeUnit); + await(woCompleted.evalMany(map, setValueMetasConsumer(metaLifespan, metaMaxIdle))); + } + + @Override + public V putIfAbsent(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, lifespanUnit); + final MetaMaxIdle metaMaxIdle = createMetaMaxIdle(maxIdleTime, maxIdleTimeUnit); + return await(rwCompleted.eval(key, value, setValueMetasIfAbsentReturnPrevOrNull(metaLifespan, metaMaxIdle))); + } + + @Override + public V replace(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, lifespanUnit); + final MetaMaxIdle metaMaxIdle = createMetaMaxIdle(maxIdleTime, maxIdleTimeUnit); + return await(rwCompleted.eval(key, value, setValueMetasIfPresentReturnPrevOrNull(metaLifespan, metaMaxIdle))); + } + + @Override + public boolean replace(K key, V oldValue, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, lifespanUnit); + final MetaMaxIdle metaMaxIdle = createMetaMaxIdle(maxIdleTime, maxIdleTimeUnit); + return await(rwCompleted.eval(key, value, setValueIfEqualsReturnBoolean(oldValue, metaLifespan, metaMaxIdle))); + } + + @Override + public V put(K key, V value, long lifespan, TimeUnit unit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, unit); + return await(rwCompleted.eval(key, value, setValueMetasReturnPrevOrNull(metaLifespan))); + } + + @Override + public void putAll(Map map, long lifespan, TimeUnit unit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, unit); + await(woCompleted.evalMany(map, setValueMetasConsumer(metaLifespan))); + } + + @Override + public V putIfAbsent(K key, V value, long lifespan, TimeUnit unit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, unit); + return await(rwCompleted.eval(key, value, setValueMetasIfAbsentReturnPrevOrNull(metaLifespan))); + } + + @Override + public V replace(K key, V value, long lifespan, TimeUnit unit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, unit); + return await(rwCompleted.eval(key, value, setValueMetasIfPresentReturnPrevOrNull(metaLifespan))); + } + + @Override + public boolean replace(K key, V oldValue, V value, long lifespan, TimeUnit unit) { + final MetaLifespan metaLifespan = createMetaLifespan(lifespan, unit); + return await(rwCompleted.eval(key, value, setValueIfEqualsReturnBoolean(oldValue, metaLifespan))); + } + + private MetaLifespan createMetaLifespan(long lifespan, TimeUnit lifespanUnit) { + return new MetaLifespan(lifespanUnit.toMillis(lifespan)); + } + + private MetaMaxIdle createMetaMaxIdle(long maxIdleTime, TimeUnit maxIdleTimeUnit) { + return new MetaMaxIdle(maxIdleTimeUnit.toMillis(maxIdleTime)); + } + //////////////////////////////////////////////////////////////////////////// @Override @@ -394,56 +492,6 @@ public String getVersion() { return null; // TODO: Customise this generated block } - @Override - public V put(K key, V value, long lifespan, TimeUnit unit) { - return null; // TODO: Customise this generated block - } - - @Override - public V putIfAbsent(K key, V value, long lifespan, TimeUnit unit) { - return null; // TODO: Customise this generated block - } - - @Override - public void putAll(Map map, long lifespan, TimeUnit unit) { - // TODO: Customise this generated block - } - - @Override - public V replace(K key, V value, long lifespan, TimeUnit unit) { - return null; // TODO: Customise this generated block - } - - @Override - public boolean replace(K key, V oldValue, V value, long lifespan, TimeUnit unit) { - return false; // TODO: Customise this generated block - } - - @Override - public V put(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { - return null; // TODO: Customise this generated block - } - - @Override - public V putIfAbsent(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { - return null; // TODO: Customise this generated block - } - - @Override - public void putAll(Map map, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { - // TODO: Customise this generated block - } - - @Override - public V replace(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { - return null; // TODO: Customise this generated block - } - - @Override - public boolean replace(K key, V oldValue, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { - return false; // TODO: Customise this generated block - } - @Override public void putAll(Map m) { // TODO: Customise this generated block @@ -588,4 +636,12 @@ public void removeListener(Object listener) { public Set getListeners() { return null; // TODO: Customise this generated block } + + public static T await(CompletableFuture cf) { + try { + return cf.get(); + } catch (InterruptedException | ExecutionException e) { + throw new Error(e); + } + } } diff --git a/core/src/test/java/org/infinispan/functional/expiry/FunctionalExpiryTest.java b/core/src/test/java/org/infinispan/functional/expiry/FunctionalExpiryTest.java new file mode 100644 index 000000000000..63b33b7a8f5f --- /dev/null +++ b/core/src/test/java/org/infinispan/functional/expiry/FunctionalExpiryTest.java @@ -0,0 +1,17 @@ +package org.infinispan.functional.expiry; + +import org.infinispan.Cache; +import org.infinispan.expiry.ExpiryTest; +import org.infinispan.functional.decorators.FunctionalAdvancedCache; +import org.testng.annotations.Test; + +@Test(groups = "functional", testName = "functional.expiry.FunctionalExpiryTest") +public class FunctionalExpiryTest extends ExpiryTest { + + @Override + protected Cache getCache() { + Cache cache = super.getCache(); + return FunctionalAdvancedCache.create(cache.getAdvancedCache()); + } + +}