package org.wonderdb.server;
/*******************************************************************************
* Copyright 2013 Vilas Athavale
*
* 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.
*******************************************************************************/
import java.io.File;
import java.net.InetSocketAddress;
import java.sql.DriverManager;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.ChannelGroupFuture;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import org.wonderdb.cache.impl.CacheBean;
import org.wonderdb.cache.impl.CacheHandler;
import org.wonderdb.cache.impl.CacheLock;
import org.wonderdb.cache.impl.CacheState;
import org.wonderdb.cache.impl.CacheWriter;
import org.wonderdb.cache.impl.MemoryCacheMap;
import org.wonderdb.query.sql.WonderDBDriver;
import org.wonderdb.types.BlockPtr;
import org.wonderdb.types.record.Record;
public class WonderDBServer {
public static final int DEFAULT_BLOCK_SIZE = 2048;
static final ChannelGroup allServerChannels = new DefaultChannelGroup("wonderdb-server");
static final ChannelGroup allShardChannels = new DefaultChannelGroup("wonderdb-shard");
static boolean shutdown = false;
static Object lock = new Object();
static CacheBean primaryCacheBean = new CacheBean();
static CacheState primaryCacheState = new CacheState();
static MemoryCacheMap<BlockPtr, List<Record>> primaryCacheMap = new MemoryCacheMap<BlockPtr, List<Record>>(1000, 5, false);
static CacheLock cacheLock = new CacheLock();
static CacheBean secondaryCacheBean = new CacheBean();
static CacheState secondaryCacheState = new CacheState();
static MemoryCacheMap<BlockPtr, ChannelBuffer> secondaryCacheMap = new MemoryCacheMap<BlockPtr, ChannelBuffer>(1500, 5, true);
// static SecondaryCacheResourceProvider resourceProvider = null;
static int colId = -1;
static CacheHandler<BlockPtr, List<Record>> primaryCacheHandler = null;
static CacheHandler<BlockPtr, ChannelBuffer> secondaryCacheHandler = null;
public static CacheWriter<BlockPtr, ChannelBuffer> writer = null;
static {
File file = new File("./log4j.properties");
if (file.exists()) {
PropertyConfigurator.configure("./log4j.properties");
} else {
String val = System.getProperty("log4j.configuration");
file = null;
if (val != null && val.length() > 0) {
file = new File(val);
}
if (file != null && file.exists()) {
PropertyConfigurator.configure(val);
} else {
BasicConfigurator.configure();
}
}
}
public static void main(String[] args) throws Exception {
if (args == null || args.length != 1) {
System.out.println("Please provide init file at strartup");
Logger.getRootLogger().fatal("Please provide init file at strartup");
return;
}
WonderDBCacheService.getInstance().init(args[0]);
ExecutorService serverBoss = new ThreadPoolExecutor(WonderDBPropertyManager.getInstance().getNettyBossThreadPoolCoreSize(),
WonderDBPropertyManager.getInstance().getNettyBossThreadPoolMaxSize(), 5, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(WonderDBPropertyManager.getInstance().getNettyBossThreadPoolQueueSize())); // 10, 50, 5, 20
ExecutorService serverWorker = new ThreadPoolExecutor(WonderDBPropertyManager.getInstance().getNettyWorkerThreadPoolCoreSize(),
WonderDBPropertyManager.getInstance().getNettyWorkerThreadPoolMaxSize(), 5, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(WonderDBPropertyManager.getInstance().getNettyWorkerThreadPoolQueueSize())); // 10, 50, 5, 20
ChannelFactory serverFactory =
new NioServerSocketChannelFactory(
Executors.unconfigurableExecutorService(serverBoss),
Executors.unconfigurableExecutorService(serverWorker));
ServerBootstrap serverBootstrap = new ServerBootstrap(serverFactory);
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(new BufferDecoder(),
new WonderDBShardServerHandler(WonderDBShardServerHandler.SERVER_HANDLER));
}
});
serverBootstrap.setOption("child.tcpNoDelay", true);
serverBootstrap.setOption("child.keepAlive", true);
Channel serverChannel = serverBootstrap.bind(new InetSocketAddress(WonderDBPropertyManager.getInstance().getShardPort()));
allServerChannels.add(serverChannel);
ExecutorService shardBoss = new ThreadPoolExecutor(WonderDBPropertyManager.getInstance().getNettyBossThreadPoolCoreSize(),
WonderDBPropertyManager.getInstance().getNettyBossThreadPoolMaxSize(), 5, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(WonderDBPropertyManager.getInstance().getNettyBossThreadPoolQueueSize())); // 10, 50, 5, 20
ExecutorService shardWorker = new ThreadPoolExecutor(WonderDBPropertyManager.getInstance().getNettyWorkerThreadPoolCoreSize(),
WonderDBPropertyManager.getInstance().getNettyWorkerThreadPoolMaxSize(), 5, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(WonderDBPropertyManager.getInstance().getNettyWorkerThreadPoolQueueSize())); // 10, 50, 5, 20
ChannelFactory shardFactory =
new NioServerSocketChannelFactory(
Executors.unconfigurableExecutorService(shardBoss),
Executors.unconfigurableExecutorService(shardWorker));
ServerBootstrap shardBootstrap = new ServerBootstrap(shardFactory);
shardBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(new BufferDecoder(),
new WonderDBShardServerHandler(WonderDBShardServerHandler.SHARD_HANDLER));
}
});
shardBootstrap.setOption("child.tcpNoDelay", true);
shardBootstrap.setOption("child.keepAlive", true);
Channel shardChannel = shardBootstrap.bind(new InetSocketAddress(WonderDBPropertyManager.getInstance().getServerPort()));
allShardChannels.add(shardChannel);
// ExecutorService replicaSetBoss = new ThreadPoolExecutor(DreamDBPropertyManager.getInstance().getNettyBossThreadPoolCoreSize(),
// DreamDBPropertyManager.getInstance().getNettyBossThreadPoolMaxSize(), 5, TimeUnit.MINUTES,
// new ArrayBlockingQueue<Runnable>(DreamDBPropertyManager.getInstance().getNettyBossThreadPoolQueueSize())); // 10, 50, 5, 20
//
// ExecutorService replicaSetWorker = new ThreadPoolExecutor(DreamDBPropertyManager.getInstance().getNettyWorkerThreadPoolCoreSize(),
// DreamDBPropertyManager.getInstance().getNettyWorkerThreadPoolMaxSize(), 5, TimeUnit.MINUTES,
// new ArrayBlockingQueue<Runnable>(DreamDBPropertyManager.getInstance().getNettyWorkerThreadPoolQueueSize())); // 10, 50, 5, 20
//
// ChannelFactory replicaSetFactory =
// new NioServerSocketChannelFactory(
// Executors.unconfigurableExecutorService(replicaSetBoss),
// Executors.unconfigurableExecutorService(replicaSetWorker));
//
// ServerBootstrap replicaSetBootstrap = new ServerBootstrap(replicaSetFactory);
//
// replicaSetBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
// public ChannelPipeline getPipeline() {
// return Channels.pipeline(new BufferDecoder(),
// new DreamDBShardServerHandler(DreamDBShardServerHandler.REPLICASET_HANDLER));
// }
// });
//
// replicaSetBootstrap.setOption("child.tcpNoDelay", true);
// replicaSetBootstrap.setOption("child.keepAlive", true);
// Channel replicaSetChannel = shardBootstrap.bind(new InetSocketAddress(DreamDBPropertyManager.getInstance().getReplicaSetPort()));
// allChannels.add(replicaSetChannel);
DriverManager.registerDriver(new WonderDBDriver());
synchronized(lock) {
while (shutdown == false) {
try {
lock.wait();
} catch (Exception e) {
}
}
}
ChannelGroupFuture future = allServerChannels.close();
future = allServerChannels.close();
future.awaitUninterruptibly();
future = allShardChannels.close();
future.awaitUninterruptibly();
shardFactory.releaseExternalResources();
serverFactory.releaseExternalResources();
WonderDBCacheService.getInstance().shutdown();
}
public static class BufferDecoder extends FrameDecoder {
@Override
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
if (buffer.capacity() >= 4) {
buffer.resetReaderIndex();
int count = buffer.readInt();
buffer.resetReaderIndex();
if (buffer.capacity() < count+4) {
return null;
} else {
buffer.clear();
buffer.writerIndex(buffer.capacity());
buffer.readerIndex(4);
return buffer.readBytes(buffer.readableBytes());
}
}
return null;
}
}
}