Mina代码跟踪(1)
1 NioSocketAcceptor类关系图

1.1 NioSocketAcceptor acceptor = new NioSocketAcceptor(5);
NioSocketAcceptor 初始化顺序
AbstractIoService构造函数
protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) {
if (sessionConfig == null) {
throw new IllegalArgumentException("sessionConfig");
}
if (getTransportMetadata() == null) {
throw new IllegalArgumentException("TransportMetadata");
}
if (!getTransportMetadata().getSessionConfigType().isAssignableFrom(
sessionConfig.getClass())) {
throw new IllegalArgumentException("sessionConfig type: "
+ sessionConfig.getClass() + " (expected: "
+ getTransportMetadata().getSessionConfigType() + ")");
}
// Create the listeners, and add a first listener : a activation listener
// for this service, which will give information on the service state.
listeners = new IoServiceListenerSupport(this);
listeners.add(serviceActivationListener);
// Stores the given session configuration
this.sessionConfig = sessionConfig;
// Make JVM load the exception monitor before some transports
// change the thread context class loader.
ExceptionMonitor.getInstance();
if (executor == null) {
this.executor = Executors.newCachedThreadPool();
createdExecutor = true;
} else {
this.executor = executor;
createdExecutor = false;
}
threadName = getClass().getSimpleName() + '-' + id.incrementAndGet();
}
protected AbstractIoAcceptor(IoSessionConfig sessionConfig, Executor executor) {
super(sessionConfig, executor);
defaultLocalAddresses.add(null);
}
AbstractPollingIoAcceptor 构造函数
private AbstractPollingIoAcceptor(IoSessionConfig sessionConfig,
Executor executor, IoProcessor<S> processor,
boolean createdProcessor) {
super(sessionConfig, executor); if (processor == null) {
throw new IllegalArgumentException("processor");
} this.processor = processor;
this.createdProcessor = createdProcessor; try {
// Initialize the selector
init(); // The selector is now ready, we can switch the
// flag to true so that incoming connection can be accepted
selectable = true;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeIoException("Failed to initialize.", e);
} finally {
if (!selectable) {
try {
destroy();
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
}
}
}
}
NioSocketAcceptor 构造函数
public NioSocketAcceptor(int processorCount) {
super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount);
((DefaultSocketSessionConfig) getSessionConfig()).init(this);
}
1.2 IoFilterChain 过滤链
aaarticlea/png;base64,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" alt="" />
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
/** AbstractIoService
* {@inheritDoc}
*/
public final DefaultIoFilterChainBuilder getFilterChain() {
if (filterChainBuilder instanceof DefaultIoFilterChainBuilder) {
return (DefaultIoFilterChainBuilder) filterChainBuilder;
} throw new IllegalStateException(
"Current filter chain builder is not a DefaultIoFilterChainBuilder.");
}
源代码:
public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder {
private final static Logger LOGGER =
LoggerFactory.getLogger(DefaultIoFilterChainBuilder.class);
private final List<Entry> entries;
/**
* Creates a new instance with an empty filter list.
*/
public DefaultIoFilterChainBuilder() {
entries = new CopyOnWriteArrayList<Entry>();
}
/**
* Creates a new copy of the specified {@link DefaultIoFilterChainBuilder}.
*/
public DefaultIoFilterChainBuilder(DefaultIoFilterChainBuilder filterChain) {
if (filterChain == null) {
throw new IllegalArgumentException("filterChain");
}
entries = new CopyOnWriteArrayList<Entry>(filterChain.entries);
}
addLast
/**
* @see IoFilterChain#addLast(String, IoFilter)
*/
public synchronized void addLast(String name, IoFilter filter) {
register(entries.size(), new EntryImpl(name, filter));
}
private void register(int index, Entry e) {
if (contains(e.getName())) {
throw new IllegalArgumentException(
"Other filter is using the same name: " + e.getName());
} entries.add(index, e);
}
1.3 IoFilter
aaarticlea/png;base64,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" alt="" />
1.4 IoSessionConfig
1.4 IoProcess
aaarticlea/png;base64,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" alt="" />
1.5 acceptor.bind(new InetSocketAddress(this.serverAddr, this.serverPort));
最终会运行AbstractPollingIoAcceptor.bindInternal
AbstractPollingIoAcceptor
protected final Set<SocketAddress> bindInternal(
List<? extends SocketAddress> localAddresses) throws Exception {
// Create a bind request as a Future operation. When the selector
// have handled the registration, it will signal this future.
AcceptorOperationFuture request = new AcceptorOperationFuture(
localAddresses); // adds the Registration request to the queue for the Workers
// to handle
registerQueue.add(request); // creates the Acceptor instance and has the local
// executor kick it off.
startupAcceptor(); // As we just started the acceptor, we have to unblock the select()
// in order to process the bind request we just have added to the
// registerQueue.
wakeup(); // Now, we wait until this request is completed.
request.awaitUninterruptibly(); if (request.getException() != null) {
throw request.getException();
} // Update the local addresses.
// setLocalAddresses() shouldn't be called from the worker thread
// because of deadlock.
Set<SocketAddress> newLocalAddresses = new HashSet<SocketAddress>(); for (H handle:boundHandles.values()) {
newLocalAddresses.add(localAddress(handle));
} return newLocalAddresses;
}
1.5.1 startupAcceptor() 使用线程池执行Acceptor
/**
* This method is called by the doBind() and doUnbind()
* methods. If the acceptor is null, the acceptor object will
* be created and kicked off by the executor. If the acceptor
* object is null, probably already created and this class
* is now working, then nothing will happen and the method
* will just return.
*/
private void startupAcceptor() {
// If the acceptor is not ready, clear the queues
// TODO : they should already be clean : do we have to do that ?
if (!selectable) {
registerQueue.clear();
cancelQueue.clear();
} // start the acceptor if not already started
Acceptor acceptor = acceptorRef.get(); if (acceptor == null) {
acceptor = new Acceptor(); if (acceptorRef.compareAndSet(null, acceptor)) {
executeWorker(acceptor);
}
}
}
Acceptor() 实现了Runnable接口 不停的执行
/**
* This class is called by the startupAcceptor() method and is
* placed into a NamePreservingRunnable class.
* It's a thread accepting incoming connections from clients.
* The loop is stopped when all the bound handlers are unbound.
*/
private class Acceptor implements Runnable {
public void run() {
assert (acceptorRef.get() == this); int nHandles = 0; while (selectable) {
try {
// Detect if we have some keys ready to be processed
// The select() will be woke up if some new connection
// have occurred, or if the selector has been explicitly
// woke up
int selected = select(); // this actually sets the selector to OP_ACCEPT,
// and binds to the port on which this class will
// listen on
nHandles += registerHandles(); // Now, if the number of registred handles is 0, we can
// quit the loop: we don't have any socket listening
// for incoming connection.
if (nHandles == 0) {
acceptorRef.set(null); if (registerQueue.isEmpty() && cancelQueue.isEmpty()) {
assert (acceptorRef.get() != this);
break;
} if (!acceptorRef.compareAndSet(null, this)) {
assert (acceptorRef.get() != this);
break;
} assert (acceptorRef.get() == this);
} if (selected > 0) {
// We have some connection request, let's process
// them here.
processHandles(selectedHandles());
} // check to see if any cancellation request has been made.
nHandles -= unregisterHandles();
} catch (ClosedSelectorException cse) {
// If the selector has been closed, we can exit the loop
break;
} catch (Throwable e) {
ExceptionMonitor.getInstance().exceptionCaught(e); try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
ExceptionMonitor.getInstance().exceptionCaught(e1);
}
}
} // Cleanup all the processors, and shutdown the acceptor.
if (selectable && isDisposing()) {
selectable = false;
try {
if (createdProcessor) {
processor.dispose();
}
} finally {
try {
synchronized (disposalLock) {
if (isDisposing()) {
destroy();
}
}
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
} finally {
disposalFuture.setDone();
}
}
}
}
NioSocketAcceptor
/**
* Check if we have at least one key whose corresponding channels is
* ready for I/O operations.
*
* This method performs a blocking selection operation.
* It returns only after at least one channel is selected,
* this selector's wakeup method is invoked, or the current thread
* is interrupted, whichever comes first.
*
* @return The number of keys having their ready-operation set updated
* @throws IOException If an I/O error occurs
* @throws ClosedSelectorException If this selector is closed
*/
@Override
protected int select() throws Exception {
return selector.select();
}
请问
/**
* Sets up the socket communications. Sets items such as:
* <p/>
* Blocking
* Reuse address
* Receive buffer size
* Bind to listen port
* Registers OP_ACCEPT for selector
*/
private int registerHandles() {
for (;;) {
// The register queue contains the list of services to manage
// in this acceptor.
AcceptorOperationFuture future = registerQueue.poll(); if (future == null) {
return 0;
} // We create a temporary map to store the bound handles,
// as we may have to remove them all if there is an exception
// during the sockets opening.
Map<SocketAddress, H> newHandles = new ConcurrentHashMap<SocketAddress, H>();
List<SocketAddress> localAddresses = future.getLocalAddresses(); try {
// Process all the addresses
for (SocketAddress a : localAddresses) {
H handle = open(a);
newHandles.put(localAddress(handle), handle);
} // Everything went ok, we can now update the map storing
// all the bound sockets.
boundHandles.putAll(newHandles); // and notify.
future.setDone();
return newHandles.size();
} catch (Exception e) {
// We store the exception in the future
future.setException(e);
} finally {
// Roll back if failed to bind all addresses.
if (future.getException() != null) {
for (H handle : newHandles.values()) {
try {
close(handle);
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
}
} // TODO : add some comment : what is the wakeup() waking up ?
wakeup();
}
}
}
}
接上图open方法 jdk自带的NIO
/**
* {@inheritDoc}
*/
@Override
protected ServerSocketChannel open(SocketAddress localAddress)
throws Exception {
// Creates the listening ServerSocket
ServerSocketChannel channel = ServerSocketChannel.open(); boolean success = false; try {
// This is a non blocking socket channel
channel.configureBlocking(false); // Configure the server socket,
ServerSocket socket = channel.socket(); // Set the reuseAddress flag accordingly with the setting
socket.setReuseAddress(isReuseAddress()); // and bind.
socket.bind(localAddress, getBacklog()); // Register the channel within the selector for ACCEPT event
channel.register(selector, SelectionKey.OP_ACCEPT);
success = true;
} finally {
if (!success) {
close(channel);
}
}
return channel;
}
Acceptor接收数据
if (selected > 0) {
// We have some connection request, let's process
// them here.
processHandles(selectedHandles());
}
/**
* This method will process new sessions for the Worker class. All
* keys that have had their status updates as per the Selector.selectedKeys()
* method will be processed here. Only keys that are ready to accept
* connections are handled here.
* <p/>
* Session objects are created by making new instances of SocketSessionImpl
* and passing the session object to the SocketIoProcessor class.
*/
@SuppressWarnings("unchecked")
private void processHandles(Iterator<H> handles) throws Exception {
while (handles.hasNext()) {
H handle = handles.next();
handles.remove(); // Associates a new created connection to a processor,
// and get back a session
S session = accept(processor, handle); if (session == null) {
break;
}
//初始化session
initSession(session, null, null); // add the session to the SocketIoProcessor 过滤链处理数据入口
session.getProcessor().add(session);
}
}
processHandles 的accept 获取SocketChannel 封装成NioSocketSession
protected NioSession accept(IoProcessor<NioSession> processor,
ServerSocketChannel handle) throws Exception { SelectionKey key = handle.keyFor(selector); if ((key == null) || (!key.isValid()) || (!key.isAcceptable()) ) {
return null;
} // accept the connection from the client
SocketChannel ch = handle.accept(); if (ch == null) {
return null;
} return new NioSocketSession(this, processor, ch);
}
processor
/**
* {@inheritDoc}
*/
public final void add(S session) {
if (disposed || disposing) {
throw new IllegalStateException("Already disposed.");
} // Adds the session to the newSession queue and starts the worker
newSessions.add(session);
startupProcessor();
}
/**
* Starts the inner Processor, asking the executor to pick a thread in its
* pool. The Runnable will be renamed
*/
private void startupProcessor() {
Processor processor = processorRef.get(); if (processor == null) {
processor = new Processor(); if (processorRef.compareAndSet(null, processor)) {
executor.execute(new NamePreservingRunnable(processor, threadName));
}
} // Just stop the select() and start it again, so that the processor
// can be activated immediately.
wakeup();
}
主要接收数据处理代码逻辑
/**
* The main loop. This is the place in charge to poll the Selector, and to
* process the active sessions. It's done in
* - handle the newly created sessions
* -
*/
private class Processor implements Runnable {
public void run() {
assert (processorRef.get() == this); int nSessions = 0;
lastIdleCheckTime = System.currentTimeMillis(); for (;;) {
try {
// This select has a timeout so that we can manage
// idle session when we get out of the select every
// second. (note : this is a hack to avoid creating
// a dedicated thread).
long t0 = System.currentTimeMillis();
int selected = select(SELECT_TIMEOUT);
long t1 = System.currentTimeMillis();
long delta = (t1 - t0); if ((selected == 0) && !wakeupCalled.get() && (delta < 100)) {
// Last chance : the select() may have been
// interrupted because we have had an closed channel.
if (isBrokenConnection()) {
LOG.warn("Broken connection"); // we can reselect immediately
// set back the flag to false
wakeupCalled.getAndSet(false); continue;
} else {
LOG.warn("Create a new selector. Selected is 0, delta = "
+ (t1 - t0));
// Ok, we are hit by the nasty epoll
// spinning.
// Basically, there is a race condition
// which causes a closing file descriptor not to be
// considered as available as a selected channel, but
// it stopped the select. The next time we will
// call select(), it will exit immediately for the same
// reason, and do so forever, consuming 100%
// CPU.
// We have to destroy the selector, and
// register all the socket on a new one.
registerNewSelector();
} // Set back the flag to false
wakeupCalled.getAndSet(false); // and continue the loop
continue;
} // Manage newly created session first
nSessions += handleNewSessions(); updateTrafficMask(); // Now, if we have had some incoming or outgoing events,
// deal with them
if (selected > 0) {
//LOG.debug("Processing ..."); // This log hurts one of the MDCFilter test...
process();
} // Write the pending requests
long currentTime = System.currentTimeMillis();
flush(currentTime); // And manage removed sessions
nSessions -= removeSessions(); // Last, not least, send Idle events to the idle sessions
notifyIdleSessions(currentTime); // Get a chance to exit the infinite loop if there are no
// more sessions on this Processor
if (nSessions == 0) {
processorRef.set(null); if (newSessions.isEmpty() && isSelectorEmpty()) {
// newSessions.add() precedes startupProcessor
assert (processorRef.get() != this);
break;
} assert (processorRef.get() != this); if (!processorRef.compareAndSet(null, this)) {
// startupProcessor won race, so must exit processor
assert (processorRef.get() != this);
break;
} assert (processorRef.get() == this);
} // Disconnect all sessions immediately if disposal has been
// requested so that we exit this loop eventually.
if (isDisposing()) {
for (Iterator<S> i = allSessions(); i.hasNext();) {
scheduleRemove(i.next());
} wakeup();
}
} catch (ClosedSelectorException cse) {
// If the selector has been closed, we can exit the loop
break;
} catch (Throwable t) {
ExceptionMonitor.getInstance().exceptionCaught(t); try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
ExceptionMonitor.getInstance().exceptionCaught(e1);
}
}
} try {
synchronized (disposalLock) {
if (disposing) {
doDispose();
}
}
} catch (Throwable t) {
ExceptionMonitor.getInstance().exceptionCaught(t);
} finally {
disposalFuture.setValue(true);
}
}
}
过滤链:
private void process() throws Exception {
for (Iterator<S> i = selectedSessions(); i.hasNext();) {
S session = i.next();
process(session);
i.remove();
}
}
/**
* Deal with session ready for the read or write operations, or both.
*/
private void process(S session) {
// Process Reads
if (isReadable(session) && !session.isReadSuspended()) {
read(session);
}
// Process writes
if (isWritable(session) && !session.isWriteSuspended()) {
// add the session to the queue, if it's not already there
if (session.setScheduledForFlush(true)) {
flushingSessions.add(session);
}
}
}
private void read(S session) {
IoSessionConfig config = session.getConfig();
int bufferSize = config.getReadBufferSize();
IoBuffer buf = IoBuffer.allocate(bufferSize);
final boolean hasFragmentation = session.getTransportMetadata()
.hasFragmentation();
try {
int readBytes = 0;
int ret;
try {
if (hasFragmentation) {
while ((ret = read(session, buf)) > 0) {
readBytes += ret;
if (!buf.hasRemaining()) {
break;
}
}
} else {
ret = read(session, buf);
if (ret > 0) {
readBytes = ret;
}
}
} finally {
buf.flip();
}
if (readBytes > 0) {
//处理逻辑
IoFilterChain filterChain = session.getFilterChain();
filterChain.fireMessageReceived(buf);
buf = null;
if (hasFragmentation) {
if (readBytes << 1 < config.getReadBufferSize()) {
session.decreaseReadBufferSize();
} else if (readBytes == config.getReadBufferSize()) {
session.increaseReadBufferSize();
}
}
}
if (ret < 0) {
scheduleRemove(session);
}
} catch (Throwable e) {
if (e instanceof IOException) {
if (!(e instanceof PortUnreachableException)
|| !AbstractDatagramSessionConfig.class.isAssignableFrom(config.getClass())
|| ((AbstractDatagramSessionConfig) config).isCloseOnPortUnreachable()) {
scheduleRemove(session);
}
}
IoFilterChain filterChain = session.getFilterChain();
filterChain.fireExceptionCaught(e);
}
}
调用过滤连: DefaultIoFilterChain
public void fireMessageReceived(Object message) {
if (message instanceof IoBuffer) {
session.increaseReadBytes(((IoBuffer) message).remaining(), System
.currentTimeMillis());
}
Entry head = this.head;
callNextMessageReceived(head, session, message);
}
private void callNextMessageReceived(Entry entry, IoSession session,
Object message) {
try {
IoFilter filter = entry.getFilter();
NextFilter nextFilter = entry.getNextFilter();
filter.messageReceived(nextFilter, session,
message);
} catch (Throwable e) {
fireExceptionCaught(e);
}
}
业务处理handler总是最后处理
Mina代码跟踪(1)的更多相关文章
- AM335x tscadc platform driver 相关代码跟踪
TI AM335x ti am335x_tsc.c 代码跟踪 在kernel 首层目录: 先运行make ARCH=arm tags 这个作用是建立tags文件,只含有arm架构的,利用ctag即可进 ...
- openstack学习笔记一 虚拟机启动过程代码跟踪
openstack学习笔记一 虚拟机启动过程代码跟踪 本文主要通过对虚拟机创建过程的代码跟踪.观察虚拟机启动任务状态的变化,来透彻理解openstack各组件之间的作用过程. 当从horizon界面发 ...
- 简单 php 代码跟踪调试实现
简单 php 代码跟踪调试实现 debug_backtrace:生成回溯 debug_print_backtrace:打印回溯 1. debug_backtrace ($options = DEBUG ...
- trace与代码跟踪服务
首先开篇引用<MVC2 2 in action>里面一段关于这个跟踪服务的话 When you called Trace.Write() in Web Forms, you were in ...
- Linux 内核高-低端内存设置代码跟踪(ARM构架)
对于ARM中内核如何在启动的时候设置高低端内存的分界线(也是逻辑地址与虚拟地址分界线(虚拟地址)减去那个固定的偏移),这里我稍微引导下(内核分析使用Linux-3.0): 首先定位设置内核虚拟地址起始 ...
- saiku执行过程代码跟踪
使用了很久的saiku,决定跟踪一下代码,看看它的执行核心过程: 一.入口controller代码 1.1.页面打开之后,会发送一个ajax请求 Request URL: http://l-tdata ...
- 【实习记】2014-08-10(上)代码跟踪git的想法+归并排序的debug过程
(冒泡,选择,插入,希尔,快速,归并,堆排)周末加班学习C++,打算用C++写七大经典排序代码.发现3个月前自己写的七大经典排序代码(C Language)突然运行出错. Makefile内容 ...
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
root@xuanfei-desktop:~/cpropram/2# cat global.h //头文件#ifndef CLOBAL_H #define GLOBAL_H ...
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试
转:http://www.cnitblog.com/zouzheng/archive/2007/08/31/32691.aspx 先看下简单的初始代码:注意其编译运行后的结果. root@xuanfe ...
随机推荐
- DIV层+CSS实现锁屏
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- 通过PHP current()函数获取未知字符键名数组第一个元素的值
在开发中经常遇到这样问题,获取数组第一个元素的值,如果是数字索引那还好,直接$array[0],如果键名是字符串,你又未知这个字符串呢?用current()函数就可以做到. 当然,你可以用array_ ...
- word如何修改尾注
两篇处理利用尾注处理参考文献的方式,值得注意. 实用技巧:Word 2003中修改尾注位置http://www.kuqin.com/shuoit/20090422/47316.html Word尾注格 ...
- 深入理解dataset及其用法
DataSet是ADO.NET的中心概念.可以把DataSet当成内存中的数据库,DataSet是不依赖于数据库的独立数据集合.所谓独立, 就是说,即使断开数据链路,或者关闭数据库,DataSet依然 ...
- [React] Use react-rewards to add microinteractions to React app to reward users for some actions
It's important that our users enjoy using our application or website. One way we can make it happen ...
- 9.11排序与查找(一)——给定两个排序后的数组A和B,当中A的末端有足够的缓冲空间容纳B。将B合并入A并排序
/** * 功能:给定两个排序后的数组A和B,当中A的末端有足够的缓冲空间容纳B.将B合并入A并排序. */ /** * 问题:假设将元素插入数组A的前端,就必须将原有的元素向后移动,以腾出空间. ...
- MyBatis Generator生成DAO——序列化
MyBatis Generator生成DAO 的时候,生成的类都是没有序列化的. 还以为要手工加入(開始是手工加入的),今天遇到分页的问题,才发现生成的时候能够加入插件. 既然分页能够有插件.序列化是 ...
- 【转】WEB开发三层架构概述
关于 三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了“高内聚,低耦合” ...
- 【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记30 ScrollView Demo实战
在上一话中我们创建了一个通过URL读取图片的Demo,这个Demo是不能拖动和缩放的.如今给它添加选项让它能够手动切换URL,并把图片加入到ScrollView中. 向Storyboard中拖入一个s ...
- Oracle 创建表空间与用户
/* 说明:若已经存在相应的用户和表空间,则需要先删除相应的用户和表空间 然后再全部重新建立 */ --删除用户 drop user XNZQWEIXIN cascade; --删除表空间 drop ...