Hi Karl,

I've prototyped the integration of the HikariCP JDBC connection pool [1]. For details you can have a look at the attached file ConnectionFactory.java.

There are two additional dependencies needed in order to get this run:

>    <dependency>
>        <groupId>com.zaxxer</groupId>
>        <artifactId>HikariCP-java6</artifactId>
>        <version>2.3.8</version>
>        <scope>compile</scope>
>    </dependency>
>    <dependency>
>        <groupId>org.javassist</groupId>
>        <artifactId>javassist</artifactId>
>        <version>3.18.1-GA</version>
>        <scope>runtime</scope>
>    </dependency>

To get this well done, I would like to change the initialization of the data source into the following style:

>    HikariConfig config = new HikariConfig("some/path/hikari.properties");
>    HikariDataSource ds = new HikariDataSource(config);

At least I would like to make sure this core changes do work stable. Do you see any gaps or issues with this approach? Which test essential cases do I need to run?

BTW: I think the test case RSSFlakyHSQLDBIT switches between an "exception"-mode and a "non-exception"-mode, but does not turn off the database and restarting it. So all the connections within the pool will be alive anyways. Very likely I've missed something important, so please correct me, if my assumption is wrong. I'm new to ManifoldCF ;-)

-Rüdiger

[1] https://github.com/brettwooldridge/HikariCP


On Thu, May 21, 2015 at 1:47 PM, Karl Wright <[email protected]> wrote:

> I should also mention that I've done *precisely* the test you
> describe against PostgreSQL -- shutting the database down in the
> middle of a crawl, and restarting it.  Everything works fine in that
> case -- the PostgreSQL JDBC driver seems quite able to reestablish
> connections that have gone stale.  It's just MySQL that doesn't do it
> properly, apparently.
>
> Karl
>
>
> On Thu, May 21, 2015 at 6:49 AM, Karl Wright <[email protected]>
> wrote:
>
>> The test is:
>>
>> RSSFlakyHSQLDBIT
>>
>> It's one of the RSS connector tests, and simulates database
>> interruption by way of a replacing the HSQLDB database instance with
>> one that generates database errors when told to.
>>
>> Karl
>>
>>
>> On Thu, May 21, 2015 at 6:02 AM, <[email protected]>
>> wrote:
>>
>>> Hi Karl,
>>>
>>> could you please point us to the test case class, that checks the
>>> reconnect capabilty?
>>>
>>> Thanks in advance!
>>> -Rüdiger
/* $Id: ConnectionFactory.java 988245 2010-08-23 18:39:35Z kwright $ */

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.manifoldcf.core.database;

import java.sql.SQLException;
import java.util.concurrent.ExecutionException;

import org.apache.manifoldcf.core.interfaces.ManifoldCFException;
import org.apache.manifoldcf.core.jdbcpool.WrappedConnection;
import org.apache.manifoldcf.core.system.Logging;
import org.apache.manifoldcf.core.system.ManifoldCF;

import com.zaxxer.hikari.HikariDataSource;

/**
 * This class creates a connection, and may at our discretion manage a 
connection pool someday.
 */
public class ConnectionFactory {

    public static final String      _rcsid = "@(#)$Id: ConnectionFactory.java 
988245 2010-08-23 18:39:35Z kwright $";

    private static HikariDataSource datasource;

    private ConnectionFactory() {

        // noop
    }

    public static WrappedConnection getConnection(String jdbcUrl, String 
jdbcDriver, String database, String userName, String password, int 
maxDBConnections, boolean debug) throws ManifoldCFException {

        try {
            if (datasource == null) {
                datasource = new HikariDataSource();
                datasource.setJdbcUrl(jdbcUrl);
                datasource.setUsername(userName);
                datasource.setPassword(password);
            }

            return getConnectionWithRetries();

        } catch (SQLException e) {
            throw new ManifoldCFException("Error getting connection: " + 
e.getMessage(), e, ManifoldCFException.DATABASE_CONNECTION_ERROR);
        } catch (InterruptedException e) {
            throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, 
ManifoldCFException.INTERRUPTED);
        } catch (ExecutionException e) {
            throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, 
ManifoldCFException.INTERRUPTED);
        }
    }

    protected static WrappedConnection getConnectionWithRetries() throws 
SQLException, InterruptedException, ExecutionException {

        // If we have a problem, we will wait a grand total of 30 seconds
        int retryCount = 3;
        while (true) {
            try {
                return new WrappedConnection(null, datasource.getConnection());
            } catch (SQLException e) {
                if (retryCount == 0) {
                    throw e;
                }
                // Eat the exception and try again
                retryCount--;
            }
            // Ten seconds is a long time
            ManifoldCF.sleep(10000L);
        }
    }

    public static void releaseConnection(WrappedConnection c) throws 
ManifoldCFException {

        try {
            if (c.getConnection() != null) {
                c.getConnection().close();
            }
        } catch (SQLException e) {
            Logging.db.debug("SQL Exception when try to close connection.", e);
        }
    }

    public static void releaseAll() {

        // nothing to do here
    }
}

Reply via email to