
com.taobao.tair.impl.DefaultTairManager Maven / Gradle / Ivy
/**
* (C) 2007-2010 Taobao Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
package com.taobao.tair.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.taobao.tair.DataEntry;
import com.taobao.tair.Result;
import com.taobao.tair.ResultCode;
import com.taobao.tair.TairManager;
import com.taobao.tair.comm.DefaultTranscoder;
import com.taobao.tair.comm.MultiSender;
import com.taobao.tair.comm.TairClient;
import com.taobao.tair.comm.TairClientFactory;
import com.taobao.tair.comm.Transcoder;
import com.taobao.tair.etc.IncData;
import com.taobao.tair.etc.TairClientException;
import com.taobao.tair.etc.TairConstant;
import com.taobao.tair.etc.TairUtil;
import com.taobao.tair.json.Json;
import com.taobao.tair.packet.BasePacket;
import com.taobao.tair.packet.RequestAddItemsPacket;
import com.taobao.tair.packet.RequestCommandCollection;
import com.taobao.tair.packet.RequestGetAndRemoveItemsPacket;
import com.taobao.tair.packet.RequestGetItemsCountPacket;
import com.taobao.tair.packet.RequestGetItemsPacket;
import com.taobao.tair.packet.RequestGetPacket;
import com.taobao.tair.packet.RequestIncDecPacket;
import com.taobao.tair.packet.RequestLockPacket;
import com.taobao.tair.packet.RequestPutPacket;
import com.taobao.tair.packet.RequestRemoveItemsPacket;
import com.taobao.tair.packet.RequestRemovePacket;
import com.taobao.tair.packet.ResponseGetItemsPacket;
import com.taobao.tair.packet.ResponseGetPacket;
import com.taobao.tair.packet.ResponseIncDecPacket;
import com.taobao.tair.packet.ReturnPacket;
import com.taobao.tair.packet.TairPacketStreamer;
public class DefaultTairManager implements TairManager {
private static final Log log = LogFactory.getLog(DefaultTairManager.class);
protected static String clientVersion = "TairClient 2.3.5";
protected List configServerList = null;
protected String groupName = null;
protected ConfigServer configServer = null;
protected MultiSender multiSender = null;
protected int timeout = TairConstant.DEFAULT_TIMEOUT;
protected int maxWaitThread = TairConstant.DEFAULT_WAIT_THREAD;
protected TairPacketStreamer packetStreamer = null;
protected Transcoder transcoder = null;
protected int compressionThreshold = 0;
protected String charset = null;
protected String name = null;
protected AtomicInteger failCounter = new AtomicInteger(0);
protected TairClientFactory clientFactory = null;
public DefaultTairManager() {
this("DefaultTairManager", true);
}
public DefaultTairManager(String name, boolean sharedFactory) {
this.name = name;
if (sharedFactory)
clientFactory = TairClientFactory.getSingleInstance();
else
clientFactory = new TairClientFactory();
}
/**
* 鏇存柊鏈嶅姟鍒楄〃
*/
protected void updateConfigServer(){
configServer.checkConfigVersion(0);
failCounter.set(0);
}
public void init() {
transcoder = new DefaultTranscoder(compressionThreshold, charset);
packetStreamer = new TairPacketStreamer(transcoder);
configServer = new ConfigServer(clientFactory, groupName, configServerList,
packetStreamer);
if (!configServer.retrieveConfigure()) {
throw new RuntimeException(clientVersion + ": init config failed");
}
multiSender = new MultiSender(clientFactory, packetStreamer);
log.warn(name + " [" + getVersion() + "] started...");
}
public void close() {
if (clientFactory != null) {
clientFactory.close();
}
}
private TairClient getClient(Object key, boolean isRead) {
long address = configServer.getServer(transcoder.encode(key), isRead);
if (address == 0)
return null;
String host = TairUtil.idToAddress(address);
if (host != null) {
try {
return clientFactory.get(host, timeout, packetStreamer);
} catch (TairClientException e) {
log.error("getClient failed " + host, e);
}
}
return null;
}
private BasePacket sendRequest(Object key, BasePacket packet) {
return sendRequest(key, packet, false);
}
protected BasePacket sendRequest(Object key, BasePacket packet, boolean isRead) {
TairClient client = getClient(key, isRead);
if (client == null) {
int value = failCounter.incrementAndGet();
if (value > 100) {
configServer.checkConfigVersion(0);
failCounter.set(0);
log.warn("connection failed happened 100 times, sync configuration");
}
log.warn("conn is null ");
return null;
}
BasePacket returnPacket = null;
long startTime = System.currentTimeMillis();
try {
returnPacket = (BasePacket) client.invoke(packet, timeout);
} catch (TairClientException e) {
log.error("send request to " + client + " failed ", e);
}
long endTime = System.currentTimeMillis();
if (returnPacket == null) {
if (failCounter.incrementAndGet() > 100) {
configServer.checkConfigVersion(0);
failCounter.set(0);
log.warn("connection failed happened 100 times, sync configuration");
}
return null;
} else {
if (log.isDebugEnabled()) {
log.debug("key=" + key + ", timeout: " + timeout + ", used: " + (endTime - startTime)
+ " (ms), client: " + client);
}
}
return returnPacket;
}
public Result decr(int namespace, Serializable key, int value,
int defaultValue, int expireTime) {
if (value < 0){
return new Result(ResultCode.ITEMSIZEERROR);
}
return addCount(namespace, key, -value, defaultValue, expireTime);
}
public ResultCode delete(int namespace, Serializable key) {
if ((namespace < 0) || (namespace > TairConstant.NAMESPACE_MAX)) {
return ResultCode.NSERROR;
}
if (key == null) {
return ResultCode.SERIALIZEERROR;
}
RequestRemovePacket packet = new RequestRemovePacket(transcoder);
packet.setNamespace((short) namespace);
packet.addKey(key);
int ec = packet.encode();
if (ec == 1) {
return ResultCode.KEYTOLARGE;
}
ResultCode rc = ResultCode.CONNERROR;
BasePacket returnPacket = sendRequest(key, packet);
if ((returnPacket != null) && returnPacket instanceof ReturnPacket) {
rc = ResultCode.valueOf(((ReturnPacket) returnPacket).getCode());
}
return rc;
}
public ResultCode invalid(int namespace, Serializable key) {
return delete(namespace, key);
}
public ResultCode minvalid(int namespace, List extends Object> keys) {
return mdelete(namespace, keys);
}
public Result get(int namespace, Serializable key) {
if ((namespace < 0) || (namespace > TairConstant.NAMESPACE_MAX)) {
return new Result(ResultCode.NSERROR);
}
RequestGetPacket packet = new RequestGetPacket(transcoder);
packet.setNamespace((short) namespace);
packet.addKey(key);
int ec = packet.encode();
if (ec == 1) {
return new Result(ResultCode.KEYTOLARGE);
}
ResultCode rc = ResultCode.CONNERROR;
BasePacket returnPacket = sendRequest(key, packet, true);
if ((returnPacket != null) && returnPacket instanceof ResponseGetPacket) {
ResponseGetPacket r = (ResponseGetPacket) returnPacket;
DataEntry resultObject = null;
List entryList = r.getEntryList();
rc = ResultCode.valueOf(r.getResultCode());
if (rc == ResultCode.SUCCESS && entryList.size() > 0){
resultObject = entryList.get(0);
}
configServer.checkConfigVersion(r.getConfigVersion());
return new Result(rc, resultObject);
}
return new Result(rc);
}
public String getVersion() {
return clientVersion;
}
public Result incr(int namespace, Serializable key, int value,
int defaultValue, int expireTime) {
if (value < 0){
return new Result(ResultCode.ITEMSIZEERROR);
}
return addCount(namespace, key, value, defaultValue, expireTime);
}
public ResultCode setCount(int namespace, Serializable key, int count) {
return setCount(namespace, key, count, 0, 0);
}
public ResultCode setCount(int namespace, Serializable key, int count, int version, int expireTime) {
if ((namespace < 0) || (namespace > TairConstant.NAMESPACE_MAX)) {
return ResultCode.NSERROR;
}
RequestPutPacket packet = new RequestPutPacket(transcoder);
IncData value = new IncData(count);
packet.setNamespace((short) namespace);
packet.setKey(key);
packet.setData(value);
packet.setVersion((short) version);
packet.setExpired(expireTime);
// set flag implicitly
int ec = packet.encode(DataEntry.TAIR_ITEM_FLAG_ADDCOUNT);
if (ec == TairConstant.KEYTOLARGE) {
return ResultCode.KEYTOLARGE;
} else if (ec == TairConstant.VALUETOLARGE) {
return ResultCode.VALUETOLARGE;
} else if (ec == TairConstant.SERIALIZEERROR) {
return ResultCode.SERIALIZEERROR;
}
ResultCode rc = ResultCode.CONNERROR;
BasePacket returnPacket = sendRequest(key, packet);
if ((returnPacket != null) && returnPacket instanceof ReturnPacket) {
ReturnPacket r = (ReturnPacket) returnPacket;
if (log.isDebugEnabled()) {
log.debug("get return packet: " + returnPacket + ", code="
+ r.getCode() + ", msg=" + r.getMsg());
}
rc = ResultCode.valueOf(r.getCode());
configServer.checkConfigVersion(r.getConfigVersion());
}
return rc;
}
private Result addCount(int namespace, Serializable key, int value,
int defaultValue, int expireTime) {
if ((namespace < 0) || (namespace > TairConstant.NAMESPACE_MAX)) {
return new Result(ResultCode.NSERROR);
}
RequestIncDecPacket packet = new RequestIncDecPacket(transcoder);
packet.setNamespace((short) namespace);
packet.setKey(key);
packet.setCount(value);
packet.setInitValue(defaultValue);
packet.setExpireTime(expireTime);
int ec = packet.encode();
if (ec == 1) {
return new Result(ResultCode.KEYTOLARGE);
}
ResultCode rc = ResultCode.CONNERROR;
BasePacket returnPacket = sendRequest(key, packet);
if ((returnPacket != null)) {
if (returnPacket instanceof ResponseIncDecPacket) {
ResponseIncDecPacket r = (ResponseIncDecPacket) returnPacket;
rc = ResultCode.SUCCESS;
configServer.checkConfigVersion(r.getConfigVersion());
return new Result(rc, r.getValue());
} else if (returnPacket instanceof ReturnPacket) {
ReturnPacket rp = (ReturnPacket) returnPacket;
rc = ResultCode.valueOf(rp.getCode());
configServer.checkConfigVersion(rp.getConfigVersion());
}
}
return new Result(rc);
}
public ResultCode mdelete(int namespace, List extends Object> keys) {
if ((namespace < 0) || (namespace > TairConstant.NAMESPACE_MAX)) {
return ResultCode.NSERROR;
}
RequestCommandCollection rcc = new RequestCommandCollection();
for (Object key : keys) {
long address = configServer
.getServer(transcoder.encode(key), false);
if (address == 0) {
continue;
}
RequestRemovePacket packet = (RequestRemovePacket) rcc
.findRequest(address);
if (packet == null) {
packet = new RequestRemovePacket(transcoder);
packet.setNamespace((short) namespace);
packet.addKey(key);
rcc.addRequest(address, packet);
} else {
packet.addKey(key);
}
}
for (BasePacket p : rcc.getRequestCommandMap().values()) {
RequestGetPacket rp = (RequestGetPacket) p;
// check key size
int ec = rp.encode();
if (ec == 1) {
log.error("key too larget: ");
return ResultCode.KEYTOLARGE;
}
}
ResultCode rc = ResultCode.CONNERROR;
boolean ret = multiSender.sendRequest(rcc, timeout);
if (ret) {
int maxConfigVersion = 0;
rc = ResultCode.SUCCESS;
for (BasePacket rp : rcc.getResultList()) {
if (rp instanceof ReturnPacket) {
ReturnPacket returnPacket = (ReturnPacket) rp;
returnPacket.decode();
if (returnPacket.getConfigVersion() > maxConfigVersion) {
maxConfigVersion = returnPacket.getConfigVersion();
}
ResultCode drc = ResultCode.valueOf(returnPacket.getCode());
if (drc.isSuccess() == false) {
log.debug("mdelete not return success, result code: " + ResultCode.valueOf(returnPacket.getCode()));
rc = ResultCode.PARTSUCC;
}
}
}
configServer.checkConfigVersion(maxConfigVersion);
}else{
//鍦ㄥ苟鍙戣姹�鍑虹幇闂 璁板綍閿欒鏁伴噺(鍘熷厛杩欎釜缂哄け)
if (failCounter.incrementAndGet() > 100) {
configServer.checkConfigVersion(0);
failCounter.set(0);
log.warn("connection failed happened 100 times, sync configuration");
}
}
return rc;
}
public Result> mget(int namespace,
List extends Object> keys) {
if ((namespace < 0) || (namespace > TairConstant.NAMESPACE_MAX)) {
return new Result>(ResultCode.NSERROR);
}
RequestCommandCollection rcc = new RequestCommandCollection();
for (Object key : keys) {
long address = configServer.getServer(transcoder.encode(key), true);
if (address == 0) {
continue;
}
RequestGetPacket packet = (RequestGetPacket) rcc
.findRequest(address);
if (packet == null) {
packet = new RequestGetPacket(transcoder);
packet.setNamespace((short) namespace);
packet.addKey(key);
rcc.addRequest(address, packet);
} else {
packet.addKey(key);
}
}
int reqSize = 0;
for (BasePacket p : rcc.getRequestCommandMap().values()) {
RequestGetPacket rp = (RequestGetPacket) p;
// calculate uniq key number
reqSize += rp.getKeyList().size();
// check key size
int ec = rp.encode();
if (ec == 1) {
log.error("key too larget: ");
return new Result>(ResultCode.KEYTOLARGE);
}
}
boolean ret = multiSender.sendRequest(rcc, timeout);
if (!ret) {
//鍦ㄥ苟鍙戣姹�鍑虹幇闂 璁板綍閿欒鏁伴噺(鍘熷厛杩欎釜缂哄け)
if (failCounter.incrementAndGet() > 100) {
configServer.checkConfigVersion(0);
failCounter.set(0);
log.warn("connection failed happened 100 times, sync configuration");
}
return new Result>(ResultCode.CONNERROR);
}
List results = new ArrayList();
ResultCode rc = ResultCode.SUCCESS;
ResponseGetPacket resp = null;
int maxConfigVersion = 0;
for (BasePacket bp : rcc.getResultList()) {
if (bp instanceof ResponseGetPacket) {
resp = (ResponseGetPacket) bp;
resp.decode();
results.addAll(resp.getEntryList());
// calculate max config version
if (resp.getConfigVersion() > maxConfigVersion) {
maxConfigVersion = resp.getConfigVersion();
}
} else {
log.warn("receive wrong packet type: " + bp);
}
}
configServer.checkConfigVersion(maxConfigVersion);
if (results.size() == 0) {
rc = ResultCode.DATANOTEXSITS;
} else if (results.size() != reqSize) {
if (log.isDebugEnabled()) {
log.debug("mget partly success: request key size: " + reqSize
+ ", get " + results.size());
}
rc = ResultCode.PARTSUCC;
}
return new Result>(rc, results);
}
public ResultCode put(int namespace, Serializable key, Serializable value) {
return put(namespace, key, value, 0, 0);
}
public ResultCode put(int namespace, Serializable key, Serializable value,
int version) {
return put(namespace, key, value, version, 0);
}
public ResultCode put(int namespace, Serializable key, Serializable value,
int version, int expireTime) {
if ((namespace < 0) || (namespace > TairConstant.NAMESPACE_MAX)) {
return ResultCode.NSERROR;
}
if (expireTime < 0){
return ResultCode.INVALIDARG;
}
RequestPutPacket packet = new RequestPutPacket(transcoder);
packet.setNamespace((short) namespace);
packet.setKey(key);
packet.setData(value);
packet.setVersion((short) version);
packet.setExpired(expireTime);
int ec = packet.encode();
if (ec == TairConstant.KEYTOLARGE) {
return ResultCode.KEYTOLARGE;
} else if (ec == TairConstant.VALUETOLARGE) {
return ResultCode.VALUETOLARGE;
} else if (ec == TairConstant.SERIALIZEERROR) {
return ResultCode.SERIALIZEERROR;
}
ResultCode rc = ResultCode.CONNERROR;
BasePacket returnPacket = sendRequest(key, packet);
if ((returnPacket != null) && returnPacket instanceof ReturnPacket) {
ReturnPacket r = (ReturnPacket) returnPacket;
if (log.isDebugEnabled()) {
log.debug("get return packet: " + returnPacket + ", code="
+ r.getCode() + ", msg=" + r.getMsg());
}
rc = ResultCode.valueOf(r.getCode());
configServer.checkConfigVersion(r.getConfigVersion());
}
return rc;
}
// @nayan. lock/unlock/mlock/munlock to lock a key
public ResultCode lock(int namespace, Serializable key) {
return doLock(namespace, key, RequestLockPacket.LOCK_VALUE, "lock");
}
public ResultCode unlock(int namespace, Serializable key) {
return doLock(namespace, key, RequestLockPacket.UNLOCK_VALUE, "unlock");
}
public Result> mlock(int namespace, List extends Object> keys) {
return doMLock(namespace, keys, RequestLockPacket.LOCK_VALUE, "mlock", null);
}
public Result> mlock(int namespace, List extends Object> keys, Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy