zhub-client/src/com/zdemo/cachex/RedisCacheSource.java
2021-10-12 19:00:06 +08:00

2241 lines
105 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 com.zdemo.cachex;
import org.redkale.convert.Convert;
import org.redkale.convert.bson.BsonByteBufferWriter;
import org.redkale.convert.json.JsonConvert;
import org.redkale.convert.json.JsonFactory;
import org.redkale.net.AsyncConnection;
import org.redkale.net.Transport;
import org.redkale.net.TransportFactory;
import org.redkale.service.AbstractService;
import org.redkale.service.Local;
import org.redkale.service.Service;
import org.redkale.source.CacheSource;
import org.redkale.source.Flipper;
import org.redkale.util.*;
import org.redkale.util.AnyValue.DefaultAnyValue;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* 详情见: https://redkale.org
*
* @param <V> Value
* @author zhangjx
*/
@Local
@AutoLoad(false)
@ResourceType(CacheSource.class)
public class RedisCacheSource<V extends Object> extends AbstractService implements CacheSource<V>, Service, AutoCloseable, Resourcable {
protected static final byte DOLLAR_BYTE = '$';
protected static final byte ASTERISK_BYTE = '*';
protected static final byte PLUS_BYTE = '+';
protected static final byte MINUS_BYTE = '-';
protected static final byte COLON_BYTE = ':';
private final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
@Resource
protected JsonConvert defaultConvert;
@Resource(name = "$_convert")
protected JsonConvert convert;
protected Type objValueType = String.class;
protected Map<SocketAddress, byte[]> passwords;
protected List<InetSocketAddress> nodeAddrs;
protected int db;
protected Transport transport;
@Override
public void init(AnyValue conf) {
if (this.convert == null) this.convert = this.defaultConvert;
if (conf == null) conf = new AnyValue.DefaultAnyValue();
AnyValue prop = conf.getAnyValue("properties");
if (prop != null) {
String storeValueStr = prop.getValue("value-type");
if (storeValueStr != null) {
try {
this.initValueType(Thread.currentThread().getContextClassLoader().loadClass(storeValueStr));
} catch (Throwable e) {
logger.log(Level.SEVERE, this.getClass().getSimpleName() + " load key & value store class (" + storeValueStr + ") error", e);
}
}
}
final int bufferCapacity = conf.getIntValue("bufferCapacity", 8 * 1024);
final int bufferPoolSize = conf.getIntValue("bufferPoolSize", Runtime.getRuntime().availableProcessors() * 8);
final int threads = conf.getIntValue("threads", Runtime.getRuntime().availableProcessors() * 8);
final int readTimeoutSeconds = conf.getIntValue("readTimeoutSeconds", TransportFactory.DEFAULT_READTIMEOUTSECONDS);
final int writeTimeoutSeconds = conf.getIntValue("writeTimeoutSeconds", TransportFactory.DEFAULT_WRITETIMEOUTSECONDS);
final List<InetSocketAddress> addresses = new ArrayList<>();
Map<SocketAddress, byte[]> passwords0 = new HashMap<>();
for (AnyValue node : conf.getAnyValues("node")) {
String addrstr = node.getValue("addr");
InetSocketAddress addr = null;
if (addrstr.startsWith("redis://")) {
addrstr = addrstr.substring("redis://".length());
int pos = addrstr.indexOf(':');
addr = new InetSocketAddress(addrstr.substring(0, pos), Integer.parseInt(addrstr.substring(pos + 1)));
addresses.add(addr);
} else {
addr = new InetSocketAddress(addrstr, node.getIntValue("port"));
addresses.add(addr);
}
String password = node.getValue("password", "").trim();
if (!password.isEmpty()) passwords0.put(addr, password.getBytes(StandardCharsets.UTF_8));
String db0 = node.getValue("db", "").trim();
if (!db0.isEmpty()) this.db = Integer.valueOf(db0);
}
if (!passwords0.isEmpty()) this.passwords = passwords0;
this.nodeAddrs = addresses;
TransportFactory transportFactory = TransportFactory.create(threads, bufferPoolSize, bufferCapacity, readTimeoutSeconds, writeTimeoutSeconds);
this.transport = transportFactory.createTransportTCP("Redis-Transport", null, addresses);
this.transport.setSemaphore(new Semaphore(conf.getIntValue("maxconns", threads)));
if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, RedisCacheSource.class.getSimpleName() + ": addrs=" + addresses + ", db=" + db);
}
@Override //ServiceLoader时判断配置是否符合当前实现类
public boolean match(AnyValue config) {
if (config == null) return false;
AnyValue[] nodes = config.getAnyValues("node");
if (nodes == null || nodes.length == 0) return false;
for (AnyValue node : nodes) {
if (node.getValue("addr") != null && node.getValue("port") != null) return true;
if (node.getValue("addr") != null && node.getValue("addr").startsWith("redis://")) return true;
}
return false;
}
public void updateRemoteAddresses(final Collection<InetSocketAddress> addresses) {
this.transport.updateRemoteAddresses(addresses);
}
@Override
@Deprecated
public final void initValueType(Type valueType) {
this.objValueType = valueType == null ? String.class : valueType;
}
@Override
@Deprecated
public final void initTransient(boolean flag) {
}
@Override
public final String getType() {
return "redis";
}
public static void main(String[] args) throws Exception {
DefaultAnyValue conf = new DefaultAnyValue().addValue("maxconns", "1");
conf.addValue("node", new DefaultAnyValue().addValue("addr", "127.0.0.1").addValue("port", "6363"));
RedisCacheSource source = new RedisCacheSource();
source.defaultConvert = JsonFactory.root().getConvert();
source.init(conf);
InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 7788);
try {
System.out.println("------------------------------------");
source.removeAsync("stritem1");
source.removeAsync("stritem2");
source.setStringAsync("stritem1", "value1");
source.setStringAsync("stritem2", "value2");
System.out.println("stritem开头的key有两个: " + source.queryKeysStartsWith("stritem"));
System.out.println("[有值] MGET : " + source.getStringMap("stritem1", "stritem2"));
System.out.println("[有值] MGET : " + Arrays.toString(source.getStringArray("stritem1", "stritem2")));
source.remove("intitem1");
source.remove("intitem2");
source.setLong("intitem1", 333);
source.setLong("intitem2", 444);
System.out.println("[有值] MGET : " + source.getStringMap("intitem1", "intitem22", "intitem2"));
System.out.println("[有值] MGET : " + Arrays.toString(source.getStringArray("intitem1", "intitem22", "intitem2")));
source.remove("objitem1");
source.remove("objitem2");
source.set("objitem1", Flipper.class, new Flipper(10));
source.set("objitem2", Flipper.class, new Flipper(20));
System.out.println("[有值] MGET : " + source.getMap(Flipper.class, "objitem1", "objitem2"));
source.remove("key1");
source.remove("key2");
source.remove("300");
source.set(1000, "key1", String.class, "value1");
source.set("key1", String.class, "value1");
source.setString("keystr1", "strvalue1");
source.setLong("keylong1", 333L);
source.set("300", String.class, "4000");
source.getAndRefresh("key1", 3500, String.class);
System.out.println("[有值] 300 GET : " + source.get("300", String.class));
System.out.println("[有值] key1 GET : " + source.get("key1", String.class));
System.out.println("[无值] key2 GET : " + source.get("key2", String.class));
System.out.println("[有值] keystr1 GET : " + source.getString("keystr1"));
System.out.println("[有值] keylong1 GET : " + source.getLong("keylong1", 0L));
System.out.println("[有值] key1 EXISTS : " + source.exists("key1"));
System.out.println("[无值] key2 EXISTS : " + source.exists("key2"));
source.remove("keys3");
source.appendListItem("keys3", String.class, "vals1");
source.appendListItem("keys3", String.class, "vals2");
System.out.println("-------- keys3 追加了两个值 --------");
System.out.println("[两值] keys3 VALUES : " + source.getCollection("keys3", String.class));
System.out.println("[有值] keys3 EXISTS : " + source.exists("keys3"));
source.removeListItem("keys3", String.class, "vals1");
System.out.println("[一值] keys3 VALUES : " + source.getCollection("keys3", String.class));
source.getCollectionAndRefresh("keys3", 3000, String.class);
source.remove("stringmap");
source.appendSetItem("stringmap", JsonConvert.TYPE_MAP_STRING_STRING, Utility.ofMap("a", "aa", "b", "bb"));
source.appendSetItem("stringmap", JsonConvert.TYPE_MAP_STRING_STRING, Utility.ofMap("c", "cc", "d", "dd"));
System.out.println("[两值] stringmap VALUES : " + source.getCollectionAsync("stringmap", JsonConvert.TYPE_MAP_STRING_STRING).join());
source.remove("sets3");
source.remove("sets4");
source.appendSetItem("sets3", String.class, "setvals1");
source.appendSetItem("sets3", String.class, "setvals2");
source.appendSetItem("sets3", String.class, "setvals1");
source.appendSetItem("sets4", String.class, "setvals2");
source.appendSetItem("sets4", String.class, "setvals1");
System.out.println("[两值] sets3 VALUES : " + source.getCollection("sets3", String.class));
System.out.println("[有值] sets3 EXISTS : " + source.exists("sets3"));
System.out.println("[有值] sets3-setvals2 EXISTSITEM : " + source.existsSetItem("sets3", String.class, "setvals2"));
System.out.println("[有值] sets3-setvals3 EXISTSITEM : " + source.existsSetItem("sets3", String.class, "setvals3"));
source.removeSetItem("sets3", String.class, "setvals1");
System.out.println("[一值] sets3 VALUES : " + source.getCollection("sets3", String.class));
System.out.println("sets3 大小 : " + source.getCollectionSize("sets3"));
System.out.println("all keys: " + source.queryKeys());
System.out.println("key startkeys: " + source.queryKeysStartsWith("key"));
System.out.println("newnum 值 : " + source.incr("newnum"));
System.out.println("newnum 值 : " + source.decr("newnum"));
System.out.println("sets3&sets4: " + source.getStringCollectionMap(true, "sets3", "sets4"));
System.out.println("------------------------------------");
source.set("myaddr", InetSocketAddress.class, addr);
System.out.println("myaddrstr: " + source.getString("myaddr"));
System.out.println("myaddr: " + source.get("myaddr", InetSocketAddress.class));
source.remove("myaddrs");
source.remove("myaddrs2");
source.appendSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788));
source.appendSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7799));
System.out.println("myaddrs: " + source.getCollection("myaddrs", InetSocketAddress.class));
source.removeSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788));
System.out.println("myaddrs: " + source.getCollection("myaddrs", InetSocketAddress.class));
source.appendSetItem("myaddrs2", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788));
source.appendSetItem("myaddrs2", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7799));
System.out.println("myaddrs&myaddrs2: " + source.getCollectionMap(true, InetSocketAddress.class, "myaddrs", "myaddrs2"));
System.out.println("------------------------------------");
source.remove("myaddrs");
Type mapType = new TypeToken<Map<String, Integer>>() {
}.getType();
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
source.set("mapvals", mapType, map);
System.out.println("mapvals: " + source.get("mapvals", mapType));
source.remove("byteskey");
source.setBytes("byteskey", new byte[]{1, 2, 3});
System.out.println("byteskey 值 : " + Arrays.toString(source.getBytes("byteskey")));
//h
source.remove("hmap");
source.hincr("hmap", "key1");
System.out.println("hmap.key1 值 : " + source.hgetLong("hmap", "key1", -1));
source.hmset("hmap", "key2", "haha", "key3", 333);
source.hmset("hmap", "sm", (HashMap) Utility.ofMap("a", "aa", "b", "bb"));
System.out.println("hmap.sm 值 : " + source.hget("hmap", "sm", JsonConvert.TYPE_MAP_STRING_STRING));
System.out.println("hmap.[key1,key2,key3] 值 : " + source.hmget("hmap", String.class, "key1", "key2", "key3"));
System.out.println("hmap.keys 四值 : " + source.hkeys("hmap"));
source.hremove("hmap", "key1", "key3");
System.out.println("hmap.keys 两值 : " + source.hkeys("hmap"));
System.out.println("hmap.key2 值 : " + source.hgetString("hmap", "key2"));
System.out.println("hmap列表(2)大小 : " + source.hsize("hmap"));
source.remove("hmaplong");
source.hincr("hmaplong", "key1", 10);
source.hsetLong("hmaplong", "key2", 30);
System.out.println("hmaplong.所有两值 : " + source.hmap("hmaplong", long.class, 0, 10));
source.remove("hmapstr");
source.hsetString("hmapstr", "key1", "str10");
source.hsetString("hmapstr", "key2", null);
System.out.println("hmapstr.所有一值 : " + source.hmap("hmapstr", String.class, 0, 10));
source.remove("hmapstrmap");
source.hset("hmapstrmap", "key1", JsonConvert.TYPE_MAP_STRING_STRING, (HashMap) Utility.ofMap("ks11", "vv11"));
source.hset("hmapstrmap", "key2", JsonConvert.TYPE_MAP_STRING_STRING, null);
System.out.println("hmapstrmap.无值 : " + source.hmap("hmapstrmap", JsonConvert.TYPE_MAP_STRING_STRING, 0, 10, "key2*"));
source.remove("popset");
source.appendStringSetItem("popset", "111");
source.appendStringSetItem("popset", "222");
source.appendStringSetItem("popset", "333");
source.appendStringSetItem("popset", "444");
source.appendStringSetItem("popset", "555");
System.out.println("SPOP一个元素" + source.spopStringSetItem("popset"));
System.out.println("SPOP两个元素" + source.spopStringSetItem("popset", 2));
System.out.println("SPOP五个元素" + source.spopStringSetItem("popset", 5));
source.appendLongSetItem("popset", 111);
source.appendLongSetItem("popset", 222);
source.appendLongSetItem("popset", 333);
source.appendLongSetItem("popset", 444);
source.appendLongSetItem("popset", 555);
System.out.println("SPOP一个元素" + source.spopLongSetItem("popset"));
System.out.println("SPOP两个元素" + source.spopLongSetItem("popset", 2));
System.out.println("SPOP五个元素" + source.spopLongSetItem("popset", 5));
System.out.println("SPOP一个元素" + source.spopLongSetItem("popset"));
//清除
int rs = source.remove("stritem1");
System.out.println("删除stritem1个数: " + rs);
source.remove("popset");
source.remove("stritem2");
source.remove("intitem1");
source.remove("intitem2");
source.remove("keylong1");
source.remove("keystr1");
source.remove("mapvals");
source.remove("myaddr");
source.remove("myaddrs2");
source.remove("newnum");
source.remove("objitem1");
source.remove("objitem2");
source.remove("key1");
source.remove("key2");
source.remove("keys3");
source.remove("sets3");
source.remove("sets4");
source.remove("myaddrs");
source.remove("300");
source.remove("stringmap");
source.remove("hmap");
source.remove("hmaplong");
source.remove("hmapstr");
source.remove("hmapstrmap");
source.remove("byteskey");
System.out.println("------------------------------------");
// System.out.println("--------------测试大文本---------------");
// HashMap<String, String> bigmap = new HashMap<>();
// StringBuilder sb = new StringBuilder();
// sb.append("起始");
// for (int i = 0; i < 1024 * 1024; i++) {
// sb.append("abcde");
// }
// sb.append("结束");
// bigmap.put("val", sb.toString());
// System.out.println("文本长度: " + sb.length());
// source.set("bigmap", JsonConvert.TYPE_MAP_STRING_STRING, bigmap);
// System.out.println("写入完成");
// for (int i = 0; i < 1; i++) {
// HashMap<String, String> fs = (HashMap) source.get("bigmap", JsonConvert.TYPE_MAP_STRING_STRING);
// System.out.println("内容长度: " + fs.get("val").length());
// }
source.remove("bigmap");
} finally {
source.close();
}
}
@Override
public void close() throws Exception { //在 Application 关闭时调用
destroy(null);
}
@Override
public String resourceName() {
Resource res = this.getClass().getAnnotation(Resource.class);
return res == null ? "" : res.name();
}
@Override
public String toString() {
return getClass().getSimpleName() + "{addrs = " + this.nodeAddrs + ", db=" + this.db + "}";
}
@Override
public void destroy(AnyValue conf) {
if (transport != null) transport.close();
}
//--------------------- exists ------------------------------
@Override
public CompletableFuture<Boolean> existsAsync(String key) {
return (CompletableFuture) send("EXISTS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public boolean exists(String key) {
return existsAsync(key).join();
}
//--------------------- get ------------------------------
@Override
@Deprecated
public CompletableFuture<V> getAsync(String key) {
return (CompletableFuture) send("GET", CacheEntryType.OBJECT, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public <T> CompletableFuture<T> getAsync(String key, Type type) {
return (CompletableFuture) send("GET", CacheEntryType.OBJECT, type, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<String> getStringAsync(String key) {
return (CompletableFuture) send("GET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<Long> getLongAsync(String key, long defValue) {
return ((CompletableFuture) send("GET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8))).thenApplyAsync(v -> v == null ? defValue : v);
}
@Override
@Deprecated
public V get(String key) {
return getAsync(key).join();
}
@Override
public <T> T get(String key, final Type type) {
return (T) getAsync(key, type).join();
}
@Override
public String getString(String key) {
return getStringAsync(key).join();
}
@Override
public long getLong(String key, long defValue) {
return getLongAsync(key, defValue).join();
}
//--------------------- getAndRefresh ------------------------------
@Override
@Deprecated
public CompletableFuture<V> getAndRefreshAsync(String key, int expireSeconds) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getAsync(key));
}
@Override
public <T> CompletableFuture<T> getAndRefreshAsync(String key, int expireSeconds, final Type type) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getAsync(key, type));
}
@Override
@Deprecated
public V getAndRefresh(String key, final int expireSeconds) {
return getAndRefreshAsync(key, expireSeconds).join();
}
@Override
public <T> T getAndRefresh(String key, final int expireSeconds, final Type type) {
return (T) getAndRefreshAsync(key, expireSeconds, type).join();
}
@Override
public CompletableFuture<String> getStringAndRefreshAsync(String key, int expireSeconds) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getStringAsync(key));
}
@Override
public String getStringAndRefresh(String key, final int expireSeconds) {
return getStringAndRefreshAsync(key, expireSeconds).join();
}
@Override
public CompletableFuture<Long> getLongAndRefreshAsync(String key, int expireSeconds, long defValue) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getLongAsync(key, defValue));
}
@Override
public long getLongAndRefresh(String key, final int expireSeconds, long defValue) {
return getLongAndRefreshAsync(key, expireSeconds, defValue).join();
}
//--------------------- refresh ------------------------------
@Override
public CompletableFuture<Void> refreshAsync(String key, int expireSeconds) {
return setExpireSecondsAsync(key, expireSeconds);
}
@Override
public void refresh(String key, final int expireSeconds) {
setExpireSeconds(key, expireSeconds);
}
//--------------------- set ------------------------------
@Override
@Deprecated
public CompletableFuture<Void> setAsync(String key, V value) {
CacheEntryType cet = this.objValueType == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT;
return (CompletableFuture) send("SET", cet, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, (Convert) null, (Type) null, value));
}
@Override
public <T> CompletableFuture<Void> setAsync(String key, Convert convert, T value) {
CacheEntryType cet = value instanceof CharSequence ? CacheEntryType.STRING : CacheEntryType.OBJECT;
return (CompletableFuture) send("SET", cet, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, convert, (Type) null, value));
}
@Override
public <T> CompletableFuture<Void> setAsync(String key, final Type type, T value) {
CacheEntryType cet = type == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT;
return (CompletableFuture) send("SET", cet, type, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, (Convert) null, type, value));
}
@Override
public <T> CompletableFuture<Void> setAsync(String key, Convert convert, final Type type, T value) {
CacheEntryType cet = type == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT;
return (CompletableFuture) send("SET", cet, type, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, convert, type, value));
}
@Override
@Deprecated
public void set(final String key, V value) {
setAsync(key, value).join();
}
@Override
public <T> void set(final String key, final Convert convert, T value) {
setAsync(key, convert, value).join();
}
@Override
public <T> void set(final String key, final Type type, T value) {
setAsync(key, type, value).join();
}
@Override
public <T> void set(String key, final Convert convert, final Type type, T value) {
setAsync(key, convert, type, value).join();
}
@Override
public CompletableFuture<Void> setStringAsync(String key, String value) {
return (CompletableFuture) send("SET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value));
}
@Override
public void setString(String key, String value) {
setStringAsync(key, value).join();
}
@Override
public CompletableFuture<Void> setLongAsync(String key, long value) {
return (CompletableFuture) send("SET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value));
}
@Override
public void setLong(String key, long value) {
setLongAsync(key, value).join();
}
//--------------------- set ------------------------------
@Override
@Deprecated
public CompletableFuture<Void> setAsync(int expireSeconds, String key, V value) {
return (CompletableFuture) setAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds));
}
@Override
public <T> CompletableFuture<Void> setAsync(int expireSeconds, String key, Convert convert, T value) {
return (CompletableFuture) setAsync(key, convert, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds));
}
@Override
public <T> CompletableFuture<Void> setAsync(int expireSeconds, String key, final Type type, T value) {
return (CompletableFuture) setAsync(key, type, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds));
}
@Override
public <T> CompletableFuture<Void> setAsync(int expireSeconds, String key, Convert convert, final Type type, T value) {
return (CompletableFuture) setAsync(key, convert, type, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds));
}
@Override
@Deprecated
public void set(int expireSeconds, String key, V value) {
setAsync(expireSeconds, key, value).join();
}
@Override
public <T> void set(int expireSeconds, String key, Convert convert, T value) {
setAsync(expireSeconds, key, convert, value).join();
}
@Override
public <T> void set(int expireSeconds, String key, final Type type, T value) {
setAsync(expireSeconds, key, type, value).join();
}
@Override
public <T> void set(int expireSeconds, String key, Convert convert, final Type type, T value) {
setAsync(expireSeconds, key, convert, type, value).join();
}
@Override
public CompletableFuture<Void> setStringAsync(int expireSeconds, String key, String value) {
return (CompletableFuture) setStringAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds));
}
@Override
public void setString(int expireSeconds, String key, String value) {
setStringAsync(expireSeconds, key, value).join();
}
@Override
public CompletableFuture<Void> setLongAsync(int expireSeconds, String key, long value) {
return (CompletableFuture) setLongAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds));
}
@Override
public void setLong(int expireSeconds, String key, long value) {
setLongAsync(expireSeconds, key, value).join();
}
//--------------------- setExpireSeconds ------------------------------
@Override
public CompletableFuture<Void> setExpireSecondsAsync(String key, int expireSeconds) {
return (CompletableFuture) send("EXPIRE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8));
}
@Override
public void setExpireSeconds(String key, int expireSeconds) {
setExpireSecondsAsync(key, expireSeconds).join();
}
//--------------------- remove ------------------------------
@Override
public CompletableFuture<Integer> removeAsync(String key) {
return (CompletableFuture) send("DEL", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public int remove(String key) {
return removeAsync(key).join();
}
//--------------------- incr ------------------------------
@Override
public long incr(final String key) {
return incrAsync(key).join();
}
@Override
public CompletableFuture<Long> incrAsync(final String key) {
return (CompletableFuture) send("INCR", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public long incr(final String key, long num) {
return incrAsync(key, num).join();
}
@Override
public CompletableFuture<Long> incrAsync(final String key, long num) {
return (CompletableFuture) send("INCRBY", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8));
}
//--------------------- decr ------------------------------
@Override
public long decr(final String key) {
return decrAsync(key).join();
}
@Override
public CompletableFuture<Long> decrAsync(final String key) {
return (CompletableFuture) send("DECR", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public long decr(final String key, long num) {
return decrAsync(key, num).join();
}
@Override
public CompletableFuture<Long> decrAsync(final String key, long num) {
return (CompletableFuture) send("DECRBY", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8));
}
@Override
public int hremove(final String key, String... fields) {
return hremoveAsync(key, fields).join();
}
@Override
public int hsize(final String key) {
return hsizeAsync(key).join();
}
@Override
public List<String> hkeys(final String key) {
return hkeysAsync(key).join();
}
@Override
public long hincr(final String key, String field) {
return hincrAsync(key, field).join();
}
@Override
public long hincr(final String key, String field, long num) {
return hincrAsync(key, field, num).join();
}
@Override
public long hdecr(final String key, String field) {
return hdecrAsync(key, field).join();
}
@Override
public long hdecr(final String key, String field, long num) {
return hdecrAsync(key, field, num).join();
}
@Override
public boolean hexists(final String key, String field) {
return hexistsAsync(key, field).join();
}
@Override
public <T> void hset(final String key, final String field, final Convert convert, final T value) {
hsetAsync(key, field, convert, value).join();
}
@Override
public <T> void hset(final String key, final String field, final Type type, final T value) {
hsetAsync(key, field, type, value).join();
}
@Override
public <T> void hset(final String key, final String field, final Convert convert, final Type type, final T value) {
hsetAsync(key, field, convert, type, value).join();
}
@Override
public void hsetString(final String key, final String field, final String value) {
hsetStringAsync(key, field, value).join();
}
@Override
public void hsetLong(final String key, final String field, final long value) {
hsetLongAsync(key, field, value).join();
}
@Override
public void hmset(final String key, final Serializable... values) {
hmsetAsync(key, values).join();
}
@Override
public List<Serializable> hmget(final String key, final Type type, final String... fields) {
return hmgetAsync(key, type, fields).join();
}
@Override
public <T> Map<String, T> hmap(final String key, final Type type, int offset, int limit, String pattern) {
return (Map) hmapAsync(key, type, offset, limit, pattern).join();
}
@Override
public <T> Map<String, T> hmap(final String key, final Type type, int offset, int limit) {
return (Map) hmapAsync(key, type, offset, limit).join();
}
@Override
public <T> T hget(final String key, final String field, final Type type) {
return (T) hgetAsync(key, field, type).join();
}
@Override
public String hgetString(final String key, final String field) {
return hgetStringAsync(key, field).join();
}
@Override
public long hgetLong(final String key, final String field, long defValue) {
return hgetLongAsync(key, field, defValue).join();
}
@Override
public CompletableFuture<Integer> hremoveAsync(final String key, String... fields) {
byte[][] bs = new byte[fields.length + 1][];
bs[0] = key.getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < fields.length; i++) {
bs[i + 1] = fields[i].getBytes(StandardCharsets.UTF_8);
}
return (CompletableFuture) send("HDEL", CacheEntryType.MAP, (Type) null, key, bs);
}
@Override
public CompletableFuture<Integer> hsizeAsync(final String key) {
return (CompletableFuture) send("HLEN", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<List<String>> hkeysAsync(final String key) {
return (CompletableFuture) send("HKEYS", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<Long> hincrAsync(final String key, String field) {
return hincrAsync(key, field, 1);
}
@Override
public CompletableFuture<Long> hincrAsync(final String key, String field, long num) {
return (CompletableFuture) send("HINCRBY", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<Long> hdecrAsync(final String key, String field) {
return hincrAsync(key, field, -1);
}
@Override
public CompletableFuture<Long> hdecrAsync(final String key, String field, long num) {
return hincrAsync(key, field, -num);
}
@Override
public CompletableFuture<Boolean> hexistsAsync(final String key, String field) {
return (CompletableFuture) send("HEXISTS", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8));
}
@Override
public <T> CompletableFuture<Void> hsetAsync(final String key, final String field, final Convert convert, final T value) {
return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, convert, null, value));
}
@Override
public <T> CompletableFuture<Void> hsetAsync(final String key, final String field, final Type type, final T value) {
return (CompletableFuture) send("HSET", CacheEntryType.MAP, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, null, type, value));
}
@Override
public <T> CompletableFuture<Void> hsetAsync(final String key, final String field, final Convert convert, final Type type, final T value) {
return (CompletableFuture) send("HSET", CacheEntryType.MAP, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, convert, type, value));
}
@Override
public CompletableFuture<Void> hsetStringAsync(final String key, final String field, final String value) {
return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, null, null, value));
}
@Override
public CompletableFuture<Void> hsetLongAsync(final String key, final String field, final long value) {
return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, null, null, value));
}
@Override
public CompletableFuture<Void> hmsetAsync(final String key, final Serializable... values) {
byte[][] bs = new byte[values.length + 1][];
bs[0] = key.getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < values.length; i += 2) {
bs[i + 1] = String.valueOf(values[i]).getBytes(StandardCharsets.UTF_8);
bs[i + 2] = formatValue(CacheEntryType.MAP, null, null, values[i + 1]);
}
return (CompletableFuture) send("HMSET", CacheEntryType.MAP, (Type) null, key, bs);
}
@Override
public CompletableFuture<List<Serializable>> hmgetAsync(final String key, final Type type, final String... fields) {
byte[][] bs = new byte[fields.length + 1][];
bs[0] = key.getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < fields.length; i++) {
bs[i + 1] = fields[i].getBytes(StandardCharsets.UTF_8);
}
return (CompletableFuture) send("HMGET", CacheEntryType.MAP, type, key, bs);
}
@Override
public <T> CompletableFuture<Map<String, T>> hmapAsync(final String key, final Type type, int offset, int limit) {
return hmapAsync(key, type, offset, limit, null);
}
@Override
public <T> CompletableFuture<Map<String, T>> hmapAsync(final String key, final Type type, int offset, int limit, String pattern) {
byte[][] bs = new byte[pattern == null || pattern.isEmpty() ? 4 : 6][limit];
int index = -1;
bs[++index] = key.getBytes(StandardCharsets.UTF_8);
bs[++index] = String.valueOf(offset).getBytes(StandardCharsets.UTF_8);
if (pattern != null && !pattern.isEmpty()) {
bs[++index] = "MATCH".getBytes(StandardCharsets.UTF_8);
bs[++index] = pattern.getBytes(StandardCharsets.UTF_8);
}
bs[++index] = "COUNT".getBytes(StandardCharsets.UTF_8);
bs[++index] = String.valueOf(limit).getBytes(StandardCharsets.UTF_8);
return (CompletableFuture) send("HSCAN", CacheEntryType.MAP, type, key, bs);
}
@Override
public <T> CompletableFuture<T> hgetAsync(final String key, final String field, final Type type) {
return (CompletableFuture) send("HGET", CacheEntryType.OBJECT, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<String> hgetStringAsync(final String key, final String field) {
return (CompletableFuture) send("HGET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<Long> hgetLongAsync(final String key, final String field, long defValue) {
return (CompletableFuture) send("HGET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)).thenApplyAsync(v -> v == null ? defValue : v);
}
//--------------------- collection ------------------------------
@Override
public CompletableFuture<Integer> getCollectionSizeAsync(String key) {
return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> {
if (t == null) return CompletableFuture.completedFuture(0);
String rs = new String((byte[]) t);
if (rs.contains("zset")) { // ziplist
return send("ZCARD", null, int.class, key, key.getBytes(StandardCharsets.UTF_8));
} else if (rs.contains("list")) { //list
return send("LLEN", null, int.class, key, key.getBytes(StandardCharsets.UTF_8));
} else if (rs.contains("hash")) {
return send("HLEN", null, int.class, key, key.getBytes(StandardCharsets.UTF_8));
} else {
return send("SCARD", null, int.class, key, key.getBytes(StandardCharsets.UTF_8));
}
});
}
@Override
public int getCollectionSize(String key) {
return getCollectionSizeAsync(key).join();
}
@Override
@Deprecated
public CompletableFuture<Collection<V>> getCollectionAsync(String key) {
return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> {
if (t == null) return CompletableFuture.completedFuture(null);
String str = new String((byte[]) t);
if (str.contains("list")) { //list
return send("LRANGE", CacheEntryType.OBJECT, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'});
} else if (str.contains("none")) {
return CompletableFuture.completedFuture(new ArrayList<>());
} else {
return send("SMEMBERS", CacheEntryType.OBJECT, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8));
}
});
}
@Override
public <T> CompletableFuture<Collection<T>> getCollectionAsync(String key, final Type componentType) {
return (CompletableFuture) send("TYPE", null, componentType, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> {
if (t == null) return CompletableFuture.completedFuture(null);
if (new String((byte[]) t).contains("list")) { //list
return send("LRANGE", CacheEntryType.OBJECT, componentType, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'});
} else {
return send("SMEMBERS", CacheEntryType.OBJECT, componentType, true, key, key.getBytes(StandardCharsets.UTF_8));
}
});
}
@Override
public CompletableFuture<Map<String, Long>> getLongMapAsync(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 (CompletableFuture) send("MGET", CacheEntryType.LONG, null, false, keys[0], bs).thenApply(r -> {
List list = (List) r;
Map map = new LinkedHashMap<>();
for (int i = 0; i < keys.length; i++) {
Object obj = list.get(i);
if (obj != null) map.put(keys[i], list.get(i));
}
return map;
});
}
@Override
public CompletableFuture<Long[]> 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 (CompletableFuture) send("MGET", CacheEntryType.LONG, null, false, keys[0], bs).thenApply(r -> {
List list = (List) r;
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
public CompletableFuture<String[]> 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 (CompletableFuture) send("MGET", CacheEntryType.STRING, null, false, keys[0], bs).thenApply(r -> {
List list = (List) r;
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
public CompletableFuture<Map<String, String>> getStringMapAsync(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 (CompletableFuture) send("MGET", CacheEntryType.STRING, null, false, keys[0], bs).thenApply(r -> {
List list = (List) r;
Map map = new LinkedHashMap<>();
for (int i = 0; i < keys.length; i++) {
Object obj = list.get(i);
if (obj != null) map.put(keys[i], list.get(i));
}
return map;
});
}
@Override
public <T> CompletableFuture<Map<String, T>> getMapAsync(final Type componentType, 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 (CompletableFuture) send("MGET", CacheEntryType.OBJECT, componentType, false, keys[0], bs).thenApply(r -> {
List list = (List) r;
Map map = new LinkedHashMap<>();
for (int i = 0; i < keys.length; i++) {
Object obj = list.get(i);
if (obj != null) map.put(keys[i], list.get(i));
}
return map;
});
}
@Override
public <T> CompletableFuture<Map<String, Collection<T>>> getCollectionMapAsync(final boolean set, final Type componentType, final String... keys) {
final CompletableFuture<Map<String, Collection<T>>> rsFuture = new CompletableFuture<>();
final Map<String, Collection<T>> map = new HashMap<>();
final CompletableFuture[] futures = new CompletableFuture[keys.length];
if (!set) { //list
for (int i = 0; i < keys.length; i++) {
final String key = keys[i];
futures[i] = send("LRANGE", CacheEntryType.OBJECT, componentType, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> {
if (c != null) {
synchronized (map) {
map.put(key, (Collection) c);
}
}
});
}
} else {
for (int i = 0; i < keys.length; i++) {
final String key = keys[i];
futures[i] = send("SMEMBERS", CacheEntryType.OBJECT, componentType, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> {
if (c != null) {
synchronized (map) {
map.put(key, (Collection) c);
}
}
});
}
}
CompletableFuture.allOf(futures).whenComplete((w, e) -> {
if (e != null) {
rsFuture.completeExceptionally(e);
} else {
rsFuture.complete(map);
}
});
return rsFuture;
}
@Override
@Deprecated
public Collection<V> getCollection(String key) {
return getCollectionAsync(key).join();
}
@Override
public <T> Collection<T> getCollection(String key, final Type componentType) {
return (Collection) getCollectionAsync(key, componentType).join();
}
@Override
public Map<String, Long> getLongMap(final String... keys) {
return getLongMapAsync(keys).join();
}
@Override
public Long[] getLongArray(final String... keys) {
return getLongArrayAsync(keys).join();
}
@Override
public Map<String, String> getStringMap(final String... keys) {
return getStringMapAsync(keys).join();
}
@Override
public String[] getStringArray(final String... keys) {
return getStringArrayAsync(keys).join();
}
@Override
public <T> Map<String, T> getMap(final Type componentType, final String... keys) {
return (Map) getMapAsync(componentType, keys).join();
}
@Override
public <T> Map<String, Collection<T>> getCollectionMap(final boolean set, final Type componentType, String... keys) {
return (Map) getCollectionMapAsync(set, componentType, keys).join();
}
@Override
public CompletableFuture<Collection<String>> getStringCollectionAsync(String key) {
return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> {
if (t == null) return CompletableFuture.completedFuture(null);
if (new String((byte[]) t).contains("list")) { //list
return send("LRANGE", CacheEntryType.STRING, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'});
} else {
return send("SMEMBERS", CacheEntryType.STRING, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8));
}
});
}
@Override
public CompletableFuture<Map<String, Collection<String>>> getStringCollectionMapAsync(final boolean set, String... keys) {
final CompletableFuture<Map<String, Collection<String>>> rsFuture = new CompletableFuture<>();
final Map<String, Collection<String>> map = new HashMap<>();
final CompletableFuture[] futures = new CompletableFuture[keys.length];
if (!set) { //list
for (int i = 0; i < keys.length; i++) {
final String key = keys[i];
futures[i] = send("LRANGE", CacheEntryType.STRING, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> {
if (c != null) {
synchronized (map) {
map.put(key, (Collection) c);
}
}
});
}
} else {
for (int i = 0; i < keys.length; i++) {
final String key = keys[i];
futures[i] = send("SMEMBERS", CacheEntryType.STRING, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> {
if (c != null) {
synchronized (map) {
map.put(key, (Collection) c);
}
}
});
}
}
CompletableFuture.allOf(futures).whenComplete((w, e) -> {
if (e != null) {
rsFuture.completeExceptionally(e);
} else {
rsFuture.complete(map);
}
});
return rsFuture;
}
@Override
public Collection<String> getStringCollection(String key) {
return getStringCollectionAsync(key).join();
}
@Override
public Map<String, Collection<String>> getStringCollectionMap(final boolean set, String... keys) {
return getStringCollectionMapAsync(set, keys).join();
}
@Override
public CompletableFuture<Collection<Long>> getLongCollectionAsync(String key) {
return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> {
if (t == null) return CompletableFuture.completedFuture(null);
if (new String((byte[]) t).contains("list")) { //list
return send("LRANGE", CacheEntryType.LONG, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'});
} else {
return send("SMEMBERS", CacheEntryType.LONG, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8));
}
});
}
@Override
public CompletableFuture<Map<String, Collection<Long>>> getLongCollectionMapAsync(final boolean set, String... keys) {
final CompletableFuture<Map<String, Collection<Long>>> rsFuture = new CompletableFuture<>();
final Map<String, Collection<Long>> map = new HashMap<>();
final CompletableFuture[] futures = new CompletableFuture[keys.length];
if (!set) { //list
for (int i = 0; i < keys.length; i++) {
final String key = keys[i];
futures[i] = send("LRANGE", CacheEntryType.LONG, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> {
if (c != null) {
synchronized (map) {
map.put(key, (Collection) c);
}
}
});
}
} else {
for (int i = 0; i < keys.length; i++) {
final String key = keys[i];
futures[i] = send("SMEMBERS", CacheEntryType.LONG, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> {
if (c != null) {
synchronized (map) {
map.put(key, (Collection) c);
}
}
});
}
}
CompletableFuture.allOf(futures).whenComplete((w, e) -> {
if (e != null) {
rsFuture.completeExceptionally(e);
} else {
rsFuture.complete(map);
}
});
return rsFuture;
}
@Override
public Collection<Long> getLongCollection(String key) {
return getLongCollectionAsync(key).join();
}
@Override
public Map<String, Collection<Long>> getLongCollectionMap(final boolean set, String... keys) {
return getLongCollectionMapAsync(set, keys).join();
}
//--------------------- getCollectionAndRefresh ------------------------------
@Override
@Deprecated
public CompletableFuture<Collection<V>> getCollectionAndRefreshAsync(String key, int expireSeconds) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key));
}
@Override
public <T> CompletableFuture<Collection<T>> getCollectionAndRefreshAsync(String key, int expireSeconds, final Type componentType) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key, componentType));
}
@Override
@Deprecated
public Collection<V> getCollectionAndRefresh(String key, final int expireSeconds) {
return getCollectionAndRefreshAsync(key, expireSeconds).join();
}
@Override
public <T> Collection<T> getCollectionAndRefresh(String key, final int expireSeconds, final Type componentType) {
return (Collection) getCollectionAndRefreshAsync(key, expireSeconds, componentType).join();
}
@Override
public CompletableFuture<Collection<String>> getStringCollectionAndRefreshAsync(String key, int expireSeconds) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getStringCollectionAsync(key));
}
@Override
public Collection<String> getStringCollectionAndRefresh(String key, final int expireSeconds) {
return getStringCollectionAndRefreshAsync(key, expireSeconds).join();
}
@Override
public CompletableFuture<Collection<Long>> getLongCollectionAndRefreshAsync(String key, int expireSeconds) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getLongCollectionAsync(key));
}
@Override
public Collection<Long> getLongCollectionAndRefresh(String key, final int expireSeconds) {
return getLongCollectionAndRefreshAsync(key, expireSeconds).join();
}
//--------------------- existsItem ------------------------------
@Override
@Deprecated
public boolean existsSetItem(String key, V value) {
return existsSetItemAsync(key, value).join();
}
@Override
public <T> boolean existsSetItem(String key, final Type componentType, T value) {
return existsSetItemAsync(key, componentType, value).join();
}
@Override
@Deprecated
public CompletableFuture<Boolean> existsSetItemAsync(String key, V value) {
return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value));
}
@Override
public <T> CompletableFuture<Boolean> existsSetItemAsync(String key, final Type componentType, T value) {
return (CompletableFuture) send("SISMEMBER", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value));
}
@Override
public boolean existsStringSetItem(String key, String value) {
return existsStringSetItemAsync(key, value).join();
}
@Override
public CompletableFuture<Boolean> existsStringSetItemAsync(String key, String value) {
return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value));
}
@Override
public boolean existsLongSetItem(String key, long value) {
return existsLongSetItemAsync(key, value).join();
}
@Override
public CompletableFuture<Boolean> existsLongSetItemAsync(String key, long value) {
return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value));
}
//--------------------- appendListItem ------------------------------
@Override
@Deprecated
public CompletableFuture<Void> appendListItemAsync(String key, V value) {
return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value));
}
@Override
public <T> CompletableFuture<Void> appendListItemAsync(String key, final Type componentType, T value) {
return (CompletableFuture) send("RPUSH", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value));
}
@Override
@Deprecated
public void appendListItem(String key, V value) {
appendListItemAsync(key, value).join();
}
@Override
public <T> void appendListItem(String key, final Type componentType, T value) {
appendListItemAsync(key, componentType, value).join();
}
@Override
public CompletableFuture<Void> appendStringListItemAsync(String key, String value) {
return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value));
}
@Override
public void appendStringListItem(String key, String value) {
appendStringListItemAsync(key, value).join();
}
@Override
public CompletableFuture<Void> appendLongListItemAsync(String key, long value) {
return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value));
}
@Override
public void appendLongListItem(String key, long value) {
appendLongListItemAsync(key, value).join();
}
//--------------------- removeListItem ------------------------------
@Override
@Deprecated
public CompletableFuture<Integer> removeListItemAsync(String key, V value) {
return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value));
}
@Override
public <T> CompletableFuture<Integer> removeListItemAsync(String key, final Type componentType, T value) {
return (CompletableFuture) send("LREM", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value));
}
@Override
@Deprecated
public int removeListItem(String key, V value) {
return removeListItemAsync(key, value).join();
}
@Override
public <T> int removeListItem(String key, final Type componentType, T value) {
return removeListItemAsync(key, componentType, value).join();
}
@Override
public CompletableFuture<Integer> removeStringListItemAsync(String key, String value) {
return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value));
}
@Override
public int removeStringListItem(String key, String value) {
return removeStringListItemAsync(key, value).join();
}
@Override
public CompletableFuture<Integer> removeLongListItemAsync(String key, long value) {
return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value));
}
@Override
public int removeLongListItem(String key, long value) {
return removeLongListItemAsync(key, value).join();
}
//--------------------- appendSetItem ------------------------------
@Override
@Deprecated
public CompletableFuture<Void> appendSetItemAsync(String key, V value) {
return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value));
}
@Override
public <T> CompletableFuture<Void> appendSetItemAsync(String key, Type componentType, T value) {
return (CompletableFuture) send("SADD", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value));
}
@Override
public <T> CompletableFuture<T> spopSetItemAsync(String key, Type componentType) {
return (CompletableFuture) send("SPOP", CacheEntryType.OBJECT, componentType, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public <T> CompletableFuture<List<T>> spopSetItemAsync(String key, int count, Type componentType) {
return (CompletableFuture) send("SPOP", CacheEntryType.OBJECT, componentType, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<String> spopStringSetItemAsync(String key) {
return (CompletableFuture) send("SPOP", CacheEntryType.STRING, String.class, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<List<String>> spopStringSetItemAsync(String key, int count) {
return (CompletableFuture) send("SPOP", CacheEntryType.STRING, String.class, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<Long> spopLongSetItemAsync(String key) {
return (CompletableFuture) send("SPOP", CacheEntryType.LONG, long.class, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<List<Long>> spopLongSetItemAsync(String key, int count) {
return (CompletableFuture) send("SPOP", CacheEntryType.LONG, long.class, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8));
}
@Override
@Deprecated
public void appendSetItem(String key, V value) {
appendSetItemAsync(key, value).join();
}
@Override
public <T> void appendSetItem(String key, final Type componentType, T value) {
appendSetItemAsync(key, componentType, value).join();
}
@Override
public <T> T spopSetItem(String key, final Type componentType) {
return (T) spopSetItemAsync(key, componentType).join();
}
@Override
public <T> List<T> spopSetItem(String key, int count, final Type componentType) {
return (List) spopSetItemAsync(key, count, componentType).join();
}
@Override
public String spopStringSetItem(String key) {
return spopStringSetItemAsync(key).join();
}
@Override
public List<String> spopStringSetItem(String key, int count) {
return spopStringSetItemAsync(key, count).join();
}
@Override
public Long spopLongSetItem(String key) {
return spopLongSetItemAsync(key).join();
}
@Override
public List<Long> spopLongSetItem(String key, int count) {
return spopLongSetItemAsync(key, count).join();
}
@Override
public CompletableFuture<Void> appendStringSetItemAsync(String key, String value) {
return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value));
}
@Override
public void appendStringSetItem(String key, String value) {
appendStringSetItemAsync(key, value).join();
}
@Override
public CompletableFuture<Void> appendLongSetItemAsync(String key, long value) {
return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value));
}
@Override
public void appendLongSetItem(String key, long value) {
appendLongSetItemAsync(key, value).join();
}
//--------------------- removeSetItem ------------------------------
@Override
@Deprecated
public CompletableFuture<Integer> removeSetItemAsync(String key, V value) {
return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value));
}
@Override
public <T> CompletableFuture<Integer> removeSetItemAsync(String key, final Type componentType, T value) {
return (CompletableFuture) send("SREM", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value));
}
@Override
@Deprecated
public int removeSetItem(String key, V value) {
return removeSetItemAsync(key, value).join();
}
@Override
public <T> int removeSetItem(String key, final Type componentType, T value) {
return removeSetItemAsync(key, componentType, value).join();
}
@Override
public CompletableFuture<Integer> removeStringSetItemAsync(String key, String value) {
return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value));
}
@Override
public int removeStringSetItem(String key, String value) {
return removeStringSetItemAsync(key, value).join();
}
@Override
public CompletableFuture<Integer> removeLongSetItemAsync(String key, long value) {
return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value));
}
@Override
public int removeLongSetItem(String key, long value) {
return removeLongSetItemAsync(key, value).join();
}
//--------------------- queryKeys ------------------------------
@Override
public List<String> queryKeys() {
return queryKeysAsync().join();
}
@Override
public List<String> queryKeysStartsWith(String startsWith) {
return queryKeysStartsWithAsync(startsWith).join();
}
@Override
public List<String> queryKeysEndsWith(String endsWith) {
return queryKeysEndsWithAsync(endsWith).join();
}
@Override
public byte[] getBytes(final String key) {
return getBytesAsync(key).join();
}
@Override
public byte[] getBytesAndRefresh(final String key, final int expireSeconds) {
return getBytesAndRefreshAsync(key, expireSeconds).join();
}
@Override
public void setBytes(final String key, final byte[] value) {
setBytesAsync(key, value).join();
}
@Override
public void setBytes(final int expireSeconds, final String key, final byte[] value) {
setBytesAsync(expireSeconds, key, value).join();
}
@Override
public <T> void setBytes(final String key, final Convert convert, final Type type, final T value) {
setBytesAsync(key, convert, type, value).join();
}
@Override
public <T> void setBytes(final int expireSeconds, final String key, final Convert convert, final Type type, final T value) {
setBytesAsync(expireSeconds, key, convert, type, value).join();
}
@Override
public CompletableFuture<byte[]> getBytesAsync(final String key) {
return (CompletableFuture) send("GET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<byte[]> getBytesAndRefreshAsync(final String key, final int expireSeconds) {
return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getBytesAsync(key));
}
@Override
public CompletableFuture<Void> setBytesAsync(final String key, final byte[] value) {
return (CompletableFuture) send("SET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), value);
}
@Override
public CompletableFuture<Void> setBytesAsync(final int expireSeconds, final String key, final byte[] value) {
return (CompletableFuture) setBytesAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds));
}
@Override
public <T> CompletableFuture<Void> setBytesAsync(final String key, final Convert convert, final Type type, final T value) {
return (CompletableFuture) send("SET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), convert.convertToBytes(type, value));
}
@Override
public <T> CompletableFuture<Void> setBytesAsync(final int expireSeconds, final String key, final Convert convert, final Type type, final T value) {
return (CompletableFuture) setBytesAsync(key, convert.convertToBytes(type, value)).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds));
}
@Override
public CompletableFuture<List<String>> queryKeysAsync() {
return (CompletableFuture) send("KEYS", null, (Type) null, "*", new byte[]{(byte) '*'});
}
@Override
public CompletableFuture<List<String>> queryKeysStartsWithAsync(String startsWith) {
if (startsWith == null) return queryKeysAsync();
String key = startsWith + "*";
return (CompletableFuture) send("KEYS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
@Override
public CompletableFuture<List<String>> queryKeysEndsWithAsync(String endsWith) {
if (endsWith == null) return queryKeysAsync();
String key = "*" + endsWith;
return (CompletableFuture) send("KEYS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8));
}
//--------------------- getKeySize ------------------------------
@Override
public int getKeySize() {
return getKeySizeAsync().join();
}
@Override
public CompletableFuture<Integer> getKeySizeAsync() {
return (CompletableFuture) send("DBSIZE", null, (Type) null, null);
}
//--------------------- queryList ------------------------------
@Override
public List<CacheEntry<Object>> queryList() {
return queryListAsync().join();
}
@Override
public CompletableFuture<List<CacheEntry<Object>>> queryListAsync() {
return CompletableFuture.completedFuture(new ArrayList<>()); //不返回数据
}
//--------------------- send ------------------------------
private byte[] formatValue(CacheEntryType cacheType, Convert convert0, Type resultType, Object value) {
if (value == null) return "null".getBytes(StandardCharsets.UTF_8);
if (value instanceof byte[]) return (byte[]) value;
if (convert0 == null) convert0 = convert;
if (cacheType == CacheEntryType.MAP) {
if ((value instanceof CharSequence) || (value instanceof Number)) {
return String.valueOf(value).getBytes(StandardCharsets.UTF_8);
}
if (objValueType == String.class && !(value instanceof CharSequence)) resultType = value.getClass();
return convert0.convertToBytes(resultType == null ? objValueType : resultType, value);
}
if (cacheType == CacheEntryType.LONG || cacheType == CacheEntryType.ATOMIC || value.getClass() == String.class)
return String.valueOf(value).getBytes(StandardCharsets.UTF_8);
if (cacheType == CacheEntryType.STRING) return convert0.convertToBytes(String.class, value);
return convert0.convertToBytes(resultType == null ? objValueType : resultType, value);
}
protected CompletableFuture<Serializable> send(final String command, final CacheEntryType cacheType, final Type resultType, final String key, final byte[]... args) {
return send(command, cacheType, resultType, false, key, args);
}
protected CompletableFuture<Serializable> send(final String command, final CacheEntryType cacheType, final Type resultType, final boolean set, final String key, final byte[]... args) {
return send(null, command, cacheType, resultType, set, key, args);
}
private CompletableFuture<Serializable> send(final CompletionHandler callback, final String command, final CacheEntryType cacheType, final Type resultType, final boolean set, final String key, final byte[]... args) {
final BsonByteBufferWriter writer = new BsonByteBufferWriter(transport.getBufferSupplier());
writer.writeTo(ASTERISK_BYTE);
writer.writeTo(String.valueOf(args.length + 1).getBytes(StandardCharsets.UTF_8));
writer.writeTo((byte) '\r', (byte) '\n');
writer.writeTo(DOLLAR_BYTE);
writer.writeTo(String.valueOf(command.length()).getBytes(StandardCharsets.UTF_8));
writer.writeTo((byte) '\r', (byte) '\n');
writer.writeTo(command.getBytes(StandardCharsets.UTF_8));
writer.writeTo((byte) '\r', (byte) '\n');
for (final byte[] arg : args) {
writer.writeTo(DOLLAR_BYTE);
writer.writeTo(String.valueOf(arg.length).getBytes(StandardCharsets.UTF_8));
writer.writeTo((byte) '\r', (byte) '\n');
writer.writeTo(arg);
writer.writeTo((byte) '\r', (byte) '\n');
}
final ByteBuffer[] buffers = writer.toBuffers();
final CompletableFuture<Serializable> future = callback == null ? new CompletableFuture<>() : null;
CompletableFuture<AsyncConnection> connFuture = this.transport.pollConnection(null);
if (passwords != null) {
connFuture = connFuture.thenCompose(conn -> {
if (conn.getSubobject() != null) return CompletableFuture.completedFuture(conn);
byte[] password = passwords.get(conn.getRemoteAddress());
if (password == null) return CompletableFuture.completedFuture(conn);
CompletableFuture<AsyncConnection> rs = auth(conn, password, command);
if (db > 0) {
rs = rs.thenCompose(conn2 -> {
if (conn2.getSubobject() != null) return CompletableFuture.completedFuture(conn2);
return selectdb(conn2, db, command);
});
}
return rs;
});
} else if (db > 0) {
connFuture = connFuture.thenCompose(conn2 -> {
if (conn2.getSubobject() != null) return CompletableFuture.completedFuture(conn2);
return selectdb(conn2, db, command);
});
}
connFuture.whenComplete((conn, ex) -> {
if (ex != null) {
transport.offerBuffer(buffers);
if (future == null) {
callback.failed(ex, null);
} else {
future.completeExceptionally(ex);
}
return;
}
conn.write(buffers, buffers, new CompletionHandler<Integer, ByteBuffer[]>() {
@Override
public void completed(Integer result, ByteBuffer[] attachments) {
int index = -1;
try {
for (int i = 0; i < attachments.length; i++) {
if (attachments[i].hasRemaining()) {
index = i;
break;
} else {
transport.offerBuffer(attachments[i]);
}
}
if (index == 0) {
conn.write(attachments, attachments, this);
return;
} else if (index > 0) {
ByteBuffer[] newattachs = new ByteBuffer[attachments.length - index];
System.arraycopy(attachments, index, newattachs, 0, newattachs.length);
conn.write(newattachs, newattachs, this);
return;
}
//----------------------- 读取返回结果 -------------------------------------
conn.read(new ReplyCompletionHandler(conn) {
@Override
public void completed(Integer result, ByteBuffer buffer) {
buffer.flip();
try {
final byte sign = buffer.get();
if (sign == PLUS_BYTE) { // +
byte[] bs = readBytes(buffer);
if (future == null) {
transport.offerConnection(false, conn); //必须在complete之前防止并发是conn还没回收完毕
callback.completed(null, key);
} else {
transport.offerConnection(false, conn);
future.complete(("SET".equals(command) || "HSET".equals(command)) ? null : bs);
}
} else if (sign == MINUS_BYTE) { // -
String bs = readString(buffer);
if (future == null) {
transport.offerConnection(false, conn);
callback.failed(new RuntimeException(bs), key);
} else {
transport.offerConnection(false, conn);
future.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs));
}
} else if (sign == COLON_BYTE) { // :
long rs = readLong(buffer);
if (future == null) {
if (command.startsWith("INCR") || command.startsWith("DECR") || command.startsWith("HINCR")) {
transport.offerConnection(false, conn);
callback.completed(rs, key);
} else {
transport.offerConnection(false, conn);
callback.completed((command.endsWith("EXISTS") || "SISMEMBER".equals(command)) ? (rs > 0) : (("LLEN".equals(command) || "SCARD".equals(command) || "SREM".equals(command) || "LREM".equals(command) || "DEL".equals(command) || "HDEL".equals(command) || "HLEN".equals(command) || "DBSIZE".equals(command)) ? (int) rs : null), key);
}
} else {
if (command.startsWith("INCR") || command.startsWith("DECR") || command.startsWith("HINCR") || command.startsWith("HGET")) {
transport.offerConnection(false, conn);
future.complete(rs);
} else if (command.equals("ZRANK") || command.equals("ZREVRANK")) {
transport.offerConnection(false, conn);
future.complete(rs);
} else if (command.equals("GETBIT")) {
transport.offerConnection(false, conn);
future.complete(rs);
} else if (command.equals("TTL") || command.equals("PTTL")) {
transport.offerConnection(false, conn);
future.complete(rs);
} else if (command.equals("SETNX")) {
transport.offerConnection(false, conn);
future.complete(rs);
} else {
transport.offerConnection(false, conn);
future.complete((command.endsWith("EXISTS") || "SISMEMBER".equals(command)) ? (rs > 0) : (("LLEN".equals(command) || "SCARD".equals(command) || "SREM".equals(command) || "LREM".equals(command) || "DEL".equals(command) || "HDEL".equals(command) || "HLEN".equals(command) || "DBSIZE".equals(command) || "ZCARD".equals(command) || "EVAL".equals(command)) ? (int) rs : null));
}
}
} else if (sign == DOLLAR_BYTE) { // $
long val = readLong(buffer);
byte[] rs = val <= 0 ? null : readBytes(buffer);
Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType));
if (future == null) {
transport.offerConnection(false, conn);
callback.completed((("SPOP".equals(command) || command.endsWith("GET") || rs == null) ? (ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, new String(rs, StandardCharsets.UTF_8))) : null), key);
} else {
transport.offerConnection(false, conn);
if ("ZSCORE".equals(command)) {
future.complete(ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, rs == null ? null : new String(rs, StandardCharsets.UTF_8)));
} else if (command.equals("HINCRBYFLOAT")) {
future.complete(new String(rs, StandardCharsets.UTF_8));
} else {
future.complete("SPOP".equals(command) || command.endsWith("GET") || command.endsWith("ZINCRBY") ? (ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, rs == null ? null : new String(rs, StandardCharsets.UTF_8))) : rs);
}
}
} else if (sign == ASTERISK_BYTE) { // *
final int len = readInt(buffer);
if (len < 0) {
if (future == null) {
transport.offerConnection(false, conn);
callback.completed(null, key);
} else {
transport.offerConnection(false, conn);
future.complete((byte[]) null);
}
} else {
Object rsobj;
if (command.endsWith("SCAN")) {
LinkedHashMap rs = new LinkedHashMap();
rsobj = rs;
for (int i = 0; i < len; i++) {
int l = readInt(buffer);
if (l > 0) {
readBytes(buffer);
} else {
while (buffer.hasRemaining()) {
readBytes(buffer);
String field = new String(readBytes(buffer), StandardCharsets.UTF_8);
String value = null;
if (readInt(buffer) > 0) {
value = new String(readBytes(buffer), StandardCharsets.UTF_8);
}
Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType));
try {
rs.put(field, value == null ? null : (ct == String.class ? value : convert.convertFrom(ct, value)));
} catch (RuntimeException e) {
buffer.flip();
byte[] bsss = new byte[buffer.remaining()];
buffer.get(bsss);
logger.log(Level.SEVERE, "异常: " + new String(bsss));
throw e;
}
}
}
}
} else {
Collection rs = set ? new HashSet() : new ArrayList();
rsobj = rs;
boolean keys = "KEYS".equals(command) || "HKEYS".equals(command);
boolean mget = !keys && ("MGET".equals(command) || "HMGET".equals(command));
boolean zsetscore = !keys && ("ZREVRANGE".equals(command) || "ZRANGE".equals(command));
boolean hgetall = !keys && "HGETALL".equals(command);
boolean lpop = !keys && "BRPOP".equals(command);
Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType));
for (int i = 0; i < len; i++) {
int l = readInt(buffer);
if (l > 0) {
// 1、zsetscore 查询 偶数元素统一返回 string 方法内自定义转换
// 2、hgetall 基数元素返回 string
if ((zsetscore && rs.size() % 2 == 1) || (hgetall && rs.size() % 2 == 0)) {
rs.add(readString(buffer));
} else if (lpop && i == 1) {
rsobj = convert.convertFrom(ct, new String(readBytes(buffer), StandardCharsets.UTF_8));
} else {
rs.add(keys ? new String(readBytes(buffer), StandardCharsets.UTF_8) : (ct == String.class ? new String(readBytes(buffer), StandardCharsets.UTF_8) : convert.convertFrom(ct, new String(readBytes(buffer), StandardCharsets.UTF_8))));
}
} else if (mget) {
rs.add(null);
}
}
}
if (future == null) {
transport.offerConnection(false, conn);
callback.completed(rsobj, key);
} else {
transport.offerConnection(false, conn);
future.complete((Serializable) rsobj);
}
}
} else {
String exstr = "Unknown reply: " + (char) sign;
if (future == null) {
transport.offerConnection(false, conn);
callback.failed(new RuntimeException(exstr), key);
} else {
transport.offerConnection(false, conn);
future.completeExceptionally(new RuntimeException(exstr));
}
}
} catch (Exception e) {
logger.log(Level.WARNING, "", e);
failed(e, buffer);
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
conn.offerBuffer(attachment);
transport.offerConnection(true, conn);
if (future == null) {
callback.failed(exc, attachments);
} else {
future.completeExceptionally(exc);
}
}
});
} catch (Exception e) {
failed(e, attachments);
}
}
@Override
public void failed(Throwable exc, ByteBuffer[] attachments) {
transport.offerConnection(true, conn);
if (future == null) {
callback.failed(exc, attachments);
} else {
future.completeExceptionally(exc);
}
}
});
});
return future; //.orTimeout(3, TimeUnit.SECONDS) JDK9以上才支持
}
private CompletableFuture<AsyncConnection> selectdb(final AsyncConnection conn, final int db, final String command) {
final CompletableFuture<AsyncConnection> rsfuture = new CompletableFuture();
try {
final BsonByteBufferWriter dbwriter = new BsonByteBufferWriter(transport.getBufferSupplier());
dbwriter.writeTo(ASTERISK_BYTE);
dbwriter.writeTo((byte) '2');
dbwriter.writeTo((byte) '\r', (byte) '\n');
dbwriter.writeTo(DOLLAR_BYTE);
dbwriter.writeTo((byte) '6');
dbwriter.writeTo((byte) '\r', (byte) '\n');
dbwriter.writeTo("SELECT".getBytes(StandardCharsets.UTF_8));
dbwriter.writeTo((byte) '\r', (byte) '\n');
dbwriter.writeTo(DOLLAR_BYTE);
dbwriter.writeTo(String.valueOf(String.valueOf(db).length()).getBytes(StandardCharsets.UTF_8));
dbwriter.writeTo((byte) '\r', (byte) '\n');
dbwriter.writeTo(String.valueOf(db).getBytes(StandardCharsets.UTF_8));
dbwriter.writeTo((byte) '\r', (byte) '\n');
final ByteBuffer[] authbuffers = dbwriter.toBuffers();
conn.write(authbuffers, authbuffers, new CompletionHandler<Integer, ByteBuffer[]>() {
@Override
public void completed(Integer result, ByteBuffer[] attachments) {
int index = -1;
try {
for (int i = 0; i < attachments.length; i++) {
if (attachments[i].hasRemaining()) {
index = i;
break;
} else {
transport.offerBuffer(attachments[i]);
}
}
if (index == 0) {
conn.write(attachments, attachments, this);
return;
} else if (index > 0) {
ByteBuffer[] newattachs = new ByteBuffer[attachments.length - index];
System.arraycopy(attachments, index, newattachs, 0, newattachs.length);
conn.write(newattachs, newattachs, this);
return;
}
//----------------------- 读取返回结果 -------------------------------------
conn.read(new ReplyCompletionHandler(conn) {
@Override
public void completed(Integer result, ByteBuffer buffer) {
buffer.flip();
try {
final byte sign = buffer.get();
if (sign == PLUS_BYTE) { // +
byte[] bs = readBytes(buffer);
if ("OK".equalsIgnoreCase(new String(bs))) {
conn.setSubobject("authed+db");
rsfuture.complete(conn);
} else {
transport.offerConnection(false, conn);
rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs));
}
} else if (sign == MINUS_BYTE) { // - 异常
String bs = readString(buffer);
transport.offerConnection(false, conn);
rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs));
} else {
String exstr = "Unknown reply: " + (char) sign;
transport.offerConnection(false, conn);
rsfuture.completeExceptionally(new RuntimeException(exstr));
}
} catch (Exception e) {
failed(e, buffer);
}
}
@Override
public void failed(Throwable exc, ByteBuffer buffer) {
conn.offerBuffer(buffer);
transport.offerConnection(true, conn);
rsfuture.completeExceptionally(exc);
}
});
} catch (Exception e) {
failed(e, attachments);
}
}
@Override
public void failed(Throwable exc, ByteBuffer[] attachments) {
transport.offerConnection(true, conn);
rsfuture.completeExceptionally(exc);
}
});
} catch (Exception e) {
rsfuture.completeExceptionally(e);
}
return rsfuture;
}
private CompletableFuture<AsyncConnection> auth(final AsyncConnection conn, final byte[] password, final String command) {
final CompletableFuture<AsyncConnection> rsfuture = new CompletableFuture();
try {
final BsonByteBufferWriter authwriter = new BsonByteBufferWriter(transport.getBufferSupplier());
authwriter.writeTo(ASTERISK_BYTE);
authwriter.writeTo((byte) '2');
authwriter.writeTo((byte) '\r', (byte) '\n');
authwriter.writeTo(DOLLAR_BYTE);
authwriter.writeTo((byte) '4');
authwriter.writeTo((byte) '\r', (byte) '\n');
authwriter.writeTo("AUTH".getBytes(StandardCharsets.UTF_8));
authwriter.writeTo((byte) '\r', (byte) '\n');
authwriter.writeTo(DOLLAR_BYTE);
authwriter.writeTo(String.valueOf(password.length).getBytes(StandardCharsets.UTF_8));
authwriter.writeTo((byte) '\r', (byte) '\n');
authwriter.writeTo(password);
authwriter.writeTo((byte) '\r', (byte) '\n');
final ByteBuffer[] authbuffers = authwriter.toBuffers();
conn.write(authbuffers, authbuffers, new CompletionHandler<Integer, ByteBuffer[]>() {
@Override
public void completed(Integer result, ByteBuffer[] attachments) {
int index = -1;
try {
for (int i = 0; i < attachments.length; i++) {
if (attachments[i].hasRemaining()) {
index = i;
break;
} else {
transport.offerBuffer(attachments[i]);
}
}
if (index == 0) {
conn.write(attachments, attachments, this);
return;
} else if (index > 0) {
ByteBuffer[] newattachs = new ByteBuffer[attachments.length - index];
System.arraycopy(attachments, index, newattachs, 0, newattachs.length);
conn.write(newattachs, newattachs, this);
return;
}
//----------------------- 读取返回结果 -------------------------------------
conn.read(new ReplyCompletionHandler(conn) {
@Override
public void completed(Integer result, ByteBuffer buffer) {
buffer.flip();
try {
final byte sign = buffer.get();
if (sign == PLUS_BYTE) { // +
byte[] bs = readBytes(buffer);
if ("OK".equalsIgnoreCase(new String(bs))) {
conn.setSubobject("authed");
rsfuture.complete(conn);
} else {
transport.offerConnection(false, conn);
rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs));
}
} else if (sign == MINUS_BYTE) { // - 异常
String bs = readString(buffer);
transport.offerConnection(false, conn);
rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs));
} else {
String exstr = "Unknown reply: " + (char) sign;
transport.offerConnection(false, conn);
rsfuture.completeExceptionally(new RuntimeException(exstr));
}
} catch (Exception e) {
failed(e, buffer);
}
}
@Override
public void failed(Throwable exc, ByteBuffer buffer) {
conn.offerBuffer(buffer);
transport.offerConnection(true, conn);
rsfuture.completeExceptionally(exc);
}
});
} catch (Exception e) {
failed(e, attachments);
}
}
@Override
public void failed(Throwable exc, ByteBuffer[] attachments) {
transport.offerConnection(true, conn);
rsfuture.completeExceptionally(exc);
}
});
} catch (Exception e) {
rsfuture.completeExceptionally(e);
}
return rsfuture;
}
}
abstract class ReplyCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {
private final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
protected final ByteArray out = new ByteArray();
protected final AsyncConnection conn;
public ReplyCompletionHandler(AsyncConnection conn) {
this.conn = conn;
}
protected byte[] readBytes(ByteBuffer buffer) throws IOException {
readLine(buffer);
return out.getBytesAndClear();
}
protected String readString(ByteBuffer buffer) throws IOException {
readLine(buffer);
return out.toStringAndClear(null);//传null则表示使用StandardCharsets.UTF_8
}
protected int readInt(ByteBuffer buffer) throws IOException {
return (int) readLong(buffer);
}
protected long readLong(ByteBuffer buffer) throws IOException {
readLine(buffer);
int start = 0;
if (out.get(0) == '$') start = 1;
boolean negative = out.get(start) == '-';
long value = negative ? 0 : (out.get(start) - '0');
for (int i = 1 + start; i < out.size(); i++) {
value = value * 10 + (out.get(i) - '0');
}
out.clear();
return negative ? -value : value;
}
private void readLine(ByteBuffer buffer) throws IOException {
boolean has = buffer.hasRemaining();
byte lasted = has ? buffer.get() : 0;
if (lasted == '\n' && !out.isEmpty() && out.getLastByte() == '\r') {
out.removeLastByte();//读掉 \r
//buffer.get();//读掉 \n
//logger.info("打印buffer.get()---> " + buffer.get());
//logger.info("--- 打印buffer start --- ");
return;//传null则表示使用StandardCharsets.UTF_8
}
if (has) out.write(lasted);
while (buffer.hasRemaining()) {
byte b = buffer.get();
if (b == '\n' && lasted == '\r') {
out.removeLastByte();
return;
}
out.write(lasted = b);
}
//说明数据还没读取完
buffer.clear();
conn.readableByteChannel().read(buffer);
buffer.flip();
readLine(buffer);
}
}