package com.chamago.bison.server;
import com.chamago.bison.ServiceContext;
import com.chamago.bison.codec.BeanCallCode;
import com.chamago.bison.dbpool.JdbcPoolManager;
import com.chamago.bison.logger.Logger;
import com.chamago.bison.logger.LoggerFactory;
import com.chamago.bison.queue.CallQueueListener;
import com.chamago.bison.queue.Handler;
import com.chamago.bison.queue.LinkListQueue;
import com.chamago.bison.thread.BisonThreadManager;
import com.chamago.bison.util.ByteUtil;
import com.chamago.bison.util.xml.JXmlWapper;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.Hashtable;
import java.util.Iterator;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.cliffc.high_scale_lib.Counter;
/**
*
* @author Gavin.peng
*
* 2013-10-15 下午12:18:11
× bison
*/
public class BisonServerHandler extends IoHandlerAdapter
{
private final Logger logger;
private JdbcPoolManager pool = null;
protected BisonServer bison;
protected LinkListQueue<Call> recvQueue;
private String accessIps;
protected BisonBusiProcessor processor;
protected Hashtable<String, Handler> hThreads;
protected final Counter callQueueSize = new Counter();
private BisonThreadManager rtm;
public BisonServerHandler(BisonServer bison)
{
this.logger = LoggerFactory.getLogger("bison");
this.bison = bison;
load_access_list();
String cfgFile = System.getProperty("conf.dir") + File.separator + "config.xml";
this.pool = new JdbcPoolManager(cfgFile);
this.pool.loadDataSource();
// this.recvQueue = new LinkListQueue<Call>();
// this.processor = new BisonBusiProcessor();
// int handlers = bison.getHandlers();
// this.hThreads = new Hashtable<String, Handler>(handlers);
// CallQueueListener<Call> listener = new RecvListener<Call>();
// for (int i = 0; i < handlers; i++) {
//
// Handler handler = new Handler(recvQueue,i,"CallQueueConsumeThread");
// ServiceContext sc = new ServiceContext();
// sc.setJdbcPoolManager(this.pool);
// sc.setThreadID(i);
// handler.setAttachment(sc);
// handler.registerListener(listener);
// handler.setDaemon(true);
// handler.start();
// this.hThreads.put(String.valueOf(i), handler);
// }
//rtm = new BisonThreadManager(cfgFile,this);
//rtm.startBisonThread(null, this.pool);
}
@Override
public void sessionOpened(IoSession session) {
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);
if ((this.accessIps != null) && (this.accessIps.length() > 0)) {
String ip = ((InetSocketAddress)session.getRemoteAddress()).getAddress().getHostAddress();
//1 全量匹配,如果没有,则看是否有通配定义。
if (this.accessIps.indexOf(ip) < 0) {
ip = ip.substring(0,ip.lastIndexOf("."));
if(this.accessIps.indexOf(ip)< 0){
this.logger.error("非法地址连接 ip=" + ip);
}
session.close(true);
}
}
}
public void setAccessIps(String accessIps){
if(accessIps!=null){
this.accessIps = accessIps;
}
}
public BisonServer getBisonServer(){
return this.bison;
}
private void load_access_list() {
try {
File cFile = new File(System.getProperty("conf.dir") + File.separator + "config.xml");
JXmlWapper xml = JXmlWapper.parse(cFile);
int count = xml.countXmlNodes("access");
this.accessIps = "";
for (int i = 0; i < count; i++) {
String ip = xml.getStringValue("access[" + i + "].@ip");
if(ip!=null&&ip.endsWith(".*")){
ip = ip.substring(0, ip.indexOf(".*"));
}
this.accessIps = (this.accessIps + ip + ",");
this.logger.info("授权 ip=" + ip);
}
cFile = null;
} catch (Exception e) {
e.printStackTrace();
}
}
public void messageReceived(IoSession session, Object message) throws Exception
{
byte[] buf = (byte[])message;
int callSize = buf.length;
if((callSize+callQueueSize.get())>bison.getMaxQueueSize()){
logger.warn("bison server call queue size is too big,execced the max size:"+bison.getMaxQueueSize());
writerFull(message,session,null);
return;
}
callQueueSize.add(callSize);
if (!this.recvQueue.offer(new Call(session, message,callSize)))
this.logger.error("入队列失败");
}
public void sessionIdle(IoSession session, IdleStatus status)
{
byte[] buf = new byte[8];
ByteUtil.write(buf, 0, 0);
ByteUtil.write(buf, 4, 1);
session.write(buf);
}
public void writerFull(Object message,IoSession session, IdleStatus status)
{
byte[] msg = (byte[])message;
int msgID = ByteUtil.readInt(msg, 0);
int skey = ByteUtil.readInt(msg, 4);
byte[] buf = new byte[12];
ByteUtil.writeInt(buf, 0, msgID);
ByteUtil.writeInt(buf, 4, skey);
ByteUtil.writeInt(buf, 8, BeanCallCode.CALL_SEROVERLOAD);
session.write(buf);
buf = null;
}
public void cleanAll(){
this.recvQueue.clear();
Iterator<String> iterator = this.hThreads.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
Handler dt = (Handler)this.hThreads.get(key);
dt.stopThread();
this.logger.info("停止Bison RPC 线程 " + dt.getName());
dt = null;
}
this.hThreads.clear();
this.hThreads = null;
this.rtm.stopRbcThread(null);
}
public void exceptionCaught(IoSession session, Throwable cause) {
session.close(false);
}
public void setClassLoader(ClassLoader clsLoader)
{
this.processor.setClassLoader(clsLoader);
}
class RecvListener<E>
implements CallQueueListener<E>
{
RecvListener()
{
}
public void processQueueElement(E o, int threadID)
{
BisonServerHandler.Call obj = (BisonServerHandler.Call)o;
// try {
// BisonServerHandler.this.processor.process_message(obj.session, obj.message, BisonServerHandler.this.pool, threadID);
// callQueueSize.add(obj.size*-1);
// } catch (Exception e) {
// BisonServerHandler.this.logger.error("", e);
// } finally {
// obj.session = null;
// obj.message = null;
// obj.size = 0;
// obj = null;
// }
}
}
public class Call
{
public IoSession session;
public Object message;
public int size;
public Call(IoSession sess, Object msg,int size)
{
this.session = sess;
this.message = msg;
this.size = size;
}
}
}