/*
 * 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.ConnectorsUtil;
import com.sun.enterprise.config.serverbeans.ResourcePool;
import com.sun.enterprise.connectors.ConnectorRuntime;
import com.sun.enterprise.resource.listener.PoolLifeCycleListener;
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.resourcebase.resources.api.PoolInfo;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Implementation of PoolLifeCycleListener interface to listen to events related
 * to jdbc monitoring. The methods invoke the probe providers internally to
 * provide the monitoring related information.
 *
 * @author Shalini M
 */
public class ConnectionPoolEmitterImpl implements PoolLifeCycleListener {
    private String poolName;
    private String appName;
    private String moduleName;
    private PoolInfo poolInfo;
    private ConnectionPoolProbeProvider poolProbeProvider;
    //Map of app names and respective emitters for a pool.
    private Map<PoolInfo, Map<String, ConnectionPoolAppEmitterImpl>> appStatsMap = null;
    //Map of app names for a resource handle id
    private Map<Long, String> resourceAppAssociationMap;
    private static Logger _logger = LogDomains.getLogger(ConnectionPoolEmitterImpl.class,
            LogDomains.RSR_LOGGER);
    private List<ConnectorConnPoolAppStatsProvider> ccPoolAppStatsProviders = null;
    private ConnectorRuntime runtime;

    //keep a static reference to InitialContext so as to avoid performance issues.
    private volatile static InitialContext ic = null;

    /**
     * Constructor
     * @param poolInfo connection pool on whose behalf this emitter emits pool related
     * probe events
     * @param provider
     */
    public ConnectionPoolEmitterImpl(PoolInfo poolInfo, ConnectionPoolProbeProvider provider) {
        this.poolInfo = poolInfo;
        this.poolName = poolInfo.getName();
        this.appName = poolInfo.getApplicationName();
        this.moduleName = poolInfo.getModuleName();
        this.poolProbeProvider = provider;
        this.ccPoolAppStatsProviders = new ArrayList<ConnectorConnPoolAppStatsProvider>();
        this.appStatsMap = new HashMap<PoolInfo, Map<String, ConnectionPoolAppEmitterImpl>>();
    this.resourceAppAssociationMap = new ConcurrentHashMap<Long, String>();
        runtime = ConnectorRuntime.getRuntime();
        if (ic == null) {
            synchronized (ConnectionPoolEmitterImpl.class) {
                if(ic == null) {
                    try{
                        ic = new InitialContext();
                    } catch (NamingException e) {
                        //ignore
                    }
                }
            }
        }
    }

    /**
     * Fires probe event that a stack trace is to be printed on the server.log.
     * The stack trace is mainly related to connection leak tracing for the
     * given jdbc connection pool.
     * @param stackTrace
     */
    public void toString(StringBuffer stackTrace) {
        stackTrace.append("\n Monitoring Statistics for \n" + poolName);
        poolProbeProvider.toString(poolName, appName, moduleName, stackTrace);
    }

    /**
     * Fires probe event that a connection has been acquired by the application
     * for the given jdbc connection pool.
     */
    public void connectionAcquired(long resourceHandleId) {
        ConnectionPoolAppEmitterImpl appEmitter =
                detectAppBasedProviders(getAppName(resourceHandleId));
        poolProbeProvider.connectionAcquiredEvent(poolName, appName, moduleName);
        if(appEmitter != null) {
            appEmitter.connectionAcquired();
        }
    }

    /**
     * Fires probe event related to the fact that a connection request is served
     * in the time <code>timeTakenInMillis</code> for the given jdbc connection
     * pool.
     *
     * @param timeTakenInMillis time taken to serve a connection
     */
    public void connectionRequestServed(long timeTakenInMillis) {
        poolProbeProvider.connectionRequestServedEvent(poolName, appName, moduleName, timeTakenInMillis);
    }

    /**
     * Fires probe event related to the fact that the given jdbc connection pool
     * has got a connection timed-out event.
     */
    public void connectionTimedOut() {
        poolProbeProvider.connectionTimedOutEvent(poolName, appName, moduleName);
    }

    /**
     * Fires probe event that a connection under test does not match the
     * current request for the given jdbc connection pool.
     */
    public void connectionNotMatched() {
        poolProbeProvider.connectionNotMatchedEvent(poolName, appName, moduleName);
    }

    /**
     * Fires probe event that a connection under test matches the current
     * request for the given jdbc connection pool.
     */
    public void connectionMatched() {
        poolProbeProvider.connectionMatchedEvent(poolName, appName, moduleName);
    }

    /**
     * Fires probe event that a connection is destroyed for the
     * given jdbc connection pool.
     */
    public void connectionDestroyed(long resourceHandleId) {
        poolProbeProvider.connectionDestroyedEvent(poolName, appName, moduleName);
        // Clearing the resource handle id appName mappings stored
        // This is useful in cases where connection-leak-reclaim is ON where we destroy
        // the connection. In this case, connection-release would not have happened.
        resourceAppAssociationMap.remove(resourceHandleId);
    }

    /**
     * Fires probe event that a connection is released for the given jdbc
     * connection pool.
     */
    public void connectionReleased(long resourceHandleId) {
        ConnectionPoolAppEmitterImpl appEmitter =
                detectAppBasedProviders(getAppName(resourceHandleId));
        poolProbeProvider.connectionReleasedEvent(poolName, appName, moduleName);
        if(appEmitter != null) {
            appEmitter.connectionReleased();
        }
        // Clearing the resource handle id appName mappings stored
        resourceAppAssociationMap.remove(resourceHandleId);
    }

    /**
     * Fires probe event that a connection is created for the given jdbc
     * connection pool.
     */
    public void connectionCreated() {
        poolProbeProvider.connectionCreatedEvent(poolName, appName, moduleName);
    }

    /**
     * Fires probe event related to the fact that the given jdbc connection pool
     * has got a connection leak event.
     *
     */
    public void foundPotentialConnectionLeak() {
        poolProbeProvider.potentialConnLeakEvent(poolName, appName, moduleName);
    }

    /**
     * Fires probe event related to the fact the given jdbc connection pool has
     * got a connection validation failed event.
     *
     * @param count number of times the validation failed
     */
    public void connectionValidationFailed(int count) {
        poolProbeProvider.connectionValidationFailedEvent(poolName, appName, moduleName, count);
    }

    /**
     * Fires probe event related to the fact the given jdbc connection pool has
     * got a connection used event.
     */
    public void connectionUsed(long resourceHandleId) {
        ConnectionPoolAppEmitterImpl appEmitter =
                detectAppBasedProviders(getAppName(resourceHandleId));
        poolProbeProvider.connectionUsedEvent(poolName, appName, moduleName);
        if (appEmitter != null) {
            appEmitter.connectionUsed();
        }
    }

    /**
     * Fires probe event related to the fact the given jdbc connection pool has
     * got a connection freed event.
     *
     * @param count number of connections freed to pool
     */
    public void connectionsFreed(int count) {
        poolProbeProvider.connectionsFreedEvent(poolName, appName, moduleName, count);
    }

    /**
     * Fires probe event related to the fact the given jdbc connection pool has
     * got a decrement connection used event.
     *
     */
    public void decrementConnectionUsed(long resourceHandleId) {
        ConnectionPoolAppEmitterImpl appEmitter =
                detectAppBasedProviders(getAppName(resourceHandleId));
        poolProbeProvider.decrementConnectionUsedEvent(poolName, appName, moduleName);
        if(appEmitter != null) {
            appEmitter.decrementConnectionUsed();
        }
    }

    /**
     * Fires probe event related to the fact the given jdbc connection pool has
     * got a decrement free connections size event.
     *
     */
    public void decrementNumConnFree() {
        poolProbeProvider.decrementNumConnFreeEvent(poolName, appName, moduleName);
    }

    /**
     * Fires probe event related to the fact the given jdbc connection pool has
     * got a decrement free connections size event.
     *
     * @param beingDestroyed if the connection is destroyed due to error
     * @param steadyPoolSize
     */
    public void incrementNumConnFree(boolean beingDestroyed, int steadyPoolSize) {
        poolProbeProvider.incrementNumConnFreeEvent(poolName, appName, moduleName, beingDestroyed, steadyPoolSize);
    }

    /**
     * Fires probe event related to the fact the given jdbc connection pool's
     * wait queue length has been incremented
     *
     */
    public void connectionRequestQueued() {
        poolProbeProvider.connectionRequestQueuedEvent(poolName, appName, moduleName);
    }

    /**
     * Fires probe event related to the fact the given jdbc connection pool's
     * wait queue length has been decremented.
     *
     */
    public void connectionRequestDequeued() {
        poolProbeProvider.connectionRequestDequeuedEvent(poolName, appName, moduleName);
    }

    private String getAppName(long resourceHandleId) {

        // if monitoring is disabled, avoid sending events
        // as we need to do "java:app/AppName" to get applicationName for each
        // acquire/return connection call which is a performance bottleneck.
        if(!runtime.isJdbcPoolMonitoringEnabled() && !runtime.isConnectorPoolMonitoringEnabled()){
            return null;
        }

        String appName = resourceAppAssociationMap.get(resourceHandleId);
        if(appName == null){
            try {
                if(ic == null){
                    synchronized(ConnectionPoolEmitterImpl.class) {
                        if(ic == null) {
                            ic = new InitialContext();
                        }
                    }
                }
                appName = (String) ic.lookup("java:app/AppName");
                resourceAppAssociationMap.put(resourceHandleId, appName);
            } catch (NamingException ex) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "Unable to get application name using "
                            + "java:app/AppName method");
                }

            }
        }
        return appName;
    }

    /**
     * Detect if a Stats Provider has already been registered to the
     * monitoring framework for this appName and if so, return the specific
     * emitter. If not already registered, create and register the
     * Stats Provider object to the monitoring framework and add to the list
     * of emitters.
     *
     * @param appName
     * @return
     */
    private ConnectionPoolAppEmitterImpl detectAppBasedProviders(String appName) {

        ConnectionPoolAppProbeProvider probeAppProvider = null;
        ConnectionPoolAppEmitterImpl connPoolAppEmitter = null;

        if (appName == null) {
            //Case when appname cannot be detected. Emitter cannot exist for
            //a null appName for any pool.
            return null;
        }

        if (appStatsMap.containsKey(poolInfo)) {
            //Some apps have been registered for this pool.
            //Find if this appName is already registered.
            //All appEmitters for this pool
            Map<String, ConnectionPoolAppEmitterImpl> appEmitters = appStatsMap.get(poolInfo);
            //Check if the appEmitters list has an emitter for the appName.
            ConnectionPoolAppEmitterImpl emitter = appEmitters.get(appName);
            if(emitter != null) {
                //This appName has already been registered to StatsProviderManager
                return emitter;
            } else {
                if (!ConnectorsUtil.isApplicationScopedResource(poolInfo)) {
                    //register to the StatsProviderManager and add to the list.
                    probeAppProvider = registerConnectionPool(appName);
                    connPoolAppEmitter = addToList(appName, probeAppProvider,
                            appEmitters);
                }
            }
        } else {
            if (!ConnectorsUtil.isApplicationScopedResource(poolInfo)) {
                //Does not contain any app providers associated with this poolname
                //Create a map of app emitters for the appName and add them to the
                //appStatsMap
                probeAppProvider = registerConnectionPool(appName);
                Map<String, ConnectionPoolAppEmitterImpl> appEmitters =
                        new HashMap<String, ConnectionPoolAppEmitterImpl>();
                connPoolAppEmitter = addToList(appName, probeAppProvider, appEmitters);
            }
        }
        return connPoolAppEmitter;
    }

    /**
     * Register the jdbc/connector connection pool Stats Provider object to the
     * monitoring framework under the specific application name monitoring
     * sub tree.
     *
     * @param appName
     * @return
     */
    private ConnectionPoolAppProbeProvider registerConnectionPool(String appName) {
        ResourcePool pool = runtime.getConnectionPoolConfig(poolInfo);
        ConnectionPoolAppProbeProvider probeAppProvider =
                runtime.getProbeProviderUtil().getConnPoolBootstrap().registerPool(poolInfo, appName);
        if (pool instanceof ConnectorConnectionPool) {
            probeAppProvider = new ConnectorConnPoolAppProbeProvider();
            ConnectorConnPoolAppStatsProvider ccPoolAppStatsProvider =
                    new ConnectorConnPoolAppStatsProvider(poolInfo, appName);
            StatsProviderManager.register(
                    "connector-connection-pool",
                    PluginPoint.SERVER,
                    "resources/" + ConnectorsUtil.escapeResourceNameForMonitoring(poolName) + "/" + appName,
                    ccPoolAppStatsProvider);
            ccPoolAppStatsProviders.add(ccPoolAppStatsProvider);
        }
        return probeAppProvider;
    }

    /**
     * Add to the pool emitters list. the connection pool application emitter
     * for the specific poolInfo and appName.
     * @param appName
     * @param probeAppProvider
     * @param appEmitters
     * @return
     */
    private ConnectionPoolAppEmitterImpl addToList(String appName,
            ConnectionPoolAppProbeProvider probeAppProvider,
            Map<String, ConnectionPoolAppEmitterImpl> appEmitters) {
        ConnectionPoolAppEmitterImpl connPoolAppEmitter = null;
        if (probeAppProvider != null) {
            //Add the newly created probe provider to the list.
            connPoolAppEmitter = new ConnectionPoolAppEmitterImpl(poolName,
                    appName, probeAppProvider);
            //NOTE : this appName here is different from "appName" instance variable.
            appEmitters.put(appName, connPoolAppEmitter);
            appStatsMap.put(poolInfo, appEmitters);
        }
        runtime.getProbeProviderUtil().
                getConnPoolBootstrap().addToPoolEmitters(poolInfo, this);
        return connPoolAppEmitter;
    }

    /**
     * Unregister the AppStatsProviders registered for this connection pool.
     */
    public void unregisterAppStatsProviders() {
        runtime.getProbeProviderUtil().getConnPoolBootstrap().unRegisterPool();
        Iterator ccProviders = ccPoolAppStatsProviders.iterator();
        while (ccProviders.hasNext()) {
            ConnectorConnPoolAppStatsProvider ccPoolAppStatsProvider =
                    (ConnectorConnPoolAppStatsProvider) ccProviders.next();
            StatsProviderManager.unregister(ccPoolAppStatsProvider);
        }
        ccPoolAppStatsProviders.clear();
    }
}
