jackrabbit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Matej Knopp" <matej.kn...@gmail.com>
Subject Re: Connection pooling
Date Mon, 21 Jul 2008 23:39:13 GMT
Hi,

The idea of Jackrabbit managing DataSources didn't gain much support,
so I decided to try implementing something much less intrusive. I have
abstracted connection creation/closing (ConnectionProvider[1]) from
the components that use database connections. There is one instance of
ConnectionProvider per repository, configurable in repository.xml, but
possibly with a sane default implementation so no configuration is
necessary.

The rest of jackrabbit (components that touch the database) would use
ConnectionProvider to get the connections instead of just creating
them and keeping opened. So far I've converted
BundleDbPersistenceManager (and it's subclasses) to this approach. I
would also tweak DatabasePersistenceManager  and DbFileSystem to just
borrow the connections instead of keeping them. As for journal,
keeping one opened connection per repository probably doesn't make
much difference.

The benefit of this approach is that there is zero change in
repository configuration, unless user wants to specify it's own
ConnectionProvider class, which can be specified as a simple bean with
element name ConnectionProvider.

ConnectionProvider implementation that supports pooling must take
different things into account, such as there can be request to various
connections from different databases with different URLs. The manager
must be intelligent enough to possibly maintain group of pools (e..g
per database or even per connection URL)

There is a SimplePoolingConnectionProvider implementation  included in
the patch that implements connection pooling, but it's only meant as
proof of concept and doesn't try to substitute "real" connection
pooling alternatives (dbcp, etc.)

I've attached the first patch to https://issues.apache.org/jira/browse/JCR-1456

Kind regards,
-Matej

[1] ConnectionProvider class

/**
 * Class responsible for providing SQL {@link Connection}s.
 * <p>
 * Implementation of this class can do connection pooling, in which case it must
 * take {@link ConnectionProperties} into account and only return connection
 * that matches the specified properties.
 */
public interface ConnectionProvider {

    /**
     * Returns connection with given properties.
     *
     * @param properties
     *            connection properties
     * @return SQL {@link Connection}
     *
     * @throws RepositoryException
     * @throws SQLException
     */
    public Connection getConnection(ConnectionProperties properties)
            throws RepositoryException, SQLException;

    /**
     * Closes the given connection. Classes that obtain connections through
     * {@link ConnectionProvider} must never call {@link Connection#close()}
     * directly. They are required to call {@link #closeConnection(Connection)}
     * instead.
     *
     * @param connection
     *            SQL {@link Connection}
     *
     * @throws SQLException
     */
    public void closeConnection(Connection connection) throws SQLException;

    /**
     * Invoked when the repository is being shut down.
     *
     * @throws RepositoryException
     */
    public void dispose() throws RepositoryException;

    /**
     * Bean that holds properties necessary to create or identify a SQL
     * {@link Connection}.
     */
    public final static class ConnectionProperties {
        private String user;
        private String password;
        private String url;
        private String driver;

        public String getUser() {
            return user;
        }

        public void setUser(String user) {
            this.user = user;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public void setDriver(String driver) {
            this.driver = driver;
        }

        public String getDriver() {
            return driver;
        }

        private boolean equals(String s1, String s2) {
            return s1 == s2 || (s1 != null && s1.equals(s2));
        }

        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof ConnectionProperties == false) {
                return false;
            }
            ConnectionProperties cp = (ConnectionProperties) obj;
            return equals(user, cp.user) && equals(password, cp.password)
                    && equals(url, cp.url) && equals(driver, cp.driver);

        }

        private int hashCode(String s) {
            return s != null ? s.hashCode() : 0;
        }

        public int hashCode() {
            return hashCode(user) + 37 * hashCode(password) + 373
                    & hashCode(url) + 1187 * hashCode(driver);
        }
    }
}

Mime
View raw message