From b24a3e9223bc76ec6f694f9e6476d9bb80bdb7f9 Mon Sep 17 00:00:00 2001 From: jackygurui Date: Wed, 8 Jun 2016 00:31:27 +0100 Subject: [PATCH] WIP TTL --- .../RedissonAttachedLiveObjectService.java | 17 ++- .../liveobject/LiveObjectTemplate.java | 62 +------- .../org/redisson/liveobject/RLiveObject.java | 35 ----- .../liveobject/core/AccessorInterceptor.java | 19 ++- .../liveobject/core/ExpirableInterceptor.java | 137 ++++++++++++++++++ 5 files changed, 167 insertions(+), 103 deletions(-) create mode 100644 src/main/java/org/redisson/liveobject/core/ExpirableInterceptor.java diff --git a/src/main/java/org/redisson/RedissonAttachedLiveObjectService.java b/src/main/java/org/redisson/RedissonAttachedLiveObjectService.java index b87aeb565..9f333cd96 100644 --- a/src/main/java/org/redisson/RedissonAttachedLiveObjectService.java +++ b/src/main/java/org/redisson/RedissonAttachedLiveObjectService.java @@ -1,18 +1,18 @@ package org.redisson; -import java.lang.reflect.Field; import java.util.Map; import net.bytebuddy.ByteBuddy; -import net.bytebuddy.description.ByteCodeElement; import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.field.FieldList; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; import net.bytebuddy.implementation.FieldAccessor; import net.bytebuddy.implementation.MethodDelegation; -import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatchers; +import org.redisson.core.RExpirable; +import org.redisson.core.RExpirableAsync; import org.redisson.core.RObject; +import org.redisson.core.RObjectAsync; import org.redisson.liveobject.CodecProvider; import org.redisson.liveobject.LiveObjectTemplate; import org.redisson.liveobject.RAttachedLiveObjectService; @@ -20,6 +20,7 @@ import org.redisson.liveobject.RLiveObject; import org.redisson.liveobject.annotation.REntity; import org.redisson.liveobject.annotation.RId; import org.redisson.liveobject.core.AccessorInterceptor; +import org.redisson.liveobject.core.ExpirableInterceptor; import org.redisson.liveobject.misc.Introspectior; public class RedissonAttachedLiveObjectService implements RAttachedLiveObjectService { @@ -95,8 +96,18 @@ public class RedissonAttachedLiveObjectService implements RAttachedLiveObjectSer .and(ElementMatchers.isGetter().or(ElementMatchers.isSetter()))) .intercept(FieldAccessor.ofBeanProperty()) .implement(RLiveObject.class) + .method(ElementMatchers.isDeclaredBy(RExpirable.class) + .or(ElementMatchers.isDeclaredBy(RExpirableAsync.class)) + .or(ElementMatchers.isDeclaredBy(RObject.class)) + .or(ElementMatchers.isDeclaredBy(RObjectAsync.class))) + .intercept(MethodDelegation.to(new ExpirableInterceptor())) + .implement(RExpirable.class) .method(ElementMatchers.not(ElementMatchers.isDeclaredBy(Object.class)) .and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RLiveObject.class))) + .and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RExpirable.class))) + .and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RExpirableAsync.class))) + .and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RObject.class))) + .and(ElementMatchers.not(ElementMatchers.isDeclaredBy(RObjectAsync.class))) .and(ElementMatchers.isGetter() .or(ElementMatchers.isSetter())) .and(ElementMatchers.isPublic())) diff --git a/src/main/java/org/redisson/liveobject/LiveObjectTemplate.java b/src/main/java/org/redisson/liveobject/LiveObjectTemplate.java index 408e1a1ca..38f46e8ac 100644 --- a/src/main/java/org/redisson/liveobject/LiveObjectTemplate.java +++ b/src/main/java/org/redisson/liveobject/LiveObjectTemplate.java @@ -8,43 +8,8 @@ import org.redisson.core.RMap; */ public class LiveObjectTemplate implements RLiveObject { - private Long liveObjectTTL; - private Object liveObjectId; private RMap liveObjectLiveMap; - private String liveObjectMapKey; - - /** - * @return the liveObjectTTL - */ - @Override - public Long getLiveObjectTTL() { - return liveObjectTTL; - } - - /** - * @param liveObjectTTL the liveObjectTTL to set - */ - @Override - public void setLiveObjectTTL(Long liveObjectTTL) { - this.liveObjectTTL = liveObjectTTL; - } - - /** - * @return the liveObjectId - */ - @Override - public Object getLiveObjectId() { - return liveObjectId; - } - - /** - * @param liveObjectId the liveObjectId to set - */ - @Override - public void setLiveObjectId(Object liveObjectId) { - this.liveObjectId = liveObjectId; - } - + /** * @return the liveObjectLiveMap */ @@ -53,29 +18,4 @@ public class LiveObjectTemplate implements RLiveObject { return liveObjectLiveMap; } - /** - * @param liveObjectLiveMap the liveObjectLiveMap to set - */ - @Override - public void setLiveObjectLiveMap(RMap liveObjectLiveMap) { - this.liveObjectLiveMap = liveObjectLiveMap; - } - - /** - * @return the liveObjectMapKey - */ - @Override - public String getLiveObjectMapKey() { - return liveObjectMapKey; - } - - /** - * @param liveObjectMapKey the liveObjectMapKey to set - */ - @Override - public void setLiveObjectMapKey(String liveObjectMapKey) { - this.liveObjectMapKey = liveObjectMapKey; - } - - } diff --git a/src/main/java/org/redisson/liveobject/RLiveObject.java b/src/main/java/org/redisson/liveobject/RLiveObject.java index 7e943e1ff..0372b2e7c 100644 --- a/src/main/java/org/redisson/liveobject/RLiveObject.java +++ b/src/main/java/org/redisson/liveobject/RLiveObject.java @@ -8,43 +8,8 @@ import org.redisson.core.RMap; */ public interface RLiveObject { - /** - * @return the liveObjectTTL - */ - public Long getLiveObjectTTL(); - - /** - * @param liveObjectTTL the liveObjectTTL to set - */ - public void setLiveObjectTTL(Long liveObjectTTL); - - /** - * @return the LiveObjectId - */ - public Object getLiveObjectId(); - - /** - * @param LiveObjectId the LiveObjectId to set - */ - public void setLiveObjectId(Object LiveObjectId); - /** * @return the liveObjectLiveMap */ public RMap getLiveObjectLiveMap(); - - /** - * @param liveObjectLiveMap the liveObjectLiveMap to set - */ - public void setLiveObjectLiveMap(RMap liveObjectLiveMap); - - /** - * @return the liveObjectMapKey - */ - public String getLiveObjectMapKey(); - - /** - * @param liveObjectMapKey the liveObjectMapKey to set - */ - public void setLiveObjectMapKey(String liveObjectMapKey); } diff --git a/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java b/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java index 355a5d246..4f27f6ec3 100644 --- a/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java +++ b/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java @@ -1,5 +1,6 @@ package org.redisson.liveobject.core; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.concurrent.Callable; import net.bytebuddy.implementation.bind.annotation.AllArguments; @@ -20,8 +21,9 @@ import org.redisson.liveobject.annotation.RId; import org.redisson.liveobject.misc.Introspectior; /** - * This class is going to be instantiated and becomes a static field of the proxied - * target class. That is one instance of this class per proxied class. + * This class is going to be instantiated and becomes a static field of + * the proxied target class. That is one instance of this class per proxied + * class. * * @author Rui Gu (https://github.com/jackygurui) */ @@ -47,11 +49,10 @@ public class AccessorInterceptor { @RuntimeType public Object intercept(@Origin Method method, @SuperCall Callable superMethod, @AllArguments Object[] args, @This Object me) throws Exception { + RMap liveMap = getLiveMap(me); if (isGetter(method, idFieldName)) { return superMethod.call(); } - String id = getMapKey(getId(me)); - RMap liveMap = redisson.getMap(id, codecProvider.getCodec(codecClass, RedissonMap.class, id)); if (isSetter(method, idFieldName)) { //TODO: distributed locking maybe required. try { @@ -89,6 +90,16 @@ public class AccessorInterceptor { return superMethod.call(); } + private RMap getLiveMap(Object me) throws Exception { + RMap liveMap = (RMap) me.getClass().getField("liveObjectLiveMap").get(me); + if (liveMap == null) { + String id = getMapKey(getId(me)); + liveMap = redisson.getMap(id, codecProvider.getCodec(codecClass, RedissonMap.class, id)); + me.getClass().getField("liveObjectLiveMap").set(me, liveMap); + } + return liveMap; + } + private String getFieldName(Method method) { return method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4); } diff --git a/src/main/java/org/redisson/liveobject/core/ExpirableInterceptor.java b/src/main/java/org/redisson/liveobject/core/ExpirableInterceptor.java new file mode 100644 index 000000000..9db57012a --- /dev/null +++ b/src/main/java/org/redisson/liveobject/core/ExpirableInterceptor.java @@ -0,0 +1,137 @@ +package org.redisson.liveobject.core; + +import io.netty.util.concurrent.Future; +import java.util.Date; +import java.util.concurrent.TimeUnit; +import net.bytebuddy.implementation.bind.annotation.RuntimeType; +import net.bytebuddy.implementation.bind.annotation.This; +import org.redisson.client.codec.Codec; +import org.redisson.liveobject.RLiveObject; + +/** + * + * @author Rui Gu (https://github.com/jackygurui) + */ +public class ExpirableInterceptor { + + @RuntimeType + public boolean expire(@This Object me, long timeToLive, TimeUnit timeUnit) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public boolean expireAt(@This Object me, long timestamp) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public boolean expireAt(@This Object me, Date timestamp) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public boolean clearExpire(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public long remainTimeToLive(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public void migrate(@This Object me, String host, int port, int database) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public boolean move(@This Object me, int database) { + ((RLiveObject) me).getLiveObjectLiveMap().move(database); + return true; + } + + @RuntimeType + public String getName(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public boolean delete(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public void rename(@This Object me, String newName) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public boolean renamenx(@This Object me, String newName) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public boolean isExists(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Codec getCodec(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future migrateAsync(@This Object me, String host, int port, int database) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future moveAsync(@This Object me, int database) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future deleteAsync(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future renameAsync(@This Object me, String newName) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future renamenxAsync(@This Object me, String newName) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future isExistsAsync(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future expireAsync(@This Object me, long timeToLive, TimeUnit timeUnit) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future expireAtAsync(@This Object me, Date timestamp) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future expireAtAsync(@This Object me, long timestamp) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future clearExpireAsync(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @RuntimeType + public Future remainTimeToLiveAsync(@This Object me) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } +}