package com.alibaba.doris.dataserver;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.doris.dataserver.config.ConfigureLoaderException;
import com.alibaba.doris.dataserver.config.DataServerConfigure;
import com.alibaba.doris.dataserver.config.XMLDataServerConfigureLoader;
import com.alibaba.doris.dataserver.config.data.ModuleConfigure;
import com.alibaba.doris.dataserver.core.DefaultApplicationContext;
import com.alibaba.doris.dataserver.core.DefaultModuleContext;
import com.alibaba.doris.dataserver.event.EventListenerManager;
import com.alibaba.doris.dataserver.event.server.DataServerEventListener;
import com.alibaba.doris.dataserver.event.server.ShutdownEvent;
import com.alibaba.doris.dataserver.event.server.StartupEvent;
import com.alibaba.doris.dataserver.tools.DataServerJVMShutdownHook;
/**
* @author ajun Email:jack.yuj@alibaba-inc.com
*/
public class DataServerApp implements DataServerEventListener {
public DataServerApp() {
}
public DataServerApp(String[] args) {
try {
DataServerConfigure conf = processArguments(args);
loadModules(conf);
initApplicationContext(conf);
// initializing all modules.
initModules(conf);
EventListenerManager eventListenerManager = appContext.getEventListenerManager();
eventListenerManager.registEventListener(this);
// Everything is okay, now we send an event to notify all listener that the data server has started.
eventListenerManager.fireEvent(new StartupEvent());
addJVMHook();
} catch (Throwable e) {
logger.error("Start DataServer failed!", e);
// To kill all threads.
System.exit(0);
} finally {
}
}
/**
* @param args
*/
public static void main(String[] args) {
new DataServerApp(args);
}
/**
* 从配置文件中装载所有的Module
*
* @param conf
*/
public void loadModules(DataServerConfigure conf) {
List<ModuleConfigure> moduleConfigList = conf.getModuleConfigList();
for (ModuleConfigure moduleConfig : moduleConfigList) {
Module module = createModule(moduleConfig);
if (module instanceof BaseModule) {
((BaseModule) module).setName(moduleConfig.getName());
}
modules.add(module);
}
}
private DataServerConfigure processArguments(String[] args) {
Properties commandLine = parseCommandLineArguments(args);
DataServerConfigure conf = loadDataServerConfigure(commandLine.getProperty(CONFIG_ITEM_CONFIG_FILE));
conf.setCommandLine(commandLine);
return conf;
}
private Properties parseCommandLineArguments(String[] args) {
String configureFile = DEFAULT_CONFIGURE_FILE;
Properties commandLine = new Properties();
try {
String logRoot = DEFAULT_LOG_ROOT;
String logLevel = DEFAULT_LOGLEVEL;
if (args.length > 0) {
for (int i = 0; i < args.length; i += 2) {
String name = args[i];
String value = null;
if (args.length > (i + 1)) {
value = args[i + 1];
}
if (StringUtils.isBlank(name)) {
continue;
}
// -help 去掉前面的“-”
name = name.substring(1);
commandLine.setProperty(name, value);
if (CONFIG_ITEM_CONFIG_FILE.equalsIgnoreCase(name)) {
configureFile = value;
} else if (CONFIG_ITEM_HELP.equalsIgnoreCase(name)) {
printUsage();
} else if (CONFIG_ITEM_LOG_ROOT.equals(name)) {
logRoot = value;
System.out.println("Use logConfig:" + logRoot);
} else if (CONFIG_ITEM_LOG_LEVEL.equals(name)) {
logLevel = value;
System.out.println("Use logLevel:" + logLevel);
}
}
}
System.setProperty("logRoot", logRoot);
System.setProperty("logLevel", logLevel);
logger = LoggerFactory.getLogger(DataServerApp.class);
} catch (Throwable e) {
printUsage();
System.exit(0);
}
commandLine.setProperty(CONFIG_ITEM_CONFIG_FILE, configureFile);
return commandLine;
}
private DataServerConfigure loadDataServerConfigure(String configureFile) {
try {
XMLDataServerConfigureLoader loader = new XMLDataServerConfigureLoader(configureFile);
return loader.load();
} catch (DocumentException e) {
throw new ConfigureLoaderException(e);
}
}
private void addJVMHook() {
DataServerJVMShutdownHook hook = new DataServerJVMShutdownHook(appContext);
appContext.getEventListenerManager().registEventListener(hook);
Runtime.getRuntime().addShutdownHook(hook);
}
private void initApplicationContext(DataServerConfigure conf) {
this.appContext = new DefaultApplicationContext(modules);
this.appContext.setEventListenerManager(new EventListenerManager());
this.appContext.setDataServerConfigure(conf);
}
private static void printUsage() {
System.out.println("Usage: -configFile, setting the config file of Data server.");
System.out.println(" -port , setting the listening port. Forexample: -port 8080");
System.exit(0);
}
private Module createModule(ModuleConfigure moduleConfig) {
String moduleClassName = moduleConfig.getClassName();
Module module = null;
try {
if (StringUtils.isNotBlank(moduleClassName)) {
ClassLoader classLoader = this.getClass().getClassLoader();
Class<?> clazz = classLoader.loadClass(moduleClassName);
module = (Module) clazz.newInstance();
}
} catch (Exception e) {
throw new FatalModuleInitializationException("Creating module failed! Module name:" + moduleClassName, e);
}
return module;
}
/**
* Initializing all modules.
*
* @param conf
*/
public void initModules(DataServerConfigure conf) {
for (Module module : modules) {
long startTime = System.currentTimeMillis();
ModuleContext moduleContext = new DefaultModuleContext(appContext);
appContext.addModuleContext(module, moduleContext);
if (module instanceof ModuleContextAware) {
ModuleContextAware mca = (ModuleContextAware) module;
mca.setModuleContext(moduleContext);
}
module.load(conf.getModuleConfigure(module.getClass().getName()));
if (logger.isInfoEnabled()) {
logger.info("Loading " + module.getName() + " SUCCESS. Time consuming(ms):"
+ (System.currentTimeMillis() - startTime));
}
}
}
public void destoryModules() {
int moduleCount = modules.size();
for (int index = moduleCount; index > 0; index--) {
long startTime = System.currentTimeMillis();
Module module = modules.get(index - 1);
try {
module.unload();
if (logger.isInfoEnabled()) {
logger.info("Unloading " + module.getName() + " SUCCESS. Time consuming(ms):"
+ (System.currentTimeMillis() - startTime));
}
} catch (Throwable e) {
// 出现异常,只影响某个模块的卸载。
logger.error("Unloading " + module.getName() + " FAILURE!", e);
}
}
}
public void onShutdown() {
destoryModules();
}
public void onStartup() {
System.out.println("DataServer is ready!");
if (logger.isDebugEnabled()) {
logger.debug("DataServer is ready!");
}
}
public void shutdown() {
EventListenerManager eventListenerManager = appContext.getEventListenerManager();
eventListenerManager.fireEvent(new ShutdownEvent());
}
private static Logger logger;
private DefaultApplicationContext appContext;
private List<Module> modules = new ArrayList<Module>();
private static final String DEFAULT_CONFIGURE_FILE = "dataserver.xml";
private static final String DEFAULT_LOG_ROOT = "log";
private static final String DEFAULT_LOGLEVEL = "INFO";
private static final String CONFIG_ITEM_CONFIG_FILE = "configFile";
private static final String CONFIG_ITEM_LOG_ROOT = "logRoot";
private static final String CONFIG_ITEM_LOG_LEVEL = "logLevel";
private static final String CONFIG_ITEM_HELP = "help";
}