/* * Copyright (c) 2009 - 2016 Deutsches Elektronen-Synchroton, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program (see the file COPYING.LIB for more * details); if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.dcache.xdr; import org.glassfish.grizzly.IOStrategy; import org.glassfish.grizzly.Transport; import org.glassfish.grizzly.filterchain.Filter; import org.glassfish.grizzly.nio.transport.TCPNIOTransport; import org.glassfish.grizzly.nio.transport.UDPNIOTransport; import org.glassfish.grizzly.strategies.LeaderFollowerNIOStrategy; import org.glassfish.grizzly.strategies.SameThreadIOStrategy; import org.glassfish.grizzly.strategies.WorkerThreadIOStrategy; import org.glassfish.grizzly.threadpool.ThreadPoolConfig; import static org.dcache.xdr.IoStrategy.*; import static com.google.common.base.Preconditions.checkArgument; /** * Class with utility methods for Grizzly */ public class GrizzlyUtils { /** * Minimal number of threads used by selector. */ final static int MIN_SELECTORS = 2; /** * Minimal number of threads used by for request execution. */ final static int MIN_WORKERS = 5; final static int CPUS = Runtime.getRuntime().availableProcessors(); private GrizzlyUtils(){} public static Filter rpcMessageReceiverFor(Transport t) { if (t instanceof TCPNIOTransport) { return new RpcMessageParserTCP(); } if (t instanceof UDPNIOTransport) { return new RpcMessageParserUDP(); } throw new RuntimeException("Unsupported transport: " + t.getClass().getName()); } public static Class< ? extends Transport> transportFor(int protocol) { switch(protocol) { case IpProtocolType.TCP: return TCPNIOTransport.class; case IpProtocolType.UDP: return UDPNIOTransport.class; } throw new RuntimeException("Unsupported protocol: " + protocol); } static private int getSelectorPoolSize(IoStrategy ioStrategy) { return ioStrategy == WORKER_THREAD ? Math.max(MIN_SELECTORS, CPUS / 4) : Math.max(MIN_WORKERS, CPUS); } static private int getWorkerPoolSize(IoStrategy ioStrategy) { return ioStrategy == WORKER_THREAD ? Math.max(MIN_WORKERS, (CPUS * 2)) : 0; } /** * Pre-configure Selectors thread pool for given {@link IOStrategy}, * {@code serviceName} and {@code poolSize}. If {@code poolSize} is zero, * then default value will be used. If {@code poolSize} is smaller than minimal * allowed number of threads, then {@link MIN_SELECTORS} will be used. * * @param ioStrategy to use * @param serviceName service name (affects thread names) * @param poolSize thread pool size. If zero, default thread pool is used. * @return thread pool configuration. */ static ThreadPoolConfig getSelectorPoolCfg(IoStrategy ioStrategy, String serviceName, int poolSize) { checkArgument(poolSize >= 0, "Negative thread pool size"); final int threadPoolSize = poolSize > 0 ? Math.max(poolSize, MIN_SELECTORS) : getSelectorPoolSize(ioStrategy); final ThreadPoolConfig poolCfg = ThreadPoolConfig.defaultConfig(); poolCfg.setCorePoolSize(threadPoolSize).setMaxPoolSize(threadPoolSize); if (serviceName != null) { poolCfg.setPoolName(serviceName); //grizzly will add "SelectorRunner" } return poolCfg; } /** * Pre-configure Worker thread pool for given {@link IOStrategy}, * {@code serviceName} and {@code poolSize}. If {@code poolSize} is zero, * then default value will be used. If {@code poolSize} is smaller than minimal * allowed number of threads, then {@link MIN_WORKERS} will be used. * * @param ioStrategy in use * @param serviceName service name (affects thread names) * @param poolSize thread pool size. If zero, default thread pool is used. * @return thread pool configuration or {@code null}, if ioStrategy don't * supports worker threads. */ static ThreadPoolConfig getWorkerPoolCfg(IoStrategy ioStrategy, String serviceName, int poolSize) { if (ioStrategy == SAME_THREAD) { return null; } checkArgument(poolSize >= 0, "Negative thread pool size"); final int threadPoolSize = poolSize > 0 ? Math.max(poolSize, MIN_WORKERS) : getWorkerPoolSize(ioStrategy); final ThreadPoolConfig poolCfg = ThreadPoolConfig.defaultConfig(); poolCfg.setCorePoolSize(threadPoolSize).setMaxPoolSize(threadPoolSize); if (serviceName != null) { poolCfg.setPoolName(serviceName + " Worker"); } return poolCfg; } static IOStrategy translate(IoStrategy ioStrategy) { switch (ioStrategy) { case SAME_THREAD: return SameThreadIOStrategy.getInstance(); case WORKER_THREAD: return WorkerThreadIOStrategy.getInstance(); case LEADER_FOLLOWER: return LeaderFollowerNIOStrategy.getInstance(); default: throw new UnsupportedOperationException("unhandled " + ioStrategy); } } }