com.openteach.diamond.network.waverider.session.DefaultSessionManager.java Source code

Java tutorial

Introduction

Here is the source code for com.openteach.diamond.network.waverider.session.DefaultSessionManager.java

Source

/**
 * Copyright 2013 openteach
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.openteach.diamond.network.waverider.session;

import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.openteach.diamond.network.waverider.SlaveWorker;
import com.openteach.diamond.network.waverider.command.CommandDispatcher;
import com.openteach.diamond.network.waverider.common.WaveriderThreadFactory;
import com.openteach.diamond.network.waverider.config.WaveriderConfig;
import com.openteach.diamond.network.waverider.network.NetWorkServer;

/**
 * <p>
 * MasterSession?
 * </p>
 * 
 * @author <a href="mailto:sihai@taobao.com">sihai</a>
 *
 */
public class DefaultSessionManager implements SessionManager {

    private static final Log logger = LogFactory.getLog(DefaultSessionManager.class);

    private WaveriderConfig config; // ?
    private AtomicLong sessionCount = new AtomicLong(0); // ?session
    private AtomicLong sessionId = new AtomicLong(0); // session?id

    private CommandDispatcher commandDispatcher;
    private CopyOnWriteArrayList<DefaultSession> idleSessionList;
    private ConcurrentHashMap<Long, DefaultSession> sessionMap;
    private SessionListener listener; // Session?

    private ScheduledExecutorService sessionRecycleScheduler;

    public DefaultSessionManager(WaveriderConfig config) {
        this.config = config;
        idleSessionList = new CopyOnWriteArrayList<DefaultSession>();
        sessionMap = new ConcurrentHashMap<Long, DefaultSession>();
    }

    @Override
    public boolean init() {
        increment(config.getPreInitSessionCount());
        logger.info(new StringBuilder("Pre init ").append(config.getPreInitSessionCount()).append(" sessions.")
                .toString());
        sessionRecycleScheduler = Executors.newScheduledThreadPool(1,
                new WaveriderThreadFactory(SESSION_RECYCLE_THREAD_NAME_PREFIX, null, false));
        return true;
    }

    @Override
    public boolean start() {
        sessionRecycleScheduler.scheduleAtFixedRate(new SessionRecycleTask(), config.getSessionRecycleInterval(),
                config.getSessionRecycleInterval(), TimeUnit.SECONDS);
        return true;
    }

    @Override
    public boolean stop() {
        sessionRecycleScheduler.shutdown();
        idleSessionList.clear();
        idleSessionList = null;
        Long key = null;
        Session session = null;
        Iterator<Long> iterator = sessionMap.keySet().iterator();
        while (iterator.hasNext()) {
            key = iterator.next();
            session = sessionMap.get(key);
            if (session != null) {
                session.stop();
            }
        }
        sessionMap.clear();
        sessionMap = null;

        return true;
    }

    @Override
    public boolean restart() {
        return stop() && init() && start();
    }

    private void increment() {
        if (sessionCount.get() >= config.getMaxSessionCount()) {
            logger.warn(new StringBuilder("Reach max session supported.").toString());
            return;
        }

        long count = config.getMaxSessionCount() - sessionCount.get();
        count = count < config.getIncreaseSessionCount() ? count : config.getPreInitSessionCount();
        increment(count);
    }

    /**
     * ?
     */
    private void increment(long count) {
        logger.warn(new StringBuilder("Increase ").append(count).append(" sessions").toString());
        for (long i = 0; i < count; i++) {
            DefaultSession session = SessionFactory.newSession(sessionId.getAndIncrement(), null, 1024, 1024, null,
                    commandDispatcher);
            session.init();
            idleSessionList.add(session);
        }
    }

    @Override
    public void setCommandDispatcher(CommandDispatcher commandDispatcher) {
        this.commandDispatcher = commandDispatcher;
    }

    @Override
    public Session newSession(NetWorkServer netWorkServer, SocketChannel channel, boolean start) {
        logger.info(new StringBuilder("New session for ")
                .append(channel.socket().getRemoteSocketAddress().toString()).toString());

        if (idleSessionList.isEmpty()) {
            increment();
        }

        DefaultSession session = idleSessionList.remove(0);
        session.withNetWorkServer(netWorkServer).withChannel(channel).withCommandDispatcher(commandDispatcher)
                .withSlaveWorker(SlaveWorker.fromChannel(session.getId(), "Session-" + session.getId(), channel));

        if (start) {
            session.start();
        }
        sessionMap.put(session.getId(), session);
        // ?
        listener.sessionAllocated(session);
        return session;
    }

    @Override
    public void freeSession(Session session) {
        DefaultSession ds = (DefaultSession) session;
        logger.warn(new StringBuilder("Free session : id = ").append(ds.getId()).append(", for : ")
                .append(ds.getSlaveWorker()).toString());
        sessionMap.remove(ds.getId());
        session.free();
        idleSessionList.add(ds);
        // ?
        listener.sessionReleased(session);
    }

    private void sessionRecycle() {
        logger.debug("=======Begin session recycle.=======");
        dump();
        Iterator<Long> iterator = sessionMap.keySet().iterator();
        DefaultSession session = null;
        while (iterator.hasNext()) {
            Long sessionId = iterator.next();
            session = sessionMap.get(sessionId);
            if (session == null) {
                continue;
            }

            if (session.isDead()) {
                iterator.remove();
                freeSession(session);
                //session.free();
                //idleSessionList.add(session);
                continue;
            }

            session.transit();
        }
        logger.debug("=======End session recycle.=========");
        dump();
    }

    private void dump() {
        Long key = null;
        DefaultSession session = null;
        Iterator<Long> iterator = sessionMap.keySet().iterator();
        logger.debug("Dump session state:");
        while (iterator.hasNext()) {
            key = iterator.next();
            session = sessionMap.get(key);
            if (session != null) {
                logger.debug(new StringBuilder("Session: ").append(session.getId()).append(" , State: ")
                        .append(session.getState().desc()).toString());
            }
        }
    }

    @Override
    public List<SessionState> generateSessionState() {
        SessionState sessionState = null;
        List<SessionState> sessionStateList = new LinkedList<SessionState>();
        Long key = null;
        Session session = null;
        Iterator<Long> iterator = sessionMap.keySet().iterator();
        while (iterator.hasNext()) {
            key = iterator.next();
            session = sessionMap.get(key);
            if (session != null && session.getState() != SessionStateEnum.WAVERIDER_SESSION_STATE_DEAD) {
                sessionState = new SessionState();
                sessionState.setIp(session.getSlaveWorker().getIp());
                sessionState.setPriority(computePriority(session));
                // FIXME
                sessionState.setIsMasterCandidate(false);
                sessionStateList.add(sessionState);
            }
        }

        return sessionStateList;
    }

    @Override
    public void registerSessionListener(SessionListener listener) {
        this.listener = listener;
    }

    /**
     * Slave??Master
     * @return
     */
    private Long computePriority(Session session) {
        return 0L;
    }

    private class SessionRecycleTask implements Runnable {
        public void run() {
            try {
                sessionRecycle();
            } catch (Exception e) {
                logger.error(e);
            }
        }
    }
}