blob: 1a32b8575fed4873b19adf0c75f6311f02d8d070 [file] [log] [blame]
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.enterprise.resource.pool.monitor;
import com.sun.appserv.connectors.internal.api.ConnectorConstants;
import com.sun.appserv.connectors.internal.api.ConnectorsUtil;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.ResourcePool;
import com.sun.enterprise.config.serverbeans.Resources;
import com.sun.enterprise.connectors.ConnectionPoolMonitoringExtension;
import com.sun.enterprise.connectors.ConnectorRuntime;
import com.sun.enterprise.connectors.util.ResourcesUtil;
import com.sun.enterprise.resource.listener.PoolLifeCycle;
import com.sun.enterprise.resource.pool.PoolLifeCycleListenerRegistry;
import com.sun.enterprise.resource.pool.PoolLifeCycleRegistry;
import com.sun.enterprise.resource.pool.PoolManager;
import com.sun.logging.LogDomains;
import org.glassfish.connectors.config.ConnectorConnectionPool;
import org.glassfish.external.probe.provider.PluginPoint;
import org.glassfish.external.probe.provider.StatsProviderManager;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.resourcebase.resources.api.PoolInfo;
import org.jvnet.hk2.annotations.Service;
import org.glassfish.hk2.api.ServiceLocator;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Bootstrap operations of stats provider objects are done by this class.
* Registering of provider to the StatsProviderManager, adding pools to the
* PoolLifeCycle listeners are done during the bootstrap.
* Depending on the lifecycle of the pool - creation/destroy, the listeners
* are added or removed and providers registered/unregistered.
*
* This is an implementation of PoolLifeCycle. All pool creation or destroy
* events are got and based on the type, provider is registered for a pool if pool
* is created or provider is unregistered if pool is destroyed. Monitoring
* levels when changed from HIGH-> OFF or
* OFF->HIGH are taken care and appropriate monitoring levels are set.
*
* @author Shalini M
*/
@Service
@Singleton
public class ConnectionPoolStatsProviderBootstrap implements PostConstruct,
PoolLifeCycle {
protected final static Logger logger =
LogDomains.getLogger(ConnectionPoolStatsProviderBootstrap.class,LogDomains.RSR_LOGGER);
@Inject
private PoolManager poolManager;
@Inject
private Provider<Domain> domainProvider;
@Inject
private Provider<ConnectionPoolProbeProviderUtil> connectionPoolProbeProviderUtilProvider;
@Inject
private ServiceLocator habitat;
//List of all connector conn pool stats providers that are created and stored
private List<ConnectorConnPoolStatsProvider> ccStatsProviders = null;
//Map of all ConnectionPoolEmitterImpl(s) for different pools
private Map<PoolInfo, ConnectionPoolEmitterImpl> poolEmitters = null;
private Map<PoolInfo, PoolLifeCycleListenerRegistry> poolRegistries = null;
private ConnectorRuntime runtime;
public ConnectionPoolStatsProviderBootstrap() {
ccStatsProviders = new ArrayList<ConnectorConnPoolStatsProvider>();
poolEmitters = new HashMap<PoolInfo, ConnectionPoolEmitterImpl>();
poolRegistries = new HashMap<PoolInfo, PoolLifeCycleListenerRegistry>();
runtime = ConnectorRuntime.getRuntime();
}
public void addToPoolEmitters(PoolInfo poolInfo, ConnectionPoolEmitterImpl emitter) {
poolEmitters.put(poolInfo, emitter);
}
/**
* All Jdbc Connection pools are added to the pool life cycle listener so as
* to listen to creation/destroy events. If the JdbcPoolTree is not built,
* by registering to the StatsProviderManager, its is done here.
*/
public void registerProvider() {
registerPoolLifeCycleListener();
}
public void postConstruct() {
if(logger.isLoggable(Level.FINEST)) {
logger.finest("[Monitor]In the ConnectionPoolStatsProviderBootstrap");
}
//createMonitoringConfig();
}
/**
* Registers the pool lifecycle listener for this pool by creating a
* new ConnectionPoolEmitterImpl object for this pool.
* @param poolInfo
* @return registry of pool lifecycle listeners
*/
public PoolLifeCycleListenerRegistry registerPool(PoolInfo poolInfo,
ConnectionPoolProbeProvider poolProvider) {
PoolLifeCycleListenerRegistry poolRegistry = null;
if(poolRegistries.get(poolInfo)==null){
poolRegistry =
new PoolLifeCycleListenerRegistry(poolInfo);
poolRegistries.put(poolInfo, poolRegistry);
}else{
poolRegistry = poolRegistries.get(poolInfo);
}
ConnectionPoolEmitterImpl emitter =
new com.sun.enterprise.resource.pool.monitor.ConnectionPoolEmitterImpl(
poolInfo, poolProvider);
poolRegistry.registerPoolLifeCycleListener(emitter);
addToPoolEmitters(poolInfo, emitter);
return poolRegistry;
}
public ConnectionPoolAppProbeProvider registerPool(PoolInfo poolInfo, String appName) {
ConnectionPoolAppProbeProvider probeAppProvider = null;
Collection<ConnectionPoolMonitoringExtension> extensions =
habitat.getAllServices(ConnectionPoolMonitoringExtension.class);
for(ConnectionPoolMonitoringExtension extension : extensions) {
probeAppProvider = extension.registerConnectionPool(poolInfo, appName);
}
return probeAppProvider;
}
public Resources getResources(){
return domainProvider.get().getResources();
}
public ConnectionPoolProbeProviderUtil getProbeProviderUtil(){
return connectionPoolProbeProviderUtilProvider.get();
}
/**
* Register connector connection pool to the StatsProviderManager.
* Add the pool lifecycle listeners for the pool to receive events on
* change of any of the monitoring attribute values.
* Finally, add this provider to the list of connector connection pool
* providers maintained.
* @param poolInfo
*/
private void registerCcPool(PoolInfo poolInfo) {
if(poolManager.getPool(poolInfo) != null) {
getProbeProviderUtil().createJcaProbeProvider();
//Found in the pool table (pool has been initialized/created)
ConnectorConnPoolStatsProvider ccPoolStatsProvider =
new ConnectorConnPoolStatsProvider(poolInfo, logger);
StatsProviderManager.register(
"connector-connection-pool",
PluginPoint.SERVER,
ConnectorsUtil.getPoolMonitoringSubTreeRoot(poolInfo, true), ccPoolStatsProvider);
PoolLifeCycleListenerRegistry registry = registerPool(
poolInfo, getProbeProviderUtil().getJcaProbeProvider());
ccPoolStatsProvider.setPoolRegistry(registry);
ccStatsProviders.add(ccPoolStatsProvider);
if(!ConnectorsUtil.isApplicationScopedResource(poolInfo)){
ResourcesUtil resourcesUtil = ResourcesUtil.createInstance();
ResourcePool pool = resourcesUtil.getPoolConfig(poolInfo);
Resources resources = resourcesUtil.getResources(poolInfo);
String raName = resourcesUtil.getRarNameOfResource(pool, resources);
ConnectorConnPoolStatsProvider connectorServicePoolStatsProvider =
new ConnectorConnPoolStatsProvider(poolInfo, logger);
String dottedNamesHierarchy = null;
String monitoringModuleName = null;
if(ConnectorsUtil.isJMSRA(raName)){
monitoringModuleName = ConnectorConstants.MONITORING_JMS_SERVICE_MODULE_NAME;
dottedNamesHierarchy = ConnectorConstants.MONITORING_JMS_SERVICE +
ConnectorConstants.MONITORING_SEPARATOR + ConnectorConstants.MONITORING_CONNECTION_FACTORIES
+ ConnectorConstants.MONITORING_SEPARATOR +
ConnectorsUtil.escapeResourceNameForMonitoring(poolInfo.getName());
}else{
monitoringModuleName = ConnectorConstants.MONITORING_CONNECTOR_SERVICE_MODULE_NAME;
dottedNamesHierarchy = ConnectorConstants.MONITORING_CONNECTOR_SERVICE_MODULE_NAME +
ConnectorConstants.MONITORING_SEPARATOR + raName + ConnectorConstants.MONITORING_SEPARATOR +
ConnectorsUtil.escapeResourceNameForMonitoring(poolInfo.getName());
}
StatsProviderManager.register(monitoringModuleName, PluginPoint.SERVER,
dottedNamesHierarchy, connectorServicePoolStatsProvider);
if(logger.isLoggable(Level.FINE)){
logger.log(Level.FINE, "Registered pool-monitoring stats [ "+dottedNamesHierarchy+" ] " +
"for [ " + raName + " ] with monitoring-stats-registry.");
}
/* no need to create multiple probe provider instances, one per pool will
work for multiple stats providers
PoolLifeCycleListenerRegistry poolLifeCycleListenerRegistry = registerPool(
poolInfo, getProbeProviderUtil().getJcaProbeProvider());
*/
connectorServicePoolStatsProvider.setPoolRegistry(registry);
ccStatsProviders.add(connectorServicePoolStatsProvider);
}
}
}
/**
* Register <code> this </code> to PoolLifeCycleRegistry so as to listen to
* PoolLifeCycle events - pool creation or destroy.
*/
private void registerPoolLifeCycleListener() {
//Register provider only for server and not for clients
if(runtime.isServer()) {
PoolLifeCycleRegistry poolLifeCycleRegistry = PoolLifeCycleRegistry.getRegistry();
poolLifeCycleRegistry.registerPoolLifeCycle(this);
}
}
/**
* Unregister Connector Connection pool from the StatsProviderManager.
* Remove the pool lifecycle listeners associated with this pool.
* @param poolInfo
*/
private void unregisterPool(PoolInfo poolInfo) {
if(ccStatsProviders != null) {
Iterator i = ccStatsProviders.iterator();
while (i.hasNext()) {
ConnectorConnPoolStatsProvider ccPoolStatsProvider =
(ConnectorConnPoolStatsProvider) i.next();
if (poolInfo.equals(ccPoolStatsProvider.getPoolInfo())) {
//Get registry and unregister this pool from the registry
PoolLifeCycleListenerRegistry poolRegistry = ccPoolStatsProvider.getPoolRegistry();
poolRegistry.unRegisterPoolLifeCycleListener(poolInfo);
StatsProviderManager.unregister(ccPoolStatsProvider);
i.remove();
}
}
}
postUnregisterPool(poolInfo);
}
public void unRegisterPool() {
Collection<ConnectionPoolMonitoringExtension> extensions =
habitat.getAllServices(ConnectionPoolMonitoringExtension.class);
for(ConnectionPoolMonitoringExtension extension : extensions) {
extension.unRegisterConnectionPool();
}
}
public void postUnregisterPool(PoolInfo poolInfo) {
unregisterPoolAppProviders(poolInfo);
poolRegistries.remove(poolInfo);
}
public void unregisterPoolAppProviders(PoolInfo poolInfo) {
ConnectionPoolEmitterImpl emitter = poolEmitters.get(poolInfo);
//If an emitter was created for the poolInfo
if (emitter != null) {
emitter.unregisterAppStatsProviders();
}
}
/**
* Find if the monitoring is enabled based on the monitoring level :
* <code> strEnabled </code>
* @param strEnabled
* @return
*/
public boolean getEnabledValue(String strEnabled) {
if ("OFF".equals(strEnabled)) {
return false;
}
return true;
}
/**
* When a pool is created (or initialized) the pool should be registered
* to the StatsProviderManager. Also, the pool lifecycle
* listener needs to be registered for this pool to track events on change
* of any monitoring attributes.
* @param poolInfo
*/
public void poolCreated(PoolInfo poolInfo) {
if(logger.isLoggable(Level.FINEST)) {
logger.finest("Pool created : " + poolInfo);
}
if(runtime.isServer()) {
ResourcePool pool = runtime.getConnectionPoolConfig(poolInfo);
Collection<ConnectionPoolMonitoringExtension> extensions =
habitat.getAllServices(ConnectionPoolMonitoringExtension.class);
for(ConnectionPoolMonitoringExtension extension : extensions) {
extension.registerPool(poolInfo);
}
if (pool instanceof ConnectorConnectionPool) {
registerCcPool(poolInfo);
} /*else if (poolInfo.getName().contains(ConnectorConstants.DATASOURCE_DEFINITION_JNDINAME_PREFIX)){
registerJdbcPool(poolInfo);
}*/
}
}
/**
* When a pool is destroyed, the pool should be unregistered from the
* StatsProviderManager. Also, the pool's lifecycle listener
* should be unregistered.
* @param poolInfo
*/
public void poolDestroyed(PoolInfo poolInfo) {
if(logger.isLoggable(Level.FINEST)) {
logger.finest("Pool Destroyed : " + poolInfo);
}
if (runtime.isServer()) {
Collection<ConnectionPoolMonitoringExtension> extensions =
habitat.getAllServices(ConnectionPoolMonitoringExtension.class);
for(ConnectionPoolMonitoringExtension extension : extensions) {
extension.unregisterPool(poolInfo);
}
unregisterPool(poolInfo);
}
}
/**
* Creates jdbc-connection-pool, connector-connection-pool, connector-service
* config elements for monitoring.
*/
//private void createMonitoringConfig() {
// createMonitoringConfig(JDBC_CONNECTION_POOL, JdbcConnectionPoolMI.class);
// createMonitoringConfig(CONNECTOR_CONNECTION_POOL, ConnectorConnectionPoolMI.class);
//}
/**
* Creates config elements for monitoring.
*
* Check if the monitoring config has been created.
* If it has not, then add it.
*/
/*private void createMonitoringConfig(final String name, final Class monitoringItemClass) {
if (monitoringService == null) {
logger.log(Level.SEVERE, "monitoringService is null. " +
"jdbc-connection-pool and connector-connection-pool monitoring config not created");
return;
}
List<MonitoringItem> itemList = monitoringService.getMonitoringItems();
boolean hasMonitorConfig = false;
for (MonitoringItem mi : itemList) {
if (mi.getName().equals(name)) {
hasMonitorConfig = true;
}
}
try {
if (!hasMonitorConfig) {
ConfigSupport.apply(new SingleConfigCode<MonitoringService>() {
public Object run(MonitoringService param) throws PropertyVetoException, TransactionFailure {
MonitoringItem newItem = (MonitoringItem) param.createChild(monitoringItemClass);
newItem.setName(name);
newItem.setLevel(MonitoringItem.LEVEL_OFF);
param.getMonitoringItems().add(newItem);
return newItem;
}
}, monitoringService);
}
} catch (TransactionFailure tfe) {
logger.log(Level.SEVERE, "Exception adding " + name + " MonitoringItem", tfe);
}
}*/
}