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函数只是简单地调用下一个过滤器进行处理。

java位运算20个位运算技巧【转】

一提起位运算,人们往往想到它的高效性,无论是嵌入式编程还是优化系统的核心代码,适当的运用位运算总是一种迷人的手段,或者当您求职的时候,在代码中写入适当的位运算也会让您的程序增加一丝亮点,最初当我读《编...
  • zcm101
  • zcm101
  • 2013年07月17日 16:16
  • 848

输入一个整数,判断其是否是2^n,是就输出这个数,不是就输出和它最接近的为2^n的那个整数。

输入一个整数,判断其是否是2^n,若是,输出这个数,若不是,输出和它最接近的为2^n的那个整数。 思路一:用math()函数的pow(2,n)与之比较判断 思路二:如果这个数是2的n次方幂,那可以将这...

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

Mina使用IoFuture实现了

Mina2源码分析

  • 2013年05月17日 10:23
  • 558KB
  • 下载

MINA源码分析---协议编码解码器工厂ProtocolCodecFactory接口

1、具体的解码器,编码器需要自己根据协议实现 2、实现协议编码解码器工厂ProtocolCodecFactory接口,在里面主要的工作就是创建解码器,编码器实例,并且返回实例 下面贴出三个接口的源...

mina源码分析六(转)

上文的内容还有一些没有结尾,这篇补上。在ExpiringMap类中,使用了一个私有内部类ExpiringObject来表示待检查超时的对象,它包括三个域,键,值,上次访问时间,以及用于上次访问时间这个...

MINA源码分析---协议编码解码过滤器ProtocolCodecFilter

协议数据  1、对输出的数据进行编码,把消息对象转换成二进制字节流  2、对收到的数据进行解码    过滤器ProtocolCodecFilter,对应的两个最重要的方法分别是 1、先对数据进...

Mina源码分析之数据读写

AbstractPollingIoProcessor这个类里面有个内部类Processor private class Processor implements Runnable { ...

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

分析I/O操作首先我们从NioSocketAcceptor
  • zxbcome
  • zxbcome
  • 2014年04月25日 14:07
  • 425

MINA源码分析,内涵类的讲解

  • 2013年11月05日 16:02
  • 6.43MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:mina源码分析---4
举报原因:
原因补充:

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