summaryrefslogtreecommitdiffstats
path: root/dblib/provider
diff options
context:
space:
mode:
authorDan Timoney <dtimoney@att.com>2017-07-18 19:40:01 -0400
committerDan Timoney <dtimoney@att.com>2017-07-20 16:05:57 -0400
commit2a93b9ddf308b6bdd135be182c1b3fa779891840 (patch)
tree0333ca07b5858e94e21daad13d32cdacf995861f /dblib/provider
parentf5882cb4cd6338dcd9780c770056f4047c9ff174 (diff)
Populate seed code
Add seed code for sli/core repository Issue: CCSDK-6 Change-Id: Iaeb54c6135a94a6ffec0c7fd96505d72d18aeb00 Signed-off-by: Dan Timoney <dtimoney@att.com>
Diffstat (limited to 'dblib/provider')
-rwxr-xr-xdblib/provider/pom.xml82
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java616
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSourceFactory.java45
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBConfigException.java47
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java130
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibConnection.java390
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibException.java39
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java862
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceObserver.java27
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataAccessor.java33
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataSourceComparator.java33
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DbLibService.java46
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DblibConfigurationException.java45
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/NoAvailableConnectionsException.java36
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/TerminatingCachedDataSource.java82
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/BaseDBConfiguration.java104
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/DbConfigPool.java56
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JDBCConfiguration.java31
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.java39
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java104
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java100
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/FactoryNotDefinedException.java37
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java249
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDbResourceManagerFactory.java186
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java217
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/PollingWorker.java217
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitor.java237
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitorObserver.java37
-rwxr-xr-xdblib/provider/src/main/resources/dblib.properties13
29 files changed, 4140 insertions, 0 deletions
diff --git a/dblib/provider/pom.xml b/dblib/provider/pom.xml
new file mode 100755
index 00000000..b5acc7e1
--- /dev/null
+++ b/dblib/provider/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.sdnc.core</groupId>
+ <artifactId>dblib</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>dblib-provider</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>DBLIB Adaptor - Provider</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <version>${equinox.osgi.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>${mysql.connector.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-jdbc</artifactId>
+ <version>${tomcat-jdbc.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.openecomp.sdnc.sli.resource.dblib</Bundle-SymbolicName>
+ <Bundle-Activator>org.openecomp.sdnc.sli.resource.dblib.DBLIBResourceActivator</Bundle-Activator>
+ <Export-Package>org.openecomp.sdnc.sli.resource.dblib;version=${project.version}</Export-Package>
+ <!--
+ <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.mysql.jdbc.*,javax.sql.*,org.apache.tomcat.*</Import-Package>
+ -->
+ <Import-Package>*</Import-Package>
+ <Embed-Transitive>true</Embed-Transitive>
+ </instructions>
+ </configuration>
+
+ </plugin>
+
+
+ </plugins>
+ </build>
+</project>
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
new file mode 100644
index 00000000..58a0aeb1
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java
@@ -0,0 +1,616 @@
+/*-
+ * ============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.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;
+
+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 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException;
+
+
+/**
+ * @version $Revision: 1.13 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+
+public abstract class CachedDataSource implements DataSource, SQLExecutionMonitorObserver
+{
+ private static Logger LOGGER = LoggerFactory.getLogger(CachedDataSource.class);
+
+ protected static final String AS_CONF_ERROR = "AS_CONF_ERROR: ";
+
+ protected long CONN_REQ_TIMEOUT = 30L;
+ protected long DATA_REQ_TIMEOUT = 100L;
+
+ private final SQLExecutionMonitor monitor;
+ protected DataSource ds = null;
+ protected String connectionName = null;
+ protected boolean initialized = false;
+
+ private long interval = 1000;
+ 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
+ {
+ configure(jdbcElem);
+ monitor = new SQLExecutionMonitor(this);
+ }
+
+ protected abstract void configure(BaseDBConfiguration jdbcElem) throws DBConfigException;
+ /* (non-Javadoc)
+ * @see javax.sql.DataSource#getConnection()
+ */
+ public Connection getConnection() throws SQLException
+ {
+ return ds.getConnection();
+ }
+
+ public CachedRowSet getData(String statement, ArrayList<Object> arguments) throws SQLException, Throwable
+ {
+ TestObject testObject = null;
+ testObject = monitor.registerRequest();
+
+ Connection connection = null;
+ try {
+ connection = this.getConnection();
+ if(connection == null ) {
+ throw new SQLException("Connection invalid");
+ }
+ if(LOGGER.isDebugEnabled())
+ LOGGER.debug("Obtained connection <" + connectionName + ">: "+connection.toString());
+ return executePreparedStatement(connection, statement, arguments, true);
+ } finally {
+ try {
+ if(connection != null && !connection.isClosed()) {
+ connection.close();
+ }
+ } catch(Throwable exc) {
+ // the exception not monitored
+ } finally {
+ connection = null;
+ }
+
+ monitor.deregisterReguest(testObject);
+ }
+ }
+
+ public boolean writeData(String statement, ArrayList<Object> arguments) throws SQLException, Throwable
+ {
+ TestObject testObject = null;
+ testObject = monitor.registerRequest();
+
+ Connection connection = null;
+ try {
+ connection = this.getConnection();
+ if(connection == null ) {
+ throw new SQLException("Connection invalid");
+ }
+ if(LOGGER.isDebugEnabled())
+ LOGGER.debug("Obtained connection <" + connectionName + ">: "+connection.toString());
+ return executeUpdatePreparedStatement(connection, statement, arguments, true);
+ } finally {
+ try {
+ if(connection != null && !connection.isClosed()) {
+ connection.close();
+ }
+ } catch(Throwable exc) {
+ // the exception not monitored
+ } finally {
+ connection = null;
+ }
+
+ monitor.deregisterReguest(testObject);
+ }
+ }
+
+ CachedRowSet executePreparedStatement(Connection conn, String statement, ArrayList<Object> arguments, boolean close) throws SQLException, Throwable
+ {
+ long time = System.currentTimeMillis();
+
+ CachedRowSet data = null;
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("SQL Statement: "+ statement);
+ if(arguments != null && !arguments.isEmpty()) {
+ LOGGER.debug("Argunments: "+ Arrays.toString(arguments.toArray()));
+ }
+ }
+
+ ResultSet rs = null;
+ try {
+ data = RowSetProvider.newFactory().createCachedRowSet();
+ PreparedStatement ps = conn.prepareStatement(statement);
+ if(arguments != null)
+ {
+ for(int i = 0, max = arguments.size(); i < max; i++){
+ ps.setObject(i+1, arguments.get(i));
+ }
+ }
+ rs = ps.executeQuery();
+ data.populate(rs);
+ // Point the rowset Cursor to the start
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("SQL SUCCESS. rows returned: " + data.size()+ ", time(ms): "+ (System.currentTimeMillis() - time)); }
+ } catch(SQLException exc){
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time));
+ }
+ try { conn.rollback(); } catch(Throwable thr){}
+ if(arguments != null && !arguments.isEmpty()) {
+ LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc);
+ } else {
+ LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc);
+ }
+ throw exc;
+ } catch(Throwable exc){
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time));
+ }
+ if(arguments != null && !arguments.isEmpty()) {
+ LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc);
+ } else {
+ LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc);
+ }
+ throw exc; // new SQLException(exc);
+ } finally {
+
+ try {
+ if(rs != null){
+ rs.close();
+ rs = null;
+ }
+ } catch(Exception exc){
+
+ }
+ try {
+ if(conn != null && close){
+ conn.close();
+ conn = null;
+ }
+ } catch(Exception exc){
+
+ }
+ }
+
+ return data;
+ }
+
+ boolean executeUpdatePreparedStatement(Connection conn, String statement, ArrayList<Object> arguments, boolean close) throws SQLException, Throwable {
+ long time = System.currentTimeMillis();
+
+ CachedRowSet data = null;
+
+ int rs = -1;
+ try {
+ data = RowSetProvider.newFactory().createCachedRowSet();
+ PreparedStatement ps = conn.prepareStatement(statement);
+ 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()){
+ LOGGER.debug("SQL SUCCESS. rows returned: " + data.size()+ ", time(ms): "+ (System.currentTimeMillis() - time));
+ }
+ } catch(SQLException exc){
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time));
+ }
+ try { conn.rollback(); } catch(Throwable thr){}
+ if(arguments != null && !arguments.isEmpty()) {
+ LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc);
+ } else {
+ LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc);
+ }
+ throw exc;
+ } catch(Throwable exc){
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time));
+ }
+ if(arguments != null && !arguments.isEmpty()) {
+ LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc);
+ } else {
+ LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc);
+ }
+ throw exc; // new SQLException(exc);
+ } finally {
+ try {
+ if(conn != null && close){
+ conn.close();
+ conn = null;
+ }
+ } catch(Exception exc){
+
+ }
+ }
+
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
+ */
+ public Connection getConnection(String username, String password)
+ throws SQLException
+ {
+ return ds.getConnection(username, password);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.sql.DataSource#getLogWriter()
+ */
+ public PrintWriter getLogWriter() throws SQLException
+ {
+ return ds.getLogWriter();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.sql.DataSource#getLoginTimeout()
+ */
+ public int getLoginTimeout() throws SQLException
+ {
+ return ds.getLoginTimeout();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter)
+ */
+ public void setLogWriter(PrintWriter out) throws SQLException
+ {
+ ds.setLogWriter(out);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.sql.DataSource#setLoginTimeout(int)
+ */
+ public void setLoginTimeout(int seconds) throws SQLException
+ {
+ ds.setLoginTimeout(seconds);
+ }
+
+
+ public final String getDbConnectionName(){
+ return connectionName;
+ }
+
+ protected final void setDbConnectionName(String name) {
+ this.connectionName = name;
+ }
+
+ 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();
+ }
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ protected boolean testConnection(){
+ return testConnection(false);
+ }
+
+ protected boolean testConnection(boolean error_level){
+ Connection conn = null;
+ ResultSet rs = null;
+ Statement stmt = null;
+ try
+ {
+ Boolean readOnly = null;
+ String hostname = null;
+ conn = this.getConnection();
+ stmt = conn.createStatement();
+ rs = stmt.executeQuery("SELECT @@global.read_only, @@global.hostname"); //("SELECT 1 FROM DUAL"); //"select BANNER from SYS.V_$VERSION"
+ while(rs.next())
+ {
+ readOnly = rs.getBoolean(1);
+ hostname = rs.getString(2);
+
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("SQL DataSource <"+getDbConnectionName() + "> connected to " + hostname + ", read-only is " + readOnly + ", tested successfully ");
+ }
+ }
+
+ } catch (Throwable exc) {
+ if(error_level) {
+ LOGGER.error("SQL DataSource <" + this.getDbConnectionName() + "> test failed. Cause : " + exc.getMessage());
+ } else {
+ LOGGER.info("SQL DataSource <" + this.getDbConnectionName() + "> test failed. Cause : " + exc.getMessage());
+ }
+ return false;
+ } finally {
+ if(rs != null) {
+ try {
+ rs.close();
+ rs = null;
+ } catch (SQLException e) {
+ }
+ }
+ if(stmt != null) {
+ try {
+ stmt.close();
+ stmt = null;
+ } catch (SQLException e) {
+ }
+ }
+ if(conn !=null){
+ try {
+ conn.close();
+ conn = null;
+ } catch (SQLException e) {
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return false;
+ }
+
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return null;
+ }
+
+ @SuppressWarnings("deprecation")
+ public void setConnectionCachingEnabled(boolean state)
+ {
+// if(ds != null && ds instanceof OracleDataSource)
+// try {
+// ((OracleDataSource)ds).setConnectionCachingEnabled(true);
+// } catch (SQLException exc) {
+// LOGGER.warn("", exc);
+// }
+ }
+
+ public void addObserver(Observer observer) {
+ monitor.addObserver(observer);
+ }
+
+ public void deleteObserver(Observer observer) {
+ monitor.deleteObserver(observer);
+ }
+
+ public long getInterval() {
+ return interval;
+ }
+
+ public long getInitialDelay() {
+ return initialDelay;
+ }
+
+ public void setInterval(long value) {
+ interval = value;
+ }
+
+ public void setInitialDelay(long value) {
+ initialDelay = value;
+ }
+
+ public long getExpectedCompletionTime() {
+ return expectedCompletionTime;
+ }
+
+ public void setExpectedCompletionTime(long value) {
+ expectedCompletionTime = value;
+ }
+
+ public long getUnprocessedFailoverThreshold() {
+ return unprocessedFailoverThreshold;
+ }
+
+ public void setUnprocessedFailoverThreshold(long value) {
+ this.unprocessedFailoverThreshold = value;
+ }
+
+ public boolean canTakeOffLine() {
+ return canTakeOffLine;
+ }
+
+ public void blockImmediateOffLine() {
+ canTakeOffLine = false;
+ final Thread offLineTimer = new Thread()
+ {
+ public void run(){
+ try {
+ Thread.sleep(30000L);
+ }catch(Throwable exc){
+
+ }finally{
+ canTakeOffLine = true;
+ }
+ }
+ };
+ offLineTimer.setDaemon(true);
+ offLineTimer.start();
+ }
+
+ /**
+ * @return the monitor
+ */
+ final SQLExecutionMonitor getMonitor() {
+ return monitor;
+ }
+
+ protected boolean isSlave() throws PoolExhaustedException, MySQLNonTransientConnectionException {
+ CachedRowSet rs = null;
+ boolean isSlave = true;
+ String hostname = "UNDETERMINED";
+ try {
+ boolean localSlave = true;
+ rs = this.getData("SELECT @@global.read_only, @@global.hostname", new ArrayList<Object>());
+ 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;
+ } catch (Throwable e) {
+ LOGGER.error("", e);
+ isSlave = true;
+ }
+ if(isSlave){
+ LOGGER.debug("SQL SLAVE : "+connectionName + " on server " + hostname);
+ } else {
+ 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/CachedDataSourceFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSourceFactory.java
new file mode 100644
index 00000000..3e51ed94
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSourceFactory.java
@@ -0,0 +1,45 @@
+/*-
+ * ============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 org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.jdbc.JdbcDBCachedDataSource;
+import org.openecomp.sdnc.sli.resource.dblib.jdbc.MySQLCachedDataSource;
+
+/**
+ * @version $Revision: 1.1 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class CachedDataSourceFactory {
+
+ public static CachedDataSource createDataSource(BaseDBConfiguration config) {
+ if(config instanceof JDBCConfiguration)
+ return JdbcDBCachedDataSource.createInstance(config);
+
+ return (CachedDataSource)null;
+ }
+
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBConfigException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBConfigException.java
new file mode 100644
index 00000000..b324e6a2
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBConfigException.java
@@ -0,0 +1,47 @@
+/*-
+ * ============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;
+
+
+/**
+ * @version $Revision: 1.1 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class DBConfigException extends RuntimeException
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4752405152537680257L;
+
+ public DBConfigException(Exception e)
+ {
+ super(e.toString());
+ }
+
+ public DBConfigException(String msg)
+ {
+ super(msg);
+ }
+}
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
new file mode 100644
index 00000000..150a9a82
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java
@@ -0,0 +1,130 @@
+/*-
+ * ============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.io.File;
+import java.net.URL;
+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;
+
+public class DBLIBResourceActivator implements BundleActivator {
+
+ private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR";
+
+ private static final String DBLIB_PROP_PATH = "/dblib.properties";
+
+ private ServiceRegistration registration = null;
+
+ private static final Logger LOG = LoggerFactory.getLogger(DBLIBResourceActivator.class);
+
+ @Override
+ public void start(BundleContext ctx) throws Exception {
+ LOG.info("entering DBLIBResourceActivator.start");
+
+ DbLibService jdbcDataSource = null;
+ // Read properties
+ Properties props = new Properties();
+
+ File file = null;
+ URL propURL = null;
+ String propDir = System.getenv(SDNC_CONFIG_DIR);
+ if ((propDir == null) || (propDir.length() == 0)) {
+ propDir = "/opt/sdnc/data/properties";
+ }
+ file = new File(propDir + DBLIB_PROP_PATH);
+ if(file.exists()) {
+ propURL = file.toURI().toURL();
+ LOG.info("Using property file (1): " + file.toString());
+ } else {
+ propURL = ctx.getBundle().getResource("dblib.properties");
+ URL tmp = null;
+ if (propURL == null) {
+ file = new File(DBLIB_PROP_PATH);
+ tmp = this.getClass().getResource(DBLIB_PROP_PATH);
+// if(!file.exists()) {
+ if(tmp == null) {
+ throw new DblibConfigurationException("Missing configuration properties resource(3) : " + DBLIB_PROP_PATH);
+ } else {
+ propURL = tmp; //file.toURI().toURL();
+ LOG.info("Using property file (4): " + file.toString());
+ }
+ } else {
+ LOG.info("Using property file (2): " + propURL.toString());
+ }
+ }
+
+
+ try {
+ props.load(propURL.openStream());
+ } catch (Exception e) {
+ throw new DblibConfigurationException("Could not load properties at URL " + propURL.toString(), e);
+
+ }
+
+
+
+ try {
+ jdbcDataSource = DBResourceManager.create(props);
+ } catch (Exception exc) {
+ throw new DblibConfigurationException("Could not get initialize database", exc);
+ }
+
+ String regName = jdbcDataSource.getClass().getName();
+
+ LOG.info("Registering DBResourceManager service "+regName);
+ registration = ctx.registerService(new String[] { regName, DbLibService.class.getName(), "javax.sql.DataSource" }, jdbcDataSource, null);
+ }
+
+ @Override
+ public void stop(BundleContext ctx) throws Exception {
+ 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 00000000..5c1f5104
--- /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<org.apache.tomcat.jdbc.pool.PooledConnection> 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<String> arguments) throws SQLException, Throwable
+ {
+ ArrayList<Object> newList=new ArrayList<Object>();
+ if(arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+ resetInactivityTimer();
+ return dataSource.executeUpdatePreparedStatement(connection, statement, newList, false);
+ }
+
+ public CachedRowSet getData(String statement, ArrayList<String> arguments) throws SQLException, Throwable
+ {
+ ArrayList<Object> newList=new ArrayList<Object>();
+ if(arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+ resetInactivityTimer();
+ return dataSource.executePreparedStatement(connection, statement, newList, false);
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> 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<String, Class<?>> getTypeMap() throws SQLException {
+ return connection.getTypeMap();
+ }
+
+ @Override
+ public void setTypeMap(Map<String, Class<?>> 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/DBLibException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibException.java
new file mode 100644
index 00000000..cc80741d
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibException.java
@@ -0,0 +1,39 @@
+/*-
+ * ============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;
+
+/**
+ * An exception time for handling DBLIB specific error handling.
+ */
+public class DBLibException extends SQLException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5345059355083984696L;
+
+ public DBLibException(String message){
+ super(message);
+ }
+
+}
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
new file mode 100644
index 00000000..5cf2953b
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java
@@ -0,0 +1,862 @@
+/*-
+ * ============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.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLDataException;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLIntegrityConstraintViolationException;
+import java.sql.SQLSyntaxErrorException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Observable;
+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;
+
+
+/**
+ * @version $Revision: 1.15 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class DBResourceManager implements DataSource, DataAccessor, DBResourceObserver, DbLibService {
+ private static Logger LOGGER = LoggerFactory.getLogger(DBResourceManager.class);
+
+ transient boolean terminating = false;
+ transient protected long retryInterval = 10000L;
+ transient boolean recoveryMode = true;
+
+ protected final AtomicBoolean dsSelector = new AtomicBoolean();
+
+// Queue<CachedDataSource> dsQueue = new ConcurrentLinkedQueue<CachedDataSource>();
+ Queue<CachedDataSource> dsQueue = new PriorityQueue<CachedDataSource>(4, new Comparator<CachedDataSource>(){
+
+ @Override
+ public int compare(CachedDataSource left, CachedDataSource right) {
+ try {
+ if(!left.isSlave())
+ return -1;
+ if(!right.isSlave())
+ return 1;
+
+ } catch (Throwable e) {
+ LOGGER.warn("", e);
+ }
+ return 0;
+ }
+
+ });
+ protected final Set<CachedDataSource> broken = Collections.synchronizedSet(new HashSet<CachedDataSource>());
+ protected final Object monitor = new Object();
+ protected final Properties configProps;
+ protected final Thread worker;
+
+ protected final long terminationTimeOut;
+ protected final boolean monitorDbResponse;
+ protected final long monitoringInterval;
+ protected final long monitoringInitialDelay;
+ protected final long expectedCompletionTime;
+ protected final long unprocessedFailoverThreshold;
+
+ public DBResourceManager(Properties props){
+ this.configProps = props;
+
+ // get retry interval value
+ retryInterval = getLongFromProperties(props, "org.openecomp.dblib.connection.retry", 10000L);
+
+ // get recovery mode flag
+ recoveryMode = getBooleanFromProperties(props, "org.openecomp.dblib.connection.recovery", true);
+ if(!recoveryMode)
+ {
+ recoveryMode = false;
+ LOGGER.info("Recovery Mode disabled");
+ }
+ // get time out value for thread cleanup
+ terminationTimeOut = getLongFromProperties(props, "org.openecomp.dblib.termination.timeout", 300000L);
+ // get properties for monitoring
+ monitorDbResponse = getBooleanFromProperties(props, "org.openecomp.dblib.connection.monitor", false);
+ monitoringInterval = getLongFromProperties(props, "org.openecomp.dblib.connection.monitor.interval", 1000L);
+ monitoringInitialDelay = getLongFromProperties(props, "org.openecomp.dblib.connection.monitor.startdelay", 5000L);
+ expectedCompletionTime = getLongFromProperties(props, "org.openecomp.dblib.connection.monitor.expectedcompletiontime", 5000L);
+ unprocessedFailoverThreshold = getLongFromProperties(props, "org.openecomp.dblib.connection.monitor.unprocessedfailoverthreshold", 3L);
+
+ // initialize performance monitor
+ PollingWorker.createInistance(props);
+
+ // initialize recovery thread
+ worker = new RecoveryMgr();
+ worker.setName("DBResourcemanagerWatchThread");
+ worker.setDaemon(true);
+ worker.start();
+ }
+
+ private void config(Properties ctx) throws Exception {
+
+ DbConfigPool dbConfig = DBConfigFactory.createConfig(this.configProps);
+
+ try {
+ AbstractResourceManagerFactory factory = AbstractDBResourceManagerFactory.getFactory(dbConfig.getType());
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info("Default DB config is : " + dbConfig.getType());
+ LOGGER.info("Using factory : " + factory.getClass().getName());
+ }
+ CachedDataSource[] cachedDS = factory.initDBResourceManager(dbConfig, this);
+ if(cachedDS == null || cachedDS.length == 0) {
+ LOGGER.error("Initialization of CachedDataSources failed. No instance was created.");
+ throw new Exception("Failed to initialize DB Library. No data source was created.");
+ }
+
+ for(int i=0; i<cachedDS.length; i++){
+ if(cachedDS[i] != null && cachedDS[i].isInitialized()){
+ setDataSource(cachedDS[i]);
+ cachedDS[i].setInterval(monitoringInterval);
+ cachedDS[i].setInitialDelay(monitoringInitialDelay);
+ cachedDS[i].setExpectedCompletionTime(expectedCompletionTime);
+ cachedDS[i].setUnprocessedFailoverThreshold(unprocessedFailoverThreshold);
+ cachedDS[i].addObserver(this);
+ }
+ }
+
+ } catch(Exception exc){
+ throw exc;
+ }
+ }
+
+ private long getLongFromProperties(Properties props, String property, long defaultValue)
+ {
+ String value = null;
+ long tmpLongValue = defaultValue;
+ try {
+ value = (String)props.getProperty(property);
+ if(value != null)
+ tmpLongValue = Long.parseLong(value);
+
+ } catch(NumberFormatException exc) {
+ if(LOGGER.isWarnEnabled()){
+ LOGGER.warn("'"+property+"'=" + value+" is invalid. It should be a numeric value");
+ }
+ } catch(Exception exc) {
+ }
+ return tmpLongValue;
+
+ }
+
+ private boolean getBooleanFromProperties(Properties props, String property, boolean defaultValue)
+ {
+ boolean tmpValue = defaultValue;
+ String value = null;
+
+ try {
+ value = (String)props.getProperty(property);
+ if(value != null)
+ tmpValue = Boolean.parseBoolean(value);
+
+ } catch(NumberFormatException exc) {
+ if(LOGGER.isWarnEnabled()){
+ LOGGER.warn("'"+property+"'=" + value+" is invalid. It should be a boolean value");
+ }
+ } catch(Exception exc) {
+ }
+ return tmpValue;
+
+ }
+
+
+ public void update(Observable observable, Object data) {
+ // if observable is active and there is a standby available, switch
+ if(observable instanceof SQLExecutionMonitor)
+ {
+ SQLExecutionMonitor monitor = (SQLExecutionMonitor)observable;
+ if(monitor.getParent() instanceof CachedDataSource)
+ {
+ CachedDataSource dataSource = (CachedDataSource)monitor.getParent();
+ if(dataSource == dsQueue.peek())
+ {
+ if(recoveryMode && dsQueue.size() > 1){
+ handleGetConnectionException(dataSource, new Exception(data.toString()));
+ }
+ }
+ }
+ }
+ }
+
+ public void testForceRecovery()
+ {
+ CachedDataSource active = (CachedDataSource) this.dsQueue.peek();
+ handleGetConnectionException(active, new Exception("test"));
+ }
+
+ class RecoveryMgr extends Thread {
+
+ public void run() {
+ while(!terminating)
+ {
+ try {
+ Thread.sleep(retryInterval);
+ } catch (InterruptedException e1) { }
+ CachedDataSource brokenSource = null;
+ try {
+ if (!broken.isEmpty()) {
+ CachedDataSource[] sourceArray = broken.toArray(new CachedDataSource[0]);
+ for (int i = 0; i < sourceArray.length; i++)
+ {
+ brokenSource = sourceArray[i];
+ if (brokenSource instanceof TerminatingCachedDataSource)
+ break;
+ if (resetConnectionPool(brokenSource)) {
+ broken.remove(brokenSource);
+ brokenSource.blockImmediateOffLine();
+ dsQueue.add(brokenSource);
+ LOGGER.info("DataSource <"
+ + brokenSource.getDbConnectionName()
+ + "> recovered.");
+ }
+ brokenSource = null;
+ }
+ }
+ } catch (Exception exc) {
+ LOGGER.warn(exc.getMessage());
+ if(brokenSource != null){
+ try {
+ if(!broken.contains(brokenSource))
+ broken.add(brokenSource);
+ brokenSource = null;
+ } catch (Exception e1) { }
+ }
+ }
+ }
+ LOGGER.info("DBResourceManager.RecoveryMgr <"+this.toString() +"> terminated." );
+ }
+
+ private boolean resetConnectionPool(CachedDataSource dataSource){
+ try {
+ return dataSource.testConnection();
+ } catch (Exception exc) {
+ LOGGER.info("DataSource <" + dataSource.getDbConnectionName() + "> resetCache failed with error: "+ exc.getMessage());
+ return false;
+ }
+ }
+ }
+
+ /* (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<String> arguments, String preferredDS) throws SQLException {
+ ArrayList<Object> newList=new ArrayList<Object>();
+ if(arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+ if(recoveryMode)
+ return requestDataWithRecovery(statement, newList, preferredDS);
+ else
+ return requestDataNoRecovery(statement, newList, preferredDS);
+ }
+
+ private CachedRowSet requestDataWithRecovery(String statement, ArrayList<Object> arguments, String preferredDS) throws SQLException {
+ Throwable lastException = null;
+ CachedDataSource active = null;
+
+ // test if there are any connection pools available
+ LinkedList<CachedDataSource> sources = new LinkedList<CachedDataSource>(this.dsQueue);
+ if(sources.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 RequestDataWithRecovery call.");
+ }
+ if(preferredDS != null && !sources.peek().getDbConnectionName().equals(preferredDS)) {
+ Collections.reverse(sources);
+ }
+
+
+ // loop through available data sources to retrieve data.
+ while(!sources.isEmpty())
+ {
+ active = sources.peek();
+
+ long time = System.currentTimeMillis();
+ try {
+ if(!active.isFabric()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ master = null;
+ }
+ }
+ sources.remove(active);
+ return active.getData(statement, arguments);
+ } catch(SQLDataException exc){
+ throw exc;
+ } catch(SQLSyntaxErrorException exc){
+ throw exc;
+ } catch(SQLIntegrityConstraintViolationException exc){
+ throw exc;
+ } catch(Throwable exc){
+ lastException = exc;
+ String message = exc.getMessage();
+ if(message == null) {
+ if(exc.getCause() != null) {
+ message = exc.getCause().getMessage();
+ }
+ if(message == null)
+ message = exc.getClass().getName();
+ }
+ LOGGER.error("Generated alarm: "+active.getDbConnectionName()+" - "+message);
+ handleGetConnectionException(active, exc);
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ time = (System.currentTimeMillis() - time);
+ LOGGER.debug("getData processing time : "+ active.getDbConnectionName()+" "+time+" miliseconds.");
+ }
+ }
+ }
+ if(lastException instanceof SQLException){
+ throw (SQLException)lastException;
+ }
+ // repackage the exception
+ // you are here because either you run out of available data sources
+ // or the last exception was not of SQLException type.
+ // repackage the exception
+ if(lastException == null) {
+ throw new DBLibException("The operation timed out while waiting to acquire a new connection." );
+ } else {
+ SQLException exception = new DBLibException(lastException.getMessage());
+ exception.setStackTrace(lastException.getStackTrace());
+ if(lastException.getCause() instanceof SQLException) {
+ throw (SQLException)lastException.getCause();
+ }
+ throw exception;
+ }
+ }
+
+ private CachedRowSet requestDataNoRecovery(String statement, ArrayList<Object> 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.");
+ }
+ CachedDataSource active = (CachedDataSource) this.dsQueue.peek();
+ long time = System.currentTimeMillis();
+ try {
+ if(!active.isFabric()) {
+ CachedDataSource master = findMaster();
+ if(master != null)
+ active = master;
+ }
+ return active.getData(statement, arguments);
+// } catch(SQLDataException exc){
+// throw exc;
+ } catch(Throwable exc){
+ String message = exc.getMessage();
+ if(message == null)
+ message = exc.getClass().getName();
+ LOGGER.error("Generated alarm: "+active.getDbConnectionName()+" - "+message);
+ if(exc instanceof SQLException)
+ throw (SQLException)exc;
+ else {
+ DBLibException excptn = new DBLibException(exc.getMessage());
+ excptn.setStackTrace(exc.getStackTrace());
+ throw excptn;
+ }
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ time = (System.currentTimeMillis() - time);
+ LOGGER.debug(">> getData : "+ active.getDbConnectionName()+" "+time+" miliseconds.");
+ }
+ }
+ }
+
+
+ /* (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<String> arguments, String preferredDS) throws SQLException
+ {
+ ArrayList<Object> newList=new ArrayList<Object>();
+ if(arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+
+ return writeDataNoRecovery(statement, newList, preferredDS);
+ }
+
+ CachedDataSource findMaster() throws PoolExhaustedException, MySQLNonTransientConnectionException {
+ CachedDataSource master = null;
+ CachedDataSource[] dss = this.dsQueue.toArray(new CachedDataSource[0]);
+ for(int i=0; i<dss.length; i++) {
+ if(!dss[i].isSlave()) {
+ master = dss[i];
+ if(i != 0) {
+ dsQueue.remove(master);
+ dsQueue.add(master);
+ }
+ return master;
+ }
+ }
+ if(master == null) {
+ LOGGER.warn("MASTER not found.");
+ }
+ return master;
+ }
+
+
+ private boolean writeDataNoRecovery(String statement, ArrayList<Object> 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.");
+ }
+
+ boolean initialRequest = true;
+ boolean retryAllowed = true;
+ CachedDataSource active = (CachedDataSource) this.dsQueue.peek();
+ long time = System.currentTimeMillis();
+ while(initialRequest) {
+ initialRequest = false;
+ try {
+ if(!active.isFabric()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+
+ return active.writeData(statement, arguments);
+ } catch(Throwable exc){
+ String message = exc.getMessage();
+ if(message == null)
+ message = exc.getClass().getName();
+ LOGGER.error("Generated alarm: "+active.getDbConnectionName()+" - "+message);
+ if(exc instanceof SQLException) {
+ SQLException sqlExc = SQLException.class.cast(exc);
+ // handle read-only exception
+ if(sqlExc.getErrorCode() == 1290 && "HY000".equals(sqlExc.getSQLState())) {
+ LOGGER.warn("retrying due to: " + sqlExc.getMessage());
+ dsQueue.remove(active);
+ dsQueue.add(active);
+ if(retryAllowed){
+ retryAllowed = false;
+ initialRequest = true;
+ continue;
+ }
+ }
+ throw (SQLException)exc;
+ } else {
+ DBLibException excptn = new DBLibException(exc.getMessage());
+ excptn.setStackTrace(exc.getStackTrace());
+ throw excptn;
+ }
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ time = (System.currentTimeMillis() - time);
+ LOGGER.debug("writeData processing time : "+ active.getDbConnectionName()+" "+time+" miliseconds.");
+ }
+ }
+ }
+ return true;
+ }
+
+ private void setDataSource(CachedDataSource dataSource) {
+ if(dataSource.testConnection(true)){
+ this.dsQueue.add(dataSource);
+ } else {
+ this.broken.add(dataSource);
+ }
+ }
+
+ public Connection getConnection() throws SQLException {
+ Throwable lastException = null;
+ CachedDataSource active = null;
+
+ if(dsQueue.isEmpty()){
+ throw new DBLibException("No active DB connection pools are available in GetConnection call.");
+ }
+
+ try {
+ active = dsQueue.peek();
+ CachedDataSource tmpActive = findMaster();
+ if(tmpActive != null) {
+ active = tmpActive;
+ }
+ 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 MySQLNonTransientConnectionException) {
+ throw new NoAvailableConnectionsException(exc);
+ } if(exc instanceof SQLException) {
+ throw (SQLException)exc;
+ } else {
+ DBLibException excptn = new DBLibException(exc.getMessage());
+ excptn.setStackTrace(exc.getStackTrace());
+ throw excptn;
+ }
+ }
+ } catch (Throwable trwb) {
+ DBLibException excptn = new DBLibException(trwb.getMessage());
+ excptn.setStackTrace(trwb.getStackTrace());
+ throw excptn;
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ displayState();
+ }
+ }
+
+ if(lastException instanceof SQLException){
+ throw (SQLException)lastException;
+ }
+ // repackage the exception
+ if(lastException == null) {
+ throw new DBLibException("The operation timed out while waiting to acquire a new connection." );
+ } else {
+ SQLException exception = new DBLibException(lastException.getMessage());
+ exception.setStackTrace(lastException.getStackTrace());
+ if(lastException.getCause() instanceof SQLException) {
+// exception.setNextException((SQLException)lastException.getCause());
+ throw (SQLException)lastException.getCause();
+ }
+ throw exception;
+ }
+ }
+
+ public Connection getConnection(String username, String password)
+ throws SQLException {
+ CachedDataSource active = null;
+
+ if(dsQueue.isEmpty()){
+ throw new DBLibException("No active DB connection pools are available in GetConnection call.");
+ }
+
+
+ try {
+ active = dsQueue.peek();
+ CachedDataSource tmpActive = findMaster();
+ if(tmpActive != null) {
+ active = tmpActive;
+ }
+ return active.getConnection(username, password);
+ } catch(Throwable exc){
+ if(recoveryMode){
+ handleGetConnectionException(active, exc);
+ } else {
+ if(exc instanceof SQLException)
+ throw (SQLException)exc;
+ else {
+ DBLibException excptn = new DBLibException(exc.getMessage());
+ excptn.setStackTrace(exc.getStackTrace());
+ throw excptn;
+ }
+ }
+
+ }
+
+ throw new DBLibException("No connections available in DBResourceManager in GetConnection call.");
+ }
+
+ private void handleGetConnectionException(CachedDataSource source, Throwable exc) {
+ try {
+ if(!source.canTakeOffLine())
+ {
+ LOGGER.error("Could not switch due to blocking");
+ return;
+ }
+
+ boolean removed = dsQueue.remove(source);
+ if(!broken.contains(source))
+ {
+ if(broken.add(source))
+ {
+ LOGGER.warn("DB Recovery: DataSource <" + source.getDbConnectionName() + "> put in the recovery mode. Reason : " + exc.getMessage());
+ } else {
+ LOGGER.warn("Error putting DataSource <" +source.getDbConnectionName()+ "> in recovery mode.");
+ }
+ } else {
+ LOGGER.info("DB Recovery: DataSource <" + source.getDbConnectionName() + "> already in recovery queue");
+ }
+ if(removed)
+ {
+ if(!dsQueue.isEmpty())
+ {
+ LOGGER.warn("DB DataSource <" + dsQueue.peek().getDbConnectionName() + "> became active");
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error("", e);
+ }
+ }
+
+ public void cleanUp() {
+ for(Iterator<CachedDataSource> it=dsQueue.iterator();it.hasNext();){
+ CachedDataSource cds = (CachedDataSource)it.next();
+ it.remove();
+ cds.cleanUp();
+ }
+
+ try {
+ this.terminating = true;
+ if(broken != null)
+ {
+ try {
+ broken.add( new TerminatingCachedDataSource(null));
+ } catch(Exception exc){
+ LOGGER.error("Waiting for Worker to stop", exc);
+ }
+ }
+ worker.join(terminationTimeOut);
+ LOGGER.info("DBResourceManager.RecoveryMgr <"+worker.toString() +"> termination was successful: " + worker.getState());
+ } catch(Exception exc){
+ LOGGER.error("Waiting for Worker thread to terminate ", exc);
+ }
+ }
+
+ public static DBResourceManager create(Properties props) throws Exception {
+ DBResourceManager dbmanager = new DBResourceManager(props);
+ dbmanager.config(props);
+ return dbmanager;
+ }
+
+ public PrintWriter getLogWriter() throws SQLException {
+ return ((CachedDataSource)this.dsQueue.peek()).getLogWriter();
+ }
+
+ public int getLoginTimeout() throws SQLException {
+ return ((CachedDataSource)this.dsQueue.peek()).getLoginTimeout();
+ }
+
+ public void setLogWriter(PrintWriter out) throws SQLException {
+ ((CachedDataSource)this.dsQueue.peek()).setLogWriter(out);
+ }
+
+ public void setLoginTimeout(int seconds) throws SQLException {
+ ((CachedDataSource)this.dsQueue.peek()).setLoginTimeout(seconds);
+ }
+
+ public void displayState(){
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("POOLS : Active = "+dsQueue.size() + ";\t Broken = "+broken.size());
+ CachedDataSource current = (CachedDataSource)dsQueue.peek();
+ if(current != null) {
+ LOGGER.debug("POOL : Active name = \'"+current.getDbConnectionName()+ "\'");
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.openecomp.sdnc.sli.resource.dblib.DbLibService#isActive()
+ */
+ @Override
+ public boolean isActive() {
+ return this.dsQueue.size()>0;
+ }
+
+ public String getActiveStatus(){
+ return "Connected: " + dsQueue.size()+"\tIn-recovery: "+broken.size();
+ }
+
+ public String getDBStatus(boolean htmlFormat) {
+ StringBuilder buffer = new StringBuilder();
+
+ ArrayList<CachedDataSource> list = new ArrayList<CachedDataSource>();
+ list.addAll(dsQueue);
+ list.addAll(broken);
+ if (htmlFormat)
+ {
+ buffer.append("<tr class=\"headerRow\"><th id=\"header1\">")
+ .append("Name:").append("</th>");
+ for (int i = 0; i < list.size(); i++) {
+ buffer.append("<th id=\"header").append(2 + i).append("\">");
+ buffer.append(((CachedDataSource) list.get(i)).getDbConnectionName()).append("</th>");
+ }
+ buffer.append("</tr>");
+
+ buffer.append("<tr><td>State:</td>");
+ for (int i = 0; i < list.size(); i++) {
+ if (broken.contains(list.get(i))) {
+ buffer.append("<td>in recovery</td>");
+ }
+ if (dsQueue.contains(list.get(i))) {
+ if (dsQueue.peek() == list.get(i))
+ buffer.append("<td>active</td>");
+ else
+ buffer.append("<td>standby</td>");
+ }
+ }
+ buffer.append("</tr>");
+
+ } else {
+ for (int i = 0; i < list.size(); i++) {
+ buffer.append("Name: ").append(((CachedDataSource) list.get(i)).getDbConnectionName());
+ buffer.append("\tState: ");
+ if (broken.contains(list.get(i))) {
+ buffer.append("in recovery");
+ } else
+ if (dsQueue.contains(list.get(i))) {
+ if (dsQueue.peek() == list.get(i))
+ buffer.append("active");
+ else
+ buffer.append("standby");
+ }
+
+ buffer.append("\n");
+
+ }
+ }
+ return buffer.toString();
+ }
+
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return false;
+ }
+
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return null;
+ }
+
+ /**
+ * @return the monitorDbResponse
+ */
+ public final boolean isMonitorDbResponse() {
+ return recoveryMode && monitorDbResponse;
+ }
+
+ public void test(){
+ CachedDataSource obj = dsQueue.peek();
+ Exception ption = new Exception();
+ try {
+ for(int i=0; i<5; i++)
+ {
+ handleGetConnectionException(obj, ption);
+ }
+ } catch(Throwable exc){
+ LOGGER.warn("", exc);
+ }
+ }
+
+ public String getPreferredDSName(){
+ if(isActive()){
+ return getPreferredDataSourceName(dsSelector);
+ }
+ return "";
+ }
+
+ public String getPreferredDataSourceName(AtomicBoolean flipper) {
+
+ LinkedList<CachedDataSource> snapshot = new LinkedList<CachedDataSource>(dsQueue);
+ if(snapshot.size() > 1){
+ CachedDataSource first = snapshot.getFirst();
+ CachedDataSource last = snapshot.getLast();
+
+ int delta = first.getMonitor().getPorcessedConnectionsCount() - last.getMonitor().getPorcessedConnectionsCount();
+ if(delta < 0) {
+ flipper.set(false);
+ } else if(delta > 0) {
+ flipper.set(true);
+ } else {
+ // check the last value and return !last
+ flipper.getAndSet(!flipper.get());
+ }
+
+ if (flipper.get())
+ Collections.reverse(snapshot);
+ }
+ return snapshot.peek().getDbConnectionName();
+ }
+
+ public java.util.logging.Logger getParentLogger()
+ throws SQLFeatureNotSupportedException {
+ return null;
+ }
+
+ public String getMasterName() {
+ if(isActive()){
+ return getMasterDataSourceName(dsSelector);
+ }
+ return "";
+ }
+
+
+ private String getMasterDataSourceName(AtomicBoolean flipper) {
+
+ LinkedList<CachedDataSource> snapshot = new LinkedList<CachedDataSource>(dsQueue);
+ if(snapshot.size() > 1){
+ CachedDataSource first = snapshot.getFirst();
+ CachedDataSource last = snapshot.getLast();
+
+ int delta = first.getMonitor().getPorcessedConnectionsCount() - last.getMonitor().getPorcessedConnectionsCount();
+ if(delta < 0) {
+ flipper.set(false);
+ } else if(delta > 0) {
+ flipper.set(true);
+ } else {
+ // check the last value and return !last
+ flipper.getAndSet(!flipper.get());
+ }
+
+ if (flipper.get())
+ Collections.reverse(snapshot);
+ }
+ return snapshot.peek().getDbConnectionName();
+ }
+
+ 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/DBResourceObserver.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceObserver.java
new file mode 100644
index 00000000..e06779f3
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceObserver.java
@@ -0,0 +1,27 @@
+/*-
+ * ============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.util.Observer;
+
+public interface DBResourceObserver extends Observer {
+ public boolean isMonitorDbResponse();
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataAccessor.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataAccessor.java
new file mode 100644
index 00000000..cd054a51
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataAccessor.java
@@ -0,0 +1,33 @@
+/*-
+ * ============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;
+import java.util.ArrayList;
+
+import javax.sql.rowset.CachedRowSet;
+
+public interface DataAccessor {
+
+ public abstract CachedRowSet getData(String statement, ArrayList<String> arguments, String preferredDS)
+ throws SQLException;
+
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataSourceComparator.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataSourceComparator.java
new file mode 100644
index 00000000..37d62513
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataSourceComparator.java
@@ -0,0 +1,33 @@
+/*-
+ * ============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.util.Comparator;
+
+public interface DataSourceComparator extends Comparator <CachedDataSource>{
+
+ public abstract CachedDataSource getLastUsed();
+
+ public abstract void setLastUsed(CachedDataSource lastUsed);
+
+ public abstract int compare(CachedDataSource ds1, CachedDataSource ds2);
+
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DbLibService.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DbLibService.java
new file mode 100644
index 00000000..25edd1f0
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DbLibService.java
@@ -0,0 +1,46 @@
+/*-
+ * ============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;
+import java.util.ArrayList;
+
+import javax.sql.rowset.CachedRowSet;
+
+public interface DbLibService {
+
+ /* (non-Javadoc)
+ * @see DataAccessor#getData(java.lang.String, java.util.ArrayList)
+ */
+ public abstract CachedRowSet getData(String statement,
+ ArrayList<String> arguments, String preferredDS)
+ throws SQLException;
+
+ /* (non-Javadoc)
+ * @see DataAccessor#writeData(java.lang.String, java.util.ArrayList)
+ */
+ public abstract boolean writeData(String statement,
+ ArrayList<String> arguments, String preferredDS)
+ throws SQLException;
+
+ public abstract boolean isActive();
+
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DblibConfigurationException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DblibConfigurationException.java
new file mode 100644
index 00000000..17700a5e
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DblibConfigurationException.java
@@ -0,0 +1,45 @@
+/*-
+ * ============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;
+
+
+public class DblibConfigurationException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public DblibConfigurationException()
+ {
+ super();
+ }
+
+ public DblibConfigurationException(String msg)
+ {
+ super(msg);
+ }
+
+ public DblibConfigurationException(String msg, Throwable t)
+ {
+ super(msg, t);
+ }
+}
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 00000000..16895b4d
--- /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/TerminatingCachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/TerminatingCachedDataSource.java
new file mode 100644
index 00000000..234bbed0
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/TerminatingCachedDataSource.java
@@ -0,0 +1,82 @@
+/*-
+ * ============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.SQLFeatureNotSupportedException;
+import java.util.logging.Logger;
+
+import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitorObserver;
+
+
+public class TerminatingCachedDataSource extends CachedDataSource implements SQLExecutionMonitorObserver {
+
+ public TerminatingCachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException {
+ super(jdbcElem);
+ }
+
+ protected void configure(BaseDBConfiguration jdbcElem) throws DBConfigException {
+ // no action
+ }
+
+ public long getInterval() {
+ return 1000;
+ }
+
+ public long getInitialDelay() {
+ return 1000;
+ }
+
+ public long getExpectedCompletionTime() {
+ return 50;
+ }
+
+ public void setExpectedCompletionTime(long value) {
+
+ }
+
+ public void setInterval(long value) {
+
+ }
+
+ public void setInitialDelay(long value) {
+
+ }
+
+ public long getUnprocessedFailoverThreshold() {
+ return 3;
+ }
+
+ public void setUnprocessedFailoverThreshold(long value) {
+
+ }
+
+ public int compareTo(CachedDataSource ods)
+ {
+ return 0;
+ }
+
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/BaseDBConfiguration.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/BaseDBConfiguration.java
new file mode 100644
index 00000000..976b1cf2
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/BaseDBConfiguration.java
@@ -0,0 +1,104 @@
+/*-
+ * ============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.config;
+
+import java.util.Properties;
+
+public abstract class BaseDBConfiguration {
+ public static final String DATABASE_TYPE = "org.openecomp.sdnc.sli.dbtype";
+ public static final String DATABASE_URL = "org.openecomp.sdnc.sli.jdbc.url";
+ public static final String DATABASE_NAME = "org.openecomp.sdnc.sli.jdbc.database";
+ public static final String CONNECTION_NAME = "org.openecomp.sdnc.sli.jdbc.connection.name";
+ public static final String DATABASE_USER = "org.openecomp.sdnc.sli.jdbc.user";
+ public static final String DATABASE_PSSWD = "org.openecomp.sdnc.sli.jdbc.password";
+ public static final String CONNECTION_TIMEOUT="org.openecomp.sdnc.sli.jdbc.connection.timeout";
+ public static final String REQUEST_TIMEOUT = "org.openecomp.sdnc.sli.jdbc.request.timeout";
+ public static final String MIN_LIMIT = "org.openecomp.sdnc.sli.jdbc.limit.min";
+ public static final String MAX_LIMIT = "org.openecomp.sdnc.sli.jdbc.limit.max";
+ public static final String INIT_LIMIT = "org.openecomp.sdnc.sli.jdbc.limit.init";
+ public static final String DATABASE_HOSTS = "org.openecomp.sdnc.sli.jdbc.hosts";
+
+
+ protected final Properties props;
+
+ public BaseDBConfiguration(Properties properties) {
+ this.props = properties;
+ }
+
+ public int getConnTimeout() {
+ try {
+ String value = props.getProperty(CONNECTION_TIMEOUT);
+ return Integer.parseInt(value);
+ } catch(Exception exc) {
+ return -1;
+ }
+ }
+
+ public int getRequestTimeout() {
+ try {
+ String value = props.getProperty(REQUEST_TIMEOUT);
+ if(value == null)
+ return -1;
+ return Integer.parseInt(value);
+ } catch(Exception exc) {
+ return -1;
+ }
+ }
+
+ public String getDbConnectionName() {
+ return props.getProperty(CONNECTION_NAME);
+ }
+
+ public String getDatabaseName() {
+ return props.getProperty(DATABASE_NAME);
+ }
+
+ public String getDbUserId() {
+ return props.getProperty(DATABASE_USER);
+ }
+
+ public String getDbPasswd() {
+ return props.getProperty(DATABASE_PSSWD);
+ }
+
+ public int getDbMinLimit() {
+ String value = props.getProperty(MIN_LIMIT);
+ return Integer.parseInt(value);
+ }
+
+ public int getDbMaxLimit() {
+ String value = props.getProperty(MAX_LIMIT);
+ return Integer.parseInt(value);
+ }
+
+ public int getDbInitialLimit() {
+ String value = props.getProperty(INIT_LIMIT);
+ return Integer.parseInt(value);
+ }
+
+ public String getDbUrl() {
+ return props.getProperty(DATABASE_URL);
+ }
+
+ public String getServerGroup() {
+ return null;
+ }
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/DbConfigPool.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/DbConfigPool.java
new file mode 100644
index 00000000..117f9321
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/DbConfigPool.java
@@ -0,0 +1,56 @@
+/*-
+ * ============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.config;
+
+import java.util.ArrayList;
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DbConfigPool {
+ private static Logger LOGGER = LoggerFactory.getLogger(DbConfigPool.class);
+
+ private final String type;
+
+ private ArrayList<BaseDBConfiguration> configurations = new ArrayList<BaseDBConfiguration>();
+
+ public DbConfigPool(Properties properties) {
+ LOGGER.debug("Initializing DbConfigType");
+ type = properties.getProperty(BaseDBConfiguration.DATABASE_TYPE, "JDBC").toUpperCase();
+ }
+
+ public int getTimeout() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public JDBCConfiguration[] getJDBCbSourceArray() {
+ return configurations.toArray(new JDBCConfiguration[configurations.size()]);
+ }
+
+ public void addConfiguration(BaseDBConfiguration config) {
+ configurations.add(config);
+ }
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JDBCConfiguration.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JDBCConfiguration.java
new file mode 100644
index 00000000..cb6ea3e5
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JDBCConfiguration.java
@@ -0,0 +1,31 @@
+/*-
+ * ============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.config;
+
+import java.util.Properties;
+
+public class JDBCConfiguration extends BaseDBConfiguration {
+
+ public JDBCConfiguration(Properties xmlElem) {
+ super(xmlElem);
+ }
+
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.java
new file mode 100644
index 00000000..f4291a7d
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.java
@@ -0,0 +1,39 @@
+/*-
+ * ============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.factory;
+
+import org.openecomp.sdnc.sli.resource.dblib.jdbc.JdbcDbResourceManagerFactory;
+
+/**
+ * @version $Revision: 1.1 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class AbstractDBResourceManagerFactory {
+
+ public static AbstractResourceManagerFactory getFactory(String type) throws FactoryNotDefinedException {
+
+ // JDBC
+ return JdbcDbResourceManagerFactory.createIntstance();
+ }
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java
new file mode 100644
index 00000000..0f58a3f0
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java
@@ -0,0 +1,104 @@
+/*-
+ * ============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.factory;
+
+
+import java.sql.SQLException;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.openecomp.sdnc.sli.resource.dblib.CachedDataSource;
+import org.openecomp.sdnc.sli.resource.dblib.CachedDataSourceFactory;
+import org.openecomp.sdnc.sli.resource.dblib.DBConfigException;
+import org.openecomp.sdnc.sli.resource.dblib.DBResourceManager;
+import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.config.DbConfigPool;
+import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Revision: 1.6 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public abstract class AbstractResourceManagerFactory {
+ private static Logger LOGGER = LoggerFactory.getLogger(AbstractResourceManagerFactory.class);
+
+ public abstract CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager manager) throws Exception;
+ public abstract CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager dbResourceManager, String sourceName) throws SQLException ;
+
+
+ public static AbstractResourceManagerFactory createIntstance() throws FactoryNotDefinedException {
+ throw new FactoryNotDefinedException("Factory method 'createIntstance' needs to be overriden in DBResourceManagerFactory");
+ }
+
+ public class DBInitTask implements Callable<CachedDataSource>
+ {
+ private BaseDBConfiguration config = null;
+ private Set<DBInitTask> activeTasks;
+
+ public DBInitTask(JDBCConfiguration jdbcconfig, Set<DBInitTask> tasks) {
+ this.config = jdbcconfig;
+ this.activeTasks = tasks;
+ }
+
+ public CachedDataSource call() throws Exception {
+ CachedDataSource ds = null;
+ try {
+ ds = CachedDataSourceFactory.createDataSource(config);
+ return ds;
+ } finally {
+ synchronized(activeTasks) {
+ activeTasks.remove(this);
+ if (activeTasks.isEmpty()) {
+ final Runnable closure = new Runnable() {
+
+ public void run() {
+ try {
+ Thread.sleep(300);
+ } catch (Exception e) {
+ }
+ synchronized(activeTasks) {
+ activeTasks.notifyAll();
+ }
+ }
+ };
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Completed CachedDataSource.Call and notifyAll from " + ds.getDbConnectionName());
+ }
+ Thread worker = new Thread(closure);
+ worker.setDaemon(true);
+ worker.start();
+ } else {
+ if (LOGGER.isDebugEnabled()) {
+ if (ds != null) {
+ LOGGER.debug("Completed CachedDataSource.Call from " + ds.getDbConnectionName());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
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
new file mode 100644
index 00000000..8aadcae6
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java
@@ -0,0 +1,100 @@
+/*-
+ * ============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.factory;
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.slf4j.LoggerFactory;
+
+import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.config.DbConfigPool;
+import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration;
+
+/**
+ * @version $Revision: 1.1 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki 01/17/08 Initial version
+ */
+public class DBConfigFactory {
+
+ public static DbConfigPool createConfig(Properties resource) {
+ return getConfigparams(resource);
+ }
+
+ static DbConfigPool getConfigparams(Properties properties){
+ DbConfigPool xmlConfig = new DbConfigPool(properties);
+ ArrayList<Properties> propertySets = new ArrayList<Properties>();
+
+ if("JDBC".equalsIgnoreCase(xmlConfig.getType())) {
+ String hosts = properties.getProperty(BaseDBConfiguration.DATABASE_HOSTS);
+ if(hosts == null || hosts.isEmpty()) {
+ propertySets.add(properties);
+ } else {
+ String[] newhost = hosts.split(",");
+ for(int i=0; i< newhost.length; i++) {
+ Properties localset = new Properties();
+ localset.putAll(properties);
+ String url = localset.getProperty(BaseDBConfiguration.DATABASE_URL);
+ if(url.contains("DBHOST"))
+ url = url.replace("DBHOST", newhost[i]);
+ if(url.contains("dbhost"))
+ url = url.replace("dbhost", newhost[i]);
+ localset.setProperty(BaseDBConfiguration.DATABASE_URL, url);
+ localset.setProperty(BaseDBConfiguration.CONNECTION_NAME, newhost[i]);
+ propertySets.add(localset);
+ }
+ }
+ } else {
+ propertySets.add(properties);
+ }
+ try {
+ Iterator<Properties> it = propertySets.iterator();
+ while(it.hasNext()) {
+ BaseDBConfiguration config = parse(it.next());
+ xmlConfig.addConfiguration(config);
+ }
+
+ } catch (Exception e) {
+ LoggerFactory.getLogger(DBConfigFactory.class).warn("",e);
+ }
+
+ return xmlConfig;
+ }
+
+ public static BaseDBConfiguration parse(Properties props) throws Exception {
+
+ String type = props.getProperty(BaseDBConfiguration.DATABASE_TYPE);
+
+ BaseDBConfiguration config = null;
+
+ if("JDBC".equalsIgnoreCase(type)) {
+ config = new JDBCConfiguration(props);
+ }
+
+ return config;
+
+ }
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/FactoryNotDefinedException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/FactoryNotDefinedException.java
new file mode 100644
index 00000000..e38cd351
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/FactoryNotDefinedException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============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.factory;
+
+
+/**
+ * @version 1.3
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki 01/16/08 Initial version
+ */
+public class FactoryNotDefinedException extends Exception {
+
+ public FactoryNotDefinedException(String message) {
+ super(message);
+ }
+
+}
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
new file mode 100644
index 00000000..90c76f63
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java
@@ -0,0 +1,249 @@
+/*-
+ * ============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.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLFeatureNotSupportedException;
+
+import org.apache.tomcat.jdbc.pool.DataSource;
+import org.apache.tomcat.jdbc.pool.PoolProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.openecomp.sdnc.sli.resource.dblib.CachedDataSource;
+import org.openecomp.sdnc.sli.resource.dblib.DBConfigException;
+import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration;
+import com.mysql.jdbc.Driver;
+
+
+/**
+ * @version $Revision: 1.7 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+
+public class JdbcDBCachedDataSource extends CachedDataSource
+{
+ private String dbUserId;
+ private String dbPasswd;
+ private String dbUrl;
+
+ private int minLimit;
+ private int maxLimit;
+ private int initialLimit;
+
+ private static final String AS_CONF_ERROR = "AS_CONF_ERROR: ";
+
+ private static Logger LOGGER = LoggerFactory.getLogger(JdbcDBCachedDataSource.class);
+
+ /**
+ * @param jdbcElem
+ */
+ public JdbcDBCachedDataSource(BaseDBConfiguration jdbcElem)
+ {
+ super(jdbcElem);
+ }
+
+ @Override
+ protected void configure(BaseDBConfiguration xmlElem) throws DBConfigException
+ {
+ BaseDBConfiguration jdbcConfig = (BaseDBConfiguration)xmlElem;
+ if(jdbcConfig.getConnTimeout() > 0){
+ this.CONN_REQ_TIMEOUT = jdbcConfig.getConnTimeout();
+ }
+ if(jdbcConfig.getRequestTimeout() > 0){
+ this.DATA_REQ_TIMEOUT = jdbcConfig.getRequestTimeout();
+ }
+
+ // set connection pool name
+ String dbConnectionName = jdbcConfig.getDbConnectionName();
+ super.setDbConnectionName(dbConnectionName);
+ // Configure the JDBC connection
+ dbUserId = jdbcConfig.getDbUserId();
+ if (dbUserId == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbUserId attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ dbPasswd = jdbcConfig.getDbPasswd();
+ if (dbPasswd == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbPasswd attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+ /*
+ dbDriver = jdbcConfig.getDbDriver();
+ if (dbDriver == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbDriver attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new ScpTblUpdateError(errorMsg);
+ }
+ */
+
+ minLimit = jdbcConfig.getDbMinLimit();
+// if (minLimit == null)
+// {
+// String errorMsg = "Invalid XML contents: JDBC Connection missing minLimit attribute";
+// LOGGER.error(AS_CONF_ERROR + errorMsg);
+// throw new DBConfigException(errorMsg);
+// }
+ maxLimit = jdbcConfig.getDbMaxLimit();
+// if (maxLimit == null)
+// {
+// String errorMsg = "Invalid XML contents: JDBC Connection missing maxLimit attribute";
+// LOGGER.error(AS_CONF_ERROR + errorMsg);
+// throw new DBConfigException(errorMsg);
+// }
+ initialLimit = jdbcConfig.getDbInitialLimit();
+// if (initialLimit == null)
+// {
+// String errorMsg = "Invalid XML contents: JDBC Connection missing initialLimit attribute";
+// LOGGER.error(AS_CONF_ERROR + errorMsg);
+// throw new DBConfigException(errorMsg);
+// }
+
+ dbUrl = jdbcConfig.getDbUrl();
+ if(dbUrl == null){
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbUrl attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ try {
+ Driver dr = new com.mysql.jdbc.Driver();
+ Class clazz = Class.forName("com.mysql.jdbc.Driver") ;
+
+ PoolProperties p = new PoolProperties();
+ p.setDriverClassName("com.mysql.jdbc.Driver");
+ p.setUrl(dbUrl);
+ p.setUsername(dbUserId);
+ p.setPassword(dbPasswd);
+ p.setJmxEnabled(true);
+ p.setTestWhileIdle(false);
+ p.setTestOnBorrow(true);
+ p.setValidationQuery("SELECT 1");
+ p.setTestOnReturn(false);
+ p.setValidationInterval(30000);
+ p.setTimeBetweenEvictionRunsMillis(30000);
+ p.setInitialSize(initialLimit);
+ p.setMaxActive(maxLimit);
+ p.setMaxIdle(maxLimit);
+ p.setMaxWait(10000);
+ p.setRemoveAbandonedTimeout(60);
+ p.setMinEvictableIdleTimeMillis(30000);
+ p.setMinIdle(minLimit);
+ p.setLogAbandoned(true);
+ p.setRemoveAbandoned(true);
+ p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
+ + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
+
+ DataSource dataSource = new DataSource(p);
+
+ synchronized(this)
+ {
+ this.ds = dataSource;
+ Connection con = null;
+ PreparedStatement st = null;
+ ResultSet rs = null;
+
+ try {
+ con = dataSource.getConnection();
+ st = con.prepareStatement("Select 1 FROM DUAL");
+ rs = st.executeQuery();
+ } catch(Exception exc) {
+ LOGGER.error(exc.getMessage());
+ } finally {
+ if(rs != null) rs.close();
+ if(st != null) st.close();
+ if(con != null) con.close();
+ }
+
+ initialized = true;
+ LOGGER.info("MySQLDataSource <"+dbConnectionName+"> configured successfully. Using URL: "+dbUrl);
+ }
+
+// } catch (SQLException exc) {
+// initialized = false;
+// StringBuffer sb = new StringBuffer();
+// sb.append("Failed to initialize MySQLDataSource<");
+// sb.append(dbConnectionName).append(">. Reason: ");
+// sb.append(exc.getMessage());
+// LOGGER.error("AS_CONF_ERROR: " + sb.toString());
+//// throw new DBConfigException(e.getMessage());
+ } catch (Exception exc) {
+ initialized = false;
+ StringBuffer sb = new StringBuffer();
+ sb.append("Failed to initialize MySQLCachedDataSource <");
+ sb.append(dbConnectionName).append(">. Reason: ");
+ sb.append(exc.getMessage());
+ LOGGER.error("AS_CONF_ERROR: " + sb.toString());
+// throw new DBConfigException(e.getMessage());
+ }
+ }
+
+ public final String getDbUrl()
+ {
+ return dbUrl;
+ }
+
+ public final String getDbUserId()
+ {
+ return dbUserId;
+ }
+
+ public final String getDbPasswd()
+ {
+ return dbPasswd;
+ }
+
+ public static JdbcDBCachedDataSource createInstance(BaseDBConfiguration config) /*throws Exception*/ {
+ return new JdbcDBCachedDataSource(config);
+ }
+
+ public String toString(){
+ return getDbConnectionName();
+ }
+
+ public java.util.logging.Logger getParentLogger()
+ throws SQLFeatureNotSupportedException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void cleanUp(){
+ DataSource dataSource = (DataSource)ds;
+ dataSource.getPool().purge();
+ int active = dataSource.getActive();
+ int size = dataSource.getSize();
+ dataSource.close(true);
+ super.cleanUp();
+ }
+
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDbResourceManagerFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDbResourceManagerFactory.java
new file mode 100644
index 00000000..84399dfd
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDbResourceManagerFactory.java
@@ -0,0 +1,186 @@
+/*-
+ * ============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.jdbc;
+
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+
+import org.openecomp.sdnc.sli.resource.dblib.CachedDataSource;
+import org.openecomp.sdnc.sli.resource.dblib.CachedDataSourceFactory;
+import org.openecomp.sdnc.sli.resource.dblib.DBResourceManager;
+import org.openecomp.sdnc.sli.resource.dblib.DataSourceComparator;
+import org.openecomp.sdnc.sli.resource.dblib.config.DbConfigPool;
+import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.factory.AbstractResourceManagerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Revision: 1.6 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class JdbcDbResourceManagerFactory extends AbstractResourceManagerFactory {
+ private static Logger LOGGER = LoggerFactory.getLogger(JdbcDbResourceManagerFactory.class );
+ private JdbcDbResourceManagerFactory(){
+
+ }
+
+ class MyFutureTask extends FutureTask<CachedDataSource>
+ {
+
+ public MyFutureTask(Callable<CachedDataSource> result) {
+ super(result);
+ }
+
+ }
+
+ public CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager manager, String sourceName) throws SQLException
+ {
+ // here create the data sources objects
+ JDBCConfiguration[] list = dbConfig.getJDBCbSourceArray();
+ CachedDataSource[] cachedDS = new CachedDataSource[1];
+
+ for(int i=0, max=list.length; i<max; i++){
+ if(!sourceName.equals(list[i].getDbConnectionName()))
+ continue;
+
+ JDBCConfiguration config = list[i];
+ CachedDataSource dataSource = CachedDataSourceFactory.createDataSource(config);
+ cachedDS[0] = dataSource;
+ }
+ return cachedDS;
+ }
+
+ public CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager manager) /* throws Exception */ {
+
+ ExecutorService threadExecutor = Executors.newFixedThreadPool(2);
+ // here create the data sources objects
+ JDBCConfiguration[] list = dbConfig.getJDBCbSourceArray();
+
+ MyFutureTask[] futures = new MyFutureTask[list.length];
+ final Set<DBInitTask> tasks = new HashSet<DBInitTask>();
+ if(LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Creating " + list.length + " datasources.");
+ }
+
+ for(int i=0, max=list.length; i<max; i++){
+ JDBCConfiguration config = list[i];
+
+ DBInitTask task = new DBInitTask(config, tasks);
+ tasks.add(task);
+ futures[i] = new MyFutureTask(task);
+ }
+
+ try {
+ synchronized(tasks){
+ for(int i=0, max=list.length; i<max; i++){
+ if(LOGGER.isDebugEnabled())
+ LOGGER.debug("Starting executor tasks.");
+ threadExecutor.execute(futures[i]);
+ }
+ // the timeout param is set is seconds.
+ long timeout = ((dbConfig.getTimeout() <= 0) ? 60L : dbConfig.getTimeout());
+ LOGGER.debug("Timeout set to " +timeout+" seconds");
+ timeout *= 1000;
+ // the timeout param is set is seconds, hence it needs to be multiplied by 1000.
+ tasks.wait(timeout);
+ if(LOGGER.isDebugEnabled())
+ LOGGER.debug("initDBResourceManager wait completed.");
+ }
+ } catch(Exception exc) {
+ LOGGER.error("Failed to initialize JndiCachedDataSource. Reason: ", exc);
+ }
+
+ if(threadExecutor != null){
+ try {
+ threadExecutor.shutdown();
+ } catch(Exception exc){}
+ }
+
+ CachedDataSource[] cachedDS = new CachedDataSource[futures.length];
+
+ boolean initialized = false;
+ for(int i=0; i<futures.length; i++){
+ Object obj = null;
+ if(futures[i].isDone()){
+ try {
+ obj = futures[i].get();
+ if(obj instanceof CachedDataSource){
+ cachedDS[i] = (CachedDataSource)obj;
+ initialized |= cachedDS[i].isInitialized();
+ if(cachedDS[i].isInitialized())
+ LOGGER.info("DataSource "+list[i].getDbConnectionName()+" initialized successfully");
+ else
+ LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed");
+ } else {
+ if(obj == null) {
+ LOGGER.warn("DataSource " + i + " initialization failed. Returned object is null");
+ } else {
+ LOGGER.warn("DataSource " + i + " initialization failed. Returned object is " + obj.getClass().getName());
+ }
+ }
+ } catch (InterruptedException exc) {
+ LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed", exc);
+ } catch (ExecutionException exc) {
+ LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed", exc);
+ } catch (Exception exc) {
+ LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed", exc);
+ }
+ } else {
+ try {
+ obj = futures[i].get();
+ if(obj instanceof CachedDataSource){
+ LOGGER.warn("DataSource "+((CachedDataSource)obj).getDbConnectionName()+" failed");
+ } else {
+ if(obj == null) {
+ LOGGER.warn("DataSource " + i + " initialization failed. Returned object is null");
+ } else {
+ LOGGER.warn("DataSource " + i + " initialization failed. Returned object is " + obj.getClass().getName());
+ }
+ }
+ } catch (Exception exc) {
+ LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed", exc);
+ }
+ }
+ }
+
+ if(!initialized){
+ new Error("Failed to initialize DB Library.");
+ }
+ return cachedDS;
+ }
+
+ public static AbstractResourceManagerFactory createIntstance() {
+ return new JdbcDbResourceManagerFactory();
+ }
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java
new file mode 100644
index 00000000..a5482d08
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java
@@ -0,0 +1,217 @@
+/*-
+ * ============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.jdbc;
+
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+
+import org.openecomp.sdnc.sli.resource.dblib.CachedDataSource;
+import org.openecomp.sdnc.sli.resource.dblib.DBConfigException;
+import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
+
+
+
+
+/**
+ * @version $Revision: 1.7 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+
+public class MySQLCachedDataSource extends CachedDataSource
+{
+ private String dbUserId;
+ private String dbPasswd;
+ private String dbUrl;
+
+ private String minLimit;
+ private String maxLimit;
+ private String initialLimit;
+
+ private static final String AS_CONF_ERROR = "AS_CONF_ERROR: ";
+
+ private static Logger LOGGER = LoggerFactory.getLogger(MySQLCachedDataSource.class);
+
+ /**
+ * @param jdbcElem
+ */
+ public MySQLCachedDataSource(BaseDBConfiguration jdbcElem)
+ {
+ super(jdbcElem);
+ }
+
+ @Override
+ protected void configure(BaseDBConfiguration xmlElem) throws DBConfigException
+ {
+ BaseDBConfiguration jdbcConfig = (BaseDBConfiguration)xmlElem;
+ if(jdbcConfig.getConnTimeout() > 0){
+ this.CONN_REQ_TIMEOUT = jdbcConfig.getConnTimeout();
+ }
+ if(jdbcConfig.getRequestTimeout() > 0){
+ this.DATA_REQ_TIMEOUT = jdbcConfig.getRequestTimeout();
+ }
+
+ // set connection pool name
+ String dbConnectionName = jdbcConfig.getDbConnectionName();
+ super.setDbConnectionName(dbConnectionName);
+ // Configure the JDBC connection
+ dbUserId = jdbcConfig.getDbUserId();
+ if (dbUserId == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbUserId attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ dbPasswd = jdbcConfig.getDbPasswd();
+ if (dbPasswd == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbPasswd attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+ /*
+ dbDriver = jdbcConfig.getDbDriver();
+ if (dbDriver == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbDriver attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new ScpTblUpdateError(errorMsg);
+ }
+ */
+
+ minLimit = Integer.toString(jdbcConfig.getDbMinLimit());
+ if (minLimit == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBC Connection missing minLimit attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+ maxLimit = Integer.toString(jdbcConfig.getDbMaxLimit());
+ if (maxLimit == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBC Connection missing maxLimit attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+ initialLimit = Integer.toString(jdbcConfig.getDbInitialLimit());
+ if (initialLimit == null)
+ {
+ String errorMsg = "Invalid XML contents: JDBC Connection missing initialLimit attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ dbUrl = jdbcConfig.getDbUrl();
+ if(dbUrl == null){
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbUrl attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ try {
+
+ MysqlDataSource dataSource = new MysqlDataSource();
+ dataSource.setUser(dbUserId);
+ dataSource.setPassword(dbPasswd);
+ dataSource.setURL(dbUrl);
+// dataSource.setInitialSize(5);
+// dataSource.setMaxTotal(60);
+// dataSource.setMaxActive(100);
+// dataSource.setMaxWait(10000);
+// dataSource.setMaxIdle(10);
+
+ Properties connAttr = new Properties();
+
+ connAttr.setProperty("MinLimit", minLimit);
+ connAttr.setProperty("MaxLimit", maxLimit);
+ connAttr.setProperty("InitialLimit", initialLimit);
+ connAttr.setProperty("TRANSACTION_ISOLATION","SERIALIZABLE");
+ connAttr.setProperty("CONNECTION_TAG", dbConnectionName.toUpperCase()+"_CONNECTION");
+ connAttr.setProperty("InactivityTimeout", "900");
+ connAttr.setProperty("AbandonedConnectionTimeout", "600");
+ connAttr.setProperty("PropertyCheckInterval", "60");
+ connAttr.setProperty("ValidateConnection", "true");
+
+
+ synchronized(this)
+ {
+ this.ds = dataSource;
+
+ initialized = true;
+ LOGGER.info("MySQLDataSource <"+dbConnectionName+"> configured successfully. Using URL: "+dbUrl);
+ }
+
+// } catch (SQLException exc) {
+// initialized = false;
+// StringBuffer sb = new StringBuffer();
+// sb.append("Failed to initialize MySQLDataSource<");
+// sb.append(dbConnectionName).append(">. Reason: ");
+// sb.append(exc.getMessage());
+// LOGGER.error("AS_CONF_ERROR: " + sb.toString());
+//// throw new DBConfigException(e.getMessage());
+ } catch (Exception exc) {
+ initialized = false;
+ StringBuffer sb = new StringBuffer();
+ sb.append("Failed to initialize MySQLCachedDataSource <");
+ sb.append(dbConnectionName).append(">. Reason: ");
+ sb.append(exc.getMessage());
+ LOGGER.error("AS_CONF_ERROR: " + sb.toString());
+// throw new DBConfigException(e.getMessage());
+ }
+ }
+
+ public final String getDbUrl()
+ {
+ return dbUrl;
+ }
+
+ public final String getDbUserId()
+ {
+ return dbUserId;
+ }
+
+ public final String getDbPasswd()
+ {
+ return dbPasswd;
+ }
+
+ public static MySQLCachedDataSource createInstance(BaseDBConfiguration config) /*throws Exception*/ {
+ return new MySQLCachedDataSource(config);
+ }
+
+ public String toString(){
+ return getDbConnectionName();
+ }
+
+ public java.util.logging.Logger getParentLogger()
+ throws SQLFeatureNotSupportedException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/PollingWorker.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/PollingWorker.java
new file mode 100644
index 00000000..de87fa7e
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/PollingWorker.java
@@ -0,0 +1,217 @@
+/*-
+ * ============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.pm;
+
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.TreeSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class PollingWorker implements Runnable {
+
+ private Logger LOGGER = LoggerFactory.getLogger(PollingWorker.class);
+
+ private static PollingWorker self = null;
+
+ private LinkedBlockingQueue tasks = new LinkedBlockingQueue(100);
+ private long interval = 1000L;
+ private Thread worker = null;
+ private AtomicLong[] counters = null;
+ private int[] bucketUnit = null;
+ private static boolean enabled = false;
+ private Timer timer = null;
+
+ public static void post(long starttime){
+ PollingWorker temp = self;
+ if(temp != null && enabled) {
+ temp.register(new TestSample(starttime));
+ }
+ }
+
+ public static void createInistance(Properties props){
+ self = new PollingWorker(props);
+ }
+
+ private PollingWorker(Properties ctxprops){
+ if(ctxprops==null || ctxprops.getProperty("org.openecomp.sdnc.dblib.pm") == null){
+ enabled = false;
+ } else {
+ if("true".equalsIgnoreCase((String)ctxprops.getProperty("org.openecomp.sdnc.dblib.pm"))){
+ enabled = true;
+ } else {
+ enabled = false;
+ }
+ }
+
+ interval = Long.parseLong(( ctxprops == null || ctxprops.getProperty("org.openecomp.sdnc.dblib.pm.interval") == null) ? "60" : (String)ctxprops.getProperty("org.openecomp.sdnc.dblib.pm.interval"));
+ // '0' bucket is to count exceptions
+ String sampling[] = ((ctxprops == null || ctxprops.getProperty("org.openecomp.sdnc.dblib.pm.sampling")==null) ? "0,2,5,10,20,50,100" : (String)ctxprops.getProperty("org.openecomp.sdnc.dblib.pm.sampling")).split(",");
+
+ if(enabled){
+ bucketUnit = new int[sampling.length];
+ for(int i=0, max = bucketUnit.length; i<max; i++){
+ bucketUnit[i] = Integer.parseInt(sampling[i].trim());
+ }
+ counters = new AtomicLong[bucketUnit.length+1];
+ for(int i=0, max = counters.length; i<max; i++){
+ counters[i] = new AtomicLong();
+ }
+ worker = new Thread(this);
+ worker.setDaemon(true);
+ worker.start();
+ timer = new Timer(true);
+ timer.schedule(new MyTimerTask(), interval*1000L, interval*1000L);
+ }
+ }
+
+ private void register(TestSample object){
+ try {
+ tasks.add(object);
+ } catch(Throwable exc) {
+ // if cannot add an object to the queue, do nothing
+ }
+ }
+
+ private void deRegister(TestSample object){
+ tasks.remove(object);
+ }
+
+ public void run() {
+ for(;;){
+ Set data = new TreeSet();
+ tasks.drainTo(data);
+ for(Iterator it = data.iterator(); it.hasNext(); ){
+ Object next = it.next();
+ if(next instanceof TestSample){
+ consume((TestSample)next);
+ } else {
+ System.out.println(next.getClass().getName());
+ }
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+ public void clearReqister(){
+ AtomicLong[] tmp = new AtomicLong[counters.length];
+ for(int i=0, max = tmp.length; i<max; i++){
+ tmp[i] = new AtomicLong();
+ }
+ AtomicLong[] tmp2 = counters;
+ synchronized(tmp2){
+ counters = tmp;
+ }
+ StringBuffer sb = new StringBuffer("CPM: ");
+ for(int i=0, max = tmp2.length; i < max; i++){
+ if(i==0 && bucketUnit[0]==0){
+ sb.append("[Exc]=");
+ } else {
+ sb.append("[");
+ if(i==bucketUnit.length){
+ sb.append("Other]=");
+ } else {
+ sb.append(bucketUnit[i]).append(" ms]=");
+ }
+ }
+ sb.append(tmp2[i].get()).append("\t");
+ }
+ LOGGER.info(sb.toString());
+ }
+
+ class MyTimerTask extends TimerTask{
+
+ public void run() {
+
+ clearReqister();
+ }
+
+ }
+
+ private void consume(TestSample probe) {
+ AtomicLong[] tmp = counters;
+ synchronized(tmp){
+ counters[getBucket(probe.getDuration())].incrementAndGet();
+ }
+ }
+
+ /*
+ * This method is used to find the offset of the bucket in
+ * counters. 'counters' array is 1 size longer than bucketUnit,
+ * hence by default it returns 'bucketUnit.length'
+ */
+ private int getBucket(long difftime){
+ for(int i=0; i<bucketUnit.length; i++){
+ if(difftime < bucketUnit[i]){
+ return i;
+ }
+ }
+ return bucketUnit.length;
+ }
+
+ private static boolean isEnabled() {
+ return enabled;
+ }
+ /**
+ * @author Rich Tabedzki
+ * A helper class to pass measured parameter to the counter.
+ */
+ static class TestSample implements Comparable{
+ private long starttime;
+ private long endtime;
+
+ public TestSample(long starttime) {
+ this.endtime = System.currentTimeMillis();
+ this.starttime = starttime;
+ }
+
+ public long getDuration(){
+ return endtime - starttime;
+ }
+
+ public int compareTo(Object o) {
+ if(o instanceof TestSample){
+ TestSample x = (TestSample)o;
+ if(starttime < x.starttime)
+ return 1;
+ if(endtime < x.endtime)
+ return 1;
+ if(starttime > x.starttime)
+ return -1;
+ if(endtime > x.endtime)
+ return -1;
+ return 0;
+ }
+ return 1;
+ }
+ }
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitor.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitor.java
new file mode 100644
index 00000000..c58c9db7
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitor.java
@@ -0,0 +1,237 @@
+/*-
+ * ============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.pm;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Observable;
+import java.util.Observer;
+import java.util.SortedSet;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.openecomp.sdnc.sli.resource.dblib.DBResourceObserver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SQLExecutionMonitor extends Observable
+{
+ private static Logger LOGGER = LoggerFactory.getLogger(SQLExecutionMonitor.class);
+
+ final static long MILISECOND = 1000000L;
+ final static long SECOND = 1000L*MILISECOND;
+
+ private final Timer timer;
+ // collection
+ private final SortedSet<TestObject> innerSet;
+ private SQLExecutionMonitorObserver parent = null;
+ private final AtomicLong completionCounter;
+ private boolean activeState = false;
+ private final long interval;
+ private final long initialDelay;
+ private final long EXPECTED_TIME_TO_COMPLETE;
+ private final long UNPROCESSED_FAILOVER_THRESHOLD;
+
+ private final class MonitoringTask extends TimerTask
+ {
+
+ public void run()
+ {
+ try {
+ TestObject testObj = new TestObject();
+ testObj.setStartTime(testObj.getStartTime() - EXPECTED_TIME_TO_COMPLETE);
+
+ // take a snapshot of the current task list
+ TestObject[] array = innerSet.toArray(new TestObject[0]);
+ SortedSet<TestObject> copyCurrent = new TreeSet<TestObject>(Arrays.asList(array));
+ // get the list of the tasks that are older than the specified
+ // interval.
+ SortedSet<TestObject> unprocessed = copyCurrent.headSet(testObj);
+
+ long succesfulCount = completionCounter.get();
+ int unprocessedCount = unprocessed.size();
+
+ if (!unprocessed.isEmpty() && unprocessedCount > UNPROCESSED_FAILOVER_THRESHOLD && succesfulCount == 0)
+ {
+ // switch the Connection Pool to passive
+ setChanged();
+ notifyObservers("Open JDBC requests=" + unprocessedCount+" in "+SQLExecutionMonitor.this.parent.getDbConnectionName());
+ }
+ } catch (Exception exc) {
+ LOGGER.error("", exc);
+ } finally {
+ completionCounter.set(0L);
+ }
+ }
+ }
+
+ public static class TestObject implements Comparable<TestObject>, Serializable
+ {
+
+ private static final long serialVersionUID = 1L;
+ private long starttime;
+ private long randId;
+
+ public TestObject()
+ {
+ starttime = System.nanoTime();
+ }
+
+ public long getStartTime()
+ {
+ return starttime;
+ }
+
+ public void setStartTime(long newTime)
+ {
+ starttime = newTime;
+ }
+
+ public int compareTo(TestObject o)
+ {
+ if( this == o)
+ return 0;
+ if(this.starttime > o.getStartTime())
+ return 1;
+ if(this.starttime < o.getStartTime())
+ return -1;
+
+ if(this.hashCode() > o.hashCode())
+ return 1;
+ if(this.hashCode() < o.hashCode())
+ return -1;
+
+ return 0;
+ }
+
+ public String toString()
+ {
+ return Long.toString(starttime)+"#"+ this.hashCode();
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+
+ return (obj instanceof TestObject
+ && starttime == ((TestObject) obj).getStartTime()
+ && hashCode() == ((TestObject) obj).hashCode());
+ }
+ }
+
+ public SQLExecutionMonitor(SQLExecutionMonitorObserver parent)
+ {
+ this.parent = parent;
+ completionCounter = new AtomicLong(0L);
+ interval = parent.getInterval();
+ initialDelay = parent.getInitialDelay();
+ this.UNPROCESSED_FAILOVER_THRESHOLD = parent.getUnprocessedFailoverThreshold();
+ this.EXPECTED_TIME_TO_COMPLETE = parent.getExpectedCompletionTime()*MILISECOND;
+
+ innerSet = Collections.synchronizedSortedSet(new TreeSet<TestObject>());
+ timer = new Timer();
+ }
+
+ public void cleanup()
+ {
+ timer.cancel();
+ }
+
+ // registerRequest
+ public TestObject registerRequest()
+ {
+ if(activeState)
+ {
+ TestObject test = new TestObject();
+ if(innerSet.add(test))
+ return test;
+ }
+ return null;
+ }
+
+ // deregisterSuccessfulReguest
+ public boolean deregisterReguest(TestObject test)
+ {
+ if(test == null)
+ return false;
+ // remove from the collection
+ if(innerSet.remove(test) && activeState)
+ {
+ completionCounter.incrementAndGet();
+ return true;
+ }
+ return false;
+ }
+
+ public void terminate() {
+ timer.cancel();
+ }
+
+ /**
+ * @return the parent
+ */
+ public final Object getParent() {
+ return parent;
+ }
+
+ public void addObserver(Observer observer)
+ {
+ if(observer instanceof DBResourceObserver)
+ {
+ DBResourceObserver dbObserver = (DBResourceObserver)observer;
+ if(dbObserver.isMonitorDbResponse())
+ {
+ if(countObservers() == 0)
+ {
+ TimerTask remindTask = new MonitoringTask();
+ timer.schedule(remindTask, initialDelay, interval);
+ activeState = true;
+ }
+ }
+ }
+ super.addObserver(observer);
+ }
+
+ public void deleteObserver(Observer observer)
+ {
+ super.deleteObserver(observer);
+ if(observer instanceof DBResourceObserver)
+ {
+ DBResourceObserver dbObserver = (DBResourceObserver)observer;
+ if(dbObserver.isMonitorDbResponse())
+ {
+ if(countObservers() == 0)
+ {
+ timer.cancel();
+ activeState = false;
+ }
+ }
+ }
+ }
+
+ public final int getPorcessedConnectionsCount() {
+ return innerSet.size();
+ }
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitorObserver.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitorObserver.java
new file mode 100644
index 00000000..1f329750
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitorObserver.java
@@ -0,0 +1,37 @@
+/*-
+ * ============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.pm;
+
+public interface SQLExecutionMonitorObserver {
+ public String getDbConnectionName();
+
+ public long getInterval();
+ public void setInterval(long value);
+
+ public long getInitialDelay();
+ public void setInitialDelay(long value);
+
+ public long getExpectedCompletionTime();
+ public void setExpectedCompletionTime(long value);
+
+ public long getUnprocessedFailoverThreshold();
+ public void setUnprocessedFailoverThreshold(long value);
+}
diff --git a/dblib/provider/src/main/resources/dblib.properties b/dblib/provider/src/main/resources/dblib.properties
new file mode 100755
index 00000000..ac295c78
--- /dev/null
+++ b/dblib/provider/src/main/resources/dblib.properties
@@ -0,0 +1,13 @@
+org.openecomp.sdnc.sli.dbtype=jdbc
+org.openecomp.sdnc.sli.jdbc.hosts=sdnctldb01,sdnctldb02
+org.openecomp.sdnc.sli.jdbc.url=jdbc:mysql://DBHOST:3306/sdnctl
+org.openecomp.sdnc.sli.jdbc.database=sdnctl
+org.openecomp.sdnc.sli.jdbc.user={user for sdnctl}
+org.openecomp.sdnc.sli.jdbc.password={password for sdnctl}
+org.openecomp.sdnc.sli.jdbc.connection.name=sdnctldb01
+
+org.openecomp.sdnc.sli.jdbc.connection.timeout=50
+org.openecomp.sdnc.sli.jdbc.request.timeout=100
+org.openecomp.sdnc.sli.jdbc.limit.init=10
+org.openecomp.sdnc.sli.jdbc.limit.min=10
+org.openecomp.sdnc.sli.jdbc.limit.max=20