/*
 * 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.
 */

package org.apache.shardingsphere.proxy.frontend;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.proxy.backend.context.BackendExecutorContext;
import org.apache.shardingsphere.proxy.frontend.netty.ServerHandlerInitializer;

/**
 * ShardingSphere-Proxy.
 */
@Slf4j
public final class ShardingSphereProxy {
    
    private EventLoopGroup bossGroup;
    
    private EventLoopGroup workerGroup;
    
    /**
     * Start ShardingSphere-Proxy.
     *
     * @param port port
     */
    @SneakyThrows(InterruptedException.class)
    public void start(final int port) {
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bossGroup = createEventLoopGroup();
            if (bossGroup instanceof EpollEventLoopGroup) {
                groupsEpoll(bootstrap);
            } else {
                groupsNio(bootstrap);
            }
            ChannelFuture future = bootstrap.bind(port).sync();
            log.info("ShardingSphere-Proxy start success.");
            future.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
            BackendExecutorContext.getInstance().getExecutorKernel().close();
        }
    }
    
    private EventLoopGroup createEventLoopGroup() {
        return Epoll.isAvailable() ? new EpollEventLoopGroup(1) : new NioEventLoopGroup(1);
    }
    
    private void groupsEpoll(final ServerBootstrap bootstrap) {
        workerGroup = new EpollEventLoopGroup();
        bootstrap.group(bossGroup, workerGroup)
                .channel(EpollServerSocketChannel.class)
                .option(EpollChannelOption.SO_BACKLOG, 128)
                .option(EpollChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(8 * 1024 * 1024, 16 * 1024 * 1024))
                .option(EpollChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childOption(EpollChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childOption(EpollChannelOption.TCP_NODELAY, true)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ServerHandlerInitializer());
    }
    
    private void groupsNio(final ServerBootstrap bootstrap) {
        workerGroup = new NioEventLoopGroup();
        bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 128)
                .option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(8 * 1024 * 1024, 16 * 1024 * 1024))
                .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ServerHandlerInitializer());
    }
}

@@ -1142,58 +1142,8 @@
 ll;%0A
-import io.netty.channel.epoll.EpollChannelOption;%0A
 impo
@@ -2015,24 +2015,60 @@
       try %7B%0A
+            createEventLoopGroup();%0A
             
@@ -2134,216 +2134,39 @@
     
-bossGroup = createEventLoopGroup();%0A            if (bossGroup instanceof EpollEventLoopGroup) %7B%0A                groupsEpoll(bootstrap);%0A            %7D else %7B%0A                groupsNio(bootstrap);%0A            %7D
+initServerBootstrap(bootstrap);
 %0A   
@@ -2559,30 +2559,20 @@
 private 
-EventLoopGroup
+void
  createE
@@ -2601,14 +2601,19 @@
     
-return
+bossGroup =
  Epo
@@ -2694,908 +2694,183 @@
     
-%7D%0A
     
-%0A    private void g
+workerG
 roup
-s
+ = 
 Epoll
-(final ServerBootstrap bootstrap) %7B%0A        workerGroup = new EpollEventLoopGroup();%0A        bootstrap.group(bossGroup, workerGroup)%0A                .channel(EpollServerSocketChannel.class)%0A                .option(EpollChannelOption.SO_BACKLOG, 128)%0A                .option(EpollChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(8 * 1024 * 1024, 16 * 1024 * 1024))
+.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
 %0A    
-    
+%7D%0A
     
+%0A
     
-.option(EpollChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)%0A                .childOption(EpollChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)%0A                .childOption(EpollChannelOption.TCP_NODELAY, true)%0A                .handler(new LoggingHandler(LogLevel.INFO))%0A                .childHandler(new ServerHandlerInitializer());%0A    %7D%0A    %0A    private void groupsNio(final ServerBootstrap bootstrap) %7B%0A        workerGroup = new NioEventLoopGroup();
+private void initServerBootstrap(final ServerBootstrap bootstrap) %7B
 %0A   
@@ -2939,16 +2939,71 @@
 channel(
+Epoll.isAvailable() ? EpollServerSocketChannel.class : 
 NioServe

refactor proxy start (#7473)