/*
* Copyright 2010 Proofpoint, Inc.
*
* Licensed 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 io.airlift.dbpool;
import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
import io.airlift.discovery.client.ServiceDescriptor;
import io.airlift.discovery.client.ServiceSelector;
import javax.sql.PooledConnection;
import java.sql.SQLException;
import java.util.UUID;
public class MySqlDataSource extends ManagedDataSource
{
private final ServiceSelector serviceSelector;
private final int defaultFetchSize;
private UUID currentServer;
private MysqlConnectionPoolDataSource dataSource;
public MySqlDataSource(ServiceSelector serviceSelector, MySqlDataSourceConfig config)
{
super(config.getMaxConnections(), config.getMaxConnectionWait());
this.serviceSelector = serviceSelector;
this.defaultFetchSize = config.getDefaultFetchSize();
}
protected PooledConnection createConnectionInternal()
throws SQLException
{
// attempt to get a connection from the current datasource if we have one
SQLException lastException = null;
if (dataSource != null) {
try {
return dataSource.getPooledConnection();
}
catch (SQLException e) {
lastException = e;
}
}
// drop reference to current datasource
dataSource = null;
// attempt to create a connection to each mysql server (except for the one that we know is bad)
for (ServiceDescriptor serviceDescriptor : serviceSelector.selectAllServices()) {
// skip the current server since it is having problems
if (serviceDescriptor.getId().equals(currentServer)) {
continue;
}
// skip bogus announcements
String jdbcUrl = serviceDescriptor.getProperties().get("jdbc");
if (jdbcUrl == null) {
continue;
}
try {
MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource();
dataSource.setUrl(jdbcUrl);
// these are in MS *not* seconds like everything else in JDBC
dataSource.setConnectTimeout(getMaxConnectionWaitMillis());
dataSource.setInitialTimeout(getMaxConnectionWaitMillis());
dataSource.setDefaultFetchSize(defaultFetchSize);
PooledConnection connection = dataSource.getPooledConnection();
// that worked so save the datasource and server id
this.dataSource = dataSource;
this.currentServer = serviceDescriptor.getId();
return connection;
}
catch (SQLException e) {
lastException = e;
}
}
// no servers found, clear the current server id since we no longer have a server at all
currentServer = null;
// throw the last exception we got
if (lastException != null) {
throw lastException;
}
throw new SQLException(String.format("No mysql servers of type '%s' available in pool '%s'", serviceSelector.getType(), serviceSelector.getPool()));
}
}