mina源码分析---4

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 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 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.9源码分析)