Commit 7776755b authored by Daniel Henninger's avatar Daniel Henninger Committed by dhenninger

[JM-343] Migrated to proxool instead of homebrew connection pool handler. ...

[JM-343] Migrated to proxool instead of homebrew connection pool handler.  Also added /proxool to admin console to see statistics from proxool.  At some point we should wrap this in a cute openfire looking page.  No API changes necessary anywhere else in code or 3rd party database connection providers!

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@9758 b35dd754-fafc-0310-a699-88a17e54d16e
parent bbc7e885
...@@ -39,6 +39,7 @@ mysql.jar | 5.0.8 ...@@ -39,6 +39,7 @@ mysql.jar | 5.0.8
objenesis | 1.0 (JMock 2.1.0) objenesis | 1.0 (JMock 2.1.0)
pack200task.jar | August 5, 2004 pack200task.jar | August 5, 2004
postgres.jar | 8.2-506.jdbc3 postgres.jar | 8.2-506.jdbc3
proxool.jar | 0.9.0RC3
rome.jar | 0.9 rome.jar | 0.9
rome-fetcher.jar | 0.9 rome-fetcher.jar | 0.9
servlet.jar | Jetty 6.1.0 (2.5) servlet.jar | Jetty 6.1.0 (2.5)
...@@ -46,4 +47,4 @@ shaj.jar | 0.5 ...@@ -46,4 +47,4 @@ shaj.jar | 0.5
sitemesh.jar | 2.2.1 sitemesh.jar | 2.2.1
standard.jar | Jakarta standard taglib 1.1.2 standard.jar | Jakarta standard taglib 1.1.2
xmltask.jar | 1.11 xmltask.jar | 1.11
xpp3.jar | XPP_3 1.1.4c xpp3.jar | XPP_3 1.1.4c
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -45,6 +45,7 @@ public interface ConnectionProvider { ...@@ -45,6 +45,7 @@ public interface ConnectionProvider {
* on the wrapper class will release the connection from the pool. * on the wrapper class will release the connection from the pool.
* *
* @return a Connection object. * @return a Connection object.
* @throws SQLException is an SQL error occured while retrieving the connection.
*/ */
public Connection getConnection() throws SQLException; public Connection getConnection() throws SQLException;
......
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.database;
import java.sql.Connection;
import java.sql.SQLException;
/**
* An implementation of the Connection interface that wraps an underlying
* Connection object. It releases the connection back to a connection pool
* when Connection.close() is called.
*
* @author Jive Software
*/
public class ConnectionWrapper extends AbstractConnection {
public ConnectionPool pool;
public boolean checkedout = false;
public long createTime;
public long lockTime;
public long checkinTime;
public Exception exception;
public boolean hasLoggedException = false;
public ConnectionWrapper(Connection connection, ConnectionPool pool) {
super(connection);
this.pool = pool;
createTime = System.currentTimeMillis();
lockTime = createTime;
checkinTime = lockTime;
}
public void setConnection(Connection connection) {
super.connection = connection;
}
/**
* Instead of closing the underlying connection, we simply release
* it back into the pool.
*/
public void close() throws SQLException {
synchronized (this) {
checkedout = false;
checkinTime = System.currentTimeMillis();
}
pool.freeConnection();
// Release object references. Any further method calls on the connection will fail.
// super.connection = null;
}
public String toString() {
if (connection != null) {
return connection.toString();
}
else {
return "Jive Software Connection Wrapper";
}
}
public synchronized boolean isCheckedOut() {
return checkedout;
}
}
...@@ -14,9 +14,10 @@ package org.jivesoftware.database; ...@@ -14,9 +14,10 @@ package org.jivesoftware.database;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import java.io.IOException;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.DriverManager;
import java.util.Properties;
/** /**
* Default Jive connection provider, which uses an internal connection pool.<p> * Default Jive connection provider, which uses an internal connection pool.<p>
...@@ -25,10 +26,10 @@ import java.sql.SQLException; ...@@ -25,10 +26,10 @@ import java.sql.SQLException;
*/ */
public class DefaultConnectionProvider implements ConnectionProvider { public class DefaultConnectionProvider implements ConnectionProvider {
private ConnectionPool connectionPool = null; private Properties settings;
private String driver; private String driver;
private String serverURL; private String serverURL;
private String proxoolURL;
private String username; private String username;
private String password; private String password;
private int minConnections = 3; private int minConnections = 3;
...@@ -46,13 +47,13 @@ public class DefaultConnectionProvider implements ConnectionProvider { ...@@ -46,13 +47,13 @@ public class DefaultConnectionProvider implements ConnectionProvider {
*/ */
private boolean mysqlUseUnicode; private boolean mysqlUseUnicode;
private Object initLock = new Object();
/** /**
* Creates a new DefaultConnectionProvider. * Creates a new DefaultConnectionProvider.
*/ */
public DefaultConnectionProvider() { public DefaultConnectionProvider() {
loadProperties(); loadProperties();
System.setProperty("org.apache.commons.logging.LogFactory", "org.jivesoftware.util.log.util.CommonsLogFactory");
} }
public boolean isPooled() { public boolean isPooled() {
...@@ -60,71 +61,40 @@ public class DefaultConnectionProvider implements ConnectionProvider { ...@@ -60,71 +61,40 @@ public class DefaultConnectionProvider implements ConnectionProvider {
} }
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
if (connectionPool == null) { Connection connection = null;
// block until the init has been done try {
synchronized (initLock) { Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
// if still null, something has gone wrong try {
if (connectionPool == null) { connection = DriverManager.getConnection(proxoolURL, settings);
Log.error("DbConnectionDefaultPool.getConnection() was " + }
"called before the internal pool has been initialized or " + catch (SQLException e) {
"there was a problem connecting to the database."); Log.error("DbConnectionProvider: Error while getting connection: ", e);
// Attempt to connect again if setup was already done
if ("true".equals(JiveGlobals.getXMLProperty("setup"))) {
this.restart();
if (connectionPool == null) {
Log.error("Recovery logic failed to reconnect to the database.");
return null;
}
}
else {
return null;
}
}
} }
} }
catch (ClassNotFoundException e) {
return connectionPool.getConnection(); Log.error("DbConnectionProvider: Unable to find driver: ", e);
}
return connection;
} }
public void start() { public void start() {
// acquire lock so that no connections can be returned. proxoolURL = "proxool.openfire:"+getDriver()+":"+getServerURL();
synchronized (initLock) { settings = new Properties();
settings.setProperty("proxool.maximum-connection-count", Integer.toString(getMaxConnections()));
try { settings.setProperty("proxool.minimum-connection-count", Integer.toString(getMinConnections()));
connectionPool = new ConnectionPool(driver, serverURL, username, settings.setProperty("proxool.maximum-connection-lifetime", Integer.toString((int)(86400000 * getConnectionTimeout())));
password, minConnections, maxConnections, connectionTimeout, settings.setProperty("proxool.test-before-use", "true");
mysqlUseUnicode); settings.setProperty("proxool.test-after-use", "true");
} settings.setProperty("proxool.house-keeping-test-sql", "select 1");
catch (IOException e) { settings.setProperty("user", getUsername());
Log.error(e); settings.setProperty("password", getPassword());
}
}
} }
public void restart() { public void restart() {
// Kill off pool.
destroy();
// Reload properties.
loadProperties();
// Start a new pool.
start();
} }
public void destroy() { public void destroy() {
if (connectionPool != null) { settings = null;
try {
connectionPool.destroy();
}
catch (Exception e) {
Log.error(e);
}
}
// Release reference to connectionPool
connectionPool = null;
}
public void finalize() {
destroy();
} }
/** /**
...@@ -293,7 +263,7 @@ public class DefaultConnectionProvider implements ConnectionProvider { ...@@ -293,7 +263,7 @@ public class DefaultConnectionProvider implements ConnectionProvider {
String maxCons = JiveGlobals.getXMLProperty("database.defaultProvider.maxConnections"); String maxCons = JiveGlobals.getXMLProperty("database.defaultProvider.maxConnections");
String conTimeout = JiveGlobals.getXMLProperty("database.defaultProvider.connectionTimeout"); String conTimeout = JiveGlobals.getXMLProperty("database.defaultProvider.connectionTimeout");
// See if we should use Unicode under MySQL // See if we should use Unicode under MySQL
mysqlUseUnicode = Boolean.valueOf(JiveGlobals.getXMLProperty("database.mysql.useUnicode")).booleanValue(); mysqlUseUnicode = Boolean.valueOf(JiveGlobals.getXMLProperty("database.mysql.useUnicode"));
try { try {
if (minCons != null) { if (minCons != null) {
minConnections = Integer.parseInt(minCons); minConnections = Integer.parseInt(minCons);
...@@ -330,6 +300,6 @@ public class DefaultConnectionProvider implements ConnectionProvider { ...@@ -330,6 +300,6 @@ public class DefaultConnectionProvider implements ConnectionProvider {
} }
public String toString() { public String toString() {
return connectionPool.toString(); return "Default Connection Provider";
} }
} }
...@@ -19,6 +19,8 @@ import java.io.IOException; ...@@ -19,6 +19,8 @@ import java.io.IOException;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.sql.DriverManager;
import java.util.Properties;
/** /**
* A connection provider for the embedded hsqlDB database. The database file is stored at * A connection provider for the embedded hsqlDB database. The database file is stored at
...@@ -30,55 +32,56 @@ import java.sql.Statement; ...@@ -30,55 +32,56 @@ import java.sql.Statement;
*/ */
public class EmbeddedConnectionProvider implements ConnectionProvider { public class EmbeddedConnectionProvider implements ConnectionProvider {
private ConnectionPool connectionPool = null; private Properties settings;
private final Object initLock = new Object(); private String serverURL;
private String driver = "org.hsqldb.jdbcDriver";
private String proxoolURL;
public EmbeddedConnectionProvider() {
System.setProperty("org.apache.commons.logging.LogFactory", "org.jivesoftware.util.log.util.CommonsLogFactory");
}
public boolean isPooled() { public boolean isPooled() {
return true; return true;
} }
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
if (connectionPool == null) { Connection connection = null;
// Block until the init has been done try {
synchronized (initLock) { Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
// If still null, something has gone wrong try {
if (connectionPool == null) { connection = DriverManager.getConnection(proxoolURL, settings);
Log.error("Error: EmbeddedConnectionProvider.getConnection() was" + }
"called before the internal pool has been initialized."); catch (SQLException e) {
return null; Log.error("EmbeddedConnectionProvider: Error while getting connection: ", e);
}
} }
} }
return connectionPool.getConnection(); catch (ClassNotFoundException e) {
Log.error("EmbeddedConnectionProvider: Unable to find driver: ", e);
}
return connection;
} }
public void start() { public void start() {
// Acquire lock so that no connections can be returned while creating the pool. File databaseDir = new File(JiveGlobals.getHomeDirectory(), File.separator + "embedded-db");
synchronized (initLock) { // If the database doesn't exist, create it.
try { if (!databaseDir.exists()) {
String driver = "org.hsqldb.jdbcDriver"; databaseDir.mkdirs();
File databaseDir = new File(JiveGlobals.getHomeDirectory(), File.separator + }
"embedded-db");
// If the database doesn't exist, create it.
if (!databaseDir.exists()) {
databaseDir.mkdirs();
}
String serverURL = "jdbc:hsqldb:" + databaseDir.getCanonicalPath() +
File.separator + "openfire";
String username = "sa";
String password = "";
int minConnections = 3;
int maxConnections = 25;
double connectionTimeout = 0.5;
connectionPool = new ConnectionPool(driver, serverURL, username, password, try {
minConnections, maxConnections, connectionTimeout, false); serverURL = "jdbc:hsqldb:" + databaseDir.getCanonicalPath() + File.separator + "openfire";
} }
catch (IOException ioe) { catch (IOException ioe) {
Log.error("Error starting connection pool.", ioe); Log.error("EmbeddedConnectionProvider: Error starting connection pool: ", ioe);
}
} }
proxoolURL = "proxool.openfire:"+driver+":"+serverURL;
settings = new Properties();
settings.setProperty("proxool.maximum-connection-count", "25");
settings.setProperty("proxool.minimum-connection-count", "3");
settings.setProperty("proxool.maximum-connection-lifetime", Integer.toString((int)(86400000 * 0.5)));
settings.setProperty("user", "sa");
settings.setProperty("password", "");
} }
public void restart() { public void restart() {
...@@ -89,9 +92,6 @@ public class EmbeddedConnectionProvider implements ConnectionProvider { ...@@ -89,9 +92,6 @@ public class EmbeddedConnectionProvider implements ConnectionProvider {
} }
public void destroy() { public void destroy() {
if (connectionPool == null) {
return;
}
// Shutdown the database. // Shutdown the database.
Connection con = null; Connection con = null;
try { try {
...@@ -107,15 +107,8 @@ public class EmbeddedConnectionProvider implements ConnectionProvider { ...@@ -107,15 +107,8 @@ public class EmbeddedConnectionProvider implements ConnectionProvider {
try { if (con != null) { con.close(); } } try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); } catch (Exception e) { Log.error(e); }
} }
// Close the connection pool. // Blank out the settings
try { settings = null;
connectionPool.destroy();
}
catch (Exception e) {
Log.error(e);
}
// Release reference to connectionPool
connectionPool = null;
} }
public void finalize() throws Throwable { public void finalize() throws Throwable {
......
...@@ -89,6 +89,11 @@ ...@@ -89,6 +89,11 @@
<servlet-name>dwr-invoker</servlet-name> <servlet-name>dwr-invoker</servlet-name>
</filter-mapping> </filter-mapping>
<filter-mapping>
<filter-name>AuthCheck</filter-name>
<servlet-name>Proxool</servlet-name>
</filter-mapping>
<listener> <listener>
<listener-class>org.jivesoftware.openfire.XMPPContextListener</listener-class> <listener-class>org.jivesoftware.openfire.XMPPContextListener</listener-class>
...@@ -116,9 +121,23 @@ ...@@ -116,9 +121,23 @@
<servlet-class>org.jivesoftware.openfire.container.PluginIconServlet</servlet-class> <servlet-class>org.jivesoftware.openfire.container.PluginIconServlet</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>Proxool</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
<init-param>
<param-name>output</param-name>
<param-value>full</param-value>
</init-param>
</servlet>
<!--@@JSPC-SERVLETS@@--> <!--@@JSPC-SERVLETS@@-->
<servlet-mapping>
<servlet-name>Proxool</servlet-name>
<url-pattern>/proxool</url-pattern>
</servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>PluginServlet</servlet-name> <servlet-name>PluginServlet</servlet-name>
<url-pattern>/plugins/*</url-pattern> <url-pattern>/plugins/*</url-pattern>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment