diff --git a/pom.xml b/pom.xml index ecde36d..5426985 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.zhub zhub-client-redkale - x.1.1.dev + 0.1.1.dev 17 diff --git a/src/main/java/org/redkalex/cache/redis/AbstractRedisSource.java b/src/main/java/org/redkalex/cache/redis/AbstractRedisSource.java deleted file mode 100644 index 87c1f1b..0000000 --- a/src/main/java/org/redkalex/cache/redis/AbstractRedisSource.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license - * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template - */ -package org.redkalex.cache.redis; - -import org.redkale.annotation.Resource; -import org.redkale.convert.Convert; -import org.redkale.convert.json.JsonConvert; -import org.redkale.source.AbstractCacheSource; -import org.redkale.util.*; - -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Function; - -import static org.redkale.boot.Application.RESNAME_APP_EXECUTOR; -import static org.redkale.boot.Application.RESNAME_APP_NAME; - -/** - * - * @author zhangjx - * - * @since 2.8.0 - */ -public abstract class AbstractRedisSource extends AbstractCacheSource { - - public static final String CACHE_SOURCE_CRYPTOR = "cryptor"; - - protected String name; - - @Resource(name = RESNAME_APP_NAME, required = false) - protected String appName = ""; - - @Resource(required = false) - protected ResourceFactory resourceFactory; - - @Resource(required = false) - protected JsonConvert defaultConvert; - - @Resource(name = Resource.PARENT_NAME + "_convert", required = false) - protected JsonConvert convert; - - protected int db; - - protected RedisCryptor cryptor; - - protected AnyValue conf; - - private ExecutorService subExecutor; - - private final ReentrantLock subExecutorLock = new ReentrantLock(); - - @Resource(name = RESNAME_APP_EXECUTOR, required = false) - protected ExecutorService workExecutor; - - @Override - public void init(AnyValue conf) { - this.conf = conf; - super.init(conf); - this.name = conf.getValue("name", ""); - if (this.convert == null) { - this.convert = this.defaultConvert; - } - if (conf != null) { - String cryptStr = conf.getValue(CACHE_SOURCE_CRYPTOR, "").trim(); - if (!cryptStr.isEmpty()) { - try { - Class cryptClass = (Class) getClass().getClassLoader().loadClass(cryptStr); - RedkaleClassLoader.putReflectionPublicConstructors(cryptClass, cryptClass.getName()); - this.cryptor = cryptClass.getConstructor().newInstance(); - } catch (ReflectiveOperationException e) { - throw new RedkaleException(e); - } - } - } - if (cryptor != null) { - if (resourceFactory != null) { - resourceFactory.inject(cryptor); - } - cryptor.init(conf); - } - } - - @Override - public void destroy(AnyValue conf) { - super.destroy(conf); - if (cryptor != null) { - cryptor.destroy(conf); - } - } - - public boolean acceptsConf(AnyValue config) { - if (config == null) { - return false; - } - return "redis".equalsIgnoreCase(config.getValue(CACHE_SOURCE_TYPE)) - || getClass().getName().equalsIgnoreCase(config.getValue(CACHE_SOURCE_TYPE)) - || config.getValue(CACHE_SOURCE_NODES, config.getValue("url", "")).startsWith("redis://") - || config.getValue(CACHE_SOURCE_NODES, config.getValue("url", "")).startsWith("rediss://"); - } - - protected ExecutorService subExecutor() { - ExecutorService executor = subExecutor; - if (executor != null) { - return executor; - } - subExecutorLock.lock(); - try { - if (subExecutor == null) { - String threadNameFormat = "CacheSource-" + resourceName() + "-SubThread-%s"; - Function func = Utility.virtualExecutorFunction(); - final AtomicInteger counter = new AtomicInteger(); - subExecutor = func == null ? Executors.newFixedThreadPool(Utility.cpus(), r -> { - Thread t = new Thread(r); - t.setDaemon(true); - int c = counter.incrementAndGet(); - t.setName(String.format(threadNameFormat, "Virtual-" + (c < 10 ? ("00" + c) : (c < 100 ? ("0" + c) : c)))); - return t; - }) : func.apply(threadNameFormat); - } - executor = subExecutor; - } finally { - subExecutorLock.unlock(); - } - return executor; - } - - protected String getNodes(AnyValue config) { - return config.getValue(CACHE_SOURCE_NODES, config.getValue("url", "")); - } - - @Override - public void close() throws Exception { //在 Application 关闭时调用 - destroy(null); - } - - @Override - public String resourceName() { - return name; - } - - protected String decryptValue(String key, RedisCryptor cryptor, String value) { - return cryptor != null ? cryptor.decrypt(key, value) : value; - } - - protected T decryptValue(String key, RedisCryptor cryptor, Type type, byte[] bs) { - return decryptValue(key, cryptor, convert, type, bs); - } - - protected T decryptValue(String key, RedisCryptor cryptor, Convert c, Type type, byte[] bs) { - if (bs == null) { - return null; - } - if (type == byte[].class) { - return (T) bs; - } - if (cryptor == null && type == String.class) { - return (T) new String(bs, StandardCharsets.UTF_8); - } - if (cryptor == null || (type instanceof Class && (((Class) type).isPrimitive() || Number.class.isAssignableFrom((Class) type)))) { - return (T) (c == null ? this.convert : c).convertFrom(type, bs); - } - String deval = cryptor.decrypt(key, new String(bs, StandardCharsets.UTF_8)); - if (type == String.class) { - return (T) deval; - } - return deval == null ? null : (T) (c == null ? this.convert : c).convertFrom(type, deval.getBytes(StandardCharsets.UTF_8)); - } - - protected String encryptValue(String key, RedisCryptor cryptor, String value) { - return cryptor != null ? cryptor.encrypt(key, value) : value; - } - - protected byte[] encryptValue(String key, RedisCryptor cryptor, Convert c, T value) { - return encryptValue(key, cryptor, null, c, value); - } - - protected byte[] encryptValue(String key, RedisCryptor cryptor, Type type, Convert c, T value) { - if (value == null) { - return null; - } - Type t = type == null ? value.getClass() : type; - if (cryptor == null && t == String.class) { - return value.toString().getBytes(StandardCharsets.UTF_8); - } - byte[] bs = (c == null ? this.convert : c).convertToBytes(t, value); - if (bs.length > 1 && t instanceof Class && !CharSequence.class.isAssignableFrom((Class) t)) { - if (bs[0] == '"' && bs[bs.length - 1] == '"') { - bs = Arrays.copyOfRange(bs, 1, bs.length - 1); - } - } - return encryptValue(key, cryptor, t, bs); - } - - protected byte[] encryptValue(String key, RedisCryptor cryptor, Type type, byte[] bs) { - if (bs == null) { - return null; - } - if (cryptor == null || (type instanceof Class && (((Class) type).isPrimitive() || Number.class.isAssignableFrom((Class) type)))) { - return bs; - } - String enval = cryptor.encrypt(key, new String(bs, StandardCharsets.UTF_8)); - return enval == null ? null : enval.getBytes(StandardCharsets.UTF_8); - } - - protected T decryptScore(Class scoreType, Double score) { - if (score == null) { - return null; - } - if (scoreType == int.class || scoreType == Integer.class) { - return (T) (Number) score.intValue(); - } else if (scoreType == long.class || scoreType == Long.class) { - return (T) (Number) score.longValue(); - } else if (scoreType == float.class || scoreType == Float.class) { - return (T) (Number) score.floatValue(); - } else if (scoreType == double.class || scoreType == Double.class) { - return (T) (Number) score; - } else { - return JsonConvert.root().convertFrom(scoreType, score.toString()); - } - } - - protected CompletableFuture returnFutureSize(List> futures) { - return futures == null || futures.isEmpty() ? CompletableFuture.completedFuture(0) : Utility.allOfFutures(futures).thenApply(v -> futures.size()); - } -} diff --git a/src/main/java/org/redkalex/cache/redis/MyRedisCacheSource.java b/src/main/java/org/redkalex/cache/redis/MyRedisCacheSource.java deleted file mode 100644 index a81859e..0000000 --- a/src/main/java/org/redkalex/cache/redis/MyRedisCacheSource.java +++ /dev/null @@ -1,350 +0,0 @@ -package org.redkalex.cache.redis; - -import org.redkale.annotation.AutoLoad; -import org.redkale.annotation.ResourceType; -import org.redkale.service.Local; -import org.redkale.source.CacheSource; -import org.redkale.util.AnyValue; - -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.CompletableFuture; - -@Local -@AutoLoad(false) -@ResourceType(CacheSource.class) -public class MyRedisCacheSource extends RedisCacheSource { - - @Override - public void init(AnyValue conf) { - super.init(conf); - } -/* -//--------------------- zset ------------------------------ - - public int getZrank(String key, V v) { - byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Long t = (Long) send("ZRANK", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - return t == null ? -1 : (int) (long) t; - } - - public int getZrevrank(String key, V v) { - byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Long t = (Long) send("ZREVRANK", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - return t == null ? -1 : (int) (long) t; - } - - //ZRANGE/ZREVRANGE key start stop - public List getZset(String key) { - byte[][] bytes = Stream.of(key, 0, -1).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - List vs2 = new ArrayList(vs.size()); - - for (int i = 0; i < vs.size(); ++i) { - if (i % 2 == 1) { - vs2.add(this.convert.convertFrom(this.objValueType, String.valueOf(vs.get(i)))); - } else { - vs2.add(vs.get(i)); - } - } - - return vs2; - } - - public List getZset(String key, int offset, int limit) { - byte[][] bytes = Stream.of(key, offset, offset + limit - 1).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - List vs2 = new ArrayList(vs.size()); - - for (int i = 0; i < vs.size(); ++i) { - if (i % 2 == 1) { - vs2.add(this.convert.convertFrom(this.objValueType, String.valueOf(vs.get(i)))); - } else { - vs2.add(vs.get(i)); - } - } - - return vs2; - } - - public LinkedHashMap getZsetLongScore(String key) { - LinkedHashMap map = getZsetDoubleScore(key); - if (map.isEmpty()) { - return new LinkedHashMap<>(); - } - - LinkedHashMap map2 = new LinkedHashMap<>(map.size()); - map.forEach((k, v) -> map2.put(k, (long) (double) v)); - return map2; - } - - public LinkedHashMap getZsetItemsLongScore(String key) { - byte[][] bytes = Stream.of(key, 0, -1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - LinkedHashMap map = new LinkedHashMap<>(); - for (int i = 0; i < vs.size(); i += 2) { - map.put((V) vs.get(i), (long) Double.parseDouble((String) vs.get(i + 1))); - } - return map; - } - - public Long getZsetLongScore(String key, V v) { - Double score = getZsetDoubleScore(key, v); - if (score == null) { - return null; - } - return (long) (double) score; - } - - public LinkedHashMap getZsetDoubleScore(String key) { - byte[][] bytes = Stream.of(key, 0, -1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - LinkedHashMap map = new LinkedHashMap<>(); - for (int i = 0; i < vs.size(); i += 2) { - map.put((V) vs.get(i), Double.parseDouble((String) vs.get(i + 1))); - } - return map; - } - - public Double getZsetDoubleScore(String key, V v) { - byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Serializable zscore = send("ZSCORE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - if (zscore == null) { - return null; - } - - return Double.parseDouble(String.valueOf(zscore)); - } - - public LinkedHashMap getZsetLongScore(String key, int offset, int limit) { - byte[][] bytes = Stream.of(key, offset, offset + limit - 1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - LinkedHashMap map = new LinkedHashMap<>(); - for (int i = 0; i < vs.size(); i += 2) { - map.put((V) vs.get(i), (long) Double.parseDouble((String) vs.get(i + 1))); - } - return map; - } - - public LinkedHashMap getZsetDoubleScore(String key, int offset, int limit) { - byte[][] bytes = Stream.of(key, offset, offset + limit - 1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - LinkedHashMap map = new LinkedHashMap<>(); - for (int i = 0; i < vs.size(); i += 2) { - map.put((V) vs.get(i), Double.parseDouble(vs.get(i + 1) + "")); - } - return map; - } -* */ - - // -------------------- - /* - supper had support - public void zadd(String key, Map kv) { - if (kv == null || kv.isEmpty()) { - return; - } - List args = new ArrayList(); - kv.forEach((k, v) -> { - args.add(k); - args.add(v); - }); - - sendAsync(RedisCommand.ZADD, key, args.toArray(Serializable[]::new)).join(); - } - - public double zincr(String key, Serializable number, N n) { - return sendAsync(RedisCommand.ZINCRBY, key, number, n).thenApply(x -> x.getDoubleValue(0d)).join(); - } - - @Override - public long zrem(String key, String... vs) { - return sendAsync(RedisCommand.ZREM, key, keysArgs(key, vs)).thenApply(x -> x.getLongValue(0L)).join(); - }*/ - - /*public List zexists(String key, T... fields) { - if (fields == null || fields.length == 0) { - return new ArrayList<>(); - } - List para = new ArrayList<>(); - para.add("" + - " local key = KEYS[1];" + - " local args = ARGV;" + - " local result = {};" + - " for i,v in ipairs(args) do" + - " local inx = redis.call('ZREVRANK', key, v);" + - " if(inx) then" + - " table.insert(result,1,v);" + - " end" + - " end" + - " return result;"); - para.add("1"); - para.add(key); - for (Object field : fields) { - para.add(String.valueOf(field)); - } - - // todo: - //sendAsync("EVAL", null, para.toArray(Serializable[]::new)).thenApply(x -> x.).join(); - - return null; - }*/ - - //--------------------- bit ------------------------------ - public boolean getBit(String key, int offset) { - return sendAsync(RedisCommand.GETBIT, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(offset).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0) > 0).join(); - } - - public void setBit(String key, int offset, boolean bool) { - sendAsync(RedisCommand.SETBIT, key, keysArgs(key, offset + "", bool ? "1" : "0")).join(); - } - //--------------------- bit ------------------------------ - - //--------------------- lock ------------------------------ - // 尝试加锁,成功返回0,否则返回上一锁剩余毫秒值 - public long tryLock(String key, int millis) { - String[] obj = {"" + - "if (redis.call('EXISTS',KEYS[1]) == 0) then " + - "redis.call('PSETEX',KEYS[1],ARGV[1],1); " + - "return 0; " + - "else " + - "return redis.call('PTTL',KEYS[1]); " + - "end;", 1 + "", key, millis + "" - }; - - return sendAsync(RedisCommand.EVAL, null, keysArgs(null, obj)).thenApply(v -> v.getIntValue(1)).join(); - } - - // 加锁 - public void lock(String key, int millis) { - long i; - do { - i = tryLock(key, millis); - try { - Thread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } while (i > 0); - } - - // 解锁 - public void unlock(String key) { - remove(key); - } - - //--------------------- key ------------------------------ - - public String get(String key) { - return get(key, String.class); - } - - public void set(String key, Serializable value) { - sendAsync(RedisCommand.SET, key, keysArgs(key, value + "")).join(); - } - - //--------------------- set ------------------------------ - /*public void sadd(String key, Collection args) { - saddAsync(key, args.toArray(T[]::new)).join(); - }*/ - - /*public void sadd(String key, Serializable... args) { - String[] arr = new String[args.length]; - for (int i = 0; i < args.length; i++) { - arr[i] = args[i] + ""; - } - saddAsync(key, arr).join(); - } - - public void srem(String key, String... args) { - sremAsync(key, args).join(); - } - - public CompletableFuture saddAsync(String key, Serializable... args) { - return sendAsync(RedisCommand.SADD, key, keysArgs(key, args)); - } - - public CompletableFuture sremAsync(String key, String... args) { - return sendAsync(RedisCommand.SREM, key, keysArgs(key, args)); - }*/ - - //--------------------- hm ------------------------------ - - /*public Long incrHm(String key, String field, int value) { - return sendAsync("HINCRBY", key, field, value).thenApply(x -> x.getLongValue(0l)).join(); - } - - public Double incrHm(String key, String field, double value) { - return sendAsync("HINCRBYFLOAT", key, field, value).thenApply(x -> x.getDoubleValue(0d)).join(); - }*/ - - public void setHm(String key, String field, Serializable value) { - setHmsAsync(key, Map.of(field, value)).join(); - } - - public void setHms(String key, Map kv) { - setHmsAsync(key, kv).join(); - } - - public CompletableFuture setHmsAsync(String key, Map kv) { - List args = new ArrayList(); - kv.forEach((k, v) -> { - args.add(k); - args.add(v + ""); - }); - - return sendAsync(RedisCommand.HMSET, key, keysArgs(key, args.toArray(String[]::new))); - } - - public String getHm(String key, String field) { - return getHm(key, String.class, field); - } - - public T getHm(String key, Class type, String field) { - List list = super.hmget(key, type, field); - if (list == null && list.isEmpty()) { - return null; - } - return (T) list.get(0); - } - - public Map getHms(String key, String... field) { - return getHms(key, String.class, field); - } - - public Map getHms(String key, Class type, String... field) { - List list = super.hmget(key, type, field); - if (list == null && list.isEmpty()) { - return null; - } - Map map = new HashMap<>(field.length); - - for (int i = 0; i < field.length; i++) { - if (list.get(i) == null) { - continue; - } - map.put(field[i], (T) list.get(i)); - } - return map; - } - - /*public Map getHmall(String key) { - List list = null; // TODO: - Map map = new HashMap<>(); - if (list.isEmpty()) { - return map; - } - - for (int i = 0; i + 1 < list.size(); i += 2) { - map.put((String) list.get(i), list.get(i + 1)); - } - return map; - }*/ -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCRC16.java b/src/main/java/org/redkalex/cache/redis/RedisCRC16.java deleted file mode 100644 index a0e74db..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCRC16.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - */ -package org.redkalex.cache.redis; - -import org.redkale.util.Utility; - -import java.util.Arrays; - -/** - * - * @author zhangjx - */ -public class RedisCRC16 { - - private static final int MAX_SLOT = 16384; - - private static final int[] LOOKUP_TABLE = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, - 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, - 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, - 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, - 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, - 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, - 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, - 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, - 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, - 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, - 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, - 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, - 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, - 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, - 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, - 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, - 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, - 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, - 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, - 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, - 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, - 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; - - private RedisCRC16() { - } - - public static int crc16(byte[] bytes) { - int crc = 0x0000; - for (byte b : bytes) { - crc = (crc << 8) ^ LOOKUP_TABLE[((crc >>> 8) ^ (b & 0xFF)) & 0xFF]; - } - return crc & 0xFFFF; - } - - public static int calcSlot(byte[] key) { - if (key == null) { - return 0; - } - int start = Utility.indexOf(key, (byte) '{'); - if (start != -1) { - int end = Utility.indexOf(key, start + 1, (byte) '}'); - if (end != -1) { - key = Arrays.copyOfRange(key, start + 1, end); - } - } - return crc16(key) % MAX_SLOT; - } - - public static int calcSlot(String key) { - if (key == null) { - return 0; - } - int start = key.indexOf('{'); - if (start != -1) { - int end = key.indexOf('}'); - if (end != -1 && start + 1 < end) { - key = key.substring(start + 1, end); - } - } - return crc16(key.getBytes()) % MAX_SLOT; - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheClient.java b/src/main/java/org/redkalex/cache/redis/RedisCacheClient.java deleted file mode 100644 index d089cf3..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheClient.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.net.AsyncConnection; -import org.redkale.net.AsyncGroup; -import org.redkale.net.client.Client; -import org.redkale.net.client.ClientAddress; -import org.redkale.util.Traces; - -/** - * - * @author zhangjx - */ -public class RedisCacheClient extends Client { - - public RedisCacheClient(String appName, String name, AsyncGroup group, String key, - ClientAddress address, int maxConns, int maxPipelines, RedisCacheReqAuth authReq, RedisCacheReqDB dbReq) { - super(name, group, true, address, maxConns, maxPipelines, () -> new RedisCacheReqPing(), () -> new RedisCacheReqClose(), null); //maxConns - RedisCacheReqClientName clientNameReq = new RedisCacheReqClientName(appName, name); - if (authReq != null && dbReq != null) { - this.authenticate = traceid -> { - Traces.currentTraceid(traceid); - return conn -> writeChannelBatch(conn, authReq.createTime(), dbReq.createTime(), clientNameReq.createTime()) - .thenApply(v -> conn); - }; - } else if (authReq != null) { - this.authenticate = traceid -> { - Traces.currentTraceid(traceid); - return conn -> writeChannelBatch(conn, authReq.createTime(), clientNameReq.createTime()) - .thenApply(v -> conn); - }; - } else if (dbReq != null) { - this.authenticate = traceid -> { - Traces.currentTraceid(traceid); - return conn -> writeChannelBatch(conn, dbReq.createTime(), clientNameReq.createTime()) - .thenApply(v -> conn); - }; - } else { - this.authenticate = traceid -> { - Traces.currentTraceid(traceid); - return conn -> writeChannel(conn, clientNameReq.createTime()) - .thenApply(v -> conn); - }; - } - this.readTimeoutSeconds = 3; - this.writeTimeoutSeconds = 3; - } - - @Override - protected RedisCacheConnection createClientConnection(final int index, AsyncConnection channel) { - return new RedisCacheConnection(this, index, channel); - } - -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheCodec.java b/src/main/java/org/redkalex/cache/redis/RedisCacheCodec.java deleted file mode 100644 index 793df77..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheCodec.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.net.client.ClientCodec; -import org.redkale.net.client.ClientConnection; -import org.redkale.util.ByteArray; -import org.redkale.util.RedkaleException; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * - * @author zhangjx - */ -public class RedisCacheCodec extends ClientCodec { - - protected static final byte TYPE_BULK = '$'; //字符串块类型, 例如:$6\r\n\abcdef\r\n,NULL字符串:$-1\r\n - - protected static final byte TYPE_MULTI = '*'; //数组,紧接的数字为数组长度 - - protected static final byte TYPE_STRING = '+'; //字符串值类型,字符串以\r\n结尾, 例如:+OK\r\n - - protected static final byte TYPE_ERROR = '-'; //错误字符串类型,字符串以\r\n结尾, 例如:-ERR unknown command 'red'\r\n - - protected static final byte TYPE_NUMBER = ':'; //整型, 例如::2\r\n - - private static final Logger logger = Logger.getLogger(RedisCacheCodec.class.getSimpleName()); - - private ByteArray halfFrameBytes; - - private int halfFrameBulkLength = Integer.MIN_VALUE; - - private int halfFrameMultiSize = Integer.MIN_VALUE; - - private int halfFrameMultiItemIndex; //从0开始 - - private byte halfFrameMultiItemType; - - private int halfFrameMultiItemLength = Integer.MIN_VALUE; - - private byte frameType; - - private byte[] frameCursor; - - private byte[] frameValue; - - private List frameList; - - private ByteArray recyclableArray; - - public RedisCacheCodec(ClientConnection connection) { - super(connection); - } - - private ByteArray pollArray(ByteArray array) { - if (recyclableArray == null) { - recyclableArray = new ByteArray(); - } - recyclableArray.clear(); - if (array != null) { - recyclableArray.put(array); - } - return recyclableArray; - } - - private boolean readFrames(RedisCacheConnection conn, ByteBuffer buffer, ByteArray array) { -// byte[] dbs = new byte[buffer.remaining()]; -// for (int i = 0; i < dbs.length; i++) { -// dbs[i] = buffer.get(buffer.position() + i); -// } -// (System. out).println("[" + Utility.nowMillis() + "] [" + Thread.currentThread().getName() + "]: " + conn + ", 原始数据: " + new String(dbs).replace("\r\n", " ")); - - array.clear(); - if (this.frameType == 0) { - this.frameType = buffer.get(); - } else if (halfFrameBytes != null) { - array.put(halfFrameBytes); - halfFrameBytes = null; - } - if (frameType == TYPE_STRING || frameType == TYPE_ERROR || frameType == TYPE_NUMBER) { - if (!readComplete(buffer, array)) { - halfFrameBytes = pollArray(array); - return false; - } - frameValue = array.getBytes(); - } else if (frameType == TYPE_BULK) { - if (halfFrameBulkLength == Integer.MIN_VALUE) { - if (!readComplete(buffer, array)) { //没有读到bulkLength - halfFrameBytes = pollArray(array); - return false; - } - halfFrameBulkLength = readInt(array); - array.clear(); - } - if (halfFrameBulkLength == -1) { - frameValue = null; - } else { - int expect = halfFrameBulkLength + 2 - array.length(); - if (buffer.remaining() < expect) { - array.put(buffer); - halfFrameBytes = pollArray(array); - return false; - } - array.put(buffer, expect); - array.removeLastByte(); //移除\n - array.removeLastByte(); //移除\r - frameValue = array.getBytes(); - } - } else if (frameType == TYPE_MULTI) { - int size = halfFrameMultiSize; - if (size == Integer.MIN_VALUE) { - if (!readComplete(buffer, array)) { //没有读到bulkLength - halfFrameBytes = pollArray(array); - return false; - } - size = readInt(array); - halfFrameMultiSize = size; - array.clear(); - frameValue = null; - } - if (frameList == null) { - frameList = new ArrayList<>(); - } - if (size > 0) { - int index = halfFrameMultiItemIndex; - for (int i = index; i < size; i++) { - if (!buffer.hasRemaining()) { - return false; - } - if (halfFrameMultiItemType == 0) { - halfFrameMultiItemType = buffer.get(); - } - halfFrameMultiItemIndex = i; - final byte itemType = halfFrameMultiItemType; - if (itemType == TYPE_STRING || itemType == TYPE_ERROR || itemType == TYPE_NUMBER) { - if (!readComplete(buffer, array)) { - halfFrameBytes = pollArray(array); - return false; - } - frameList.add(array.getBytes()); - } else if (itemType == TYPE_BULK) { - if (halfFrameMultiItemLength == Integer.MIN_VALUE) { - if (!readComplete(buffer, array)) { //没有读到bulkLength - halfFrameBytes = pollArray(array); - return false; - } - halfFrameMultiItemLength = readInt(array); - array.clear(); - } - if (halfFrameMultiItemLength == -1) { - frameList.add(null); - } else { - int expect = halfFrameMultiItemLength + 2 - array.length(); - if (buffer.remaining() < expect) { - array.put(buffer); - halfFrameBytes = pollArray(array); - return false; - } - array.put(buffer, expect); - array.removeLastByte(); //移除\n - array.removeLastByte(); //移除\r - frameList.add(array.getBytes()); - } - } else if (itemType == TYPE_MULTI) { //数组中嵌套数组,例如: SCAN、HSCAN - if (size == 2 && frameList != null && frameList.size() == 1) { - //读游标 数据例如: *2 $1 0 *4 $4 key1 $2 10 $4 key2 $2 30 - frameCursor = frameList.get(0); - frameList.clear(); - clearHalfFrame(); - return readFrames(conn, buffer, array); - } else { - throw new RedkaleException("Not support multi type in array data"); - } - } - halfFrameMultiItemType = 0; - halfFrameMultiItemLength = Integer.MIN_VALUE; - array.clear(); - } - } - } - return true; - } - - private void clearHalfFrame() { - halfFrameBytes = null; - halfFrameBulkLength = Integer.MIN_VALUE; - halfFrameMultiSize = Integer.MIN_VALUE; - halfFrameMultiItemLength = Integer.MIN_VALUE; - halfFrameMultiItemIndex = 0; //从0开始 - halfFrameMultiItemType = 0; - } - - @Override - public void decodeMessages(ByteBuffer realbuf, ByteArray array) { - RedisCacheConnection conn = (RedisCacheConnection) connection; - if (!realbuf.hasRemaining()) { - return; - } - ByteBuffer buffer = realbuf; - - while (buffer.hasRemaining()) { - if (!readFrames(conn, buffer, array)) { - break; - } - RedisCacheRequest request = nextRequest(); - if (frameType == TYPE_ERROR) { - addMessage(request, new RedkaleException(new String(frameValue, StandardCharsets.UTF_8))); - } else { - addMessage(request, conn.pollResultSet(request).prepare(frameType, frameCursor, frameValue, frameList)); - } - frameType = 0; - frameCursor = null; - frameValue = null; - frameList = null; - clearHalfFrame(); - buffer = realbuf; - } - } - - protected RedisCacheRequest nextRequest() { - return super.nextRequest(); - } - - private boolean readComplete(ByteBuffer buffer, ByteArray array) { - while (buffer.hasRemaining()) { - byte b = buffer.get(); - if (b == '\n') { - array.removeLastByte(); //移除 \r - return true; - } - array.put(b); - } - return false; - } - - private int readInt(ByteArray array) { - String val = array.toString(StandardCharsets.ISO_8859_1); - if (val.length() == 1 && val.charAt(0) == '0') { - return 0; - } - if (val.length() == 2 && val.charAt(0) == '-' && val.charAt(1) == '1') { - return -1; - } - return Integer.parseInt(val); - } - -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheConnection.java b/src/main/java/org/redkalex/cache/redis/RedisCacheConnection.java deleted file mode 100644 index a0ae7b7..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheConnection.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.net.AsyncConnection; -import org.redkale.net.WorkThread; -import org.redkale.net.client.Client; -import org.redkale.net.client.ClientCodec; -import org.redkale.net.client.ClientConnection; -import org.redkale.net.client.ClientFuture; - -import java.io.Serializable; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; - -/** - * - * @author zhangjx - */ -public class RedisCacheConnection extends ClientConnection { - - public RedisCacheConnection(Client client, int index, AsyncConnection channel) { - super(client, index, channel); - } - - @Override - protected ClientCodec createCodec() { - return new RedisCacheCodec(this); - } - - protected CompletableFuture writeRequest(RedisCacheRequest request) { - return super.writeChannel(request); - } - - protected CompletableFuture> writeRequest(RedisCacheRequest[] requests) { - return super.writeChannel(requests); - } - - protected CompletableFuture writeRequest(RedisCacheRequest request, Function respTransfer) { - return super.writeChannel(request, respTransfer); - } - - protected CompletableFuture> writeRequest(RedisCacheRequest[] requests, Function respTransfer) { - return super.writeChannel(requests, respTransfer); - } - - public RedisCacheResult pollResultSet(RedisCacheRequest request) { - RedisCacheResult rs = new RedisCacheResult(); - return rs; - } - - public RedisCacheRequest pollRequest(WorkThread workThread, String traceid) { - RedisCacheRequest rs = new RedisCacheRequest().workThread(workThread).traceid(traceid); - return rs; - } - - protected ClientFuture pollRespFuture(Serializable requestid) { - return super.pollRespFuture(requestid); - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqAuth.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqAuth.java deleted file mode 100644 index b83f70d..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheReqAuth.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.net.client.ClientConnection; -import org.redkale.util.ByteArray; - -import java.nio.charset.StandardCharsets; - -/** - * - * @author zhangjx - */ -public class RedisCacheReqAuth extends RedisCacheRequest { - - private static final byte[] PS = "AUTH\r\n".getBytes(StandardCharsets.UTF_8); - - protected String password; - - public RedisCacheReqAuth(String password) { - this.password = password; - } - - @Override - public void writeTo(ClientConnection conn, ByteArray writer) { - byte[] pwd = password.getBytes(); - writer.put(mutliLengthBytes(2)); - writer.put(bulkLengthBytes(4)); - writer.put(PS); - - writer.put(bulkLengthBytes(pwd.length)); - writer.put(pwd); - writer.put(CRLF); - - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{AUTH " + password + "}"; - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqClientName.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqClientName.java deleted file mode 100644 index 1407344..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheReqClientName.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - */ -package org.redkalex.cache.redis; - -import org.redkale.net.client.ClientConnection; -import org.redkale.util.ByteArray; -import org.redkale.util.Utility; - -import java.nio.charset.StandardCharsets; - -/** - * - * @author zhangjx - */ -public class RedisCacheReqClientName extends RedisCacheRequest { - - private final String clientName; - - public RedisCacheReqClientName(String appName, String resourceName) { - this.clientName = "redkalex" + (Utility.isEmpty(appName) ? "" : ("-" + appName)) - + (Utility.isEmpty(resourceName) ? "" : (":" + resourceName)); - } - - @Override - public void writeTo(ClientConnection conn, ByteArray writer) { - writer.put(mutliLengthBytes(3)); - - writer.put(bulkLengthBytes(6)); - writer.put("CLIENT\r\n".getBytes(StandardCharsets.UTF_8)); - - writer.put(bulkLengthBytes(7)); - writer.put("SETNAME\r\n".getBytes(StandardCharsets.UTF_8)); - - byte[] ns = clientName.getBytes(StandardCharsets.UTF_8); - writer.put(bulkLengthBytes(ns.length)); - writer.put(ns); - writer.put(CRLF); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{CLIENT SETNAME " + clientName + "}"; - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqClose.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqClose.java deleted file mode 100644 index f1a304d..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheReqClose.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.net.client.ClientConnection; -import org.redkale.util.ByteArray; - -import java.nio.charset.StandardCharsets; - -/** - * - * @author zhangjx - */ -public class RedisCacheReqClose extends RedisCacheRequest { - - private static final byte[] BYTES = new ByteArray() - .put((byte) '*') - .put((byte) '1') - .put((byte) '\r', (byte) '\n') - .put((byte) '$') - .put((byte) '4') - .put((byte) '\r', (byte) '\n') - .put("QUIT".getBytes(StandardCharsets.UTF_8)) - .put((byte) '\r', (byte) '\n').getBytes(); - - @Override - public final boolean isCloseType() { - return true; - } - - @Override - public void writeTo(ClientConnection conn, ByteArray writer) { - writer.put(BYTES); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{QUIT}"; - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqDB.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqDB.java deleted file mode 100644 index d9848e0..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheReqDB.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.net.client.ClientConnection; -import org.redkale.util.ByteArray; - -import java.nio.charset.StandardCharsets; - -/** - * - * @author zhangjx - */ -public class RedisCacheReqDB extends RedisCacheRequest { - - protected int db; - - public RedisCacheReqDB(int db) { - this.db = db; - } - - @Override - public void writeTo(ClientConnection conn, ByteArray writer) { - writer.put(mutliLengthBytes(2)); - writer.put(bulkLengthBytes(6)); - writer.put("SELECT\r\n".getBytes(StandardCharsets.UTF_8)); - - byte[] dbs = String.valueOf(db).getBytes(StandardCharsets.UTF_8); - writer.put(bulkLengthBytes(dbs.length)); - writer.put(dbs); - writer.put(CRLF); - - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{SELECT " + db + "}"; - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqPing.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqPing.java deleted file mode 100644 index b6d469a..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheReqPing.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.net.client.ClientConnection; -import org.redkale.util.ByteArray; - -import java.nio.charset.StandardCharsets; - -/** - * - * @author zhangjx - */ -public class RedisCacheReqPing extends RedisCacheRequest { - - private static final byte[] BYTES = new ByteArray() - .put((byte) '*') - .put((byte) '1') - .put((byte) '\r', (byte) '\n') - .put((byte) '$') - .put((byte) '4') - .put((byte) '\r', (byte) '\n') - .put("PING".getBytes(StandardCharsets.UTF_8)) - .put((byte) '\r', (byte) '\n').getBytes(); - - @Override - public void writeTo(ClientConnection conn, ByteArray writer) { - writer.put(BYTES); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{PING}"; - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheRequest.java b/src/main/java/org/redkalex/cache/redis/RedisCacheRequest.java deleted file mode 100644 index c32029a..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheRequest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.net.client.ClientConnection; -import org.redkale.net.client.ClientRequest; -import org.redkale.util.ByteArray; - -import java.nio.charset.StandardCharsets; - -/** - * - * @author zhangjx - */ -public class RedisCacheRequest extends ClientRequest { - - static final byte[] BYTES_TRUE = new byte[]{'t'}; - - static final byte[] BYTES_FALSE = new byte[]{'f'}; - - static final byte[] BYTES_MATCH = "MATCH".getBytes(StandardCharsets.UTF_8); - - static final byte[] BYTES_COUNT = "COUNT".getBytes(StandardCharsets.UTF_8); - - protected static final byte[] CRLF = new byte[]{'\r', '\n'}; - - private static final byte[][] starLengthBytes; - - private static final byte[][] dollarLengthBytes; - - static { - starLengthBytes = new byte[1024][]; - dollarLengthBytes = new byte[1024][]; - for (int i = 0; i < dollarLengthBytes.length; i++) { - starLengthBytes[i] = ("*" + i + "\r\n").getBytes(StandardCharsets.ISO_8859_1); - dollarLengthBytes[i] = ("$" + i + "\r\n").getBytes(StandardCharsets.ISO_8859_1); - } - } - - protected RedisCommand command; - - protected String key; - - protected byte[][] args; - - public static RedisCacheRequest create(RedisCommand command, String key, String... args) { - return new RedisCacheRequest().prepare(command, key, RedisCacheSource.keysArgs(key, args)); - } - - public static RedisCacheRequest create(RedisCommand command, String key, byte[]... args) { - return new RedisCacheRequest().prepare(command, key, args); - } - - public RedisCacheRequest prepare(RedisCommand command, String key, byte[]... args) { - super.prepare(); - this.command = command; - this.key = key; - this.args = args; - return this; - } - - public RedisCacheRequest createTime() { - this.createTime = System.currentTimeMillis(); - return this; - } - - @Override - public void writeTo(ClientConnection conn, ByteArray writer) { - writer.put(mutliLengthBytes(args.length + 1)); - writer.put(command.getBytes()); - - for (final byte[] arg : args) { - putArgBytes(writer, arg); - } - } - - protected void putArgBytes(ByteArray writer, byte[] arg) { - writer.put(bulkLengthBytes(arg.length)); - writer.put(arg); - writer.put(CRLF); - } - - protected static byte[] mutliLengthBytes(int length) { - if (length >= 0 && length < starLengthBytes.length) { - return starLengthBytes[length]; - } else { - return ("*" + length + "\r\n").getBytes(StandardCharsets.ISO_8859_1); - } - } - - protected static byte[] bulkLengthBytes(int length) { - if (length >= 0 && length < dollarLengthBytes.length) { - return dollarLengthBytes[length]; - } else { - return ("$" + length + "\r\n").getBytes(StandardCharsets.ISO_8859_1); - } - } - - @Override - public String toString() { - if (args == null || args.length == 0) { - return getClass().getSimpleName() + "{" + command + " " + key + "}"; - } else { - StringBuilder sb = new StringBuilder(); - sb.append(command); - sb.append(" ").append(key); - for (final byte[] arg : args) { - sb.append(" ").append(arg == null ? null : new String(arg, StandardCharsets.UTF_8)); - } - return sb.toString(); - } - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheResult.java b/src/main/java/org/redkalex/cache/redis/RedisCacheResult.java deleted file mode 100644 index 330569a..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheResult.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.convert.json.JsonConvert; -import org.redkale.net.client.ClientResult; -import org.redkale.source.CacheScoredValue; - -import java.lang.reflect.Type; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.util.*; - -/** - * - * @author zhangjx - */ -public class RedisCacheResult implements ClientResult { - - //$ 块字符串类型 - //* 数组 - //+ 简单字符串类型 - //- 错误类型 - //: 整型 - protected byte frameType; - - protected byte[] frameCursor; - - protected byte[] frameValue; - - protected List frameList; - - public RedisCacheResult prepare(byte byteType, byte[] frameCursor, byte[] frameValue, List frameList) { - this.frameType = byteType; - this.frameCursor = frameCursor; - this.frameValue = frameValue; - this.frameList = frameList; - return this; - } - - @Override - public boolean isKeepAlive() { - return true; - } - - public Void getVoidValue() { - return null; - } - - public byte[] getFrameValue() { - return frameValue; - } - - public int getCursor() { - if (frameCursor == null || frameCursor.length < 1) { - return -1; - } else { - return Integer.parseInt(new String(frameCursor)); - } - } - - public Boolean getBoolValue() { - if (frameValue == null) { - return false; - } - String val = new String(frameValue, StandardCharsets.UTF_8); - if ("OK".equals(val)) { - return true; - } - if (val.isEmpty()) { - return false; - } - for (char ch : val.toCharArray()) { - if (!Character.isDigit(ch)) { - return false; - } - } - return Integer.parseInt(val) > 0; - } - - public Double getDoubleValue(Double defValue) { - if (frameValue == null) { - return defValue; - } - String val = new String(frameValue, StandardCharsets.UTF_8); - if ("nan".equalsIgnoreCase(val) || "-nan".equalsIgnoreCase(val)) { - return Double.NaN; - } else if ("inf".equalsIgnoreCase(val)) { - return Double.POSITIVE_INFINITY; - } else if ("-inf".equalsIgnoreCase(val)) { - return Double.NEGATIVE_INFINITY; - } else if ("-1".equalsIgnoreCase(val)) { - return -1.0; - } else if ("0".equalsIgnoreCase(val)) { - return 0.0; - } else if ("1".equalsIgnoreCase(val)) { - return 1.0; - } else { - return Double.parseDouble(val); - } - } - - public Long getLongValue(Long defValue) { - if (frameValue == null) { - return defValue; - } - String val = new String(frameValue, StandardCharsets.UTF_8); - if ("-1".equalsIgnoreCase(val)) { - return -1L; - } else if ("0".equalsIgnoreCase(val)) { - return 0L; - } else if ("1".equalsIgnoreCase(val)) { - return 1L; - } else { - return Long.parseLong(val); - } - } - - public Integer getIntValue(Integer defValue) { - if (frameValue == null) { - return defValue; - } - String val = new String(frameValue, StandardCharsets.UTF_8); - if ("-1".equalsIgnoreCase(val)) { - return -1; - } else if ("0".equalsIgnoreCase(val)) { - return 0; - } else if ("1".equalsIgnoreCase(val)) { - return 1; - } else { - return Integer.parseInt(val); - } - } - - public T getObjectValue(String key, RedisCryptor cryptor, Type type) { - return decodeValue(key, cryptor, frameValue, type); - } - - protected Set getSetValue(String key, RedisCryptor cryptor, Type type) { - if (frameList == null || frameList.isEmpty()) { - return new LinkedHashSet<>(); - } - Set set = new LinkedHashSet<>(); - for (byte[] bs : frameList) { - set.add(decodeValue(key, cryptor, bs, type)); - } - return set; - } - - protected List getScoreListValue(String key, RedisCryptor cryptor, Type scoreType) { - if (frameList == null || frameList.isEmpty()) { - return new ArrayList<>(); - } - List set = new ArrayList<>(); - for (int i = 0; i < frameList.size(); i += 2) { - byte[] bs1 = frameList.get(i); - byte[] bs2 = frameList.get(i + 1); - Number val = decodeValue(key, cryptor, bs2, scoreType); - if (val != null) { - set.add(CacheScoredValue.create(val, new String(bs1, StandardCharsets.UTF_8))); - } - } - return set; - } - - protected List getListValue(String key, RedisCryptor cryptor, Type type) { - if (frameList == null || frameList.isEmpty()) { - return new ArrayList<>(); - } - List list = new ArrayList<>(); - for (byte[] bs : frameList) { - list.add(decodeValue(key, cryptor, bs, type)); - } - return list; - } - - protected Map getMapValue(String key, RedisCryptor cryptor, Type type) { - if (frameList == null || frameList.isEmpty()) { - return new LinkedHashMap<>(); - } - Map map = new LinkedHashMap<>(); - for (int i = 0; i < frameList.size(); i += 2) { - byte[] bs1 = frameList.get(i); - byte[] bs2 = frameList.get(i + 1); - T val = decodeValue(key, cryptor, bs2, type); - if (val != null) { - map.put(decodeValue(key, cryptor, bs1, String.class).toString(), val); - } - } - return map; - } - - protected static T decodeValue(String key, RedisCryptor cryptor, byte[] frames, Type type) { - if (frames == null) { - return null; - } - if (type == byte[].class) { - return (T) frames; - } - if (type == String.class) { - String val = new String(frames, StandardCharsets.UTF_8); - if (cryptor != null) { - val = cryptor.decrypt(key, val); - } - return (T) val; - } - if (type == int.class || type == Integer.class) { - return (T) (Integer) Integer.parseInt(new String(frames, StandardCharsets.UTF_8)); - } - if (type == long.class || type == Long.class) { - return (T) (Long) Long.parseLong(new String(frames, StandardCharsets.UTF_8)); - } - if (type == float.class || type == Float.class) { - return (T) (Float) Float.parseFloat(new String(frames, StandardCharsets.UTF_8)); - } - if (type == BigInteger.class) { - return (T) new BigInteger(new String(frames, StandardCharsets.UTF_8)); - } - if (type == BigDecimal.class) { - return (T) new BigDecimal(new String(frames, StandardCharsets.UTF_8)); - } - if (type == boolean.class || type == Boolean.class) { - String v = new String(frames, StandardCharsets.UTF_8); - return (T) (Boolean) ("t".equalsIgnoreCase(v) || "1".equals(v)); - } - if (type == double.class || type == Double.class) { - return (T) (Double) Double.parseDouble(new String(frames, StandardCharsets.UTF_8)); - } - if (cryptor != null) { - String val = cryptor.decrypt(key, new String(frames, StandardCharsets.UTF_8)); - return (T) JsonConvert.root().convertFrom(type, val); - } - return (T) JsonConvert.root().convertFrom(type, frames); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("{type: ").append(frameType); - if (frameValue != null) { - sb.append(", value: ").append(new String(frameValue, StandardCharsets.UTF_8)); - } - if (frameList != null) { - sb.append(", list: ["); - boolean first = true; - for (byte[] bs : frameList) { - if (!first) { - sb.append(", "); - } - sb.append(bs == null ? null : new String(bs, StandardCharsets.UTF_8)); - first = false; - } - sb.append("]"); - } - return sb.append("}").toString(); - } - -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheSource.java b/src/main/java/org/redkalex/cache/redis/RedisCacheSource.java deleted file mode 100644 index 68ffeb5..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheSource.java +++ /dev/null @@ -1,1353 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.annotation.AutoLoad; -import org.redkale.annotation.ResourceListener; -import org.redkale.annotation.ResourceType; -import org.redkale.annotation.*; -import org.redkale.convert.Convert; -import org.redkale.convert.json.JsonConvert; -import org.redkale.net.AsyncGroup; -import org.redkale.net.WorkThread; -import org.redkale.net.client.*; -import org.redkale.service.Local; -import org.redkale.source.CacheEventListener; -import org.redkale.source.CacheScoredValue; -import org.redkale.source.CacheSource; -import org.redkale.util.*; - -import java.io.Serializable; -import java.lang.reflect.Type; -import java.net.InetSocketAddress; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static org.redkale.boot.Application.RESNAME_APP_CLIENT_ASYNCGROUP; -import static org.redkale.boot.Application.RESNAME_APP_EXECUTOR; -import static org.redkale.util.Utility.isEmpty; -import static org.redkale.util.Utility.isNotEmpty; -import static org.redkalex.cache.redis.RedisCacheRequest.BYTES_COUNT; -import static org.redkalex.cache.redis.RedisCacheRequest.BYTES_MATCH; - -/** - * 详情见: https://redkale.org - * - * - * @author zhangjx - */ -@Local -@AutoLoad(false) -@ResourceType(CacheSource.class) -public class RedisCacheSource extends AbstractRedisSource { - - static final boolean debug = false; //System.getProperty("os.name").contains("Window") || System.getProperty("os.name").contains("Mac"); - - protected static final byte[] NX = "NX".getBytes(); - - protected static final byte[] EX = "EX".getBytes(); - - protected static final byte[] CHANNELS = "CHANNELS".getBytes(); - - private final Logger logger = Logger.getLogger(getClass().getSimpleName()); - - @Resource(name = RESNAME_APP_CLIENT_ASYNCGROUP, required = false) - private AsyncGroup clientAsyncGroup; - - //配置 APP_EXECUTOR资源为null - @Resource(name = RESNAME_APP_EXECUTOR, required = false) - private ExecutorService workExecutor; - - private RedisCacheClient client; - - private InetSocketAddress address; - - private RedisCacheConnection subConn; - - private final ReentrantLock pubsubLock = new ReentrantLock(); - - //key: topic - private final Map>> pubsubListeners = new ConcurrentHashMap<>(); - - @Override - public void init(AnyValue conf) { - super.init(conf); - if (conf == null) { - conf = AnyValue.create(); - } - initClient(conf); - } - - private void initClient(AnyValue conf) { - RedisConfig config = RedisConfig.create(conf); - if (config.getAddresses().size() != 1) { - throw new RedkaleException("Only one address supported for " + getClass().getSimpleName()); - } - String oneAddr = config.getAddresses().get(0); - if (oneAddr.contains("://")) { - URI uri = URI.create(oneAddr); - address = new InetSocketAddress(uri.getHost(), uri.getPort() > 0 ? uri.getPort() : 6379); - } else { - int pos = oneAddr.indexOf(':'); - address = new InetSocketAddress(pos < 0 ? oneAddr : oneAddr.substring(0, pos), pos < 0 ? 6379 : Integer.parseInt(oneAddr.substring(pos + 1))); - } - AsyncGroup ioGroup = clientAsyncGroup; - if (clientAsyncGroup == null) { - String f = "Redkalex-Redis-IOThread-" + resourceName() + "-%s"; - ioGroup = AsyncGroup.create(f, workExecutor, 16 * 1024, Utility.cpus() * 4).start(); - } - RedisCacheClient old = this.client; - this.client = new RedisCacheClient(appName, resourceName(), ioGroup, resourceName() + "." + config.getDb(), - new ClientAddress(address), config.getMaxconns(Runtime.getRuntime().availableProcessors()), config.getPipelines(), - isEmpty(config.getPassword()) ? null : new RedisCacheReqAuth(config.getPassword()), - config.getDb() < 1 ? null : new RedisCacheReqDB(config.getDb())); - if (this.subConn != null) { - this.subConn.dispose(null); - this.subConn = null; - } - if (old != null) { - old.close(); - } - if (!pubsubListeners.isEmpty()) { - subConn().join(); - } - //if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, RedisCacheSource.class.getSimpleName() + ": addr=" + address + ", db=" + db); - } - - @Override - @ResourceListener - public void onResourceChange(ResourceEvent[] events) { - if (events == null || events.length < 1) { - return; - } - StringBuilder sb = new StringBuilder(); - for (ResourceEvent event : events) { - sb.append("CacheSource(name=").append(resourceName()).append(") change '").append(event.name()).append("' to '").append(event.coverNewValue()).append("'\r\n"); - } - initClient(this.conf); - if (sb.length() > 0) { - logger.log(Level.INFO, sb.toString()); - } - } - - @Override - public final String getType() { - return "redis"; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{name=" + resourceName() + ", addrs=" + this.address + ", db=" + this.db + "}"; - } - - @Override - public void destroy(AnyValue conf) { - super.destroy(conf); - if (client != null) { - client.close(); - } - } - - protected CompletableFuture subConn() { - RedisCacheConnection conn = this.subConn; - if (conn != null) { - return CompletableFuture.completedFuture(conn); - } - return client.newConnection().thenApply(r -> { - pubsubLock.lock(); - try { - if (subConn == null) { - subConn = r; - r.getCodec().withMessageListener(new ClientMessageListener() { - @Override - public void onMessage(ClientConnection conn, ClientResponse resp) { - if (resp.getCause() == null) { - RedisCacheResult result = (RedisCacheResult) resp.getMessage(); - if (result.getFrameValue() == null) { - List events = result.getListValue(null, null, byte[].class); - String type = new String(events.get(0), StandardCharsets.UTF_8); - if (events.size() == 3 && "message".equals(type)) { - String channel = new String(events.get(1), StandardCharsets.UTF_8); - Set> set = pubsubListeners.get(channel); - if (set != null) { - byte[] msg = events.get(2); - for (CacheEventListener item : set) { - subExecutor().execute(() -> { - try { - item.onMessage(channel, msg); - } catch (Throwable t) { - logger.log(Level.SEVERE, "CacheSource subscribe message error, topic: " + channel, t); - } - }); - } - } - } else { - RedisCacheRequest request = ((RedisCacheCodec) conn.getCodec()).nextRequest(); - ClientFuture respFuture = ((RedisCacheConnection) conn).pollRespFuture(request.getRequestid()); - respFuture.complete(result); - } - } else { - RedisCacheRequest request = ((RedisCacheCodec) conn.getCodec()).nextRequest(); - ClientFuture respFuture = ((RedisCacheConnection) conn).pollRespFuture(request.getRequestid()); - respFuture.complete(result); - } - } else { - RedisCacheRequest request = ((RedisCacheCodec) conn.getCodec()).nextRequest(); - ClientFuture respFuture = ((RedisCacheConnection) conn).pollRespFuture(request.getRequestid()); - respFuture.completeExceptionally(resp.getCause()); - } - } - - public void onClose(ClientConnection conn) { - subConn = null; - } - }); - //重连时重新订阅 - if (!pubsubListeners.isEmpty()) { - final Map, HashSet> listeners = new HashMap<>(); - pubsubListeners.forEach((t, s) -> { - s.forEach(l -> listeners.computeIfAbsent(l, x -> new HashSet<>()).add(t)); - }); - listeners.forEach((listener, topics) -> { - subscribeAsync(listener, topics.toArray(Creator.funcStringArray())); - }); - } - } - return subConn; - } finally { - pubsubLock.unlock(); - } - }); - } - - @Override - public CompletableFuture isOpenAsync() { - return CompletableFuture.completedFuture(client != null); - } - - //------------------------ 订阅发布 SUB/PUB ------------------------ - @Override - public CompletableFuture> pubsubChannelsAsync(@Nullable String pattern) { - CompletableFuture future = pattern == null ? sendAsync(RedisCommand.PUBSUB, "CHANNELS", CHANNELS) - : sendAsync(RedisCommand.PUBSUB, "CHANNELS", CHANNELS, pattern.getBytes(StandardCharsets.UTF_8)); - return future.thenApply(v -> v.getListValue("CHANNELS", null, String.class)); - } - - @Override - public CompletableFuture subscribeAsync(CacheEventListener listener, String... topics) { - Objects.requireNonNull(listener); - if (topics == null || topics.length < 1) { - throw new RedkaleException("topics is empty"); - } - WorkThread workThread = WorkThread.currentWorkThread(); - String traceid = Traces.currentTraceid(); - return subConn() - .thenCompose(conn - -> conn.writeRequest(conn.pollRequest(workThread, traceid).prepare(RedisCommand.SUBSCRIBE, null, keysArgs(topics))) - .thenApply(v -> { - for (String topic : topics) { - pubsubListeners.computeIfAbsent(topic, y -> new CopyOnWriteArraySet<>()).add(listener); - } - return null; - }) - ); - } - - @Override - public CompletableFuture unsubscribeAsync(CacheEventListener listener, String... topics) { - if (listener == null) { //清掉指定topic的所有订阅者 - Set delTopics = new HashSet<>(); - if (topics == null || topics.length < 1) { - delTopics.addAll(pubsubListeners.keySet()); - } else { - delTopics.addAll(Arrays.asList(topics)); - } - List> futures = new ArrayList<>(); - delTopics.forEach(topic -> { - futures.add(subConn().thenCompose(conn -> conn.writeRequest(RedisCacheRequest.create(RedisCommand.UNSUBSCRIBE, topic, topic.getBytes(StandardCharsets.UTF_8))) - .thenApply(r -> { - pubsubListeners.remove(topic); - return null; - }) - )); - }); - return returnFutureSize(futures); - } else { //清掉指定topic的指定订阅者 - List> futures = new ArrayList<>(); - for (String topic : topics) { - CopyOnWriteArraySet> listens = pubsubListeners.get(topic); - if (listens == null) { - continue; - } - listens.remove(listener); - if (listens.isEmpty()) { - futures.add(subConn().thenCompose(conn -> conn.writeRequest(RedisCacheRequest.create(RedisCommand.UNSUBSCRIBE, topic, topic.getBytes(StandardCharsets.UTF_8))) - .thenApply(r -> { - pubsubListeners.remove(topic); - return null; - }) - )); - } - } - return returnFutureSize(futures); - } - } - - @Override - public CompletableFuture publishAsync(String topic, byte[] message) { - Objects.requireNonNull(topic); - Objects.requireNonNull(message); - return sendAsync(RedisCommand.PUBLISH, topic, topic.getBytes(StandardCharsets.UTF_8), message).thenApply(v -> v.getIntValue(0)); - } - - //--------------------- exists ------------------------------ - @Override - public CompletableFuture existsAsync(String key) { - return sendAsync(RedisCommand.EXISTS, key, keyArgs(key)).thenApply(v -> v.getIntValue(0) > 0); - } - - //--------------------- get ------------------------------ - @Override - public CompletableFuture getAsync(String key, Type type) { - return sendAsync(RedisCommand.GET, key, keyArgs(key)).thenApply(v -> v.getObjectValue(key, cryptor, type)); - } - - //--------------------- getex ------------------------------ - @Override - public CompletableFuture getexAsync(String key, int expireSeconds, final Type type) { - return sendAsync(RedisCommand.GETEX, key, keyArgs(key, "EX", expireSeconds)).thenApply(v -> v.getObjectValue(key, cryptor, type)); - } - - @Override - public CompletableFuture msetAsync(final Serializable... keyVals) { - if (keyVals.length % 2 != 0) { - throw new RedkaleException("key value must be paired"); - } - return sendAsync(RedisCommand.MSET, keyVals[0].toString(), keymArgs(keyVals)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture msetAsync(final Map map) { - if (isEmpty(map)) { - return CompletableFuture.completedFuture(null); - } - return sendAsync(RedisCommand.MSET, map.keySet().stream().findFirst().orElse("").toString(), keymArgs(map)).thenApply(v -> v.getVoidValue()); - } - - //--------------------- setex ------------------------------ - @Override - public CompletableFuture setAsync(String key, Convert convert, final Type type, T value) { - return sendAsync(RedisCommand.SET, key, keyArgs(key, convert, type, value)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture setnxAsync(String key, Convert convert, final Type type, T value) { - return sendAsync(RedisCommand.SETNX, key, keyArgs(key, convert, type, value)).thenApply(v -> v.getBoolValue()); - } - - @Override - public CompletableFuture getSetAsync(String key, Convert convert, final Type type, T value) { - return sendAsync(RedisCommand.GETSET, key, keyArgs(key, convert, type, value)).thenApply(v -> v.getObjectValue(key, cryptor, type)); - } - - @Override - public CompletableFuture getDelAsync(String key, final Type type) { - return sendAsync(RedisCommand.GETDEL, key, keyArgs(key)).thenApply(v -> v.getObjectValue(key, cryptor, type)); - } - - //--------------------- setex ------------------------------ - @Override - public CompletableFuture setexAsync(String key, int expireSeconds, Convert convert, final Type type, T value) { - return sendAsync(RedisCommand.SETEX, key, keyArgs(key, expireSeconds, convert, type, value)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture setnxexAsync(String key, int expireSeconds, Convert convert, final Type type, T value) { - return sendAsync(RedisCommand.SET, key, keyArgs(key, expireSeconds, NX, EX, convert, type, value)).thenApply(v -> v.getBoolValue()); - } - - //--------------------- expire ------------------------------ - @Override - public CompletableFuture expireAsync(String key, int expireSeconds) { - return sendAsync(RedisCommand.EXPIRE, key, keyArgs(key, expireSeconds)).thenApply(v -> v.getVoidValue()); - } - - //--------------------- persist ------------------------------ - @Override - public CompletableFuture persistAsync(String key) { - return sendAsync(RedisCommand.PERSIST, key, keyArgs(key)).thenApply(v -> v.getBoolValue()); - } - - //--------------------- rename ------------------------------ - @Override - public CompletableFuture renameAsync(String oldKey, String newKey) { - return sendAsync(RedisCommand.RENAME, oldKey, keysArgs(oldKey, newKey)).thenApply(v -> v.getBoolValue()); - } - - @Override - public CompletableFuture renamenxAsync(String oldKey, String newKey) { - return sendAsync(RedisCommand.RENAMENX, oldKey, keysArgs(oldKey, newKey)).thenApply(v -> v.getBoolValue()); - } - - //--------------------- del ------------------------------ - @Override - public CompletableFuture delAsync(String... keys) { - if (keys.length == 0) { - return CompletableFuture.completedFuture(0L); - } - return sendAsync(RedisCommand.DEL, keys[0], keysArgs(keys)).thenApply(v -> v.getLongValue(0L)); - } - - //--------------------- incrby ------------------------------ - @Override - public CompletableFuture incrAsync(final String key) { - return sendAsync(RedisCommand.INCR, key, keyArgs(key)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture incrbyAsync(final String key, long num) { - return sendAsync(RedisCommand.INCRBY, key, keyArgs(key, num)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture incrbyFloatAsync(final String key, double num) { - return sendAsync(RedisCommand.INCRBYFLOAT, key, keyArgs(key, num)).thenApply(v -> v.getDoubleValue(0.d)); - } - - //--------------------- decrby ------------------------------ - @Override - public CompletableFuture decrAsync(final String key) { - return sendAsync(RedisCommand.DECR, key, keyArgs(key)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture decrbyAsync(final String key, long num) { - return sendAsync(RedisCommand.DECRBY, key, keyArgs(key, num)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture hdelAsync(final String key, String... fields) { - return sendAsync(RedisCommand.HDEL, key, keysArgs(key, fields)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture hlenAsync(final String key) { - return sendAsync(RedisCommand.HLEN, key, keyArgs(key)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture> hkeysAsync(final String key) { - return sendAsync(RedisCommand.HKEYS, key, keyArgs(key)).thenApply(v -> (List) v.getListValue(key, cryptor, String.class)); - } - - @Override - public CompletableFuture hincrAsync(final String key, String field) { - return hincrbyAsync(key, field, 1); - } - - @Override - public CompletableFuture hincrbyAsync(final String key, String field, long num) { - return sendAsync(RedisCommand.HINCRBY, key, keysArgs(key, field, String.valueOf(num))).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture hincrbyFloatAsync(final String key, String field, double num) { - return sendAsync(RedisCommand.HINCRBYFLOAT, key, keysArgs(key, field, String.valueOf(num))).thenApply(v -> v.getDoubleValue(0.d)); - } - - @Override - public CompletableFuture hdecrAsync(final String key, String field) { - return hincrbyAsync(key, field, -1); - } - - @Override - public CompletableFuture hdecrbyAsync(final String key, String field, long num) { - return hincrbyAsync(key, field, -num); - } - - @Override - public CompletableFuture hexistsAsync(final String key, String field) { - return sendAsync(RedisCommand.HEXISTS, key, keysArgs(key, field)).thenApply(v -> v.getIntValue(0) > 0); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Convert convert, final Type type, final T value) { - if (value == null) { - return CompletableFuture.completedFuture(null); - } - return sendAsync(RedisCommand.HSET, key, keyArgs(key, field, convert, type, value)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture hsetnxAsync(final String key, final String field, final Convert convert, final Type type, final T value) { - if (value == null) { - return CompletableFuture.completedFuture(null); - } - return sendAsync(RedisCommand.HSETNX, key, keyArgs(key, field, convert, type, value)).thenApply(v -> v.getBoolValue()); - } - - @Override - public CompletableFuture hmsetAsync(final String key, final Serializable... values) { - return sendAsync(RedisCommand.HMSET, key, keyMapArgs(key, values)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture hmsetAsync(final String key, final Map map) { - if (isEmpty(map)) { - return CompletableFuture.completedFuture(null); - } - return sendAsync(RedisCommand.HMSET, key, keyMapArgs(key, map)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture> hmgetAsync(final String key, final Type type, final String... fields) { - return sendAsync(RedisCommand.HMGET, key, keysArgs(key, fields)).thenApply(v -> (List) v.getListValue(key, cryptor, type)); - } - - @Override - public CompletableFuture> hscanAsync(final String key, final Type type, AtomicLong cursor, int limit, String pattern) { - return sendAsync(RedisCommand.HSCAN, key, keyArgs(key, cursor, limit, pattern)).thenApply(v -> { - Map map = v.getMapValue(key, cryptor, type); - cursor.set(v.getCursor()); - return map; - }); - } - - @Override - public CompletableFuture> hgetallAsync(final String key, final Type type) { - return sendAsync(RedisCommand.HGETALL, key, keyArgs(key)).thenApply(v -> v.getMapValue(key, cryptor, type)); - } - - @Override - public CompletableFuture> hvalsAsync(final String key, final Type type) { - return sendAsync(RedisCommand.HVALS, key, keyArgs(key)).thenApply(v -> v.getListValue(key, cryptor, type)); - } - - @Override - public CompletableFuture hgetAsync(final String key, final String field, final Type type) { - return sendAsync(RedisCommand.HGET, key, keysArgs(key, field)).thenApply(v -> v.getObjectValue(key, cryptor, type)); - } - - @Override - public CompletableFuture hstrlenAsync(String key, final String field) { - return sendAsync(RedisCommand.HSTRLEN, key, keysArgs(key, field)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture> smembersAsync(String key, final Type componentType) { - return sendAsync(RedisCommand.SMEMBERS, key, keyArgs(key)).thenApply(v -> v.getSetValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture> lrangeAsync(String key, final Type componentType, int start, int stop) { - return sendAsync(RedisCommand.LRANGE, key, keyArgs(key, start, stop)).thenApply(v -> v.getListValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture lindexAsync(String key, Type componentType, int index) { - return sendAsync(RedisCommand.LINDEX, key, keyArgs(key, index)).thenApply(v -> v.getObjectValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture linsertBeforeAsync(String key, Type componentType, T pivot, T value) { - return sendAsync(RedisCommand.LINSERT, key, keyArgs(key, "BEFORE", componentType, pivot, value)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture linsertAfterAsync(String key, Type componentType, T pivot, T value) { - return sendAsync(RedisCommand.LINSERT, key, keyArgs(key, "AFTER", componentType, pivot, value)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture ltrimAsync(final String key, int start, int stop) { - return sendAsync(RedisCommand.LTRIM, key, keyArgs(key, start, stop)).thenApply(v -> null); - } - - @Override - public CompletableFuture lpopAsync(final String key, final Type componentType) { - return sendAsync(RedisCommand.LPOP, key, keyArgs(key)).thenApply(v -> v.getObjectValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture lpushAsync(final String key, final Type componentType, T... values) { - return sendAsync(RedisCommand.LPUSH, key, keyArgs(key, componentType, values)).thenApply(v -> null); - } - - @Override - public CompletableFuture lpushxAsync(final String key, final Type componentType, T... values) { - return sendAsync(RedisCommand.LPUSHX, key, keyArgs(key, componentType, values)).thenApply(v -> null); - } - - @Override - public CompletableFuture rpopAsync(final String key, final Type componentType) { - return sendAsync(RedisCommand.RPOP, key, keyArgs(key)).thenApply(v -> v.getObjectValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture rpoplpushAsync(final String key, final String key2, final Type componentType) { - return sendAsync(RedisCommand.RPOPLPUSH, key, keysArgs(key, key2)).thenApply(v -> v.getObjectValue(key, cryptor, componentType)); - } - - //--------------------- collection ------------------------------ - @Override - public CompletableFuture llenAsync(String key) { - return sendAsync(RedisCommand.LLEN, key, keyArgs(key)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture scardAsync(String key) { - return sendAsync(RedisCommand.SCARD, key, keyArgs(key)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture> smismembersAsync(final String key, final String... members) { - return sendAsync(RedisCommand.SMISMEMBER, key, keysArgs(key, members)).thenApply(v -> v.getListValue(key, cryptor, Boolean.class)); - } - - @Override - public CompletableFuture smoveAsync(String key, String key2, Type componentType, T member) { - return sendAsync(RedisCommand.SMOVE, key, keyArgs(key, key2, componentType, member)).thenApply(v -> v.getBoolValue()); - } - - @Override - public CompletableFuture> srandmemberAsync(String key, Type componentType, int count) { - return sendAsync(RedisCommand.SRANDMEMBER, key, keyArgs(key, count)).thenApply(v -> v.getListValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture> sdiffAsync(final String key, final Type componentType, final String... key2s) { - return sendAsync(RedisCommand.SDIFF, key, keysArgs(key, key2s)).thenApply(v -> v.getSetValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture sdiffstoreAsync(final String key, final String srcKey, final String... srcKey2s) { - return sendAsync(RedisCommand.SDIFFSTORE, key, keysArgs(Utility.append(key, srcKey, srcKey2s))).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture> sinterAsync(final String key, final Type componentType, final String... key2s) { - return sendAsync(RedisCommand.SINTER, key, keysArgs(key, key2s)).thenApply(v -> v.getSetValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture sinterstoreAsync(final String key, final String srcKey, final String... srcKey2s) { - return sendAsync(RedisCommand.SINTERSTORE, key, keysArgs(Utility.append(key, srcKey, srcKey2s))).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture> sunionAsync(final String key, final Type componentType, final String... key2s) { - return sendAsync(RedisCommand.SUNION, key, keysArgs(key, key2s)).thenApply(v -> v.getSetValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture sunionstoreAsync(final String key, final String srcKey, final String... srcKey2s) { - return sendAsync(RedisCommand.SUNIONSTORE, key, keysArgs(Utility.append(key, srcKey, srcKey2s))).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture> mgetAsync(final Type componentType, final String... keys) { - return sendAsync(RedisCommand.MGET, keys[0], keysArgs(keys)).thenApply(v -> (List) v.getListValue(keys[0], cryptor, componentType)); - } - - @Override - public CompletableFuture>> smembersAsync(final Type componentType, final String... keys) { - final RedisCacheRequest[] requests = new RedisCacheRequest[keys.length]; - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - requests[i] = RedisCacheRequest.create(RedisCommand.SMEMBERS, key, keyArgs(key)); - } - return sendAsync(requests).thenApply(list -> { - final Map> map = new LinkedHashMap<>(); - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - Set c = list.get(i).getSetValue(key, cryptor, componentType); - if (c != null) { - map.put(key, c); - } - } - return map; - }); - } - - @Override - public CompletableFuture>> lrangesAsync(final Type componentType, final String... keys) { - final RedisCacheRequest[] requests = new RedisCacheRequest[keys.length]; - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - requests[i] = RedisCacheRequest.create(RedisCommand.LRANGE, key, keyArgs(key, 0, -1)); - } - return sendAsync(requests).thenApply(list -> { - final Map> map = new LinkedHashMap<>(); - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - List c = list.get(i).getListValue(key, cryptor, componentType); - if (c != null) { - map.put(key, c); - } - } - return map; - }); - } - - @Override - public CompletableFuture sismemberAsync(String key, final Type componentType, T value) { - return sendAsync(RedisCommand.SISMEMBER, key, keyArgs(key, componentType, value)).thenApply(v -> v.getIntValue(0) > 0); - } - - //--------------------- rpush ------------------------------ - @Override - public CompletableFuture rpushAsync(String key, final Type componentType, T... values) { - return sendAsync(RedisCommand.RPUSH, key, keyArgs(key, componentType, values)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture rpushxAsync(String key, final Type componentType, T... values) { - return sendAsync(RedisCommand.RPUSHX, key, keyArgs(key, componentType, values)).thenApply(v -> v.getVoidValue()); - } - - //--------------------- lrem ------------------------------ - @Override - public CompletableFuture lremAsync(String key, final Type componentType, T value) { - return sendAsync(RedisCommand.LREM, key, keyArgs(key, 0, componentType, value)).thenApply(v -> v.getLongValue(0L)); - } - - //--------------------- sadd ------------------------------ - @Override - public CompletableFuture saddAsync(String key, Type componentType, T... values) { - return sendAsync(RedisCommand.SADD, key, keyArgs(key, componentType, values)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture spopAsync(String key, Type componentType) { - return sendAsync(RedisCommand.SPOP, key, keyArgs(key)).thenApply(v -> v.getObjectValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture> spopAsync(String key, int count, Type componentType) { - return sendAsync(RedisCommand.SPOP, key, keyArgs(key, count)).thenApply(v -> v.getSetValue(key, cryptor, componentType)); - } - - @Override - public CompletableFuture> sscanAsync(final String key, final Type componentType, AtomicLong cursor, int limit, String pattern) { - return sendAsync(RedisCommand.SSCAN, key, keyArgs(key, cursor, limit, pattern)).thenApply(v -> { - Set set = v.getSetValue(key, cryptor, componentType); - cursor.set(v.getCursor()); - return set; - }); - } - - @Override - public CompletableFuture sremAsync(String key, final Type componentType, T... values) { - return sendAsync(RedisCommand.SREM, key, keyArgs(key, componentType, values)).thenApply(v -> v.getLongValue(0L)); - } - - //--------------------- sorted set ------------------------------ - @Override - public CompletableFuture zaddAsync(String key, CacheScoredValue... values) { - return sendAsync(RedisCommand.ZADD, key, keyArgs(key, values)).thenApply(v -> v.getVoidValue()); - } - - @Override - public CompletableFuture zincrbyAsync(String key, CacheScoredValue value) { - return sendAsync(RedisCommand.ZINCRBY, key, keyArgs(key, value)).thenApply(v -> v.getObjectValue(key, (RedisCryptor) null, value.getScore().getClass())); - } - - @Override - public CompletableFuture zremAsync(String key, String... members) { - return sendAsync(RedisCommand.ZREM, key, keysArgs(key, members)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture> zmscoreAsync(String key, Class scoreType, String... members) { - return sendAsync(RedisCommand.ZMSCORE, key, keysArgs(key, members)).thenApply(v -> v.getListValue(key, (RedisCryptor) null, scoreType)); - } - - @Override - public CompletableFuture zscoreAsync(String key, Class scoreType, String member) { - return sendAsync(RedisCommand.ZSCORE, key, keysArgs(key, member)).thenApply(v -> v.getObjectValue(key, (RedisCryptor) null, scoreType)); - } - - @Override - public CompletableFuture zcardAsync(String key) { - return sendAsync(RedisCommand.ZCARD, key, keyArgs(key)).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture zrankAsync(String key, String member) { - return sendAsync(RedisCommand.ZRANK, key, keysArgs(key, member)).thenApply(v -> v.getLongValue(null)); - } - - @Override - public CompletableFuture zrevrankAsync(String key, String member) { - return sendAsync(RedisCommand.ZREVRANK, key, keysArgs(key, member)).thenApply(v -> v.getLongValue(null)); - } - - @Override - public CompletableFuture> zrangeAsync(String key, int start, int stop) { - return sendAsync(RedisCommand.ZRANGE, key, keyArgs(key, start, stop)).thenApply(v -> v.getListValue(key, (RedisCryptor) null, String.class)); - } - - @Override - public CompletableFuture> zscanAsync(String key, Type scoreType, AtomicLong cursor, int limit, String pattern) { - return sendAsync(RedisCommand.ZSCAN, null, keyArgs(key, cursor, limit, pattern)).thenApply(v -> { - List set = v.getScoreListValue(null, (RedisCryptor) null, scoreType); - cursor.set(v.getCursor()); - return set; - }); - } - - //--------------------- keys ------------------------------ - @Override - public CompletableFuture> keysAsync(String pattern) { - String key = isEmpty(pattern) ? "*" : pattern; - return sendAsync(RedisCommand.KEYS, key, keyArgs(key)).thenApply(v -> (List) v.getListValue(key, (RedisCryptor) null, String.class)); - } - - @Override - public CompletableFuture> scanAsync(AtomicLong cursor, int limit, String pattern) { - return sendAsync(RedisCommand.SCAN, null, keyArgs(null, cursor, limit, pattern)).thenApply(v -> { - List list = v.getListValue(null, (RedisCryptor) null, String.class); - cursor.set(v.getCursor()); - return list; - }); - } - - //--------------------- dbsize ------------------------------ - @Override - public CompletableFuture dbsizeAsync() { - return sendAsync(RedisCommand.DBSIZE, null).thenApply(v -> v.getLongValue(0L)); - } - - @Override - public CompletableFuture flushdbAsync() { - return sendAsync(RedisCommand.FLUSHDB, null).thenApply(v -> null); - } - - @Override - public CompletableFuture flushallAsync() { - return sendAsync(RedisCommand.FLUSHALL, null).thenApply(v -> null); - } - - //--------------------- send ------------------------------ - @Local - public CompletableFuture sendAsync(final RedisCommand command, final String key, final byte[]... args) { - WorkThread workThread = WorkThread.currentWorkThread(); - String traceid = Traces.currentTraceid(); - if (false && logger.isLoggable(Level.FINEST)) { - logger.log(Level.FINEST, "redis.send(traceid=" + traceid + ") " + command + " " + key); - CompletableFuture future = client.connect() - .thenCompose(conn -> { - if (isNotEmpty(traceid)) { - Traces.computeIfAbsent(traceid); - } - RedisCacheRequest req = conn.pollRequest(workThread, traceid).prepare(command, key, args); - req.traceid(traceid); - logger.log(Level.FINEST, "redis.send(traceid=" + traceid + ") request: " + req); - return conn.writeRequest(req).thenApply(v -> { - logger.log(Level.FINEST, "redis.callback(traceid=" + traceid + ") response: " + v); - return v; - }); - }); - return Utility.orTimeout(future, 6, TimeUnit.SECONDS); - } else { - return Utility.orTimeout(client.connect() - .thenCompose(conn -> { - if (isNotEmpty(traceid)) { - Traces.computeIfAbsent(traceid); - } - RedisCacheRequest req = conn.pollRequest(workThread, traceid).prepare(command, key, args); - req.traceid(traceid); - return conn.writeRequest(req); - }), - 6, TimeUnit.SECONDS); - } - } - - @Local - public CompletableFuture> sendAsync(final RedisCacheRequest... requests) { - WorkThread workThread = WorkThread.currentWorkThread(); - String traceid = Traces.currentTraceid(); - for (RedisCacheRequest request : requests) { - request.workThread(workThread).traceid(traceid); - } - return Utility.orTimeout(client.connect() - .thenCompose(conn -> { - if (isNotEmpty(traceid)) { - Traces.computeIfAbsent(traceid); - } - return conn.writeRequest(requests); - }), - 6, TimeUnit.SECONDS); - } - - private byte[][] keyArgs(String key) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keyArgs(final String key, AtomicLong cursor, int limit, String pattern) { - int c = isNotEmpty(key) ? 2 : 1; - if (isNotEmpty(pattern)) { - c += 2; - } - if (limit > 0) { - c += 2; - } - byte[][] bss = new byte[c][]; - int index = -1; - if (isNotEmpty(key)) { - bss[++index] = key.getBytes(StandardCharsets.UTF_8); - } - bss[++index] = cursor.toString().getBytes(StandardCharsets.UTF_8); - if (isNotEmpty(pattern)) { - bss[++index] = BYTES_MATCH; - bss[++index] = pattern.getBytes(StandardCharsets.UTF_8); - } - if (limit > 0) { - bss[++index] = BYTES_COUNT; - bss[++index] = String.valueOf(limit).getBytes(StandardCharsets.UTF_8); - } - return bss; - } - - private byte[][] keyArgs(String key, Number numValue) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), numValue.toString().getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keyArgs(String key, int numValue) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), String.valueOf(numValue).getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keyArgs(String key, long numValue) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), String.valueOf(numValue).getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keyArgs(String key, String ex, int numValue) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), - ex.getBytes(StandardCharsets.UTF_8), - String.valueOf(numValue).getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keyArgs(String key, int start, int stop) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), - String.valueOf(start).getBytes(StandardCharsets.UTF_8), - String.valueOf(stop).getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keyArgs(String key, Type type, Object value) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), encodeValue(key, cryptor, null, type, value)}; - } - - private byte[][] keyArgs(String key, Convert convert, Type type, Object value) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), encodeValue(key, cryptor, convert, type, value)}; - } - - private byte[][] keyArgs(String key, String field, Type type, Object value) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), encodeValue(key, cryptor, null, type, value)}; - } - - private byte[][] keyArgs(String key, String field, Convert convert, Type type, Object value) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), encodeValue(key, cryptor, convert, type, value)}; - } - - private byte[][] keyArgs(String key, int expire, Type type, Object value) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), - String.valueOf(expire).getBytes(StandardCharsets.UTF_8), - encodeValue(key, cryptor, null, type, value)}; - } - - private byte[][] keyArgs(String key, int expire, Convert convert, Type type, Object value) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), - String.valueOf(expire).getBytes(StandardCharsets.UTF_8), - encodeValue(key, cryptor, convert, type, value)}; - } - - private byte[][] keyArgs(String key, final Type componentType, T... values) { - byte[][] bss = new byte[values.length + 1][]; - bss[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < values.length; i++) { - bss[i + 1] = encodeValue(key, cryptor, null, componentType, values[i]); - } - return bss; - } - - private byte[][] keyArgs(String key, String arg, final Type componentType, T... values) { - byte[][] bss = new byte[values.length + 2][]; - bss[0] = key.getBytes(StandardCharsets.UTF_8); - bss[1] = arg.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < values.length; i++) { - bss[i + 2] = encodeValue(key, cryptor, null, componentType, values[i]); - } - return bss; - } - - private byte[][] keyArgs(String key, CacheScoredValue... values) { - byte[][] bss = new byte[values.length * 2 + 1][]; - bss[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < values.length * 2; i += 2) { - bss[i + 1] = values[i].getScore().toString().getBytes(StandardCharsets.UTF_8); - bss[i + 2] = values[i].getValue().getBytes(StandardCharsets.UTF_8); - } - return bss; - } - - private byte[][] keyArgs(String key, int expire, byte[] nx, byte[] ex, Convert convert, Type type, Object value) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), - encodeValue(key, cryptor, convert, type, value), nx, ex, - String.valueOf(expire).getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keyMapArgs(String key, Serializable... keyVals) { - byte[][] bss = new byte[keyVals.length + (key == null ? 0 : 1)][]; - int start = -1; - if (key != null) { - start++; - bss[0] = key.getBytes(StandardCharsets.UTF_8); - } - for (int i = 0; i < keyVals.length; i += 2) { - String k = keyVals[i].toString(); - bss[i + start + 1] = k.getBytes(StandardCharsets.UTF_8); - bss[i + start + 2] = encodeValue(k, cryptor, keyVals[i + 1]); - } - return bss; - } - - private byte[][] keyMapArgs(String key, Map map) { - byte[][] bss = new byte[map.size() * 2 + (key == null ? 0 : 1)][]; - int start = 0; - if (key != null) { - start++; - bss[0] = key.getBytes(StandardCharsets.UTF_8); - } - AtomicInteger index = new AtomicInteger(start); - map.forEach((k, v) -> { - int i = index.getAndAdd(2); - bss[i] = k.toString().getBytes(StandardCharsets.UTF_8); - bss[i + 1] = encodeValue(k.toString(), cryptor, v); - }); - return bss; - } - - private byte[][] keymArgs(Serializable... keyVals) { - return keyMapArgs(null, keyVals); - } - - private byte[][] keymArgs(Map map) { - return keyMapArgs(null, map); - } - - private byte[][] keysArgs(String key, String field) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keysArgs(String key, String field, String num) { - return new byte[][]{key.getBytes(StandardCharsets.UTF_8), - field.getBytes(StandardCharsets.UTF_8), - num.getBytes(StandardCharsets.UTF_8)}; - } - - private byte[][] keysArgs(String... keys) { - byte[][] bss = new byte[keys.length][]; - for (int i = 0; i < keys.length; i++) { - bss[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return bss; - } - - static byte[][] keysArgs(String key, String... keys) { - if (key == null) { - byte[][] bss = new byte[keys.length][]; - for (int i = 0; i < keys.length; i++) { - bss[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return bss; - } else { - byte[][] bss = new byte[keys.length + 1][]; - bss[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < keys.length; i++) { - bss[i + 1] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return bss; - } - } - - private byte[] encodeValue(String key, RedisCryptor cryptor, String value) { - if (cryptor != null) { - value = cryptor.encrypt(key, value); - } - if (value == null) { - throw new NullPointerException(); - } - return value.getBytes(StandardCharsets.UTF_8); - } - - private byte[] encodeValue(String key, RedisCryptor cryptor, Object value) { - return encodeValue(key, cryptor, null, null, value); - } - - private byte[] encodeValue(String key, RedisCryptor cryptor, Convert convert0, Type type, Object value) { - if (value == null) { - throw new NullPointerException(); - } - if (value instanceof Boolean) { - return (Boolean) value ? RedisCacheRequest.BYTES_TRUE : RedisCacheRequest.BYTES_FALSE; - } - if (value instanceof byte[]) { - if (cryptor != null) { - String val = cryptor.encrypt(key, new String((byte[]) value, StandardCharsets.UTF_8)); - return val.getBytes(StandardCharsets.UTF_8); - } - return (byte[]) value; - } - if (value instanceof CharSequence) { - if (cryptor != null) { - value = cryptor.encrypt(key, String.valueOf(value)); - } - return value.toString().getBytes(StandardCharsets.UTF_8); - } - if (value.getClass().isPrimitive() || Number.class.isAssignableFrom(value.getClass())) { - return value.toString().getBytes(StandardCharsets.US_ASCII); - } - if (convert0 == null) { - if (convert == null) { //compile模式下convert可能为null - convert = JsonConvert.root(); - } - convert0 = convert; - } - Type t = type == null ? value.getClass() : type; - byte[] bs = convert0.convertToBytes(t, value); - if (bs.length > 1 && t instanceof Class && !CharSequence.class.isAssignableFrom((Class) t)) { - if (bs[0] == '"' && bs[bs.length - 1] == '"') { - bs = Arrays.copyOfRange(bs, 1, bs.length - 1); - } - } - if (cryptor != null) { - String val = cryptor.encrypt(key, new String(bs, StandardCharsets.UTF_8)); - return val.getBytes(StandardCharsets.UTF_8); - } - return bs; - } - - //-------------------------- 过期方法 ---------------------------------- - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture>> getCollectionMapAsync(final boolean set, final Type componentType, final String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new LinkedHashMap<>(); - final ReentrantLock mapLock = new ReentrantLock(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = sendAsync(set ? RedisCommand.SMEMBERS : RedisCommand.LRANGE, key, set ? keyArgs(key) : keyArgs(key, 0, -1)).thenAccept(v -> { - Collection c = set ? v.getSetValue(key, cryptor, componentType) : v.getListValue(key, cryptor, componentType); - if (c != null) { - mapLock.lock(); - try { - map.put(key, (Collection) c); - } finally { - mapLock.unlock(); - } - } - }); - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture getCollectionSizeAsync(String key) { - return sendAsync(RedisCommand.TYPE, key, keyArgs(key)).thenCompose(t -> { - String type = t.getObjectValue(key, cryptor, String.class); - if (type == null) { - return CompletableFuture.completedFuture(0); - } - return sendAsync(type.contains("list") ? RedisCommand.LLEN : RedisCommand.SCARD, key, keyArgs(key)).thenApply(v -> v.getIntValue(0)); - }); - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture> getCollectionAsync(String key, final Type componentType) { - return sendAsync(RedisCommand.TYPE, key, keyArgs(key)).thenCompose(t -> { - String type = t.getObjectValue(key, cryptor, String.class); - if (type == null) { - return CompletableFuture.completedFuture(null); - } - boolean set = !type.contains("list"); - return sendAsync(set ? RedisCommand.SMEMBERS : RedisCommand.LRANGE, key, set ? keyArgs(key) : keyArgs(key, 0, -1)).thenApply(v -> set ? v.getSetValue(key, cryptor, componentType) : v.getListValue(key, cryptor, componentType)); - }); - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture getLongArrayAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return sendAsync(RedisCommand.MGET, keys[0], bs).thenApply(v -> { - List list = (List) v.getListValue(keys[0], cryptor, long.class); - Long[] rs = new Long[keys.length]; - for (int i = 0; i < keys.length; i++) { - Number obj = (Number) list.get(i); - rs[i] = obj == null ? null : obj.longValue(); - } - return rs; - }); - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture getStringArrayAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return sendAsync(RedisCommand.MGET, keys[0], bs).thenApply(v -> { - List list = (List) v.getListValue(keys[0], cryptor, String.class); - String[] rs = new String[keys.length]; - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - rs[i] = obj == null ? null : obj.toString(); - } - return rs; - }); - } - - @Override - @Deprecated(since = "2.8.0") - public Long[] getLongArray(final String... keys) { - return getLongArrayAsync(keys).join(); - } - - @Override - @Deprecated(since = "2.8.0") - public String[] getStringArray(final String... keys) { - return getStringArrayAsync(keys).join(); - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture> getStringCollectionAsync(String key) { - return sendAsync(RedisCommand.TYPE, key, keyArgs(key)).thenCompose(t -> { - String type = t.getObjectValue(key, cryptor, String.class); - if (type == null) { - return CompletableFuture.completedFuture(null); - } - boolean set = !type.contains("list"); - return sendAsync(set ? RedisCommand.SMEMBERS : RedisCommand.LRANGE, key, set ? keyArgs(key) : keyArgs(key, 0, -1)).thenApply(v -> set ? v.getSetValue(key, cryptor, String.class) : v.getListValue(key, cryptor, String.class)); - }); - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture>> getStringCollectionMapAsync(final boolean set, String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new LinkedHashMap<>(); - final ReentrantLock mapLock = new ReentrantLock(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = sendAsync(set ? RedisCommand.SMEMBERS : RedisCommand.LRANGE, key, set ? keyArgs(key) : keyArgs(key, 0, -1)).thenAccept(v -> { - Collection c = set ? v.getSetValue(key, cryptor, String.class) : v.getListValue(key, cryptor, String.class); - if (c != null) { - mapLock.lock(); - try { - map.put(key, (Collection) c); - } finally { - mapLock.unlock(); - } - } - }); - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture> getLongCollectionAsync(String key) { - return sendAsync(RedisCommand.TYPE, key, keyArgs(key)).thenCompose(t -> { - String type = t.getObjectValue(key, cryptor, String.class); - if (type == null) { - return CompletableFuture.completedFuture(null); - } - boolean set = !type.contains("list"); - return sendAsync(set ? RedisCommand.SMEMBERS : RedisCommand.LRANGE, key, set ? keyArgs(key) : keyArgs(key, 0, -1)) - .thenApply(v -> set ? v.getSetValue(key, cryptor, long.class) : v.getListValue(key, cryptor, long.class)); - }); - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture>> getLongCollectionMapAsync(final boolean set, String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new LinkedHashMap<>(); - final ReentrantLock mapLock = new ReentrantLock(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = sendAsync(set ? RedisCommand.SMEMBERS : RedisCommand.LRANGE, key, set ? keyArgs(key) : keyArgs(key, 0, -1)).thenAccept(v -> { - Collection c = set ? v.getSetValue(key, cryptor, long.class) : v.getListValue(key, cryptor, long.class); - if (c != null) { - mapLock.lock(); - try { - map.put(key, (Collection) c); - } finally { - mapLock.unlock(); - } - } - }); - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - //--------------------- getexCollection ------------------------------ - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture> getexCollectionAsync(String key, int expireSeconds, final Type componentType) { - return (CompletableFuture) expireAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key, componentType)); - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture> getexStringCollectionAsync(String key, int expireSeconds) { - return (CompletableFuture) expireAsync(key, expireSeconds).thenCompose(v -> getStringCollectionAsync(key)); - } - - @Override - @Deprecated(since = "2.8.0") - public CompletableFuture> getexLongCollectionAsync(String key, int expireSeconds) { - return (CompletableFuture) expireAsync(key, expireSeconds).thenCompose(v -> getLongCollectionAsync(key)); - } - -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheSourceProvider.java b/src/main/java/org/redkalex/cache/redis/RedisCacheSourceProvider.java deleted file mode 100644 index 3518465..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCacheSourceProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkalex.cache.redis; - -import org.redkale.annotation.Priority; -import org.redkale.source.CacheSource; -import org.redkale.source.CacheSourceProvider; -import org.redkale.util.AnyValue; - -/** - * - * @author zhangjx - */ -@Priority(-900) -public class RedisCacheSourceProvider implements CacheSourceProvider { - - @Override - public boolean acceptsConf(AnyValue config) { - return new RedisCacheSource().acceptsConf(config); - } - - @Override - public CacheSource createInstance() { - return new RedisCacheSource(); - } - -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCommand.java b/src/main/java/org/redkalex/cache/redis/RedisCommand.java deleted file mode 100644 index a876d21..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCommand.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - */ -package org.redkalex.cache.redis; - -import java.nio.charset.StandardCharsets; - -/** - * @author zhangjx - */ -public enum RedisCommand { - - EXISTS("EXISTS", true), - GET("GET", true), - GETEX("GETEX", true), - MSET("MSET", false), - SET("SET", false), - SETNX("SETNX", false), - GETSET("GETSET", false), - GETDEL("GETDEL", false), - SETEX("SETEX", false), - EXPIRE("EXPIRE", false), - PERSIST("PERSIST", false), - RENAME("RENAME", false), - RENAMENX("RENAMENX", false), - DEL("DEL", false), - INCR("INCR", false), - INCRBY("INCRBY", false), - INCRBYFLOAT("INCRBYFLOAT", false), - DECR("DECR", false), - DECRBY("DECRBY", false), - HDEL("HDEL", false), - HINCRBY("HINCRBY", false), - HINCRBYFLOAT("HINCRBYFLOAT", false), - LINSERT("LINSERT", false), - LTRIM("LTRIM", false), - LPOP("LPOP", false), - LPUSH("LPUSH", false), - LPUSHX("LPUSHX", false), - RPOP("RPOP", false), - RPOPLPUSH("RPOPLPUSH", false), - SMOVE("SMOVE", false), - RPUSH("RPUSH", false), - RPUSHX("RPUSHX", false), - LREM("LREM", false), - SADD("SADD", false), - SPOP("SPOP", false), - SSCAN("SSCAN", true), - SREM("SREM", false), - ZADD("ZADD", false), - ZINCRBY("ZINCRBY", false), - ZREM("ZREM", false), - ZMSCORE("ZMSCORE", true), - ZSCORE("ZSCORE", true), - ZCARD("ZCARD", true), - ZRANK("ZRANK", true), - ZREVRANK("ZREVRANK", true), - ZRANGE("ZRANGE", true), - ZSCAN("ZSCAN", true), - FLUSHDB("FLUSHDB", false), - FLUSHALL("FLUSHALL", false), - HMGET("HMGET", true), - HLEN("HLEN", true), - HKEYS("HKEYS", true), - HEXISTS("HEXISTS", true), - HSET("HSET", true), - HSETNX("HSETNX", true), - HMSET("HMSET", true), - HSCAN("HSCAN", true), - HGETALL("HGETALL", true), - HVALS("HVALS", true), - HGET("HGET", true), - HSTRLEN("HSTRLEN", true), - SMEMBERS("SMEMBERS", true), - SISMEMBER("SISMEMBER", true), - LRANGE("LRANGE", true), - LINDEX("LINDEX", true), - LLEN("LLEN", true), - SCARD("SCARD", true), - SMISMEMBER("SMISMEMBER", true), - SRANDMEMBER("SRANDMEMBER", true), - SDIFF("SDIFF", true), - SDIFFSTORE("SDIFFSTORE", false), - SINTER("SINTER", true), - SINTERSTORE("SINTERSTORE", false), - SUNION("SUNION", true), - SUNIONSTORE("SUNIONSTORE", false), - MGET("MGET", true), - KEYS("KEYS", true), - SCAN("SCAN", true), - DBSIZE("DBSIZE", true), - TYPE("TYPE", true), - SUBSCRIBE("SUBSCRIBE", false), - UNSUBSCRIBE("UNSUBSCRIBE", false), - PUBLISH("PUBLISH", false), - PUBSUB("PUBSUB", true), - GETBIT("GETBIT", true), - SETBIT("SETBIT", false), - EVAL("EVAL", false); - - private final String command; - - private final byte[] bytes; - - private final boolean readOnly; - - private RedisCommand(String command, boolean readOnly) { - this.command = command; - this.readOnly = readOnly; - this.bytes = ("$" + command.length() + "\r\n" + command + "\r\n").getBytes(StandardCharsets.ISO_8859_1); - } - - public String getCommand() { - return command; - } - - public byte[] getBytes() { - return bytes; - } - - public boolean isReadOnly() { - return readOnly; - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisConfig.java b/src/main/java/org/redkalex/cache/redis/RedisConfig.java deleted file mode 100644 index 0595fa0..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisConfig.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * - */ -package org.redkalex.cache.redis; - -import org.redkale.convert.json.JsonConvert; -import org.redkale.util.AnyValue; -import org.redkale.util.RedkaleException; -import org.redkale.util.Utility; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import static org.redkale.source.AbstractCacheSource.*; -import static org.redkale.util.Utility.isEmpty; -import static org.redkale.util.Utility.isNotEmpty; - -/** - * - * @author zhangjx - */ -public class RedisConfig { - - private boolean ssl; - - private int db; - - private String username; - - private String password; - - private int maxconns; - - private int pipelines; - - private List addresses; - - public static RedisConfig create(AnyValue conf) { - RedisConfig result = new RedisConfig(); - int gdb = conf.getIntValue(CACHE_SOURCE_DB, 0); - String gusername = null; - String gpassword = conf.getValue(CACHE_SOURCE_PASSWORD); - int gmaxconns = conf.getIntValue(CACHE_SOURCE_MAXCONNS, Utility.cpus()); - int gpipelines = conf.getIntValue(CACHE_SOURCE_PIPELINES, org.redkale.net.client.Client.DEFAULT_MAX_PIPELINES); - String nodes = conf.getValue(CACHE_SOURCE_NODES, conf.getValue("url", "")); - if (Utility.isEmpty(nodes)) { - throw new RedkaleException("Not found nodes config for redis"); - } - List addrs = new ArrayList<>(); - for (String url : nodes.replace(',', ';').split(";")) { - String urluser = null; - String urlpwd = null; - String urldb = null; - String urlmaxconns = null; - String urlpipelines = null; - addrs.add(url); - if (url.startsWith("redis://")) { //兼容 redis://:1234@127.0.0.1:6379?db=2 - URI uri = URI.create(url); - String userInfo = uri.getUserInfo(); - if (isEmpty(userInfo)) { - String authority = uri.getAuthority(); - if (authority != null && authority.indexOf('@') > 0) { - userInfo = authority.substring(0, authority.indexOf('@')); - } - } - if (isNotEmpty(userInfo)) { - urlpwd = userInfo; - if (urlpwd.startsWith(":")) { - urlpwd = urlpwd.substring(1); - } else { - int index = urlpwd.indexOf(':'); - if (index > 0) { - urluser = urlpwd.substring(0, index); - urlpwd = urlpwd.substring(index + 1); - } - } - } - if (isNotEmpty(uri.getQuery())) { - String[] qrys = uri.getQuery().split("&|="); - for (int i = 0; i < qrys.length; i += 2) { - if (CACHE_SOURCE_USER.equals(qrys[i])) { - urluser = i == qrys.length - 1 ? "" : qrys[i + 1]; - } else if (CACHE_SOURCE_PASSWORD.equals(qrys[i])) { - urlpwd = i == qrys.length - 1 ? "" : qrys[i + 1]; - } else if (CACHE_SOURCE_DB.equals(qrys[i])) { - urldb = i == qrys.length - 1 ? "" : qrys[i + 1]; - } else if (CACHE_SOURCE_MAXCONNS.equals(qrys[i])) { - urlmaxconns = i == qrys.length - 1 ? "" : qrys[i + 1]; - } else if (CACHE_SOURCE_PIPELINES.equals(qrys[i])) { - urlpipelines = i == qrys.length - 1 ? "" : qrys[i + 1]; - } - } - } - if (isNotEmpty(urluser)) { - gusername = urluser; - } - if (isNotEmpty(urlpwd)) { - gpassword = urlpwd; - } - if (isNotEmpty(urlmaxconns)) { - gmaxconns = Integer.parseInt(urlmaxconns); - } - if (isNotEmpty(urlpipelines)) { - gpipelines = Integer.parseInt(urlpipelines); - } - if (isNotEmpty(urldb)) { - gdb = Integer.parseInt(urldb); - } - } - } - result.ssl = nodes.startsWith("rediss://"); - result.db = gdb; - if (isNotEmpty(gusername)) { - result.username = gusername; - } - if (isNotEmpty(gpassword)) { - result.password = gpassword; - } - result.maxconns = gmaxconns; - result.pipelines = gpipelines; - result.addresses = addrs; - return result; - } - - public boolean isSsl() { - return ssl; - } - - public void setSsl(boolean ssl) { - this.ssl = ssl; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public int getDb() { - return db; - } - - public void setDb(int db) { - this.db = db; - } - - public int getMaxconns() { - return maxconns; - } - - public int getMaxconns(int min) { - return Math.max(maxconns, min); - } - - public void setMaxconns(int maxconns) { - this.maxconns = maxconns; - } - - public int getPipelines() { - return pipelines; - } - - public void setPipelines(int pipelines) { - this.pipelines = pipelines; - } - - public List getAddresses() { - return addresses; - } - - public void setAddresses(List addresses) { - this.addresses = addresses; - } - - @Override - public String toString() { - return JsonConvert.root().convertTo(this); - } -} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCryptor.java b/src/main/java/org/redkalex/cache/redis/RedisCryptor.java deleted file mode 100644 index 2cd0d5b..0000000 --- a/src/main/java/org/redkalex/cache/redis/RedisCryptor.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license - * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template - */ -package org.redkalex.cache.redis; - -import org.redkale.util.AnyValue; - -/** - * - * @author zhangjx - */ -public interface RedisCryptor { - - /** - * 初始化 - * - * @param conf 配置 - */ - public void init(AnyValue conf); - - /** - * 加密, 无需加密的key对应的值需要直接返回value - * - * @param key key - * @param value 明文 - * - * @return 密文 - */ - public String encrypt(String key, String value); - - /** - * 解密, 无需解密的key对应的值需要直接返回value - * - * @param key key - * @param value 密文 - * - * @return 明文 - */ - public String decrypt(String key, String value); - - /** - * 销毁 - * - * @param conf 配置 - */ - public void destroy(AnyValue conf); - -}