Changeset 3541
- Timestamp:
- 02/10/10 11:50:31 (6 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
trunk/twcore/src/twcore/core/sql/SQLConnectionPool.java
r2383 r3541 10 10 import java.util.Map; 11 11 import java.util.Vector; 12 13 import twcore.core.util.Tools; 12 14 13 15 /** … … 32 34 // connection is available 33 35 private Vector<Connection> availableConnections; // Connections not in use 34 private Map<String, Connection> busyConnections; // Connections currently querying36 private Map<String, Vector<Connection>> busyConnections; // Connections currently querying 35 37 36 38 private boolean connectionPending = false; // True if a connection is being made … … 67 69 } 68 70 availableConnections = new Vector<Connection>(initialConnections); 69 busyConnections = Collections.synchronizedMap(new HashMap<String, Connection>());71 busyConnections = Collections.synchronizedMap(new HashMap<String, Vector<Connection>>()); 70 72 for(int i=0; i<initialConnections; i++) { 71 73 availableConnections.addElement(makeNewConnection()); … … 86 88 try{ 87 89 Statement stmt = conn.createStatement(); 90 88 91 stmt.execute( query ); 89 free( conn );92 90 93 ResultSet set = stmt.getResultSet(); 91 94 // If ResultSet is null (INSERT statement), get auto-generated ID if available … … 94 97 else 95 98 return stmt.getGeneratedKeys(); 96 }catch( SQLException e ){ 97 free( conn ); 98 99 //throw e; 100 101 // DEBUG: Returning null to generate NullPointerExceptions in bots that 102 // do not catch SQLExceptions 103 return null; 99 } catch( SQLException e ){ 100 throw e; 101 102 } finally { 103 free( DEFAULT_UNIQUE_ID, conn ); 104 104 } 105 105 } … … 121 121 */ 122 122 public synchronized Connection getConnection(String uniqueID) throws SQLException { 123 if(uniqueID.equals("0")==false) {123 if(uniqueID.equals(DEFAULT_UNIQUE_ID)==false) { 124 124 if(busyConnections.containsKey(uniqueID)) { 125 return busyConnections.get(uniqueID) ;125 return busyConnections.get(uniqueID).firstElement(); 126 126 } 127 127 } 128 128 129 if (availableConnections.isEmpty()==false) { 130 Connection existingConnection = availableConnections.lastElement(); 129 if (availableConnections.isEmpty()==false) { // if there are availableConnections 130 131 // Get an connection from list of available connections and remove it from the list 132 Connection availableConnection = availableConnections.lastElement(); 131 133 int lastIndex = availableConnections.size() - 1; 132 134 availableConnections.removeElementAt(lastIndex); 133 if (existingConnection.isClosed()) { 135 136 if (availableConnection.isClosed()) { 137 138 // if the connection is closed, try again by calling this method again - the availableConnection is lost 134 139 notifyAll(); // Freed up a spot for anybody waiting 135 140 return(getConnection()); 141 136 142 } else { 137 busyConnections.put(uniqueID, existingConnection); 138 return(existingConnection); 139 } 140 } else { 143 if(!busyConnections.containsKey(uniqueID)) { 144 busyConnections.put(uniqueID, new Vector<Connection>()); 145 } 146 busyConnections.get(uniqueID).add(availableConnection); 147 return availableConnection; 148 } 149 150 } else { // there are no available connections 151 152 // Check if we reached the maximum amount of connections 141 153 if(( totalConnections() < maxConnections ) && !connectionPending ) { 142 154 makeBackgroundConnection(); … … 144 156 throw new SQLException("Connection limit reached"); 145 157 } 158 146 159 try { 147 160 wait(); 148 161 } catch(InterruptedException ie) {} 149 // Someone freed up a connection, so try again. 162 // Someone freed up a connection or a new connection has been made, try again. 163 150 164 return getConnection(uniqueID); 151 165 } … … 188 202 try { 189 203 Connection connection = makeNewConnection(); 204 190 205 synchronized(this) { 191 206 availableConnections.addElement(connection); … … 193 208 notifyAll(); 194 209 } 195 } catch(Exception e) { 210 } catch(SQLException e) { 211 Tools.printStackTrace(e); 196 212 } 197 213 } … … 216 232 217 233 /** 218 * Free a connection back to the available connection pool. This will notify234 * Free a specific connection back to the available connection pool. This will notify 219 235 * other threads that are waiting (using wait()) for a connection in getConnection() 220 236 * that a new connection is now available. … … 222 238 */ 223 239 public synchronized void free( String uniqueID, Connection connection ) { 224 if(busyConnections.containsKey(uniqueID)) { 225 busyConnections.remove(uniqueID); 240 if(busyConnections.containsKey(uniqueID) && busyConnections.get(uniqueID).contains(connection)) { 241 242 // Remove connection from the vector 243 busyConnections.get(uniqueID).remove(connection); 244 245 // Remove HashMap entry if vector has become empty 246 if(busyConnections.get(uniqueID).isEmpty()) { 247 busyConnections.remove(uniqueID); 248 } 249 226 250 availableConnections.addElement(connection); 251 227 252 // Wake up threads that are waiting for a connection 228 253 notifyAll(); … … 230 255 } 231 256 232 public synchronized void free( Connection connection ) {233 this.free( DEFAULT_UNIQUE_ID, connection);234 }235 236 257 /** 237 258 * @return Total number of connections either available or currently busy 238 259 */ 239 260 public synchronized int totalConnections() { 240 return(availableConnections.size() + 241 busyConnections.size()); 261 return(availableConnections.size() + busyConnections.size()); 242 262 } 243 263 … … 249 269 availableConnections = new Vector<Connection>(); 250 270 closeBusyConnections(busyConnections); 251 busyConnections = new HashMap<String, Connection>();271 busyConnections = new HashMap<String,Vector<Connection>>(); 252 272 } 253 273 … … 271 291 * @param connections Vector containing connections to close 272 292 */ 273 private void closeBusyConnections(Map<String,Connection> connections) { 274 try { 275 for(Connection conn:connections.values()) { 276 if (!conn.isClosed()) { 277 conn.close(); 278 } 279 } 293 private void closeBusyConnections(Map<String,Vector<Connection>> connections) { 294 try { 295 for(Vector<Connection> conns:connections.values()) { 296 for(Connection conn:conns) { 297 if (!conn.isClosed()) { 298 conn.close(); 299 } 300 } 301 } 280 302 } catch(SQLException sqle) { 281 303 } … … 293 315 */ 294 316 public synchronized String toString() { 295 String info =317 /*String info = 296 318 "SQL pool " + poolName + ": " + totalConnections() + "/" 297 319 + maxConnections + " connections online, " + busyConnections.size() 298 + " in use"; 299 return (info);320 + " in use";*/ 321 return "SQL pool "+ poolName + ": " + busyConnections.size() + "/" + availableConnections.size() + " connections online (background: "+getNumBackground()+") (max: "+maxConnections+")"; 300 322 } 301 323
