From dcafbd7d9285aa7df3f5010642f1c1614e1147d0 Mon Sep 17 00:00:00 2001 From: Rich Tabedzki Date: Tue, 4 Apr 2017 10:09:50 +0000 Subject: [PATCH] [SDNC-5] summary Updated dblib code from 17.07 branch Change-Id: Ifa3ef1edbaa346bb4da388bdd9abe1dbdb165516 Signed-off-by: Rich Tabedzki --- dblib/features/src/main/resources/features.xml | 1 - .../sdnc/sli/resource/dblib/CachedDataSource.java | 159 +++++++-- .../sli/resource/dblib/DBLIBResourceActivator.java | 18 + .../sdnc/sli/resource/dblib/DBLibConnection.java | 390 +++++++++++++++++++++ .../sdnc/sli/resource/dblib/DBResourceManager.java | 147 +++----- .../dblib/NoAvailableConnectionsException.java | 36 ++ .../resource/dblib/factory/DBConfigFactory.java | 1 - .../dblib/jdbc/JdbcDBCachedDataSource.java | 4 +- 8 files changed, 614 insertions(+), 142 deletions(-) create mode 100644 dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibConnection.java create mode 100644 dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/NoAvailableConnectionsException.java diff --git a/dblib/features/src/main/resources/features.xml b/dblib/features/src/main/resources/features.xml index faa1e1c..d7f0030 100755 --- a/dblib/features/src/main/resources/features.xml +++ b/dblib/features/src/main/resources/features.xml @@ -12,7 +12,6 @@ odl-mdsal-broker mvn:org.openecomp.sdnc.core/dblib-common/${project.version} mvn:org.openecomp.sdnc.core/dblib-provider/${project.version} - mvn:org.openecomp.sdnc.core/dblib-common/${project.version} mvn:mysql/mysql-connector-java/${mysql.connector.version} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java index e21e2be..ee01c1b 100644 --- a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java @@ -20,12 +20,18 @@ package org.openecomp.sdnc.sli.resource.dblib; +import java.io.Closeable; +import java.io.IOException; import java.io.PrintWriter; +import java.io.StringWriter; +import java.sql.Blob; import java.sql.Connection; +import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.Observer; @@ -34,12 +40,14 @@ import javax.sql.DataSource; import javax.sql.rowset.CachedRowSet; import javax.sql.rowset.RowSetProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.tomcat.jdbc.pool.PoolExhaustedException; import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration; import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor; import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitorObserver; import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor.TestObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException; /** @@ -65,11 +73,15 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito protected boolean initialized = false; private long interval = 1000; - private long initisalDelay = 5000; + private long initialDelay = 5000; private long expectedCompletionTime = 50L; private boolean canTakeOffLine = true; private long unprocessedFailoverThreshold = 3L; + private long nextErrorReportTime = 0L; + + private String globalHostName = null; + public CachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException { @@ -86,7 +98,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito return ds.getConnection(); } - public CachedRowSet getData(String statement, ArrayList arguments) throws SQLException, Throwable + public CachedRowSet getData(String statement, ArrayList arguments) throws SQLException, Throwable { TestObject testObject = null; testObject = monitor.registerRequest(); @@ -99,7 +111,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } if(LOGGER.isDebugEnabled()) LOGGER.debug("Obtained connection <" + connectionName + ">: "+connection.toString()); - return executePreparedStatement(connection, statement, arguments); + return executePreparedStatement(connection, statement, arguments, true); } finally { try { if(connection != null && !connection.isClosed()) { @@ -115,7 +127,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } } - public boolean writeData(String statement, ArrayList arguments) throws SQLException, Throwable + public boolean writeData(String statement, ArrayList arguments) throws SQLException, Throwable { TestObject testObject = null; testObject = monitor.registerRequest(); @@ -128,7 +140,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } if(LOGGER.isDebugEnabled()) LOGGER.debug("Obtained connection <" + connectionName + ">: "+connection.toString()); - return executeUpdatePreparedStatement(connection, statement, arguments); + return executeUpdatePreparedStatement(connection, statement, arguments, true); } finally { try { if(connection != null && !connection.isClosed()) { @@ -144,7 +156,8 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } } - private CachedRowSet executePreparedStatement(Connection conn, String statement, ArrayList arguments) throws SQLException, Throwable { + CachedRowSet executePreparedStatement(Connection conn, String statement, ArrayList arguments, boolean close) throws SQLException, Throwable + { long time = System.currentTimeMillis(); CachedRowSet data = null; @@ -202,7 +215,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } try { - if(conn != null){ + if(conn != null && close){ conn.close(); conn = null; } @@ -214,7 +227,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito return data; } - private boolean executeUpdatePreparedStatement(Connection conn, String statement, ArrayList arguments) throws SQLException, Throwable { + boolean executeUpdatePreparedStatement(Connection conn, String statement, ArrayList arguments, boolean close) throws SQLException, Throwable { long time = System.currentTimeMillis(); CachedRowSet data = null; @@ -226,9 +239,21 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito if(arguments != null) { for(int i = 0, max = arguments.size(); i < max; i++){ + if(arguments.get(i) instanceof Blob) { + ps.setBlob(i+1, (Blob)arguments.get(i)); + } else if(arguments.get(i) instanceof Timestamp) { + ps.setTimestamp(i+1, (Timestamp)arguments.get(i)); + } else if(arguments.get(i) instanceof Integer) { + ps.setInt(i+1, (Integer)arguments.get(i)); + } else if(arguments.get(i) instanceof Long) { + ps.setLong(i+1, (Long)arguments.get(i)); + } else if(arguments.get(i) instanceof Date) { + ps.setDate(i+1, (Date)arguments.get(i)); + } else { ps.setObject(i+1, arguments.get(i)); } } + } rs = ps.executeUpdate(); // Point the rowset Cursor to the start if(LOGGER.isDebugEnabled()){ @@ -256,9 +281,8 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } throw exc; // new SQLException(exc); } finally { - try { - if(conn != null){ + if(conn != null && close){ conn.close(); conn = null; } @@ -321,6 +345,13 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } public void cleanUp(){ + if(ds != null && ds instanceof Closeable) { + try { + ((Closeable)ds).close(); + } catch (IOException e) { + LOGGER.warn(e.getMessage()); + } + } ds = null; monitor.deleteObservers(); monitor.cleanup(); @@ -349,11 +380,10 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito { readOnly = rs.getBoolean(1); hostname = rs.getString(2); -// if(rs.getInt(1)==1){ + if(LOGGER.isDebugEnabled()){ LOGGER.debug("SQL DataSource <"+getDbConnectionName() + "> connected to " + hostname + ", read-only is " + readOnly + ", tested successfully "); } -// } } } catch (Throwable exc) { @@ -421,7 +451,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } public long getInitialDelay() { - return initisalDelay; + return initialDelay; } public void setInterval(long value) { @@ -429,7 +459,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito } public void setInitialDelay(long value) { - initisalDelay = value; + initialDelay = value; } public long getExpectedCompletionTime() { @@ -477,29 +507,20 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito return monitor; } - protected boolean isSlave() { + protected boolean isSlave() throws PoolExhaustedException, MySQLNonTransientConnectionException { CachedRowSet rs = null; boolean isSlave = true; String hostname = "UNDETERMINED"; try { -// rs = this.getData("show slave status", new ArrayList()); -// while(rs.next()) { -// String master = rs.getString(2); -// LOGGER.debug("database <"+connectionName+"> defines master as " + master); -// if(master == null || master.isEmpty() || master.equals(this.getDbConnectionName())) { -// isSlave = false; -// } else { -// isSlave = true; -// } -// } - boolean localSlave = true; - rs = this.getData("SELECT @@global.read_only, @@global.hostname", new ArrayList()); + rs = this.getData("SELECT @@global.read_only, @@global.hostname", new ArrayList()); while(rs.next()) { localSlave = rs.getBoolean(1); hostname = rs.getString(2); } isSlave = localSlave; + } catch(PoolExhaustedException | MySQLNonTransientConnectionException peexc){ + throw peexc; } catch (SQLException e) { LOGGER.error("", e); isSlave = true; @@ -508,14 +529,88 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito isSlave = true; } if(isSlave){ - LOGGER.debug("SQL SLAVE : "+connectionName + " on server " + hostname); + LOGGER.debug("SQL SLAVE : "+connectionName + " on server " + hostname); } else { - LOGGER.debug("SQL MASTER : "+connectionName + " on server " + hostname); + LOGGER.debug("SQL MASTER : "+connectionName + " on server " + hostname); } return isSlave; } - + public boolean isFabric() { return false; } + + protected boolean lockTable(Connection conn, String tableName) { + boolean retValue = false; + Statement lock = null; + try { + if(tableName != null) { + if(LOGGER.isDebugEnabled()) { + LOGGER.debug("Executing 'LOCK TABLES " + tableName + " WRITE' on connection " + conn.toString()); + if("SVC_LOGIC".equals(tableName)) { + Exception e = new Exception(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + LOGGER.debug(sw.toString()); + } + } + lock = conn.createStatement(); + lock.execute("LOCK TABLES " + tableName + " WRITE"); + retValue = true; + } + } catch(Exception exc){ + LOGGER.error("", exc); + retValue = false; + } finally { + try { + lock.close(); + } catch(Exception exc) { + + } + } + return retValue; + } + + protected boolean unlockTable(Connection conn) { + boolean retValue = false; + Statement lock = null; + try { + if(LOGGER.isDebugEnabled()) { + LOGGER.debug("Executing 'UNLOCK TABLES' on connection " + conn.toString()); + } + lock = conn.createStatement(); + retValue = lock.execute("UNLOCK TABLES"); + } catch(Exception exc){ + LOGGER.error("", exc); + retValue = false; + } finally { + try { + lock.close(); + } catch(Exception exc) { + + } + } + return retValue; + } + + public void getPoolInfo(boolean allocation) { + + } + + public long getNextErrorReportTime() { + return nextErrorReportTime; + } + + public void setNextErrorReportTime(long nextTime) { + this.nextErrorReportTime = nextTime; + } + + public void setGlobalHostName(String hostname) { + this.globalHostName = hostname; + } + + public String getGlobalHostName() { + return globalHostName; + } } diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java index 85cf834..ea4c52c 100644 --- a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java @@ -26,6 +26,7 @@ import java.util.Properties; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -104,6 +105,23 @@ public class DBLIBResourceActivator implements BundleActivator { LOG.info("entering DBLIBResourceActivator.stop"); if (registration != null) { + try { + ServiceReference sref = ctx.getServiceReference(DbLibService.class.getName()); + + if (sref == null) { + LOG.warn("Could not find service reference for DBLIB service (" + DbLibService.class.getName() + ")"); + } else { + DBResourceManager dblibSvc = (DBResourceManager) ctx.getService(sref); + if (dblibSvc == null) { + LOG.warn("Could not find service reference for DBLIB service (" + DbLibService.class.getName() + ")"); + } else { + dblibSvc.cleanUp(); + } + } + } catch(Throwable exc) { + LOG.warn("Cleanup", exc); + } + registration.unregister(); registration = null; LOG.debug("Deregistering DBResourceManager service"); diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibConnection.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibConnection.java new file mode 100644 index 0000000..5c1f510 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibConnection.java @@ -0,0 +1,390 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.ArrayList; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +import javax.sql.rowset.CachedRowSet; + +import org.apache.tomcat.jdbc.pool.PooledConnection; +import org.apache.tomcat.jdbc.pool.ProxyConnection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DBLibConnection implements Connection { + + private static Logger LOGGER = LoggerFactory.getLogger(DBLibConnection.class); + + private final Connection connection; + private final CachedDataSource dataSource; + private boolean locked = false; + private String tableName = null; + + public DBLibConnection(Connection con, CachedDataSource dataSource){ + this.connection = con; + this.dataSource = dataSource; + locked = false; + dataSource.getPoolInfo(true); + } + + public boolean lockTable(String tablename) { + this.tableName = tablename; + return locked = dataSource.lockTable(connection, tableName); + } + + public void resetInactivityTimer() { + Class iface = PooledConnection.class; + try { + PooledConnection pc = connection.unwrap(iface); + pc.setTimestamp(System.currentTimeMillis()); + } catch (SQLException e) { + LOGGER.warn("Failed resetting timeout timer", e); + } + } + + public boolean unlock() { + dataSource.unlockTable(connection); + return locked = false; + } + + public boolean writeData(String statement, ArrayList arguments) throws SQLException, Throwable + { + ArrayList newList=new ArrayList(); + if(arguments != null && !arguments.isEmpty()) { + newList.addAll(arguments); + } + resetInactivityTimer(); + return dataSource.executeUpdatePreparedStatement(connection, statement, newList, false); + } + + public CachedRowSet getData(String statement, ArrayList arguments) throws SQLException, Throwable + { + ArrayList newList=new ArrayList(); + if(arguments != null && !arguments.isEmpty()) { + newList.addAll(arguments); + } + resetInactivityTimer(); + return dataSource.executePreparedStatement(connection, statement, newList, false); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return connection.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return connection.isWrapperFor(iface); + } + + @Override + public Statement createStatement() throws SQLException { + return connection.createStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + return connection.prepareStatement(sql); + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + return connection.prepareCall(sql); + } + + @Override + public String nativeSQL(String sql) throws SQLException { + return connection.nativeSQL(sql); + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + connection.setAutoCommit(autoCommit); + } + + @Override + public boolean getAutoCommit() throws SQLException { + return connection.getAutoCommit(); + } + + @Override + public void commit() throws SQLException { + connection.commit(); + } + + @Override + public void rollback() throws SQLException { + connection.rollback(); + } + + @Override + public void close() throws SQLException { + if(this.locked) { + try { + this.unlock(); + } catch(Throwable th) { + LOGGER.error("Failed unlocking",th); + } + } + if(connection != null && !connection.isClosed()) { + connection.close(); + } + dataSource.getPoolInfo(false); + } + + @Override + public boolean isClosed() throws SQLException { + return connection.isClosed(); + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + return connection.getMetaData(); + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + connection.setReadOnly(readOnly); + } + + @Override + public boolean isReadOnly() throws SQLException { + return connection.isReadOnly(); + } + + @Override + public void setCatalog(String catalog) throws SQLException { + connection.setCatalog(catalog); + } + + @Override + public String getCatalog() throws SQLException { + return connection.getCatalog(); + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + connection.setTransactionIsolation(level); + } + + @Override + public int getTransactionIsolation() throws SQLException { + return connection.getTransactionIsolation(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return connection.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + connection.clearWarnings(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return connection.createStatement(resultSetType, resultSetConcurrency); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + return connection.prepareStatement(sql, resultSetType, resultSetConcurrency); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return connection.prepareCall(sql, resultSetType, resultSetConcurrency); + } + + @Override + public Map> getTypeMap() throws SQLException { + return connection.getTypeMap(); + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + connection.setTypeMap(map); + } + + @Override + public void setHoldability(int holdability) throws SQLException { + connection.setHoldability(holdability); + } + + @Override + public int getHoldability() throws SQLException { + return connection.getHoldability(); + } + + @Override + public Savepoint setSavepoint() throws SQLException { + return connection.setSavepoint(); + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + return connection.setSavepoint(name); + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + connection.rollback(savepoint); + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + connection.releaseSavepoint(savepoint); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + return connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + return connection.prepareStatement(sql, autoGeneratedKeys); + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + return connection.prepareStatement(sql, columnIndexes); + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + return connection.prepareStatement(sql, columnNames); + } + + @Override + public Clob createClob() throws SQLException { + return connection.createClob(); + } + + @Override + public Blob createBlob() throws SQLException { + return connection.createBlob(); + } + + @Override + public NClob createNClob() throws SQLException { + return connection.createNClob(); + } + + @Override + public SQLXML createSQLXML() throws SQLException { + return connection.createSQLXML(); + } + + @Override + public boolean isValid(int timeout) throws SQLException { + return connection.isValid(timeout); + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + connection.setClientInfo(name, value); + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + connection.setClientInfo(properties); + } + + @Override + public String getClientInfo(String name) throws SQLException { + return connection.getClientInfo(name); + } + + @Override + public Properties getClientInfo() throws SQLException { + return connection.getClientInfo(); + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return connection.createArrayOf(typeName, elements); + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return connection.createStruct(typeName, attributes); + } + + @Override + public void setSchema(String schema) throws SQLException { + connection.setSchema(schema); + } + + @Override + public String getSchema() throws SQLException { + return connection.getSchema(); + } + + @Override + public void abort(Executor executor) throws SQLException { + connection.abort(executor); + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + connection.setNetworkTimeout(executor, milliseconds); + } + + @Override + public int getNetworkTimeout() throws SQLException { + return connection.getNetworkTimeout(); + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java index 401c013..3c3ef94 100644 --- a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java @@ -38,18 +38,22 @@ import java.util.PriorityQueue; import java.util.Properties; import java.util.Queue; import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import javax.sql.DataSource; import javax.sql.rowset.CachedRowSet; +import org.apache.tomcat.jdbc.pool.PoolExhaustedException; import org.openecomp.sdnc.sli.resource.dblib.config.DbConfigPool; import org.openecomp.sdnc.sli.resource.dblib.factory.AbstractDBResourceManagerFactory; import org.openecomp.sdnc.sli.resource.dblib.factory.AbstractResourceManagerFactory; import org.openecomp.sdnc.sli.resource.dblib.factory.DBConfigFactory; import org.openecomp.sdnc.sli.resource.dblib.pm.PollingWorker; import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor; +import com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -280,21 +284,22 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } } - /* (non-Javadoc) - * @see org.openecomp.dblib.DataAccessor#getData(java.lang.String, java.util.ArrayList) - */ /* (non-Javadoc) * @see org.openecomp.sdnc.sli.resource.dblib.DbLibService#getData(java.lang.String, java.util.ArrayList, java.lang.String) */ @Override public CachedRowSet getData(String statement, ArrayList arguments, String preferredDS) throws SQLException { + ArrayList newList=new ArrayList(); + if(arguments != null && !arguments.isEmpty()) { + newList.addAll(arguments); + } if(recoveryMode) - return requestDataWithRecovery(statement, arguments, preferredDS); + return requestDataWithRecovery(statement, newList, preferredDS); else - return requestDataNoRecovery(statement, arguments, preferredDS); + return requestDataNoRecovery(statement, newList, preferredDS); } - private CachedRowSet requestDataWithRecovery(String statement, ArrayList arguments, String preferredDS) throws SQLException { + private CachedRowSet requestDataWithRecovery(String statement, ArrayList arguments, String preferredDS) throws SQLException { Throwable lastException = null; CachedDataSource active = null; @@ -346,7 +351,7 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } finally { if(LOGGER.isDebugEnabled()){ time = (System.currentTimeMillis() - time); - LOGGER.debug(">> getData : "+ active.getDbConnectionName()+" "+time+" miliseconds."); + LOGGER.debug("getData processing time : "+ active.getDbConnectionName()+" "+time+" miliseconds."); } } } @@ -369,7 +374,7 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } } - private CachedRowSet requestDataNoRecovery(String statement, ArrayList arguments, String preferredDS) throws SQLException { + private CachedRowSet requestDataNoRecovery(String statement, ArrayList arguments, String preferredDS) throws SQLException { if(dsQueue.isEmpty()){ LOGGER.error("Generated alarm: DBResourceManager.getData - No active DB connection pools are available."); throw new DBLibException("No active DB connection pools are available in RequestDataNoRecovery call."); @@ -406,18 +411,21 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } - /* (non-Javadoc) - * @see org.openecomp.dblib.DataAccessor#writeData(java.lang.String, java.util.ArrayList) - */ /* (non-Javadoc) * @see org.openecomp.sdnc.sli.resource.dblib.DbLibService#writeData(java.lang.String, java.util.ArrayList, java.lang.String) */ @Override - public boolean writeData(String statement, ArrayList arguments, String preferredDS) throws SQLException { - return writeDataNoRecovery(statement, arguments, preferredDS); + public boolean writeData(String statement, ArrayList arguments, String preferredDS) throws SQLException + { + ArrayList newList=new ArrayList(); + if(arguments != null && !arguments.isEmpty()) { + newList.addAll(arguments); + } + + return writeDataNoRecovery(statement, newList, preferredDS); } - CachedDataSource findMaster() { + CachedDataSource findMaster() throws PoolExhaustedException, MySQLNonTransientConnectionException { CachedDataSource master = null; CachedDataSource[] dss = this.dsQueue.toArray(new CachedDataSource[0]); for(int i=0; i arguments, String preferredDS) throws SQLException { + private boolean writeDataNoRecovery(String statement, ArrayList arguments, String preferredDS) throws SQLException { if(dsQueue.isEmpty()){ LOGGER.error("Generated alarm: DBResourceManager.getData - No active DB connection pools are available."); throw new DBLibException("No active DB connection pools are available in RequestDataNoRecovery call."); @@ -485,7 +493,7 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } finally { if(LOGGER.isDebugEnabled()){ time = (System.currentTimeMillis() - time); - LOGGER.debug(">> getData : "+ active.getDbConnectionName()+" "+time+" miliseconds."); + LOGGER.debug("writeData processing time : "+ active.getDbConnectionName()+" "+time+" miliseconds."); } } } @@ -514,19 +522,25 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb if(tmpActive != null) { active = tmpActive; } - return active.getConnection(); + return new DBLibConnection(active.getConnection(), active); } catch(javax.sql.rowset.spi.SyncFactoryException exc){ LOGGER.debug("Free memory (bytes): " + Runtime.getRuntime().freeMemory()); LOGGER.warn("CLASSPATH issue. Allowing retry", exc); lastException = exc; + } catch(PoolExhaustedException exc) { + throw new NoAvailableConnectionsException(exc); + } catch(MySQLNonTransientConnectionException exc){ + throw new NoAvailableConnectionsException(exc); } catch(Exception exc){ lastException = exc; if(recoveryMode){ handleGetConnectionException(active, exc); } else { - if(exc instanceof SQLException) + if(exc instanceof MySQLNonTransientConnectionException) { + throw new NoAvailableConnectionsException(exc); + } if(exc instanceof SQLException) { throw (SQLException)exc; - else { + } else { DBLibException excptn = new DBLibException(exc.getMessage()); excptn.setStackTrace(exc.getStackTrace()); throw excptn; @@ -779,7 +793,7 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb return ""; } - private String getPreferredDataSourceName(AtomicBoolean flipper) { + public String getPreferredDataSourceName(AtomicBoolean flipper) { LinkedList snapshot = new LinkedList(dsQueue); if(snapshot.size() > 1){ @@ -839,90 +853,11 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb return snapshot.peek().getDbConnectionName(); } - /* - private void runTest(){ - Thread producer = null; - - producer = new ProducerThread("Prod1"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Prod2"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Prod3"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Prod4"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Prod5"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Prod6"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Prod7"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Prod8"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Prod9"); - producer.setDaemon(true); - producer.start(); - - producer = new ProducerThread("Pro10"); - producer.setDaemon(true); - producer.start(); - - } - - private final class ProducerThread extends Thread { - private ProducerThread(String threadName) { - super(threadName); - } - - public void run() - { - String name = null; - for(int i=0; i<(Integer.MAX_VALUE-1); i++) - { - try { - name = getPreferredDataSourceName(dsSelector); - if(name.contains("BACK")){ - LOGGER.error(this.getName()+": <====== "); - } else { - LOGGER.error(this.getName()+": ======>"); - } - CachedRowSet rs = null; - rs = getData("select 1 from dual", new ArrayList(), name); - rs.close(); - rs = getData("select 1 from dual", new ArrayList(), name); - rs.close(); - rs = getData("select 1 from dual", new ArrayList(), name); - rs.close(); - rs = getData("select 1 from dual", new ArrayList(), name); - rs.close(); - } catch (Exception e) { - e.printStackTrace(); - } - - try { - Thread.sleep(50L); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - return; - } - } -*/ + class RemindTask extends TimerTask { + public void run() { + CachedDataSource ds = dsQueue.peek(); + if(ds != null) + ds.getPoolInfo(false); + } + } } diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/NoAvailableConnectionsException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/NoAvailableConnectionsException.java new file mode 100644 index 0000000..16895b4 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/NoAvailableConnectionsException.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.sql.SQLException; + +public class NoAvailableConnectionsException extends SQLException { + + /** + * + */ + private static final long serialVersionUID = -6259205931674413018L; + + public NoAvailableConnectionsException(Exception exc) { + super(exc); + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java index 3530459..8aadcae 100644 --- a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java @@ -45,7 +45,6 @@ public class DBConfigFactory { } static DbConfigPool getConfigparams(Properties properties){ - LoggerFactory.getLogger(DBConfigFactory.class).info(properties.toString()); DbConfigPool xmlConfig = new DbConfigPool(properties); ArrayList propertySets = new ArrayList(); diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java index ee3d4ff..42c3447 100644 --- a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java @@ -7,9 +7,9 @@ * 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. -- 2.16.6