package com.justdebugit.thrift.provider;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;
import org.apache.thrift.TProcessor;
import org.apache.thrift.server.TServer;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.justdebugit.thrift.common.AbstractLifeCycle;
import com.justdebugit.thrift.constants.Constants;
import com.justdebugit.thrift.registry.CuratorFactory;
import com.justdebugit.thrift.registry.DefaultCuratorFactory;
import com.justdebugit.thrift.registry.Registry;
import com.justdebugit.thrift.registry.ZkCuratorRegistry;
import com.justdebugit.thrift.registry.ZkPathConstants;
import com.justdebugit.thrift.server.DefaultTServerFactory;
import com.justdebugit.thrift.server.TServerFactory;
import com.justdebugit.thrift.utils.NetUtils;
import com.justdebugit.thrift.utils.ZkRegistryUtils;
public class RpcProvider extends AbstractLifeCycle{
private String host;
private int port;
private TServer server ;
private Registry registry;
private Map<String, TProcessor> processorMap = Maps.newConcurrentMap();
private Set<String> pathSet = Sets.newCopyOnWriteArraySet();
public RpcProvider(ProviderBuilder builder){
registry = makeRegistry(builder);
port = builder.getPort();
host = builder.getHost()==null?NetUtils.ANYHOST:builder.getHost();
server = makeTserver(builder);
processorMap.putAll(builder.getProcessorMap());
}
private TServer makeTserver(ProviderBuilder builder){
server = builder.gettServer();
if (server ==null) {
TServerFactory tServerFactory = null;
if ((tServerFactory=builder.gettServerFactory())!=null) {
server = tServerFactory.createTServer();
}else {
Preconditions.checkArgument(!builder.getProcessorMap().isEmpty(), "processor map can not be null ");
Preconditions.checkArgument(builder.getPort()!=0, "port must be greater than zero");
InetSocketAddress address = null;
if (builder.getHost()!=null) {
address = new InetSocketAddress(builder.getHost(), port);
}else {
address = new InetSocketAddress(port);
}
TServerFactory _tServerFactory = new DefaultTServerFactory(builder.getProcessorMap(), address);
server = _tServerFactory.createTServer();
}
}
return server;
}
private Registry makeRegistry(ProviderBuilder builder) {
registry = builder.getRegistry();
if (registry==null) {
CuratorFactory curatorFactory = new DefaultCuratorFactory(
builder.getConnectStringForzk(),
builder.getConectTimeoutForZk(),
builder.getSessionTimeoutForZk());
registry = new ZkCuratorRegistry(curatorFactory);
}
return registry;
}
public void doStart() {
for (Map.Entry<String, TProcessor> entry : processorMap.entrySet()) {
StringBuilder pathBuilder = new StringBuilder("/"+entry.getKey()+ZkPathConstants.PROVIDER_SUFFIX_PATH);
pathBuilder.append("/"+host+":"+port);
String path = pathBuilder.toString();
pathSet.add(path);
ZkRegistryUtils.registerWithGuaranteed(registry, path, String.valueOf(System.currentTimeMillis()).getBytes());
}
server.serve();
}
public void doStop() {
server.stop();
for (String path : pathSet) {
registry.unregister(path);
pathSet.remove(path);
}
}
public static ProviderBuilder builder(){
return new ProviderBuilder();
}
public static class ProviderBuilder{
private String host;
private int port;
private String connectStringForzk ;
private int sessionTimeoutForZk = Constants.DEFAULT_SESSION_TIMEOUT;
private int conectTimeoutForZk = Constants.DEFAULT_CONNECT_TIMEOUT;
private Registry registry;
private TServerFactory tServerFactory;
private TServer tServer;
private Map<String, TProcessor> processorMap = Maps.newConcurrentMap();
public RpcProvider build(){
return new RpcProvider(this);
}
public ProviderBuilder processorMap(Map<String, TProcessor> map){
processorMap.putAll(map);
return this;
}
public ProviderBuilder connectStringForzk(String connectString){
this.connectStringForzk = connectString;
return this;
}
public ProviderBuilder sessionTimeoutForZk(int sessionTimeoutForZk){
this.sessionTimeoutForZk = sessionTimeoutForZk;
return this;
}
public ProviderBuilder connectTimeoutForZk(int connectTimeoutForZk){
this.conectTimeoutForZk = connectTimeoutForZk;
return this;
}
public ProviderBuilder serverPort(int port){
this.port = port;
return this;
}
public ProviderBuilder serverHost(String hostname){
this.host= hostname;
return this;
}
public ProviderBuilder tServerFactory(TServerFactory tServerFactory){
this.tServerFactory = tServerFactory;
return this;
}
public ProviderBuilder tServer(TServer tServer){
this.tServer = tServer;
return this;
}
public ProviderBuilder registry(Registry registry){
this.registry = registry;
return this;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getConnectStringForzk() {
return connectStringForzk;
}
public int getSessionTimeoutForZk() {
return sessionTimeoutForZk;
}
public int getConectTimeoutForZk() {
return conectTimeoutForZk;
}
public Registry getRegistry() {
return registry;
}
public TServerFactory gettServerFactory() {
return tServerFactory;
}
public TServer gettServer() {
return tServer;
}
public Map<String, TProcessor> getProcessorMap() {
return processorMap;
}
}
}