All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avaje.ebeaninternal.server.lib.sql.DataSourceManager Maven / Gradle / Ivy

The newest version!
/**
 *  Copyright (C) 2006  Robin Bygrave
 *  
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 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
 *  Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
package com.avaje.ebeaninternal.server.lib.sql;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.avaje.ebean.config.DataSourceConfig;
import com.avaje.ebean.config.GlobalProperties;
import com.avaje.ebeaninternal.api.ClassUtil;
import com.avaje.ebeaninternal.server.lib.BackgroundRunnable;
import com.avaje.ebeaninternal.server.lib.BackgroundThread;


/**
 * Manages access to named DataSources.
 */
public class DataSourceManager implements DataSourceNotify {
	
	private static final Logger logger = Logger.getLogger(DataSourceManager.class.getName());
	
    /**
     * An alerter that notifies when the database has problems.
     */
    private final DataSourceAlertListener alertlistener;

    /** 
     * Cache of the named DataSources. 
     */
    private final Hashtable dsMap = new Hashtable();

    /**
     * Monitor for creating dataSources.
     */
    private final Object monitor = new Object();

    /**
     * The database checker registered with BackgroundThread.
     */
    private final BackgroundRunnable dbChecker;
    
    /**
     * The frequency to test db while it is up.
     */
    private final int dbUpFreqInSecs;
    
    /**
     * The frequency to test db while it is down.
     */
    private final int dbDownFreqInSecs;

    /**
     * Set to true when shutting down.
     */
    private boolean shuttingDown;
    	
    private boolean deregisterDriver;
    
	/** 
	 * Construct with explicit ConfigProperties.
	 */
	public DataSourceManager() {
		
		this.alertlistener = createAlertListener();
		
		// perform heart beat every 30 seconds by default
        this.dbUpFreqInSecs = GlobalProperties.getInt("datasource.heartbeatfreq",30);
        this.dbDownFreqInSecs = GlobalProperties.getInt("datasource.deadbeatfreq",10);        
        this.dbChecker = new BackgroundRunnable(new Checker(), dbUpFreqInSecs);
		this.deregisterDriver = GlobalProperties.getBoolean("datasource.deregisterDriver", true);
        
		try {
	        BackgroundThread.add(dbChecker);
            		    
		} catch (Exception e) {
			logger.log(Level.SEVERE, null, e);
		}
	}

	private DataSourceAlertListener createAlertListener() throws DataSourceException {
		
		String alertCN = GlobalProperties.get("datasource.alert.class", null);
		if (alertCN == null){
			return new SimpleAlerter();
			
		} else {
		    try {
		        return (DataSourceAlertListener)ClassUtil.newInstance(alertCN, this.getClass());
		        
		    } catch (Exception ex){
		    	throw new DataSourceException(ex);
		    }
		}
	}

    /**
     * Send an alert to say the dataSource is back up.
     */
	public void notifyDataSourceUp(String dataSourceName){

        dbChecker.setFreqInSecs(dbUpFreqInSecs);
		
		if (alertlistener != null){
		    alertlistener.dataSourceUp(dataSourceName);
		}
	}

    /**
     * Send an alert to say the dataSource is down.
     */
	public void notifyDataSourceDown(String dataSourceName){
		
        dbChecker.setFreqInSecs(dbDownFreqInSecs);
        
		if (alertlistener != null){
		    alertlistener.dataSourceDown(dataSourceName); 
		}
	}

    /**
     * Send an alert to say the dataSource is getting close to its max size.
     */
	public void notifyWarning(String subject, String msg){
		if (alertlistener != null){
		    alertlistener.warning(subject, msg);
		}
	}

    /**
     * Return true when the dataSource is shutting down.
     */
	public boolean isShuttingDown() {
		synchronized(monitor) {
			return shuttingDown;
		}
	}
	
    /**
     * Shutdown the dataSources.
     */
    public void shutdown() {
		
		synchronized(monitor) {
			
			this.shuttingDown = true;
			
			Collection values = dsMap.values();
			for (DataSourcePool ds : values) {
				try {					
					ds.shutdown();
				} catch (DataSourceException e) {
					// should never be thrown as the DataSources are all created...
					logger.log(Level.SEVERE, null, e);
				}
            }
			if (deregisterDriver){
				for (DataSourcePool ds : values) {
	                ds.deregisterDriver();
                }
			}
		}
	}

    /**
     * Return the DataSourcePool's.
     */
	public List getPools() {
		synchronized(monitor) {
			// create a copy of the DataSourcePool's
			ArrayList list = new ArrayList();
			list.addAll(dsMap.values());
			return list;
		}
	}
    
	/**
	 * Get the dataSource using the default ConfigProperties.
	 */
	public DataSourcePool getDataSource(String name) {
		return getDataSource(name, null);
	}
	
	
	public DataSourcePool getDataSource(String name, DataSourceConfig dsConfig){
		
		if (name == null){
			throw new IllegalArgumentException("name not defined");
		}
				
	    synchronized(monitor){
		    DataSourcePool pool = dsMap.get(name);
		    if (pool == null){
		    	if (dsConfig == null){
					dsConfig = new DataSourceConfig();
					dsConfig.loadSettings(name);
				}
		        pool = new DataSourcePool(this, name, dsConfig);
		        dsMap.put(name, pool); 
		    }
		    return pool;
		}
	}
	
	/**
	 * Check that the database is up by performing a simple query. This should
	 * be done periodically. By default every 30 seconds.
	 */
	private void checkDataSource() {

		synchronized (monitor) {
			if (!isShuttingDown()) {
				Iterator it = dsMap.values().iterator();
				while (it.hasNext()) {
					DataSourcePool ds = it.next();
					ds.checkDataSource();
				}
			}
		}
	}
    
    /**
     * Runs every dbUpFreqInSecs to make sure dataSource is up.
     */
    private final class Checker implements Runnable {

        public void run() {
            checkDataSource();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy