package com.alibaba.doris.client.net.netty;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.Channels;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.doris.client.net.Connection;
import com.alibaba.doris.client.net.ConnectionMetaOperation;
import com.alibaba.doris.client.net.NetException;
import com.alibaba.doris.client.net.OperationFuture;
import com.alibaba.doris.client.net.command.CheckCommand.Type;
import com.alibaba.doris.client.net.command.result.CheckResult;
import com.alibaba.doris.client.net.exception.ClientConnectionException;
import com.alibaba.doris.common.data.Key;
import com.alibaba.doris.common.data.Value;
/**
* @author ajun Email:jack.yuj@alibaba-inc.com
*/
public class NettyConnectionImpl implements Connection {
public NettyConnectionImpl(ClientBootstrap bootstrap, InetSocketAddress address) {
this.bootstrap = bootstrap;
this.address = address;
}
/**
* 关闭当前连接。
*/
public void close() throws NetException {
if (null != channel) {
Channels.close(channel).awaitUninterruptibly(500);
isOpenned.set(false);
logger.error("close connection success:" + address);
}
}
/**
* 打开并建立一个实际的连接。
*/
public void open() throws NetException {
if (isOpenned.compareAndSet(false, true)) {
long start = System.currentTimeMillis();
ChannelFuture future = bootstrap.connect(address);
future.awaitUninterruptibly(4000);
if (future.isSuccess()) {
channel = future.getChannel();
operation = channel.getPipeline().get(DorisClientHandler.class);
logger.info("open connection success:" + address + " time:" + (System.currentTimeMillis() - start));
} else {
ClientConnectionException exception = new ClientConnectionException(
"Connecting remote server failed. The Remote DataServer:"
+ address.toString(),
future.getCause());
exception.setRemoteServerAddress(address);
isOpenned.set(false);
logger.info("open connection failed:" + address + " time:" + (System.currentTimeMillis() - start));
throw exception;
}
} else {
throw new ClientConnectionException(
"Connecting remote server failed. The connection has openned before. Ip address:"
+ address.toString());
}
}
public OperationFuture<Boolean> delete(Key key) {
if (null == key) {
throw new IllegalArgumentException("The input keys is null.");
}
checkConnection();
return operation.delete(key);
}
public OperationFuture<Value> get(Key key) {
checkConnection();
return operation.get(key);
}
public OperationFuture<Map<Key, Value>> gets(Set<Key> keys) {
if (null == keys) {
throw new IllegalArgumentException("The input keys is null.");
}
if (keys.size() <= 0) {
throw new IllegalArgumentException("Couldn't find any keys,the key can't be empty. ");
}
checkConnection();
return operation.gets(keys);
}
public OperationFuture<Boolean> put(Key key, Value value) {
if (null == key) {
throw new IllegalArgumentException("The input key is null.");
}
if (null == value) {
throw new IllegalArgumentException("The input value is null.");
}
checkConnection();
return operation.put(key, value);
}
public OperationFuture<Boolean> puts(Map<Key, Value> map) {
if (null == map) {
throw new IllegalArgumentException("The input arguments of puts couldn't be null.");
}
if (map.size() <= 0) {
throw new IllegalArgumentException("Couldn't store empty map into storage.");
}
checkConnection();
return operation.puts(map);
}
public OperationFuture<String> migrate(String subcommand, String migrateRoute) {
checkConnection();
if (subcommand == null) {
throw new IllegalArgumentException("Migrate subcommand can't be emtpy.");
}
if (migrateRoute == null) {
throw new IllegalArgumentException("Migrate migrateRoute can't be emtpy.");
}
return operation.migrate(subcommand, migrateRoute);
}
public OperationFuture<String> stats(String viewType, int namespace) {
checkConnection();
return operation.stats(viewType, namespace);
}
public boolean isConnected() {
if (null != channel) {
return channel.isConnected();
}
return false;
}
public OperationFuture<CheckResult> check(Type checkType) {
checkConnection();
return operation.check(checkType);
}
public OperationFuture<Boolean> cad(Key key, Value value) {
checkConnection();
return operation.cad(key, value);
}
public OperationFuture<Boolean> cas(Key key, Value value) {
checkConnection();
return operation.cas(key, value);
}
private void checkConnection() {
if (null == channel) {
throw new NetException("Connection is not established. The Remote DataServer:" + address.toString());
}
}
private ClientBootstrap bootstrap;
private Channel channel;
private ConnectionMetaOperation operation;
private InetSocketAddress address;
private AtomicBoolean isOpenned = new AtomicBoolean(false);
private static final Logger logger = LoggerFactory.getLogger(NettyConnectionImpl.class);
}