Changeset 10004
- Timestamp:
- 12/17/09 11:55:26 (9 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
helma/helma/trunk/src/helma/main/Server.java
r10000 r10004 418 418 dbProps.setIgnoreCase(false); 419 419 dbProps.addResource(new FileResource(file)); 420 DbSource.setDefaultProps(dbProps); 420 421 421 422 // read apps.properties file helma/helma/trunk/src/helma/objectmodel/db/DbSource.java
r10000 r10004 28 28 29 29 /** 30 * This class describes a rel ational data source (URL, driver, user and password).30 * This class describes a releational data source (URL, driver, user and password). 31 31 */ 32 32 public class DbSource { 33 private static ResourceProperties defaultProps = null; 34 private Properties conProps; 33 35 private String name; 34 private int serialId = 0; 35 private ResourceProperties props; 36 private ResourceProperties props, subProps; 36 37 protected String url; 37 38 private String driver; 38 private Properties conProps;39 39 private boolean isOracle, isMySQL, isPostgreSQL, isH2; 40 40 private long lastRead = 0L; 41 41 private Hashtable dbmappings = new Hashtable(); 42 // compute hashcode statically because it's expensive and we need it often 43 private int hashcode; 42 44 // thread local connection holder for non-transactor threads 43 45 private ThreadLocal connection; … … 67 69 public synchronized Connection getConnection() 68 70 throws ClassNotFoundException, SQLException { 69 DbConnection con;71 Connection con; 70 72 Transactor tx = Transactor.getInstance(); 71 if (props.lastModified() != lastRead) { 73 if (tx != null) { 74 con = tx.getConnection(this); 75 } else { 76 con = getThreadLocalConnection(); 77 } 78 79 boolean fileUpdated = props.lastModified() > lastRead || 80 (defaultProps != null && defaultProps.lastModified() > lastRead); 81 82 if (con == null || con.isClosed() || fileUpdated) { 72 83 init(); 73 } 74 if (tx != null) { 75 con = tx.getDbConnection(name, serialId); 76 } else { 77 con = getThreadLocalDbConnection(); 78 } 79 80 if (con == null) { 81 con = new DbConnection(DriverManager.getConnection(url, conProps), serialId); 84 con = DriverManager.getConnection(url, conProps); 82 85 83 86 // If we wanted to use SQL transactions, we'd set autoCommit to … … 85 88 // System.err.println ("Created new Connection to "+url); 86 89 if (tx != null) { 87 tx.registerConnection( name, con);90 tx.registerConnection(this, con); 88 91 } else { 89 92 connection.set(con); … … 91 94 } 92 95 93 return con .getConnection();96 return con; 94 97 } 95 98 … … 98 101 * @return a thread local tested connection, or null 99 102 */ 100 private DbConnection getThreadLocalDbConnection() {103 private Connection getThreadLocalConnection() { 101 104 if (connection == null) { 102 105 connection = new ThreadLocal(); 103 106 return null; 104 107 } 105 DbConnection con = (DbConnection) connection.get(); 106 if (con != null && !con.isValid(serialId)) { 107 con.close(); 108 connection.remove(); 109 return null; 108 Connection con = (Connection) connection.get(); 109 if (con != null) { 110 // test if connection is still ok 111 try { 112 Statement stmt = con.createStatement(); 113 stmt.execute("SELECT 1"); 114 stmt.close(); 115 } catch (SQLException sx) { 116 try { 117 con.close(); 118 } catch (SQLException ignore) {/* nothing to do */} 119 return null; 120 } 110 121 } 111 122 return con; … … 132 143 */ 133 144 private synchronized void init() throws ClassNotFoundException { 134 lastRead = props.lastModified(); 135 serialId ++; 145 lastRead = (defaultProps == null) ? props.lastModified() 146 : Math.max(props.lastModified(), 147 defaultProps.lastModified()); 136 148 // refresh sub-properties for this DbSource 137 ResourceProperties subProps = props.getSubProperties(name + '.'); 149 subProps = props.getSubProperties(name + '.'); 150 // use properties hashcode for ourselves 151 hashcode = subProps.hashCode(); 138 152 // get JDBC URL and driver class name 139 153 url = subProps.getProperty("url"); … … 200 214 201 215 /** 216 * Set the default (server-wide) properties 217 * 218 * @param props server default db.properties 219 */ 220 public static void setDefaultProps(ResourceProperties props) { 221 defaultProps = props; 222 } 223 224 /** 202 225 * Check if this DbSource represents an Oracle database 203 226 * … … 256 279 } 257 280 281 /** 282 * Returns a hash code value for the object. 283 */ 284 public int hashCode() { 285 return hashcode; 286 } 287 288 /** 289 * Indicates whether some other object is "equal to" this one. 290 */ 291 public boolean equals(Object obj) { 292 return obj instanceof DbSource && subProps.equals(((DbSource) obj).subProps); 293 } 258 294 } helma/helma/trunk/src/helma/objectmodel/db/Transactor.java
r10000 r10004 235 235 /** 236 236 * Register a db connection with this transactor thread. 237 * @param name the db source name237 * @param src the db source 238 238 * @param con the connection 239 239 */ 240 public void registerConnection(String name, DbConnection con) { 241 DbConnection previous = (DbConnection) sqlConnections.put(name, con); 242 if (previous != null) { 243 nmgr.app.logEvent("Closing previous connection " + con); 244 previous.close(); 245 } 240 public void registerConnection(DbSource src, Connection con) { 241 sqlConnections.put(src, con); 246 242 // we assume a freshly created connection is ok. 247 testedConnections.put( name, new Long(System.currentTimeMillis()));243 testedConnections.put(src, new Long(System.currentTimeMillis())); 248 244 } 249 245 250 246 /** 251 247 * Get a db connection that was previously registered with this transactor thread. 252 * @param name the db source name 253 * @param serialId the current serial id of the db source definition, used for validation 254 * @return the connection, or null if no valid connection is available 255 */ 256 public DbConnection getDbConnection(String name, int serialId) { 257 DbConnection con = (DbConnection) sqlConnections.get(name); 258 Long tested = (Long) testedConnections.get(name); 248 * @param src the db source 249 * @return the connection 250 */ 251 public Connection getConnection(DbSource src) { 252 Connection con = (Connection) sqlConnections.get(src); 253 Long tested = (Long) testedConnections.get(src); 259 254 long now = System.currentTimeMillis(); 260 // Check if the connection is still valid 261 if (con != null 262 && (tested == null || now - tested.longValue() > 60000) 263 && !con.isValid(serialId)) { 264 nmgr.app.logEvent("Closing cached connection " + con); 265 sqlConnections.remove(name); 266 testedConnections.remove(name); 267 con.close(); 268 return null; 255 if (con != null && (tested == null || now - tested.longValue() > 60000)) { 256 // Check if the connection is still alive by executing a simple statement. 257 try { 258 Statement stmt = con.createStatement(); 259 stmt.execute("SELECT 1"); 260 stmt.close(); 261 testedConnections.put(src, new Long(now)); 262 } catch (SQLException sx) { 263 try { 264 con.close(); 265 } catch (SQLException ignore) {/* nothing to do */} 266 return null; 267 } 269 268 } 270 269 return con; … … 531 530 for (Iterator i = sqlConnections.values().iterator(); i.hasNext();) { 532 531 try { 533 DbConnection con = (DbConnection) i.next(); 532 Connection con = (Connection) i.next(); 533 534 534 con.close(); 535 535 nmgr.app.logEvent("Closing DB connection: " + con); 536 } catch (Exception x) {537 nmgr.app.logEvent("Error closing DB connection: " + x);536 } catch (Exception ignore) { 537 // exception closing db connection, ignore 538 538 } 539 539 }