| /*=============================================================================# |
| # Copyright (c) 2009, 2019 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.rj.servi; |
| |
| import java.rmi.Remote; |
| import java.rmi.server.RMIClientSocketFactory; |
| import java.rmi.server.RMIServerSocketFactory; |
| import java.rmi.server.UnicastRemoteObject; |
| import java.util.Collection; |
| import java.util.NoSuchElementException; |
| |
| import javax.rmi.ssl.SslRMIClientSocketFactory; |
| import javax.rmi.ssl.SslRMIServerSocketFactory; |
| |
| import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet; |
| import org.eclipse.statet.jcommons.rmi.RMIRegistry; |
| |
| import org.eclipse.statet.rj.RjException; |
| import org.eclipse.statet.rj.RjInitFailedException; |
| import org.eclipse.statet.rj.server.ServerLogin; |
| import org.eclipse.statet.rj.servi.RServi; |
| import org.eclipse.statet.rj.servi.node.RServiNodeFactory; |
| import org.eclipse.statet.rj.servi.node.RServiPool; |
| import org.eclipse.statet.rj.servi.pool.PoolConfig; |
| import org.eclipse.statet.rj.servi.pool.PoolNodeObject; |
| import org.eclipse.statet.rj.servi.pool.RServiPoolManager; |
| |
| |
| public class PoolManager implements RServiPool, RServiPoolManager { |
| |
| |
| private final String id; |
| |
| private final RMIRegistry registry; |
| |
| private Remote thisRemote; |
| |
| private APool2 pool; |
| private APool2NodeFactory poolFactory; |
| private PoolConfig poolConfig; |
| |
| private NodeFactory nodeFactory; |
| |
| private final CopyOnWriteIdentityListSet<PoolListener> poolListeners= new CopyOnWriteIdentityListSet<>(); |
| private final Stats stats; |
| |
| |
| public PoolManager(final String id, final RMIRegistry registry) { |
| if (id == null || registry == null) { |
| throw new NullPointerException(); |
| } |
| this.id= id; |
| this.registry= registry; |
| this.stats= new Stats(); |
| this.poolListeners.add(this.stats); |
| this.poolConfig= new PoolConfig(); |
| |
| Utils.preLoad(); |
| } |
| |
| |
| @Override |
| public String getId() { |
| return this.id; |
| } |
| |
| @Override |
| public NodeFactory getFactories() { |
| return this.nodeFactory; |
| } |
| |
| @Override |
| public synchronized void addNodeFactory(final RServiNodeFactory factory) { |
| this.nodeFactory= (NodeFactory) factory; |
| } |
| |
| @Override |
| public synchronized void setConfig(final PoolConfig config) { |
| if (this.pool != null) { |
| this.pool.setConfig(config); |
| this.poolFactory.setMaxUsageCount(config.getMaxUsageCount()); |
| } |
| this.poolConfig= config; |
| } |
| |
| @Override |
| public PoolConfig getConfig() { |
| return this.poolConfig; |
| } |
| |
| public void addPoolListener(final PoolListener listener) { |
| this.poolListeners.add(listener); |
| } |
| |
| public void removePoolListener(final PoolListener listener) { |
| this.poolListeners.remove(listener); |
| } |
| |
| @Override |
| public synchronized void init() throws RjException { |
| this.poolFactory= new APool2NodeFactory(this.nodeFactory, this.poolListeners); |
| this.poolFactory.setMaxUsageCount(this.poolConfig.getMaxUsageCount()); |
| this.pool= new APool2(this.poolFactory, this.poolConfig); |
| |
| Utils.logInfo("Publishing pool in registry..."); |
| if (this.registry != null) { |
| RMIClientSocketFactory clientSocketFactory= null; |
| RMIServerSocketFactory serverSocketFactory= null; |
| if (this.registry.getAddress().isSsl()) { |
| clientSocketFactory= new SslRMIClientSocketFactory(); |
| serverSocketFactory= new SslRMIServerSocketFactory(null, null, true); |
| } |
| try { |
| this.thisRemote= UnicastRemoteObject.exportObject(this, 0, |
| clientSocketFactory, serverSocketFactory ); |
| this.registry.getRegistry().rebind(PoolConfig.getPoolName(this.id), this.thisRemote); |
| } |
| catch (final Exception e) { |
| try { |
| stop(8); |
| } |
| catch (final Exception ignore) {} |
| Utils.logError("An error occurred when binding the pool in the registry.", e); |
| throw new RjInitFailedException("An error occurred when publishing the pool in the registry."); |
| } |
| } |
| } |
| |
| @Override |
| public Collection<? extends PoolNodeObject> getPoolNodeObjects() { |
| return this.poolFactory.getAllObjects(); |
| } |
| |
| public boolean isInitialized() { |
| return (this.thisRemote != null); |
| } |
| |
| @Override |
| public synchronized void stop(final int mode) throws RjException { |
| Utils.logInfo("Unpublishing pool..."); |
| if (this.registry != null) { |
| try { |
| this.registry.getRegistry().unbind(PoolConfig.getPoolName(this.id)); |
| } |
| catch (final Exception e) { |
| if (mode != 8) { |
| Utils.logError("An error occurred when unbinding the pool from the registry.", e); |
| } |
| } |
| } |
| if (this.thisRemote != null) { |
| try { |
| this.thisRemote= null; |
| UnicastRemoteObject.unexportObject(this, true); |
| } |
| catch (final Exception e) { |
| if (mode != 8) { |
| Utils.logError("An error occurred when unexport the pool.", e); |
| } |
| } |
| } |
| |
| try { |
| Thread.sleep(1000); |
| } |
| catch (final InterruptedException e) { |
| } |
| if (PoolManager.this.pool != null) { |
| Utils.logInfo("Closing R nodes..."); |
| try { |
| PoolManager.this.pool.close(this.poolConfig.getEvictionTimeout()); |
| } |
| catch (final Exception e) { |
| Utils.logError("An error occurred when closing the pool.", e); |
| } |
| finally { |
| Runtime.getRuntime().gc(); |
| } |
| } |
| } |
| |
| @Override |
| public RServi getRServi(final String name, final ServerLogin login) throws NoSuchElementException, RjException { |
| final APool2NodeHandler handler= getPoolObject(name); |
| return new RServiImpl(handler.getAccessId(), handler, handler.getClientHandler()); |
| } |
| |
| public APool2NodeHandler getPoolObject(final String client) throws NoSuchElementException, RjException { |
| try { |
| return this.pool.borrowObject(client); |
| } |
| catch (final NoSuchElementException e) { |
| this.stats.logServRequestFailed(3); |
| throw new NoSuchElementException(Messages.GetRServi_NoInstance_pub_Pool_message); |
| } |
| catch (final Exception e) { |
| this.stats.logServRequestFailed(4); |
| Utils.logError(Messages.BindClient_error_message, e); |
| throw new RjException(Messages.GetRServi_pub_error_message); |
| } |
| } |
| |
| @Override |
| public RServiPoolManager.Counter getCounter() { |
| final RServiPoolManager.Counter counter= new RServiPoolManager.Counter(); |
| synchronized (this.pool) { |
| counter.numIdling= this.pool.getNumIdle(); |
| counter.numInUse= this.pool.getNumActive(); |
| counter.numTotal= counter.numIdling + counter.numTotal; |
| counter.maxIdling= -1; |
| counter.maxInUse= this.poolFactory.getStatMaxAllocated(); |
| counter.maxTotal= this.poolFactory.getStatMaxTotal(); |
| } |
| return counter; |
| } |
| |
| } |