2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2016 - 2017 AT&T
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdnc.sli.resource.dblib;
23 import java.io.PrintWriter;
24 import java.sql.Connection;
25 import java.sql.PreparedStatement;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.sql.Statement;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Observer;
33 import javax.sql.DataSource;
34 import javax.sql.rowset.CachedRowSet;
35 import javax.sql.rowset.RowSetProvider;
37 import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration;
38 import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor;
39 import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitorObserver;
40 import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor.TestObject;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
46 * @version $Revision: 1.13 $
48 * Author Date Comments
49 * ============== ======== ====================================================
53 public abstract class CachedDataSource implements DataSource, SQLExecutionMonitorObserver
55 private static Logger LOGGER = LoggerFactory.getLogger(CachedDataSource.class);
57 protected static final String AS_CONF_ERROR = "AS_CONF_ERROR: ";
59 protected long CONN_REQ_TIMEOUT = 30L;
60 protected long DATA_REQ_TIMEOUT = 100L;
62 private final SQLExecutionMonitor monitor;
63 protected DataSource ds = null;
64 protected String connectionName = null;
65 protected boolean initialized = false;
67 private long interval = 1000;
68 private long initisalDelay = 5000;
69 private long expectedCompletionTime = 50L;
70 private boolean canTakeOffLine = true;
71 private long unprocessedFailoverThreshold = 3L;
74 public CachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException
77 monitor = new SQLExecutionMonitor(this);
80 protected abstract void configure(BaseDBConfiguration jdbcElem) throws DBConfigException;
82 * @see javax.sql.DataSource#getConnection()
84 public Connection getConnection() throws SQLException
86 return ds.getConnection();
89 public CachedRowSet getData(String statement, ArrayList<String> arguments) throws SQLException, Throwable
91 TestObject testObject = null;
92 testObject = monitor.registerRequest();
94 Connection connection = null;
96 connection = this.getConnection();
97 if(connection == null ) {
98 throw new SQLException("Connection invalid");
100 if(LOGGER.isDebugEnabled())
101 LOGGER.debug("Obtained connection <" + connectionName + ">: "+connection.toString());
102 return executePreparedStatement(connection, statement, arguments);
105 if(connection != null && !connection.isClosed()) {
108 } catch(Throwable exc) {
109 // the exception not monitored
114 monitor.deregisterReguest(testObject);
118 public boolean writeData(String statement, ArrayList<String> arguments) throws SQLException, Throwable
120 TestObject testObject = null;
121 testObject = monitor.registerRequest();
123 Connection connection = null;
125 connection = this.getConnection();
126 if(connection == null ) {
127 throw new SQLException("Connection invalid");
129 if(LOGGER.isDebugEnabled())
130 LOGGER.debug("Obtained connection <" + connectionName + ">: "+connection.toString());
131 return executeUpdatePreparedStatement(connection, statement, arguments);
134 if(connection != null && !connection.isClosed()) {
137 } catch(Throwable exc) {
138 // the exception not monitored
143 monitor.deregisterReguest(testObject);
147 private CachedRowSet executePreparedStatement(Connection conn, String statement, ArrayList<String> arguments) throws SQLException, Throwable {
148 long time = System.currentTimeMillis();
150 CachedRowSet data = null;
151 if(LOGGER.isDebugEnabled()){
152 LOGGER.debug("SQL Statement: "+ statement);
153 if(arguments != null && !arguments.isEmpty()) {
154 LOGGER.debug("Argunments: "+ Arrays.toString(arguments.toArray()));
160 data = RowSetProvider.newFactory().createCachedRowSet();
161 PreparedStatement ps = conn.prepareStatement(statement);
162 if(arguments != null)
164 for(int i = 0, max = arguments.size(); i < max; i++){
165 ps.setObject(i+1, arguments.get(i));
168 rs = ps.executeQuery();
170 // Point the rowset Cursor to the start
171 if(LOGGER.isDebugEnabled()){
172 LOGGER.debug("SQL SUCCESS. count=" + data.size()+ ", time(ms): "+ (System.currentTimeMillis() - time)); }
173 } catch(SQLException exc){
174 if(LOGGER.isDebugEnabled()){
175 LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time));
177 try { conn.rollback(); } catch(Throwable thr){}
178 if(arguments != null && !arguments.isEmpty()) {
179 LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc);
181 LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc);
184 } catch(Throwable exc){
185 if(LOGGER.isDebugEnabled()){
186 LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time));
188 if(arguments != null && !arguments.isEmpty()) {
189 LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc);
191 LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc);
193 throw exc; // new SQLException(exc);
201 } catch(Exception exc){
209 } catch(Exception exc){
217 private boolean executeUpdatePreparedStatement(Connection conn, String statement, ArrayList<String> arguments) throws SQLException, Throwable {
218 long time = System.currentTimeMillis();
220 CachedRowSet data = null;
224 data = RowSetProvider.newFactory().createCachedRowSet();
225 PreparedStatement ps = conn.prepareStatement(statement);
226 if(arguments != null)
228 for(int i = 0, max = arguments.size(); i < max; i++){
229 ps.setObject(i+1, arguments.get(i));
232 rs = ps.executeUpdate();
233 // Point the rowset Cursor to the start
234 if(LOGGER.isDebugEnabled()){
235 LOGGER.debug("SQL SUCCESS. count=" + data.size()+ ", time(ms): "+ (System.currentTimeMillis() - time));
237 } catch(SQLException exc){
238 if(LOGGER.isDebugEnabled()){
239 LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time));
241 try { conn.rollback(); } catch(Throwable thr){}
242 if(arguments != null && !arguments.isEmpty()) {
243 LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc);
245 LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc);
248 } catch(Throwable exc){
249 if(LOGGER.isDebugEnabled()){
250 LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time));
252 if(arguments != null && !arguments.isEmpty()) {
253 LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc);
255 LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc);
257 throw exc; // new SQLException(exc);
265 } catch(Exception exc){
274 * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
276 public Connection getConnection(String username, String password)
279 return ds.getConnection(username, password);
283 * @see javax.sql.DataSource#getLogWriter()
285 public PrintWriter getLogWriter() throws SQLException
287 return ds.getLogWriter();
291 * @see javax.sql.DataSource#getLoginTimeout()
293 public int getLoginTimeout() throws SQLException
295 return ds.getLoginTimeout();
299 * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter)
301 public void setLogWriter(PrintWriter out) throws SQLException
303 ds.setLogWriter(out);
307 * @see javax.sql.DataSource#setLoginTimeout(int)
309 public void setLoginTimeout(int seconds) throws SQLException
311 ds.setLoginTimeout(seconds);
315 public final String getDbConnectionName(){
316 return connectionName;
319 protected final void setDbConnectionName(String name) {
320 this.connectionName = name;
323 public void cleanUp(){
325 monitor.deleteObservers();
329 public boolean isInitialized() {
333 protected boolean testConnection(){
334 return testConnection(false);
337 protected boolean testConnection(boolean error_level){
338 Connection conn = null;
340 Statement stmt = null;
343 Boolean readOnly = null;
344 String hostname = null;
345 conn = this.getConnection();
346 stmt = conn.createStatement();
347 rs = stmt.executeQuery("SELECT @@global.read_only, @@global.hostname"); //("SELECT 1 FROM DUAL"); //"select BANNER from SYS.V_$VERSION"
350 readOnly = rs.getBoolean(1);
351 hostname = rs.getString(2);
352 // if(rs.getInt(1)==1){
353 if(LOGGER.isDebugEnabled()){
354 LOGGER.debug("SQL DataSource <"+getDbConnectionName() + "> connected to " + hostname + ", read-only is " + readOnly + ", tested successfully ");
359 } catch (Throwable exc) {
361 LOGGER.error("SQL DataSource <" + this.getDbConnectionName() + "> test failed. Cause : " + exc.getMessage());
363 LOGGER.info("SQL DataSource <" + this.getDbConnectionName() + "> test failed. Cause : " + exc.getMessage());
371 } catch (SQLException e) {
378 } catch (SQLException e) {
385 } catch (SQLException e) {
392 public boolean isWrapperFor(Class<?> iface) throws SQLException {
396 public <T> T unwrap(Class<T> iface) throws SQLException {
400 @SuppressWarnings("deprecation")
401 public void setConnectionCachingEnabled(boolean state)
403 // if(ds != null && ds instanceof OracleDataSource)
405 // ((OracleDataSource)ds).setConnectionCachingEnabled(true);
406 // } catch (SQLException exc) {
407 // LOGGER.warn("", exc);
411 public void addObserver(Observer observer) {
412 monitor.addObserver(observer);
415 public void deleteObserver(Observer observer) {
416 monitor.deleteObserver(observer);
419 public long getInterval() {
423 public long getInitialDelay() {
424 return initisalDelay;
427 public void setInterval(long value) {
431 public void setInitialDelay(long value) {
432 initisalDelay = value;
435 public long getExpectedCompletionTime() {
436 return expectedCompletionTime;
439 public void setExpectedCompletionTime(long value) {
440 expectedCompletionTime = value;
443 public long getUnprocessedFailoverThreshold() {
444 return unprocessedFailoverThreshold;
447 public void setUnprocessedFailoverThreshold(long value) {
448 this.unprocessedFailoverThreshold = value;
451 public boolean canTakeOffLine() {
452 return canTakeOffLine;
455 public void blockImmediateOffLine() {
456 canTakeOffLine = false;
457 final Thread offLineTimer = new Thread()
461 Thread.sleep(30000L);
462 }catch(Throwable exc){
465 canTakeOffLine = true;
469 offLineTimer.setDaemon(true);
470 offLineTimer.start();
474 * @return the monitor
476 final SQLExecutionMonitor getMonitor() {
480 protected boolean isSlave() {
481 CachedRowSet rs = null;
482 boolean isSlave = true;
483 String hostname = "UNDETERMINED";
485 // rs = this.getData("show slave status", new ArrayList<String>());
486 // while(rs.next()) {
487 // String master = rs.getString(2);
488 // LOGGER.debug("database <"+connectionName+"> defines master as " + master);
489 // if(master == null || master.isEmpty() || master.equals(this.getDbConnectionName())) {
496 boolean localSlave = true;
497 rs = this.getData("SELECT @@global.read_only, @@global.hostname", new ArrayList<String>());
499 localSlave = rs.getBoolean(1);
500 hostname = rs.getString(2);
502 isSlave = localSlave;
503 } catch (SQLException e) {
506 } catch (Throwable e) {
511 LOGGER.debug("SQL SLAVE : "+connectionName + " on server " + hostname);
513 LOGGER.debug("SQL MASTER : "+connectionName + " on server " + hostname);
518 public boolean isFabric() {