/* * Copyright 1999-2012 Alibaba Group. * * 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.alibaba.cobar; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.log4j.Logger; import org.apache.log4j.helpers.LogLog; import com.alibaba.cobar.config.model.SystemConfig; import com.alibaba.cobar.manager.ManagerConnectionFactory; import com.alibaba.cobar.mysql.MySQLDataNode; import com.alibaba.cobar.net.NIOAcceptor; import com.alibaba.cobar.net.NIOConnector; import com.alibaba.cobar.net.NIOProcessor; import com.alibaba.cobar.parser.recognizer.mysql.lexer.MySQLLexer; import com.alibaba.cobar.server.ServerConnectionFactory; import com.alibaba.cobar.statistic.SQLRecorder; import com.alibaba.cobar.util.ExecutorUtil; import com.alibaba.cobar.util.NameableExecutor; import com.alibaba.cobar.util.TimeUtil; /** * @author xianmao.hexm 2011-4-19 下午02:58:59 */ public class CobarServer { public static final String NAME = "Cobar"; private static final long LOG_WATCH_DELAY = 60000L; private static final long TIME_UPDATE_PERIOD = 20L; private static final CobarServer INSTANCE = new CobarServer(); private static final Logger LOGGER = Logger.getLogger(CobarServer.class); public static final CobarServer getInstance() { return INSTANCE; } private final CobarConfig config; private final Timer timer; private final NameableExecutor managerExecutor; private final NameableExecutor timerExecutor; private final NameableExecutor initExecutor; private final SQLRecorder sqlRecorder; private final AtomicBoolean isOnline; private final long startupTime; private NIOProcessor[] processors; private NIOConnector connector; private NIOAcceptor manager; private NIOAcceptor server; private CobarServer() { this.config = new CobarConfig(); SystemConfig system = config.getSystem(); MySQLLexer.setCStyleCommentVersion(system.getParserCommentVersion()); this.timer = new Timer(NAME + "Timer", true); this.initExecutor = ExecutorUtil.create("InitExecutor", system.getInitExecutor()); this.timerExecutor = ExecutorUtil.create("TimerExecutor", system.getTimerExecutor()); this.managerExecutor = ExecutorUtil.create("ManagerExecutor", system.getManagerExecutor()); this.sqlRecorder = new SQLRecorder(system.getSqlRecordCount()); this.isOnline = new AtomicBoolean(true); this.startupTime = TimeUtil.currentTimeMillis(); } public CobarConfig getConfig() { return config; } public void beforeStart(String dateFormat) { String home = System.getProperty("cobar.home"); if (home == null) { SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); LogLog.warn(sdf.format(new Date()) + " [cobar.home] is not set."); } else { Log4jInitializer.configureAndWatch(home + "/conf/log4j.xml", LOG_WATCH_DELAY); } } public void startup() throws IOException { // server startup LOGGER.info("==============================================="); LOGGER.info(NAME + " is ready to startup ..."); SystemConfig system = config.getSystem(); timer.schedule(updateTime(), 0L, TIME_UPDATE_PERIOD); // startup processors LOGGER.info("Startup processors ..."); int handler = system.getProcessorHandler(); int executor = system.getProcessorExecutor(); int committer = system.getProcessorCommitter(); processors = new NIOProcessor[system.getProcessors()]; for (int i = 0; i < processors.length; i++) { processors[i] = new NIOProcessor("Processor" + i, handler, executor, committer); processors[i].startup(); } timer.schedule(processorCheck(), 0L, system.getProcessorCheckPeriod()); // startup connector LOGGER.info("Startup connector ..."); connector = new NIOConnector(NAME + "Connector"); connector.setProcessors(processors); connector.start(); // init dataNodes Map<String, MySQLDataNode> dataNodes = config.getDataNodes(); LOGGER.info("Initialize dataNodes ..."); for (MySQLDataNode node : dataNodes.values()) { node.init(1, 0); } timer.schedule(dataNodeIdleCheck(), 0L, system.getDataNodeIdleCheckPeriod()); timer.schedule(dataNodeHeartbeat(), 0L, system.getDataNodeHeartbeatPeriod()); // startup manager ManagerConnectionFactory mf = new ManagerConnectionFactory(); mf.setCharset(system.getCharset()); mf.setIdleTimeout(system.getIdleTimeout()); manager = new NIOAcceptor(NAME + "Manager", system.getManagerPort(), mf); manager.setProcessors(processors); manager.start(); LOGGER.info(manager.getName() + " is started and listening on " + manager.getPort()); // startup server ServerConnectionFactory sf = new ServerConnectionFactory(); sf.setCharset(system.getCharset()); sf.setIdleTimeout(system.getIdleTimeout()); server = new NIOAcceptor(NAME + "Server", system.getServerPort(), sf); server.setProcessors(processors); server.start(); timer.schedule(clusterHeartbeat(), 0L, system.getClusterHeartbeatPeriod()); // server started LOGGER.info(server.getName() + " is started and listening on " + server.getPort()); LOGGER.info("==============================================="); } public NIOProcessor[] getProcessors() { return processors; } public NIOConnector getConnector() { return connector; } public NameableExecutor getManagerExecutor() { return managerExecutor; } public NameableExecutor getTimerExecutor() { return timerExecutor; } public NameableExecutor getInitExecutor() { return initExecutor; } public SQLRecorder getSqlRecorder() { return sqlRecorder; } public long getStartupTime() { return startupTime; } public boolean isOnline() { return isOnline.get(); } public void offline() { isOnline.set(false); } public void online() { isOnline.set(true); } // 系统时间定时更新任务 private TimerTask updateTime() { return new TimerTask() { @Override public void run() { TimeUtil.update(); } }; } // 处理器定时检查任务 private TimerTask processorCheck() { return new TimerTask() { @Override public void run() { timerExecutor.execute(new Runnable() { @Override public void run() { for (NIOProcessor p : processors) { p.check(); } } }); } }; } // 数据节点定时连接空闲超时检查任务 private TimerTask dataNodeIdleCheck() { return new TimerTask() { @Override public void run() { timerExecutor.execute(new Runnable() { @Override public void run() { Map<String, MySQLDataNode> nodes = config.getDataNodes(); for (MySQLDataNode node : nodes.values()) { node.idleCheck(); } Map<String, MySQLDataNode> _nodes = config.getBackupDataNodes(); if (_nodes != null) { for (MySQLDataNode node : _nodes.values()) { node.idleCheck(); } } } }); } }; } // 数据节点定时心跳任务 private TimerTask dataNodeHeartbeat() { return new TimerTask() { @Override public void run() { timerExecutor.execute(new Runnable() { @Override public void run() { Map<String, MySQLDataNode> nodes = config.getDataNodes(); for (MySQLDataNode node : nodes.values()) { node.doHeartbeat(); } } }); } }; } // 集群节点定时心跳任务 private TimerTask clusterHeartbeat() { return new TimerTask() { @Override public void run() { timerExecutor.execute(new Runnable() { @Override public void run() { Map<String, CobarNode> nodes = config.getCluster().getNodes(); for (CobarNode node : nodes.values()) { node.doHeartbeat(); } } }); } }; } }