/* * 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 com.google.common.util.concurrent.MoreExecutors; import org.dcache.xdr.gss.GssSessionManager; import org.glassfish.grizzly.threadpool.FixedThreadPool; import org.glassfish.grizzly.threadpool.ThreadPoolConfig; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import static com.google.common.base.Preconditions.checkArgument; import static org.dcache.xdr.GrizzlyUtils.getWorkerPoolCfg; import static org.dcache.xdr.IpProtocolType.*; /** * A builder of {@link OncRpcSvc} instance having any combination of: * <ul> * <li>protocol type</li> * <li>min port number</li> * <li>max port number</li> * <li>autopublish</li> * </ul> * * Usage example: * <pre> * OncRpcSvc svc = new OncRpcSvcBuilder() * .withMinPort(2400) * .withMaxPort(2500) * .withTCP() * .withUDP() * .withAutoPublish() * .withRpcService(program1, service1) * .withRpcService(program3, service2) * .withWorkerThreadPoolSize(64) * .build(); * </pre> * @since 2.0 */ public class OncRpcSvcBuilder { private int _protocol = 0; private int _minPort = 0; private int _maxPort = 0; private boolean _autoPublish = true; private IoStrategy _ioStrategy = IoStrategy.SAME_THREAD; private boolean _withJMX = false; private int _backlog = 4096; private String _bindAddress = "0.0.0.0"; private String _serviceName = "OncRpcSvc"; private GssSessionManager _gssSessionManager; private ExecutorService _workerThreadExecutionService; private boolean _isClient = false; private final Map<OncRpcProgram, RpcDispatchable> _programs = new HashMap<>(); private int _selectorThreadPoolSize = 0; private int _workerThreadPoolSize = 0; private boolean _subjectPropagation = false; public OncRpcSvcBuilder withAutoPublish() { _autoPublish = true; return this; } public OncRpcSvcBuilder withoutAutoPublish() { _autoPublish = false; return this; } public OncRpcSvcBuilder withMaxPort(int maxPort) { checkArgument(maxPort >= 0, "Illegal max port value"); _maxPort = maxPort; _minPort = Math.min(_minPort, _maxPort); return this; } public OncRpcSvcBuilder withMinPort(int minPort) { checkArgument(minPort >= 0, "Illegal min port value"); _minPort = minPort; _maxPort = Math.max(_minPort, _maxPort); return this; } public OncRpcSvcBuilder withPort(int port) { checkArgument(port >= 0, "Illegal port value"); _minPort = _maxPort = port; return this; } public OncRpcSvcBuilder withTCP() { _protocol |= TCP; return this; } public OncRpcSvcBuilder withUDP() { _protocol |= UDP; return this; } public OncRpcSvcBuilder withIpProtocolType(int protocolType) { _protocol = protocolType; return this; } public OncRpcSvcBuilder withSameThreadIoStrategy() { _ioStrategy = IoStrategy.SAME_THREAD; return this; } public OncRpcSvcBuilder withSelectorThreadPoolSize(int threadPoolSize) { checkArgument(threadPoolSize > 0, "thread pool size must be positive"); _selectorThreadPoolSize = threadPoolSize; return this; } public OncRpcSvcBuilder withWorkerThreadIoStrategy() { _ioStrategy = IoStrategy.WORKER_THREAD; return this; } public OncRpcSvcBuilder withWorkerThreadPoolSize(int threadPoolSize) { checkArgument(threadPoolSize > 0, "thread pool size must be positive"); _workerThreadPoolSize = threadPoolSize; return this; } public OncRpcSvcBuilder withIoStrategy(IoStrategy ioStrategy) { _ioStrategy = ioStrategy; return this; } public OncRpcSvcBuilder withJMX() { _withJMX = true; return this; } public OncRpcSvcBuilder withBacklog(int backlog) { _backlog = backlog; return this; } public OncRpcSvcBuilder withBindAddress(String address) { _bindAddress = address; return this; } public OncRpcSvcBuilder withServiceName(String serviceName) { _serviceName = serviceName; return this; } public OncRpcSvcBuilder withGssSessionManager(GssSessionManager gssSessionManager) { _gssSessionManager = gssSessionManager; return this; } public OncRpcSvcBuilder withWorkerThreadExecutionService(ExecutorService executorService) { _workerThreadExecutionService = executorService; return this; } public OncRpcSvcBuilder withClientMode() { _isClient = true; return this; } public OncRpcSvcBuilder withRpcService(OncRpcProgram program, RpcDispatchable service) { _programs.put(program, service); return this; } public OncRpcSvcBuilder withSubjectPropagation() { _subjectPropagation = true; return this; } public OncRpcSvcBuilder withoutSubjectPropagation() { _subjectPropagation = false; return this; } public boolean getSubjectPropagation() { return _subjectPropagation; } public int getProtocol() { return _protocol; } public int getMinPort() { return _minPort; } public int getMaxPort() { return _maxPort; } public boolean isAutoPublish() { return _autoPublish; } public IoStrategy getIoStrategy() { return _ioStrategy; } public boolean isWithJMX() { return _withJMX; } public int getBacklog() { return _backlog; } public String getBindAddress() { return _bindAddress; } public String getServiceName() { return _serviceName; } public GssSessionManager getGssSessionManager() { return _gssSessionManager; } public ExecutorService getWorkerThreadExecutorService() { if (_ioStrategy == IoStrategy.SAME_THREAD ) { return MoreExecutors.newDirectExecutorService(); } if (_workerThreadExecutionService != null) { return _workerThreadExecutionService; } ThreadPoolConfig workerPoolConfig = getWorkerPoolCfg(_ioStrategy, _serviceName, _workerThreadPoolSize); return new FixedThreadPool(workerPoolConfig); } public int getSelectorThreadPoolSize() { return _selectorThreadPoolSize; } public int getWorkerThreadPoolSize() { return _workerThreadPoolSize; } public boolean isClient() { return _isClient; } public Map<OncRpcProgram, RpcDispatchable> getRpcServices() { return _programs; } public OncRpcSvc build() { if (_protocol == 0 || (((_protocol & TCP) != TCP) && ((_protocol & UDP) != UDP))) { throw new IllegalArgumentException("invalid protocol: " + _protocol); } if (_isClient && (_protocol == (TCP | UDP)) ) { throw new IllegalArgumentException("Client mode can't be TCP and UDP at the same time"); } if (_isClient && (_maxPort != _minPort)) { throw new IllegalArgumentException("Can't use port range in client mode"); } if (_workerThreadExecutionService != null && _workerThreadPoolSize > 0) { throw new IllegalArgumentException("Can't set worker thread pool size with external execution service"); } return new OncRpcSvc(this); } }