aboutsummaryrefslogtreecommitdiffstats
path: root/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib
diff options
context:
space:
mode:
Diffstat (limited to 'dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib')
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java521
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSourceFactory.java47
-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.java113
-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.java940
-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/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.java60
-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/config/JndiConfiguration.java62
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.java46
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java106
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java103
-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/JdbcDbResourceManagerFactory.java186
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java220
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jndi/JNDIDbResourceManagerFactory.java167
-rw-r--r--dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jndi/JndiCachedDataSource.java131
-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
27 files changed, 3717 insertions, 0 deletions
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 0000000..e21e2be
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java
@@ -0,0 +1,521 @@
+/*-
+ * ============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.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+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.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor;
+import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitorObserver;
+import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor.TestObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @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 initisalDelay = 5000;
+ private long expectedCompletionTime = 50L;
+ private boolean canTakeOffLine = true;
+ private long unprocessedFailoverThreshold = 3L;
+
+
+ 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<String> 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);
+ } 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<String> 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);
+ } finally {
+ try {
+ if(connection != null && !connection.isClosed()) {
+ connection.close();
+ }
+ } catch(Throwable exc) {
+ // the exception not monitored
+ } finally {
+ connection = null;
+ }
+
+ monitor.deregisterReguest(testObject);
+ }
+ }
+
+ private CachedRowSet executePreparedStatement(Connection conn, String statement, ArrayList<String> arguments) 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. count=" + 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){
+ conn.close();
+ conn = null;
+ }
+ } catch(Exception exc){
+
+ }
+ }
+
+ return data;
+ }
+
+ private boolean executeUpdatePreparedStatement(Connection conn, String statement, ArrayList<String> arguments) 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++){
+ ps.setObject(i+1, arguments.get(i));
+ }
+ }
+ rs = ps.executeUpdate();
+ // Point the rowset Cursor to the start
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("SQL SUCCESS. count=" + 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){
+ 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(){
+ 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(rs.getInt(1)==1){
+ 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 initisalDelay;
+ }
+
+ public void setInterval(long value) {
+ interval = value;
+ }
+
+ public void setInitialDelay(long value) {
+ initisalDelay = 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() {
+ CachedRowSet rs = null;
+ boolean isSlave = true;
+ String hostname = "UNDETERMINED";
+ try {
+// rs = this.getData("show slave status", new ArrayList<String>());
+// while(rs.next()) {
+// String master = rs.getString(2);
+// LOGGER.debug("database <"+connectionName+"> defines master as " + master);
+// if(master == null || master.isEmpty() || master.equals(this.getDbConnectionName())) {
+// isSlave = false;
+// } else {
+// isSlave = true;
+// }
+// }
+
+ boolean localSlave = true;
+ rs = this.getData("SELECT @@global.read_only, @@global.hostname", new ArrayList<String>());
+ while(rs.next()) {
+ localSlave = rs.getBoolean(1);
+ hostname = rs.getString(2);
+ }
+ isSlave = localSlave;
+ } 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;
+ }
+}
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 0000000..f774748
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSourceFactory.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;
+
+
+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.config.JndiConfiguration;
+import org.openecomp.sdnc.sli.resource.dblib.jdbc.MySQLCachedDataSource;
+import org.openecomp.sdnc.sli.resource.dblib.jndi.JndiCachedDataSource;
+
+/**
+ * @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 MySQLCachedDataSource.createInstance(config);
+ if(config instanceof JndiConfiguration)
+ return JndiCachedDataSource.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 0000000..b324e6a
--- /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 0000000..85cf834
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java
@@ -0,0 +1,113 @@
+/*-
+ * ============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.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(regName, jdbcDataSource, null);
+ 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)
+ {
+ registration.unregister();
+ registration = null;
+ LOG.debug("Deregistering DBResourceManager service");
+ }
+ }
+
+}
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 0000000..cc80741
--- /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 0000000..7f85c42
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java
@@ -0,0 +1,940 @@
+/*-
+ * ============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.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.sql.DataSource;
+import javax.sql.rowset.CachedRowSet;
+
+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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.rowset.providers.RIOptimisticProvider;
+
+/**
+ * @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();
+
+ try {
+ RIOptimisticProvider rio = new RIOptimisticProvider();
+ LOGGER.info("Class " + rio.getClass().getName() + " found.");
+ Class clas = this.getClass().getClassLoader().loadClass("com.sun.rowset.providers.RIOptimisticProvider");
+ if(clas != null) {
+ LOGGER.info("Class " + rio.getClass().getName() + " found by classloader.");
+ }
+ } catch(Exception exc) {
+ LOGGER.info("Failed resolving RIOptimisticProvider class", exc);
+ }
+ }
+
+ 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.dblib.DataAccessor#getData(java.lang.String, java.util.ArrayList)
+ */
+ /* (non-Javadoc)
+ * @see org.openecomp.sdnc.sli.resource.dblib.DbLibService#getData(java.lang.String, java.util.ArrayList, java.lang.String)
+ */
+ @Override
+ public CachedRowSet getData(String statement, ArrayList<String> arguments, String preferredDS) throws SQLException {
+ if(recoveryMode)
+ return requestDataWithRecovery(statement, arguments, preferredDS);
+ else
+ return requestDataNoRecovery(statement, arguments, preferredDS);
+ }
+
+ private CachedRowSet requestDataWithRecovery(String statement, ArrayList<String> 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 : "+ 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<String> 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.dblib.DataAccessor#writeData(java.lang.String, java.util.ArrayList)
+ */
+ /* (non-Javadoc)
+ * @see org.openecomp.sdnc.sli.resource.dblib.DbLibService#writeData(java.lang.String, java.util.ArrayList, java.lang.String)
+ */
+ @Override
+ public boolean writeData(String statement, ArrayList<String> arguments, String preferredDS) throws SQLException {
+ return writeDataNoRecovery(statement, arguments, preferredDS);
+ }
+
+ CachedDataSource findMaster() {
+ 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<String> 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(">> getData : "+ 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 active.getConnection();
+ } 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(Exception exc){
+ lastException = 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;
+ }
+ }
+ } 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 "";
+ }
+
+ private 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 {
+ // TODO Auto-generated method stub
+ 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();
+ }
+
+ /*
+ private void runTest(){
+ Thread producer = null;
+
+ producer = new ProducerThread("Prod1");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Prod2");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Prod3");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Prod4");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Prod5");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Prod6");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Prod7");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Prod8");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Prod9");
+ producer.setDaemon(true);
+ producer.start();
+
+ producer = new ProducerThread("Pro10");
+ producer.setDaemon(true);
+ producer.start();
+
+ }
+
+ private final class ProducerThread extends Thread {
+ private ProducerThread(String threadName) {
+ super(threadName);
+ }
+
+ public void run()
+ {
+ String name = null;
+ for(int i=0; i<(Integer.MAX_VALUE-1); i++)
+ {
+ try {
+ name = getPreferredDataSourceName(dsSelector);
+ if(name.contains("BACK")){
+ LOGGER.error(this.getName()+": <====== ");
+ } else {
+ LOGGER.error(this.getName()+": ======>");
+ }
+ CachedRowSet rs = null;
+ rs = getData("select 1 from dual", new ArrayList<String>(), name);
+ rs.close();
+ rs = getData("select 1 from dual", new ArrayList<String>(), name);
+ rs.close();
+ rs = getData("select 1 from dual", new ArrayList<String>(), name);
+ rs.close();
+ rs = getData("select 1 from dual", new ArrayList<String>(), name);
+ rs.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ try {
+ Thread.sleep(50L);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ return;
+ }
+ }
+*/
+}
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 0000000..e06779f
--- /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 0000000..cd054a5
--- /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 0000000..37d6251
--- /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 0000000..25edd1f
--- /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 0000000..17700a5
--- /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/TerminatingCachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/TerminatingCachedDataSource.java
new file mode 100644
index 0000000..234bbed
--- /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 0000000..976b1cf
--- /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 0000000..90ea6bc
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/DbConfigPool.java
@@ -0,0 +1,60 @@
+/*-
+ * ============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 JndiConfiguration[] getJndiDbSourceArray() {
+ return configurations.toArray(new JndiConfiguration[configurations.size()]);
+ }
+
+ 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 0000000..cb6ea3e
--- /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/config/JndiConfiguration.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JndiConfiguration.java
new file mode 100644
index 0000000..292372b
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JndiConfiguration.java
@@ -0,0 +1,62 @@
+/*-
+ * ============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 JndiConfiguration extends BaseDBConfiguration{
+
+ public JndiConfiguration(Properties xmlElem) {
+ super(xmlElem);
+ // TODO Auto-generated constructor stub
+ }
+
+ public String getJndiConnectionName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getJndiContextFactory() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getJndiURL() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getJndiSource() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setJndiContextFactory(String jndiContextFactoryStr) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setJndiURL(String jndiURLStr) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
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 0000000..e6b1a35
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.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.factory;
+
+import org.openecomp.sdnc.sli.resource.dblib.jdbc.JdbcDbResourceManagerFactory;
+import org.openecomp.sdnc.sli.resource.dblib.jndi.JNDIDbResourceManagerFactory;
+
+/**
+ * @version $Revision: 1.1 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class AbstractDBResourceManagerFactory {
+
+ public static AbstractResourceManagerFactory getFactory(String type) throws FactoryNotDefinedException {
+
+ if("JNDI".equals(type)){
+ try {
+ return JNDIDbResourceManagerFactory.createIntstance();
+ } catch (Exception e) {
+ }
+ }
+ // 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 0000000..148ddac
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java
@@ -0,0 +1,106 @@
+/*-
+ * ============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.openecomp.sdnc.sli.resource.dblib.config.JndiConfiguration;
+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(JndiConfiguration jndiConfig, Set<DBInitTask> tasks){
+ this.config = jndiConfig;
+ this.activeTasks = tasks;
+ }
+
+ 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())
+ 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 0000000..7044082
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java
@@ -0,0 +1,103 @@
+/*-
+ * ============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.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.openecomp.sdnc.sli.resource.dblib.config.JndiConfiguration;
+
+/**
+ * @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){
+ org.slf4j.LoggerFactory.getLogger(DBConfigFactory.class).info(properties.toString());
+ 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) {
+ org.slf4j.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("JNDI".equalsIgnoreCase(type)) {
+ config = new JndiConfiguration(props);
+ }
+ 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 0000000..e38cd35
--- /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/JdbcDbResourceManagerFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDbResourceManagerFactory.java
new file mode 100644
index 0000000..0afb621
--- /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<DBInitTask>
+ {
+
+ public MyFutureTask(Callable<CachedDataSource> result) {
+ super((Callable)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();
+
+ FutureTask<DBInitTask>[] 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 0000000..ebfd473
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java
@@ -0,0 +1,220 @@
+/*-
+ * ============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
+ * @param alarmLog
+ * @param occManager
+ * @throws Exception
+ */
+ 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/jndi/JNDIDbResourceManagerFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jndi/JNDIDbResourceManagerFactory.java
new file mode 100644
index 0000000..2888bc5
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jndi/JNDIDbResourceManagerFactory.java
@@ -0,0 +1,167 @@
+/*-
+ * ============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.jndi;
+
+import java.sql.SQLException;
+import java.util.HashSet;
+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.config.DbConfigPool;
+import org.openecomp.sdnc.sli.resource.dblib.config.JndiConfiguration;
+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 JNDIDbResourceManagerFactory extends AbstractResourceManagerFactory {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(JNDIDbResourceManagerFactory.class);
+
+ class MyFutureTask extends FutureTask<DBInitTask>
+ {
+
+ public MyFutureTask(Callable<CachedDataSource> result) {
+ super((Callable)result);
+ }
+
+ }
+
+ public CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager manager, String sourceName) throws SQLException
+ {
+ // here create the data sources objects
+ JndiConfiguration[] list = dbConfig.getJndiDbSourceArray();
+ CachedDataSource[] cachedDS = new CachedDataSource[1];
+
+ for(int i=0, max=list.length; i<max; i++){
+ if(!sourceName.equals(list[i].getJndiConnectionName()))
+ continue;
+
+ JndiConfiguration config = list[i];
+ CachedDataSource dataSource = CachedDataSourceFactory.createDataSource(config);
+ cachedDS[0] = dataSource;
+ }
+ return cachedDS;
+ }
+
+ public CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager manager) /* throws Exception */ {
+// WSConfigManagement ws = WSConfigManagement.getInstance();
+
+ ExecutorService threadExecutor = Executors.newFixedThreadPool(2);
+ // here create the data sources objects
+ JndiConfiguration[] list = dbConfig.getJndiDbSourceArray();
+ FutureTask<DBInitTask>[] futures = new MyFutureTask[list.length];
+ final Set<DBInitTask> tasks = new HashSet<DBInitTask>();
+ if(LOGGER.isDebugEnabled())
+ LOGGER.debug("Creating datasources.");
+ for(int i=0, max=list.length; i<max; i++){
+ JndiConfiguration config = list[i];
+// if(manager.getJndiContextFactoryStr()!=null && manager.getJndiContextFactoryStr().trim().length()>0){
+// config.setJndiContextFactory(manager.getJndiContextFactoryStr());
+// }
+// if(manager.getJndiURLStr()!=null && manager.getJndiURLStr().trim().length()>0){
+// config.setJndiURL(manager.getJndiURLStr());
+// }
+ 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++){
+ threadExecutor.execute(futures[i]);
+ }
+ // the timeout param is set is seconds.
+ long timeout = ((dbConfig.getTimeout() <= 0) ? 60L : dbConfig.getTimeout());
+ 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 = true;
+ LOGGER.info("DataSource "+list[i].getJndiConnectionName()+" initialized successfully");
+ }
+ } catch (InterruptedException exc) {
+ LOGGER.error("DataSource "+list[i].getJndiConnectionName()+" initialization failed", exc);
+ } catch (ExecutionException exc) {
+ LOGGER.error("DataSource "+list[i].getJndiConnectionName()+" initialization failed", exc);
+ } catch (Exception exc) {
+ LOGGER.error("DataSource "+list[i].getJndiConnectionName()+" initialization failed", exc);
+ }
+ } else {
+ try {
+ obj = futures[i].get();
+ if(obj instanceof CachedDataSource){
+
+ LOGGER.error("DataSource "+((CachedDataSource)obj).getDbConnectionName()+" failed");
+ }
+ } catch (Exception exc) {
+ LOGGER.error("DataSource "+list[i].getJndiConnectionName()+" initialization failed", exc);
+ }
+ }
+ }
+
+ if(!initialized){
+ new Error("Failed to initialize DB Library.");
+ }
+ return cachedDS;
+ }
+
+ public static AbstractResourceManagerFactory createIntstance() {
+ return new JNDIDbResourceManagerFactory();
+ }
+
+}
diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jndi/JndiCachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jndi/JndiCachedDataSource.java
new file mode 100644
index 0000000..19fa8e9
--- /dev/null
+++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jndi/JndiCachedDataSource.java
@@ -0,0 +1,131 @@
+/*-
+ * ============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.jndi;
+
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+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.JndiConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+/**
+ * @version $Revision: 1.2 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class JndiCachedDataSource extends CachedDataSource
+{
+ private static Logger LOGGER = LoggerFactory.getLogger(JndiCachedDataSource.class);
+ /**
+ * @param alarmLog
+ * @param jdbcElem
+ * @throws SAXException
+ * @throws ScpTblUpdateError
+ */
+ public JndiCachedDataSource(BaseDBConfiguration xmlElem) throws DBConfigException
+ {
+ super(xmlElem);
+ }
+
+ protected void configure(BaseDBConfiguration xmlElem) throws DBConfigException {
+ JndiConfiguration jdbcConfig = (JndiConfiguration)xmlElem;
+ String jndiContextFactoryStr = jdbcConfig.getJndiContextFactory();
+ String jndiURLStr = jdbcConfig.getJndiURL();
+ String jndiSourceStr = jdbcConfig.getJndiSource();
+
+ if(jdbcConfig.getConnTimeout() > 0){
+ this.CONN_REQ_TIMEOUT = jdbcConfig.getConnTimeout();
+ }
+ if(jdbcConfig.getRequestTimeout() > 0){
+ this.DATA_REQ_TIMEOUT = jdbcConfig.getRequestTimeout();
+ }
+
+ super.setDbConnectionName(jdbcConfig.getJndiConnectionName());
+
+ if(jndiContextFactoryStr == null || jndiContextFactoryStr.length() == 0)
+ {
+// throw new DBConfigException("The jndi configuration is incomplete: jndiContextFactory");
+ }
+ if(jndiURLStr == null || jndiContextFactoryStr.length() == 0)
+ {
+// throw new ScpTblUpdateError("The jndi configuration is incomplete: jndiURL");
+ }
+ if(jndiSourceStr == null || jndiSourceStr.length() == 0)
+ {
+ throw new DBConfigException("The jndi configuration is incomplete: jndiSource");
+ }
+
+ Properties env = new Properties();
+ Context ctx;
+ try
+ {
+ if(jndiContextFactoryStr != null && jndiContextFactoryStr.length() != 0){
+ env.put(Context.INITIAL_CONTEXT_FACTORY, jndiContextFactoryStr);
+ ctx = new InitialContext(env);
+ } else {
+ ctx = new InitialContext();
+ }
+ ds = (javax.sql.DataSource) ctx.lookup (jndiSourceStr);
+ if(ds == null)
+ {
+ this.initialized = false;
+ LOGGER.error("AS_CONF_ERROR: Failed to initialize DataSource <"+getDbConnectionName()+"> using JNDI <"+jndiSourceStr+">");
+ return;
+ } else {
+ this.initialized = true;
+ LOGGER.info("JndiCachedDataSource <"+getDbConnectionName()+"> configured successfully.");
+ return;
+ }
+ } catch (NamingException exc) {
+ this.initialized = false;
+ LOGGER.error("AS_CONF_ERROR" + exc.getMessage());
+
+ } catch(Throwable exc) {
+ this.initialized = false;
+ LOGGER.error("AS_CONF_ERROR: " + exc.getMessage());
+ }
+ }
+
+ public static JndiCachedDataSource createInstance(BaseDBConfiguration config) {
+ return new JndiCachedDataSource(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 0000000..de87fa7
--- /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 0000000..c58c9db
--- /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 0000000..1f32975
--- /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);
+}