Mercurial > dive4elements > gnv-client
view geo-backend/src/main/java/de/intevation/gnv/geobackend/sde/datasources/ArcSDEConnectionPool.java @ 129:110e3ac1b7d2
Library Dependencies Added to pom.xml-File
Import of SDE-Datasources
geo-backend/trunk@5 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Tim Englich <tim.englich@intevation.de> |
---|---|
date | Wed, 02 Sep 2009 09:07:03 +0000 |
parents | |
children |
line wrap: on
line source
/******************************************************************************* * Copyright � 2007 52�North Initiative for Geospatial Open Source Software GmbH * * Author: Oliver Meyer, University of Muenster * * Contact: Andreas Wytzisk, 52�North Initiative for Geospatial Open Source * Software GmbH, Martin-Luther-King-Weg 24, 48155 Muenster, Germany, * info@52north.org * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; even without the implied WARRANTY OF MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program (see gnu-gpl v2.txt). If not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA or * visit the Free Software Foundation�s web page, http://www.fsf.org. * ******************************************************************************/ // Last changes on: 2007-06-03 // Last changes by: Oliver Meyer package de.intevation.gnv.geobackend.sde.datasources; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.Map.Entry; import org.apache.log4j.Logger; import com.esri.sde.sdk.client.SeConnection; import com.esri.sde.sdk.client.SeException; import de.intevation.gnv.geobackend.sde.datasources.exception.ConnectionException; import de.intevation.gnv.geobackend.sde.datasources.exception.TechnicalException; /** * Connection Pool for ArcSDE databases. * * @author Oliver Meyer * @version 1.0 */ public class ArcSDEConnectionPool { /** * Default Logging instance */ private static final Logger sLogger = Logger.getLogger(ArcSDEConnectionPool.class); private static boolean sDebug = sLogger.isDebugEnabled(); /** * timer for holding connections */ private Timer timer; /** * the logger, used to log exceptions and additonaly information */ private static Logger log = Logger.getLogger(ArcSDEConnectionPool.class); /** * Hashtable containing the connections as keys and Boolean as value (False if the connection is not used) */ private Hashtable<SeConnection, Boolean> connections; private static ArcSDEConnectionPool sInstance = null; private static ArcSDEConnectionParams sParams = null; public static ArcSDEConnectionPool getInstance() throws TechnicalException { if (sInstance == null) { throw new TechnicalException("The ArcSDEConnectionPool has to be configured first!"); } return sInstance; } public static boolean isConfigured() { return sParams != null; } public static void configure(ArcSDEConnectionParams pParams) throws TechnicalException { if (sDebug) sLogger.debug("configure()"); if (sInstance == null) { synchronized (ArcSDEConnectionPool.class) { sInstance = new ArcSDEConnectionPool(pParams); } } else { throw new TechnicalException("The ArcSDEConnectionPool is already configured: " + pParams.toString()); } } private ArcSDEConnectionPool(ArcSDEConnectionParams pParams) throws ConnectionException { if (sDebug) sLogger.debug("ArcSDEConnectionPool()"); sParams = pParams; connections = new Hashtable<SeConnection, Boolean>(); initPool(sParams.getInitConnections()); timer = new Timer("ArcSDEConnectionPoolTimer"); startConnectionTask(); } /** * help method for initializing the connection pool * * @param initConnections number of initial connections * @throws OwsExceptionReport if creating connections failed while initializing the connection pool */ protected void initPool(int initConnections) throws ConnectionException { // initialize connections; // "false" indicates that the connection is not used yet for (int i = 0; i < initConnections; ++i) { SeConnection con = getNewConnection(); connections.put(con, Boolean.FALSE); } } /** * Method returns an available connection from the pool, and sets it on "not available". After the query * operation, you have to "give back" the connection to the pool with the returnConnection method! * * @return ArcSDE connection to execute the query * @throws OwsExceptionReport If all connections are in use and no further connection could be established * @throws OwsExceptionReport */ protected SeConnection getConnection() throws ConnectionException { SeConnection con = null; Enumeration<SeConnection> cons = connections.keys(); // no other operation (maybe adding a connection) while checking which // (or whether a) connection is available synchronized (connections) { while (cons.hasMoreElements()) { con = cons.nextElement(); Boolean b = connections.get(con); // checking whether connection is available if (b == Boolean.FALSE) { // connection is available, now test, whether connection is // OK (with setAutoCommit) try { con.setTransactionAutoCommit(1000); } catch (SeException sdeEx) { // problem with connection, so remove and create new // connection connections.remove(con); con = getNewConnection(); } // set connection "not available" (Value=true) connections.put(con, Boolean.TRUE); return con; } } } // if no connections are available, create new one if (connections.size() <= sParams.getMaxConnections()) { con = getNewConnection(); connections.put(con, Boolean.TRUE); } // if maximal number of connections is arrived, throw exception! else { throw new ConnectionException("All db connections are in use. Please try again later!"); } // return new Connection return con; } /** * abstract method creates a new connection; must be implemented by all subclasses! * * @return Returns connection - new connection to the database * @throws OwsExceptionReport if creating a new connection failed */ private SeConnection getNewConnection() throws ConnectionException { SeConnection con; // creating new connection try { con = new SeConnection(sParams.getServer(), sParams.getInstance(), sParams.getDatabase(), sParams.getUser(), sParams.getPwd()); // Class.forName("org.postgresql.Driver"); // con = DriverManager.getConnection(props.getProperty("CONNECTION"), props); } catch (SeException sdeEx) { throw new ConnectionException("Establishing a connection to database failed: " + sdeEx.toString(), sdeEx); } return con; } /** * Invoke this method after executing the query with this connection, so that the connection is already * available in the pool * * @param con the connection which was used and now is available again */ public void returnConnection(SeConnection con) { if (connections.containsKey(con)) { connections.put(con, Boolean.FALSE); } } /** * method sends a query for every connection */ private void holdConnections() { Set<Entry<SeConnection, Boolean>> entrySet = connections.entrySet(); Iterator<Entry<SeConnection, Boolean>> iter = entrySet.iterator(); SeConnection con = null; while (iter.hasNext()) { Entry<SeConnection, Boolean> entry = iter.next(); //Connection in use? if (entry.getValue() == false) { con = entry.getKey(); try { con.setTransactionAutoCommit(1000); } catch (SeException sdeEx) { //if sql exception occurs, try to built new connection and put connection into pool connections.remove(con); try { SeConnection conNew = getNewConnection(); connections.put(conNew, Boolean.FALSE); } catch (ConnectionException e) { log.debug("Erroe while refreshing connections: " + e.getMessage()); } log.error("An error occurred while holding connections through query!", sdeEx); } } } } /** * method invokes the schedule method of the timer with a new InstantFeederTask, the actual date and the * period from the config file as parameters. * * @throws OwsExceptionReport if creation of the InstantFeederTask failed */ private void startConnectionTask() throws ConnectionException { timer.schedule(new ConnectionTask(), new Date(), sParams.getTimeToHold()); } /** * connection task used for holding connections and making sure, that these * * @author Christoph Stasch */ protected class ConnectionTask extends TimerTask { /** * overwritten run method of TimerTask which queries offeringIDs from db to make sure, that * connections won't be blocked by the firewalls */ public void run() { holdConnections(); } } }