class AsyncServer<T extends AsyncConnection> extends DelegatedProtocolServer
        implements AsyncConnectionManager {

    private final AtomicInteger connectionSize = new AtomicInteger();
    private SchedulerFactory schedulerFactory;
    private int serverId;

    public SchedulerFactory getSchedulerFactory() {
        return schedulerFactory;
    }

    public int getServerId() {
        return serverId;
    }

    @Override
    public void init(Map<String, String> config) {
        if (!config.containsKey("port"))
            config.put("port", String.valueOf(getDefaultPort()));
        if (!config.containsKey("name"))
            config.put("name", getName());
        serverId = AsyncServerManager.allocateServerId();
        AsyncServerManager.addServer(this);

        NetFactory factory = NetFactory.getFactory(config);
        NetServer netServer = factory.createNetServer();
        netServer.setConnectionManager(this);
        setProtocolServer(netServer);
        netServer.init(config);

        schedulerFactory = SchedulerFactory.initDefaultSchedulerFactory(GlobalScheduler.class.getName(),
                config);
    }

    @Override
    public synchronized void start() {
        if (isStarted())
            return;
        super.start();
        ProtocolServerEngine.startedServers.add(this);
        // 等所有的Server启动完成后再在Lealone.main中调用SchedulerFactory.start
        // 确保所有的初始PeriodicTask都在main线程中注册
    }

    @Override
    public void stop() {
        synchronized (this) {
            if (isStopped())
                return;
            super.stop();
            ProtocolServerEngine.startedServers.remove(this);
            AsyncServerManager.removeServer(this);
        }
        // 同步块不能包含下面的代码，否则执行System.exit时会触发ShutdownHook又调用到stop，
        // 而System.exit又需要等所有ShutdownHook结束后才能退出，所以就死锁了
        if (ProtocolServerEngine.startedServers.isEmpty()) {
            TransactionEngine.getDefaultTransactionEngine().close();
            schedulerFactory.stop();
            // 如果当前线程是ShutdownHook不能再执行System.exit，否则无法退出
            if (!Thread.currentThread().getName().contains("ShutdownHook"))
                System.exit(0);
        }
    }

    protected int getConnectionSize() {
        return connectionSize.get();
    }

    protected abstract int getDefaultPort();

    protected T createConnection(WritableChannel writableChannel, Scheduler scheduler) {
        throw DbException.getUnsupportedException("createConnection");
    }

    protected void beforeRegister(T conn, Scheduler scheduler) {
        // do nothing
    }

    protected void afterRegister(T conn, Scheduler scheduler) {
        // do nothing
    }

    protected void register(T conn, Scheduler scheduler, WritableChannel writableChannel) {<FILL_FUNCTION_BODY>}

    @Override
    public T createConnection(WritableChannel writableChannel, boolean isServer, Scheduler scheduler) {
        if (getAllowOthers() || allow(writableChannel.getHost())) {
            T conn = createConnection(writableChannel, scheduler);
            connectionSize.incrementAndGet();
            register(conn, scheduler, writableChannel);
            return conn;
        } else {
            writableChannel.close();
            throw DbException.get(ErrorCode.REMOTE_CONNECTION_NOT_ALLOWED);
        }
    }

    @Override
    public void removeConnection(AsyncConnection conn) {
        connectionSize.decrementAndGet();
        conn.close();
    }

    @Override
    public void registerAccepter(ServerSocketChannel serverChannel) {
        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.registerAccepter(this, serverChannel);
    }

    public boolean isRoundRobinAcceptEnabled() {
        return true;
    }
}

        beforeRegister(conn, scheduler);
        NetEventLoop eventLoop = (NetEventLoop) scheduler.getNetEventLoop();
        writableChannel.setEventLoop(eventLoop); // 替换掉原来的
        eventLoop.register(conn);
        afterRegister(conn, scheduler);
    
<methods>public non-sealed void <init>() ,public boolean allow(java.lang.String) ,public boolean getAllowOthers() ,public java.lang.String getBaseDir() ,public Map<java.lang.String,java.lang.String> getConfig() ,public java.lang.String getHost() ,public java.lang.String getName() ,public int getPort() ,public com.lealone.server.ProtocolServer getProtocolServer() ,public com.lealone.common.security.EncryptionOptions.ServerEncryptionOptions getServerEncryptionOptions() ,public int getSessionTimeout() ,public java.lang.String getType() ,public java.lang.String getURL() ,public void init(Map<java.lang.String,java.lang.String>) ,public boolean isDaemon() ,public boolean isSSL() ,public boolean isStarted() ,public boolean isStopped() ,public void setProtocolServer(com.lealone.server.ProtocolServer) ,public void setServerEncryptionOptions(com.lealone.common.security.EncryptionOptions.ServerEncryptionOptions) ,public void start() ,public void stop() <variables>protected com.lealone.server.ProtocolServer protocolServer