final int fixedThreadCount() {
   if (isFixedThreadPool()) {
     return pool.poolSize();
   } else {
     return pool.poolSize() + internalThreadCount;
   }
 }
 /**
  * For a fixed thread pool the task is queued to a thread waiting on I/O events. For other thread
  * pools we simply submit the task to the thread pool.
  */
 final void executeOnPooledThread(Runnable task) {
   if (isFixedThreadPool()) {
     executeOnHandlerTask(task);
   } else {
     pool.executor().execute(bindToGroup(task));
   }
 }
  AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider, ThreadPool pool) {
    super(provider);
    this.pool = pool;

    if (pool.isFixedThreadPool()) {
      taskQueue = new ConcurrentLinkedQueue<Runnable>();
    } else {
      taskQueue = null; // not used
    }

    // use default thread factory as thread should not be visible to
    // application (it doesn't execute completion handlers).
    this.timeoutExecutor =
        (ScheduledThreadPoolExecutor)
            Executors.newScheduledThreadPool(1, ThreadPool.defaultThreadFactory());
    this.timeoutExecutor.setRemoveOnCancelPolicy(true);
  }
 protected final void startThreads(Runnable task) {
   if (!isFixedThreadPool()) {
     for (int i = 0; i < internalThreadCount; i++) {
       startInternalThread(task);
       threadCount.incrementAndGet();
     }
   }
   if (pool.poolSize() > 0) {
     task = bindToGroup(task);
     try {
       for (int i = 0; i < pool.poolSize(); i++) {
         pool.executor().execute(task);
         threadCount.incrementAndGet();
       }
     } catch (RejectedExecutionException x) {
       // nothing we can do
     }
   }
 }
 /** Invoked by tasks as they terminate */
 final int threadExit(Runnable task, boolean replaceMe) {
   if (replaceMe) {
     try {
       if (Invoker.isBoundToAnyGroup()) {
         // submit new task to replace this thread
         pool.executor().execute(bindToGroup(task));
       } else {
         // replace internal thread
         startInternalThread(task);
       }
       return threadCount.get();
     } catch (RejectedExecutionException x) {
       // unable to replace
     }
   }
   return threadCount.decrementAndGet();
 }
 final boolean isFixedThreadPool() {
   return pool.isFixedThreadPool();
 }
 final ExecutorService executor() {
   return pool.executor();
 }
 @Override
 public final boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
   return pool.executor().awaitTermination(timeout, unit);
 }
 @Override
 public final boolean isTerminated() {
   return pool.executor().isTerminated();
 }
  @Test(timeout = 20000)
  public void testUpdatingThreadPoolSettings() throws Exception {
    internalCluster().startNodesAsync(2).get();
    ThreadPool threadPool = internalCluster().getDataNodeInstance(ThreadPool.class);
    // Check that settings are changed
    assertThat(
        ((ThreadPoolExecutor) threadPool.executor(Names.SEARCH)).getKeepAliveTime(TimeUnit.MINUTES),
        equalTo(5L));
    client()
        .admin()
        .cluster()
        .prepareUpdateSettings()
        .setTransientSettings(settingsBuilder().put("threadpool.search.keep_alive", "10m").build())
        .execute()
        .actionGet();
    assertThat(
        ((ThreadPoolExecutor) threadPool.executor(Names.SEARCH)).getKeepAliveTime(TimeUnit.MINUTES),
        equalTo(10L));

    // Make sure that threads continue executing when executor is replaced
    final CyclicBarrier barrier = new CyclicBarrier(2);
    Executor oldExecutor = threadPool.executor(Names.SEARCH);
    threadPool
        .executor(Names.SEARCH)
        .execute(
            new Runnable() {
              @Override
              public void run() {
                try {
                  barrier.await();
                } catch (InterruptedException ex) {
                  Thread.currentThread().interrupt();
                } catch (BrokenBarrierException ex) {
                  //
                }
              }
            });
    client()
        .admin()
        .cluster()
        .prepareUpdateSettings()
        .setTransientSettings(settingsBuilder().put("threadpool.search.type", "fixed").build())
        .execute()
        .actionGet();
    assertThat(threadPool.executor(Names.SEARCH), not(sameInstance(oldExecutor)));
    assertThat(((ThreadPoolExecutor) oldExecutor).isShutdown(), equalTo(true));
    assertThat(((ThreadPoolExecutor) oldExecutor).isTerminating(), equalTo(true));
    assertThat(((ThreadPoolExecutor) oldExecutor).isTerminated(), equalTo(false));
    barrier.await();

    // Make sure that new thread executor is functional
    threadPool
        .executor(Names.SEARCH)
        .execute(
            new Runnable() {
              @Override
              public void run() {
                try {
                  barrier.await();
                } catch (InterruptedException ex) {
                  Thread.currentThread().interrupt();
                } catch (BrokenBarrierException ex) {
                  //
                }
              }
            });
    client()
        .admin()
        .cluster()
        .prepareUpdateSettings()
        .setTransientSettings(settingsBuilder().put("threadpool.search.type", "fixed").build())
        .execute()
        .actionGet();
    barrier.await();
    Thread.sleep(200);

    // Check that node info is correct
    NodesInfoResponse nodesInfoResponse =
        client().admin().cluster().prepareNodesInfo().all().execute().actionGet();
    for (int i = 0; i < 2; i++) {
      NodeInfo nodeInfo = nodesInfoResponse.getNodes()[i];
      boolean found = false;
      for (ThreadPool.Info info : nodeInfo.getThreadPool()) {
        if (info.getName().equals(Names.SEARCH)) {
          assertThat(info.getType(), equalTo("fixed"));
          found = true;
          break;
        }
      }
      assertThat(found, equalTo(true));

      Map<String, Object> poolMap =
          getPoolSettingsThroughJson(nodeInfo.getThreadPool(), Names.SEARCH);
    }
  }