package io.blobkeeper.server;
/*
* Copyright (C) 2015 by Denis M. Gabaydulin
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 com.google.common.util.concurrent.AbstractService;
import io.blobkeeper.cluster.service.ClusterMembershipService;
import io.blobkeeper.file.service.FileStorage;
import io.blobkeeper.server.configuration.ServerConfiguration;
import io.blobkeeper.server.initializer.BlobKeeperServerInitializer;
import io.blobkeeper.server.service.FileWriterService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import javax.inject.Inject;
import javax.inject.Singleton;
import static io.netty.channel.ChannelOption.*;
import static io.netty.channel.ChannelOption.ALLOCATOR;
@Singleton
public class BlobKeeperServer extends AbstractService {
@Inject
private BlobKeeperServerInitializer serverInitializer;
@Inject
private ServerConfiguration serverConfiguration;
@Inject
private FileWriterService fileWriterService;
@Inject
private ClusterMembershipService clusterMembershipService;
private ServerBootstrap bootstrap;
private ChannelFuture serverChannel;
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
@Override
protected void doStart() {
fileWriterService.start();
clusterMembershipService.start(serverConfiguration.getServerName());
bossGroup = new EpollEventLoopGroup();
// FIXME: add to config
workerGroup = new EpollEventLoopGroup(512);
bootstrap = new ServerBootstrap();
bootstrap.option(ALLOCATOR, PooledByteBufAllocator.DEFAULT);
bootstrap.group(bossGroup, workerGroup)
.channel(EpollServerSocketChannel.class)
.childHandler(serverInitializer);
bootstrap.childOption(SO_LINGER, -1);
bootstrap.childOption(TCP_NODELAY, true);
bootstrap.childOption(SO_REUSEADDR, true);
bootstrap.childOption(ALLOCATOR, PooledByteBufAllocator.DEFAULT);
bootstrap.childOption(EpollChannelOption.SO_REUSEPORT, true);
bootstrap.childOption(EpollChannelOption.TCP_CORK, true);
try {
serverChannel = bootstrap.bind(serverConfiguration.getServerPort()).sync();
notifyStarted();
} catch (InterruptedException e) {
notifyFailed(e);
throw new RuntimeException(e);
}
}
@Override
protected void doStop() {
if (null != serverChannel) {
// close server channel and incoming connections
serverChannel.channel().close();
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
fileWriterService.stop();
serverChannel = null;
clusterMembershipService.stop();
}
notifyStopped();
}
}