public Server(File systemDir, boolean cachesInMemory) {
   Utils.setSystemRoot(systemDir);
   final ExecutorService threadPool = Executors.newCachedThreadPool();
   myScheduler =
       ConcurrencyUtil.newSingleScheduledThreadExecutor(
           "Client activity checker", Thread.MIN_PRIORITY);
   myBuildsExecutor = Executors.newFixedThreadPool(MAX_SIMULTANEOUS_BUILD_SESSIONS);
   myChannelFactory = new NioServerSocketChannelFactory(threadPool, threadPool, 1);
   final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
   myMessageHandler =
       new ServerMessageHandler(
           this,
           new AsyncTaskExecutor() {
             @Override
             public void submit(final Runnable runnable) {
               myBuildsExecutor.submit(
                   new Runnable() {
                     @Override
                     public void run() {
                       try {
                         runnable.run();
                       } finally {
                         Thread.interrupted(); // clear interrupted status before returning to pull
                       }
                     }
                   });
             }
           });
   myPipelineFactory =
       new ChannelPipelineFactory() {
         public ChannelPipeline getPipeline() throws Exception {
           return Channels.pipeline(
               channelRegistrar,
               new ProtobufVarint32FrameDecoder(),
               new ProtobufDecoder(JpsRemoteProto.Message.getDefaultInstance()),
               new ProtobufVarint32LengthFieldPrepender(),
               new ProtobufEncoder(),
               myMessageHandler);
         }
       };
   ServerState.getInstance().setKeepTempCachesInMemory(cachesInMemory);
   Runtime.getRuntime()
       .addShutdownHook(
           new Thread("Shutdown hook thread") {
             public void run() {
               try {
                 myMessageHandler.cancelAllBuildsAndClearState();
               } finally {
                 Server.this.stop();
               }
             }
           });
 }
  static {
    long ping = -1L;
    try {
      ping = Long.parseLong(System.getProperty(GlobalOptions.PING_INTERVAL_MS_OPTION, "-1"));
    } catch (NumberFormatException ignored) {
    }
    PING_INTERVAL = ping;

    int builds = 1;
    try {
      builds =
          Math.min(
              Integer.parseInt(
                  System.getProperty(GlobalOptions.MAX_SIMULTANEOUS_BUILDS_OPTION, "1")),
              Runtime.getRuntime().availableProcessors());
    } catch (NumberFormatException ignored) {
    }
    MAX_SIMULTANEOUS_BUILD_SESSIONS = builds;
  }
  public boolean bind(InetSocketAddress inetSocketAddress) {

    ServerSocketChannelFactory factory =
        new NioServerSocketChannelFactory(
            Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1),
            Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1));

    bootstrap = new ServerBootstrap(factory);

    class BlackBunnyChannelHandler extends SimpleChannelHandler {
      NetHandler netHandler;

      public BlackBunnyChannelHandler(NetHandler handler) {
        this.netHandler = handler;
      }

      @Override
      public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
          throws Exception {
        Session session = new Session(ctx.getChannel());
        netHandler.onConnected(session);
        ctx.setAttachment(session);
      }

      @Override
      public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        netHandler.onClosed((Session) ctx.getAttachment());
      }

      @Override
      public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        NetMessage message = (NetMessage) e.getMessage();
        message.setSession((Session) ctx.getAttachment());
        netHandler.messageReceived(message);
      }

      @Override
      public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        netHandler.exceptionCaught((Session) ctx.getAttachment(), e.getCause());
      }
    }

    bootstrap.setPipelineFactory(
        new ChannelPipelineFactory() {
          public ChannelPipeline getPipeline() throws Exception {
            return Channels.pipeline(
                new LengthFieldBasedFrameDecoder(8192, 0, 2, -2, 2),
                new DefaultMessageDecoder(),
                new LengthFieldPrepender(2, true),
                new DefaultMessageEncoder(),
                new BlackBunnyChannelHandler(netHandler));
          }
        });

    bootstrap.setOption("child.bufferFactory", new HeapChannelBufferFactory(NetByteOrder.order()));
    bootstrap.setOption("child.tcpNoDelay", true);
    bootstrap.setOption("child.keepAlive", true);

    bootstrap.bind(inetSocketAddress);

    logger.info("bind : {}", inetSocketAddress);

    return true;
  }