Java tutorial
/** LCG(Lunarion Consultant Group) Confidential * LCG LunarBase team is funded by LCG. * * @author LunarBase team, contacts: * feiben@lunarion.com * neo.carmack@lunarion.com * * The contents of this file are subject to the Lunarion Public License Version 1.0 * ("License"); You may not use this file except in compliance with the License. * The Original Code is: LunarBase source code * The LunarBase source code is managed by the development team at Lunarion.com. * The Initial Developer of the Original Code is the development team at Lunarion.com. * Portions created by lunarion are Copyright (C) lunarion. * All Rights Reserved. ******************************************************************************* * */ package lunarion.node; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Vector; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import org.apache.log4j.FileAppender; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.SimpleLayout; import LCG.DB.API.LunarDB; import LCG.DB.API.LunarTable; import LCG.DB.Local.NLP.FullText.Lexer.TokenizerForSearchEngine; import LCG.FSystem.Def.DBFSProperties; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.AdaptiveRecvByteBufAllocator; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import lunarion.db.local.Test.LunarServerHandlerTest; import lunarion.db.local.shell.CMDEnumeration; import lunarion.node.EDF.ExecutorCenter; import lunarion.node.EDF.ExecutorInterface; import lunarion.node.EDF.executors.AddFunctionalColumn; import lunarion.node.EDF.executors.CloseQueryResult; import lunarion.node.EDF.executors.CreateTable; import lunarion.node.EDF.executors.FTQuery; import lunarion.node.EDF.executors.FetchLog; import lunarion.node.EDF.executors.FetchQueryResultRecs; import lunarion.node.EDF.executors.FetchRecords; import lunarion.node.EDF.executors.FetchTableNamesWithSuffix; import lunarion.node.EDF.executors.FilterForWhereClause; import lunarion.node.EDF.executors.GetColumns; import lunarion.node.EDF.executors.Insert; import lunarion.node.EDF.executors.NotifySlavesUpdate; import lunarion.node.EDF.executors.RGQuery; import lunarion.node.EDF.executors.RecsCount; import lunarion.node.logger.LoggerFactory; import lunarion.node.logger.Timer; import lunarion.node.remote.protocol.CodeSucceed; import lunarion.node.replicator.DBReplicator; /* * the server part is modified from the Netty user-guild: * http://netty.io/wiki/user-guide-for-5.x.html */ public class LunarDBServerStandAlone { private Logger logger = null; /* * <db_name, LunarDB instance> */ private HashMap<String, LunarDB> db_map; private HashMap<String, DBReplicator> db_replicators; /* * <partition_name, queue of messages for this partition> */ private HashMap<String, BlockingQueue<String[]>> table_partition_notification_queue_map; /* * server processors */ private final int parallel = Runtime.getRuntime().availableProcessors(); int queue_upper_bound = 900; int queue_lower_bound = 100; protected ExecutorService thread_executor = Executors.newFixedThreadPool(parallel); EventLoopGroup bossGroup; EventLoopGroup workerGroup; private String server_root; private ExecutorCenter node_tc; /* private static class LunarServerInstatance { private static final LunarDBServerStandAlone g_server_instance = new LunarDBServerStandAlone(); } public static LunarDBServerStandAlone getInstance() { return LunarServerInstatance.g_server_instance; } */ public LunarDBServerStandAlone() { } public void startServer(String __svr_root, Logger _logger) throws IOException { if (!__svr_root.endsWith("/")) server_root = __svr_root + "/"; else server_root = __svr_root; logger = _logger; List<String> db_names = new ArrayList<String>(); File dir = new File(server_root); if (!dir.isDirectory()) { logger.info(Timer.currentTime() + " [NODE ERROR]: unable to start server at: " + server_root); logger.info(Timer.currentTime() + " [NODE ERROR]: the server root directory" + server_root + " is wrong, please start server with a correct directory"); throw new IOException("[NODE ERROR]: the server root directory" + server_root + " is wrong, please start server with a correct directory"); } else { File[] file_array = dir.listFiles(); if (file_array != null) { if (file_array.length == 0) { /* * do nothing, there is no db yet */ //System.out.println("[INFO]: there are no db on the server yet."); logger.info(Timer.currentTime() + " [NODE ERROR]:there are no db on the server yet."); } else { for (int i = 0; i < file_array.length; i++) { if (file_array[i].isDirectory()) { File db_i = new File(server_root + file_array[i].getName()); String conf = server_root + file_array[i].getName() + "/" + DBFSProperties.runtime_conf; File conf_file = new File(conf); if (!conf_file.exists()) { logger.info(Timer.currentTime() + " [NODE ERROR]: there is no db instance under this folder: " + server_root + file_array[i].getName()); } else { db_names.add(file_array[i].getName()); } } } } } } db_map = new HashMap<String, LunarDB>(); db_replicators = new HashMap<String, DBReplicator>(); table_partition_notification_queue_map = new HashMap<String, BlockingQueue<String[]>>(); for (int i = 0; i < db_names.size(); i++) { LunarDB i_db = new LunarDB(); String db_root = server_root + db_names.get(i).trim(); i_db.openDB(db_root); logger.info(Timer.currentTime() + " [NODE INFO]: database: " + i_db.dbName() + " is running now."); Iterator<String> tables = i_db.listTable(); while (tables.hasNext()) { String tt = tables.next(); Iterator<String> ft_cols = i_db.getTable(tt).getFulltextColumns(); while (ft_cols.hasNext()) { TokenizerForSearchEngine t_e = new TokenizerForSearchEngine(); i_db.getTable(tt).registerTokenizer(ft_cols.next(), t_e); } } DBReplicator replica = new DBReplicator(i_db); logger.info(Timer.currentTime() + " [NODE INFO]: database: " + i_db.dbName() + " has its replicator running now."); db_map.put(db_names.get(i).trim(), i_db); db_replicators.put(db_names.get(i).trim(), replica); } registerNodeExecutors(); bossGroup = new NioEventLoopGroup(); workerGroup = new NioEventLoopGroup(); } private void registerNodeExecutors() { node_tc = new ExecutorCenter(this, logger); node_tc.registerExecutor(CMDEnumeration.command.createTable, new CreateTable()); node_tc.registerExecutor(CMDEnumeration.command.notifySlavesUpdate, new NotifySlavesUpdate()); node_tc.registerExecutor(CMDEnumeration.command.addFulltextColumn, new AddFunctionalColumn(CMDEnumeration.command.addFulltextColumn)); node_tc.registerExecutor(CMDEnumeration.command.addAnalyticColumn, new AddFunctionalColumn(CMDEnumeration.command.addAnalyticColumn)); node_tc.registerExecutor(CMDEnumeration.command.addStorableColumn, new AddFunctionalColumn(CMDEnumeration.command.addStorableColumn)); node_tc.registerExecutor(CMDEnumeration.command.insert, new Insert()); node_tc.registerExecutor(CMDEnumeration.command.ftQuery, new FTQuery(node_tc.getResultMap())); node_tc.registerExecutor(CMDEnumeration.command.rgQuery, new RGQuery(node_tc.getResultMap())); node_tc.registerExecutor(CMDEnumeration.command.fetchQueryResultRecs, new FetchQueryResultRecs(node_tc.getResultMap())); node_tc.registerExecutor(CMDEnumeration.command.closeQueryResult, new CloseQueryResult(node_tc.getResultMap())); node_tc.registerExecutor(CMDEnumeration.command.fetchRecordsDESC, new FetchRecords(true)); node_tc.registerExecutor(CMDEnumeration.command.fetchRecordsASC, new FetchRecords(false)); node_tc.registerExecutor(CMDEnumeration.command.fetchLog, new FetchLog()); node_tc.registerExecutor(CMDEnumeration.command.fetchTableNamesWithSuffix, new FetchTableNamesWithSuffix()); node_tc.registerExecutor(CMDEnumeration.command.getColumns, new GetColumns()); node_tc.registerExecutor(CMDEnumeration.command.filterForWhereClause, new FilterForWhereClause(node_tc.getResultMap())); node_tc.registerExecutor(CMDEnumeration.command.recsCount, new RecsCount()); } public ExecutorCenter getExecutorCenter() { return this.node_tc; } public void closeServer() { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); thread_executor.shutdown(); Iterator<String> keys = db_map.keySet().iterator(); while (keys.hasNext()) { boolean dbclosed = false; String key = keys.next(); LunarDB db = db_map.get(key); try { db.closeDB(); dbclosed = true; db_replicators.get(key).close(); } catch (IOException e) { logger.info(Timer.currentTime() + " [NODE ERROR]: fail to close database: " + key); e.printStackTrace(); } if (dbclosed) logger.info( Timer.currentTime() + " [NODE INFO]: database " + key + " has been shutdown successfully"); } logger.info(Timer.currentTime() + " [NODE INFO]: server closed."); } public void bind(int port) throws InterruptedException { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, 1024, 65536 * 512)) .option(ChannelOption.SO_BACKLOG, 1024).option(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new LunarDBServerChannelInitializer(node_tc)); Channel ch = bootstrap.bind(port).sync().channel(); System.err.println(Timer.currentTime() + " DB node server channel binded at port: " + port + '.'); logger.info(Timer.currentTime() + " [NODE INFO]: DB node server channel binded at port: " + port + '.'); ch.closeFuture().sync(); /* * Bind and start to accept incoming connections. */ // ChannelFuture future = bootstrap.bind(port).sync(); /* * Wait until the server socket is closed. * In this example, this does not happen, but you can do that to gracefully * shut down your server. */ // future.channel().closeFuture().sync(); } public void submit(Runnable task) { thread_executor.submit(task); } public LunarDB getDBInstant(String db_name) { return this.db_map.get(db_name); } public void registerRoutinTableWatcherQueue(String partition_name, BlockingQueue<String[]> table_partirion_update_notification_queue) { table_partition_notification_queue_map.put(partition_name, table_partirion_update_notification_queue); } public void notifyUpdate(String partition_name, String[] update_db_and_table) { BlockingQueue<String[]> bq = table_partition_notification_queue_map.get(partition_name); if (bq != null) { logger.info("[NODE INFO]: start notifying slave on partition " + partition_name + " to update data from " + update_db_and_table[0] + "." + update_db_and_table[1]); bq.add(update_db_and_table); logger.info("[NODE INFO]: notified slave on partition " + partition_name + " to update data from " + update_db_and_table[0] + "." + update_db_and_table[1]); } else { System.err.println("[NODE ERROR]: the queue for accepting update notification must not be null."); logger.info("[NODE ERROR]: the queue for accepting update notification must not be null."); } } public static void main(String[] args) throws Exception { int port = 9090; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { } } String svr_root = "/home/feiben/DBTest/LunarNode/"; LunarDBServerStandAlone ldbssa = new LunarDBServerStandAlone(); ldbssa.startServer(svr_root, LoggerFactory.getLogger("LunarNode")); try { ldbssa.bind(port); } finally { ldbssa.closeServer(); } /* LunarDBServerStandAlone.getInstance().startServer(svr_root, LoggerFactory.getLogger("LunarNode")); try { LunarDBServerStandAlone.getInstance().bind(port); } finally { LunarDBServerStandAlone.getInstance().closeServer(); }*/ } }