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
}
}