Java tutorial
/** * 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 com.pinterest.pinlater.backends.mysql; import com.pinterest.pinlater.commons.jdbc.JdbcUtils; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.dbcp.BasicDataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Connection; import java.sql.SQLException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.sql.DataSource; /** * Helper class used by the PinLaterMySQLBackend to encapsulate JDBC data sources. */ public class MySQLDataSources { private static final Logger LOG = LoggerFactory.getLogger(MySQLDataSources.class); private final DataSource generalDataSource; private final DataSource monitorDataSource; private final String host; private final int port; private final String user; private final String passwd; private final AtomicBoolean dequeueOnly; public MySQLDataSources(PropertiesConfiguration configuration, String host, int port, String user, String passwd, boolean dequeueOnly) { int numGeneralConnections = configuration.getInt("BACKEND_CONNECTIONS_PER_SHARD"); int generalSocketTimeoutMillis = (int) TimeUnit.SECONDS .toMillis(configuration.getInt("BACKEND_SOCKET_TIMEOUT_SECONDS")); int numMonitorConnections = configuration.getInt("MONITOR_CONNECTIONS_PER_SHARD", 3); int monitorSocketTimeoutMillis = (int) TimeUnit.SECONDS .toMillis(configuration.getInt("MONITOR_SOCKET_TIMEOUT_SECONDS", 10)); int maxWaitMillis = configuration.getInt("BACKEND_CONNECTION_MAX_WAIT_MILLIS"); this.generalDataSource = createDataSource(host, port, user, passwd, numGeneralConnections, maxWaitMillis, generalSocketTimeoutMillis); this.monitorDataSource = createDataSource(host, port, user, passwd, numMonitorConnections, maxWaitMillis, monitorSocketTimeoutMillis); this.host = host; this.port = port; this.user = user; this.passwd = passwd; this.dequeueOnly = new AtomicBoolean(dequeueOnly); } public DataSource getGeneralDataSource() { return generalDataSource; } public DataSource getMonitorDataSource() { return monitorDataSource; } public boolean isDequeueOnly() { return dequeueOnly.get(); } public void setDequeueOnly(Boolean dequeueOnly) { this.dequeueOnly.set(dequeueOnly); } // NOTE: We don't check dequeueOnly here because it should be configurable while maintaining // the connection. public boolean needNewConnection(String host, int port, String user, String passwd) { return this.host.equals(host) && this.port == port && this.user.equals(user) && this.passwd.equals(passwd); } // NOTE: We intentionally clone this method from DataSourceUtil, since we want to carefully // control data source and ConnectorJ configuration. private static DataSource createDataSource(String host, int port, String user, String passwd, int poolSize, int maxWaitMillis, int socketTimeoutMillis) { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource .setUrl(String.format( "jdbc:mysql://%s:%d?" + "connectTimeout=5000&" + "socketTimeout=%d&" + "enableQueryTimeouts=false&" + "cachePrepStmts=true&" + "characterEncoding=UTF-8", host, port, socketTimeoutMillis)); dataSource.setUsername(user); dataSource.setPassword(passwd); dataSource.setDefaultAutoCommit(true); dataSource.setInitialSize(poolSize); dataSource.setMaxActive(poolSize); dataSource.setMaxIdle(poolSize); // deal with idle connection eviction dataSource.setValidationQuery("SELECT 1 FROM DUAL"); dataSource.setTestOnBorrow(false); dataSource.setTestOnReturn(false); dataSource.setTestWhileIdle(true); dataSource.setMinEvictableIdleTimeMillis(5 * 60 * 1000); dataSource.setTimeBetweenEvictionRunsMillis(3 * 60 * 1000); dataSource.setNumTestsPerEvictionRun(poolSize); // max wait in milliseconds for a connection. dataSource.setMaxWait(maxWaitMillis); // force connection pool initialization. Connection conn = null; try { // Here not getting the connection from ThreadLocal no need to worry about that. conn = dataSource.getConnection(); } catch (SQLException e) { LOG.error(String.format( "Failed to get a mysql connection when creating DataSource, " + "host: %s, port: %d", host, port), e); } finally { JdbcUtils.closeConnection(conn); } return dataSource; } }