mina源码分析---4

原创 2015年11月20日 21:02:27

ExecutorFilter和ProtocolCodecFilter源码分析

从上一章分析的callNextMessageReceived函数中得知,mina框架会调用注册进的filter对客户端请求进行处理,默认的filter有HeadFilter和TailFilter,本章就分析mina源码中提供的ExecutorFilter和ProtocolCodecFilter。

ExecutorFilter

直接看它的messageReceived函数,

    public final void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
        if (eventTypes.contains(IoEventType.MESSAGE_RECEIVED)) {
            IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.MESSAGE_RECEIVED, session, message);
            fireEvent(event);
        } else {
            nextFilter.messageReceived(session, message);
        }
    }

这里创建了一个IoFilterEvent并调用fireEvent,

    protected void fireEvent(IoFilterEvent event) {
        executor.execute(event);
    }

executor是在ExecutorFilter构造函数中创建的OrderedThreadPoolExecutor,

    public void execute(Runnable task) {

        IoEvent event = (IoEvent) task;
        IoSession session = event.getSession();

        SessionTasksQueue sessionTasksQueue = getSessionTasksQueue(session);
        Queue<Runnable> tasksQueue = sessionTasksQueue.tasksQueue;

        boolean offerSession;
        boolean offerEvent = eventQueueHandler.accept(this, event);

        if (offerEvent) {
            synchronized (tasksQueue) {
                tasksQueue.offer(event);
                if (sessionTasksQueue.processingCompleted) {
                    sessionTasksQueue.processingCompleted = false;
                    offerSession = true;
                } else {
                    offerSession = false;
                }
            }
        } else {
            offerSession = false;
        }

        if (offerSession) {
            waitingSessions.offer(session);
        }

        addWorkerIfNecessary();

        if (offerEvent) {
            eventQueueHandler.offered(this, event);
        }
    }

getSession返回的是一个NioSocketSession,getSessionTasksQueue返回的是该Session的任务队列,定义在OrderedThreadPoolExecutor中,

    private SessionTasksQueue getSessionTasksQueue(IoSession session) {
        SessionTasksQueue queue = (SessionTasksQueue) session.getAttribute(TASKS_QUEUE);

        if (queue == null) {
            queue = new SessionTasksQueue();
            SessionTasksQueue oldQueue = (SessionTasksQueue) session.setAttributeIfAbsent(TASKS_QUEUE, queue);

            if (oldQueue != null) {
                queue = oldQueue;
            }
        }

        return queue;
    }

这里会创建SessionTasksQueue并添加进session中。
回到execute函数中,eventQueueHandler默认为IoEventQueueHandler.NOOP即IoEventQueueHandler,其accept函数直接返回true,因此接下来把刚才的event添加到任务队列中。因为是刚刚添加的task,因此肯定没有被处理,于是将processingCompleted设置为false,并把刚刚的session添加到waitingSessions中,等待被处理。然后就调用addWorkerIfNecessary添加线程处理刚刚添加的task,

    private void addWorkerIfNecessary() {
        if (idleWorkers.get() == 0) {
            synchronized (workers) {
                if (workers.isEmpty() || (idleWorkers.get() == 0)) {
                    addWorker();
                }
            }
        }
    }

如果没有Worker或者所有的Worker都在处理请求中,就调用addWorker创建线程进行处理,

    private void addWorker() {
        synchronized (workers) {
            if (workers.size() >= super.getMaximumPoolSize()) {
                return;
            }

            Worker worker = new Worker();
            Thread thread = getThreadFactory().newThread(worker);
            idleWorkers.incrementAndGet();
            thread.start();

            workers.add(worker);

            if (workers.size() > largestPoolSize) {
                largestPoolSize = workers.size();
            }
        }
    }

Worker的总数量是有限制的,然后就创建Worker,启动线程进行处理,

        public void run() {
            thread = Thread.currentThread();

            try {
                for (;;) {
                    IoSession session = fetchSession();
                    idleWorkers.decrementAndGet();

                    try {
                        runTasks(getSessionTasksQueue(session));
                    } finally {
                        idleWorkers.incrementAndGet();
                    }
                }
            } finally {

                }
            }
        }

fetchSession从waitingSessions中获取刚刚添加的NioSocketSession,然后更新空闲Worker方面的信息,接着就调用runTasks处理该Session中的任务队列。

        private void runTasks(SessionTasksQueue sessionTasksQueue) {
            for (;;) {
                Runnable task;
                Queue<Runnable> tasksQueue = sessionTasksQueue.tasksQueue;

                synchronized (tasksQueue) {
                    task = tasksQueue.poll();

                    if (task == null) {
                        sessionTasksQueue.processingCompleted = true;
                        break;
                    }
                }

                eventQueueHandler.polled(OrderedThreadPoolExecutor.this, (IoEvent) task);

                runTask(task);
            }
        }

这里就是从任务队列中依次取出任务,然后调用runTask进行处理,如果没有任务可以处理了,就将processingCompleted标志位设为true并退出循环。runTask定义在OrderedThreadPoolExecutor中,

        private void runTask(Runnable task) {
            beforeExecute(thread, task);
            boolean ran = false;
            try {
                task.run();
                ran = true;
                afterExecute(task, null);
            } catch (RuntimeException e) {
                if (!ran) {
                    afterExecute(task, e);
                }
                throw e;
            }
        }

该函数就是执行task的run函数,在执行前后调用beforeExecute和afterExecute,这两函数用于重载,mina框架并未定义。任务的run函数定义在IoFilterEvent中,

    public void run() {
        fire();
    }

fire函数如下,

    public void fire() {
        IoSession session = getSession();
        NextFilter nextFilter = getNextFilter();
        IoEventType type = getType();

        switch (type) {
        case MESSAGE_RECEIVED:
            Object parameter = getParameter();
            nextFilter.messageReceived(session, parameter);
            break;

        case MESSAGE_SENT:
            WriteRequest writeRequest = (WriteRequest) getParameter();
            nextFilter.messageSent(session, writeRequest);
            break;

        case WRITE:
            writeRequest = (WriteRequest) getParameter();
            nextFilter.filterWrite(session, writeRequest);
            break;

        case CLOSE:
            nextFilter.filterClose(session);
            break;

        case EXCEPTION_CAUGHT:
            Throwable throwable = (Throwable) getParameter();
            nextFilter.exceptionCaught(session, throwable);
            break;

        case SESSION_IDLE:
            nextFilter.sessionIdle(session, (IdleStatus) getParameter());
            break;

        case SESSION_OPENED:
            nextFilter.sessionOpened(session);
            break;

        case SESSION_CREATED:
            nextFilter.sessionCreated(session);
            break;

        case SESSION_CLOSED:
            nextFilter.sessionClosed(session);
            break;

        default:
            throw new IllegalArgumentException("Unknown event type: " + type);
        }
    }

回顾前面的代码,从上层传入的事件是一个MESSAGE_RECEIVED,因此这里首先调用getParameter获得客户端的请求消息,然后直接调用下一个过滤器进行处理。从这里也可以看出,ExecutorFilter其实没有做什么实质性的事情,就是根据传入的事件类型,调用下一个过滤器的不同处理函数进行处理,相当于一个事件的分发器。

ProtocolCodecFilter

ProtocolCodecFilter用于对客户端的请求进行解码,直接看它的messageReceived函数,

    public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {

        IoBuffer in = (IoBuffer) message;
        ProtocolDecoder decoder = factory.getDecoder(session);
        ProtocolDecoderOutput decoderOut = getDecoderOut(session, nextFilter);

        while (in.hasRemaining()) {
            int oldPos = in.position();
            try {
                lock.acquire();
                decoder.decode(session, in, decoderOut);
                decoderOut.flush(nextFilter, session);
            } catch (Exception e) {

            } finally {

            }
        }
    }

这里factory假设为TextLineCodecFactory,其构造函数如下,

    public TextLineCodecFactory(Charset charset) {
        encoder = new TextLineEncoder(charset, LineDelimiter.UNIX);
        decoder = new TextLineDecoder(charset, LineDelimiter.AUTO);
    }

因此其getDecoder函数返回TextLineDecoder。
回到messageReceived中,getDecoderOut默认获得ProtocolDecoderOutputImpl,接下来调用TextLineDecoder的decode函数将数据解析到ProtocolDecoderOutputImpl的messageQueue中,再调用flush函数,flush函数只是简单地调用下一个过滤器进行处理。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Mina-2.0.7源码学习 (4) --- IoFuture

Mina使用IoFuture实现了

MINA源码分析2-I/O操作

分析I/O操作首先我们从NioSocketAcceptor

Mina2源码分析

  • 2013-05-17 10:23
  • 558KB
  • 下载

MINA源码分析---对客户端设置连接间隔时间的过滤器

如果这个IP此次发起连接距离上次发起连接的时间少于规定的时间,则关闭会话,否则建立会话,可以避免同一个远程主机在短时间内发起多个连接 下面是源代码,比较简单明了,不作解释了 厅 /* * Li...

MINA框架源码分析(二)

上一篇我们通过实例学习了MINA框架的用法,发现用起来还是挺方便的,就那么几步就可以了,本着学东西必知其原理的观念,决定看看MINA的源码实现,好了,我们开始吧!         MINA源码对于客户...

关于MINA服务端源码分析

1:NioSocketAcceptor.java 他是继承了AbstractPollingIoAcceptor.java 和 AbstractIoAcceptor.java

MINA源码分析1-服务端启动和客户端调用

最近由于需要使用MINA框架进行项目开发,所以研究了

MINA源码分析1:服务器端的启动过程

一、预备: 这篇文章假设你了解java nio 有关Java NIO的资料: 1. http://tutorials.jenkov.com/java-nio/index.html英文的,国内有很多博客...

Mina源码分析——IoService

这两天看了下Mina和Netty的源码,想比较来说Mina的结构简洁易懂。Mina和Netty出自同一人,而Netty是作者对Mina的重构版,改进了很多。如果学习网络编程的话,个人建议从Mina开始...

MINA框架源码分析(三)

我们接着上一篇继续分析;         在addNow方法执行结束之后,我们已经为当前NioProcessor里面所有的NioSocketSession对应的SocketChannel注册了OP_R...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)