From 88c5e41c5d3115521b24800b7be4e8bd77a27fc1 Mon Sep 17 00:00:00 2001 From: Rich Tabedzki Date: Fri, 22 Mar 2019 11:01:50 -0400 Subject: Support system variables in property values Changes made: * Added code in DBResourceManager to replace with its value * Expanded debug statement by adding processing time Change-Id: I22748daed50063e8e0ac7201e88d69a2609c1788 Issue-ID: CCSDK-1133 Signed-off-by: Rich Tabedzki --- .../ccsdk/sli/core/dblib/CachedDataSource.java | 41 +++++++- .../ccsdk/sli/core/dblib/DBResourceManager.java | 104 ++++++++++++++++----- .../core/dblib/TerminatingCachedDataSource.java | 7 ++ 3 files changed, 127 insertions(+), 25 deletions(-) (limited to 'dblib') diff --git a/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java index bc466d93..b9a0f071 100755 --- a/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java +++ b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java @@ -33,6 +33,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Observer; import javax.sql.DataSource; @@ -59,7 +60,7 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito private static final Logger LOGGER = LoggerFactory.getLogger(CachedDataSource.class); private static final String SQL_FAILURE = "SQL FAILURE. time(ms): "; - private static final String FAILED_TO_EXECUTE = "> failed to execute: "; + private static final String FAILED_TO_EXECUTE = "> Failed to execute: "; private static final String WITH_ARGUMENTS = " with arguments: "; private static final String WITH_NO_ARGUMENTS = " with no arguments. "; private static final String DATA_SOURCE_CONNECT_SUCCESS = "SQL DataSource < {} > connected to {}, read-only is {}, tested successfully"; @@ -82,12 +83,13 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito private long nextErrorReportTime = 0L; private String globalHostName = null; + private final int index; private boolean isDerby = false; public CachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException { ds = configure(jdbcElem); - + index = initializeIndex(jdbcElem); if ("org.apache.derby.jdbc.EmbeddedDriver".equals(jdbcElem.getDriverName())) { isDerby = true; } @@ -97,6 +99,16 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito protected abstract DataSource configure(BaseDBConfiguration jdbcElem) throws DBConfigException; protected abstract int getAvailableConnections(); + protected int initializeIndex(BaseDBConfiguration jdbcElem) { + if(jdbcElem.containsKey(BaseDBConfiguration.DATABASE_HOSTS)) { + String hosts = jdbcElem.getProperty(BaseDBConfiguration.DATABASE_HOSTS); + String name = jdbcElem.getProperty(BaseDBConfiguration.CONNECTION_NAME); + List numbers = Arrays.asList(hosts.split(",")); + return numbers.indexOf(name); + } else + return -1; + } + /* * (non-Javadoc) * @@ -104,7 +116,14 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito */ @Override public Connection getConnection() throws SQLException { + LapsedTimer lt = new LapsedTimer(); + try { return ds.getConnection(); + } finally { + if(LOGGER.isTraceEnabled()) { + LOGGER.trace(String.format("SQL Connection aquisition time : %s", lt.lapsedTime())); + } + } } public CachedRowSet getData(String statement, List arguments) throws SQLException { @@ -397,6 +416,10 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito monitor.deleteObserver(observer); } + public int getIndex() { + return index; + } + @Override public long getInterval() { return interval; @@ -487,9 +510,9 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito isSlave = true; } if (isSlave) { - LOGGER.debug("SQL SLAVE : {} on server {}, pool {}", connectionName, hostname, getAvailableConnections()); + LOGGER.debug("SQL SLAVE : {} on server {}, pool {}", connectionName, getDbConnectionName(), getAvailableConnections()); } else { - LOGGER.debug("SQL MASTER : {} on server {}, pool {}", connectionName, hostname, getAvailableConnections()); + LOGGER.debug("SQL MASTER : {} on server {}, pool {}", connectionName, getDbConnectionName(), getAvailableConnections()); } return isSlave; } @@ -557,4 +580,14 @@ public abstract class CachedDataSource implements DataSource, SQLExecutionMonito public String getGlobalHostName() { return globalHostName; } + + static class LapsedTimer { + private final long msTime = System.currentTimeMillis(); + + public String lapsedTime() { + double timediff = System.currentTimeMillis() - msTime; + timediff = timediff/1000; + return String.valueOf( timediff)+"s"; + } + } } diff --git a/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java index 236bce6e..7c71bcc8 100755 --- a/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java +++ b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java @@ -35,6 +35,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.Map; import java.util.HashSet; import java.util.Iterator; import java.util.Observable; @@ -44,6 +45,7 @@ import java.util.SortedSet; import java.util.TimerTask; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentSkipListSet; +import java.util.stream.Collectors; import javax.sql.DataSource; import javax.sql.rowset.CachedRowSet; @@ -66,7 +68,8 @@ import org.slf4j.LoggerFactory; * Rich Tabedzki */ public class DBResourceManager implements DataSource, DataAccessor, DBResourceObserver, DbLibService { - private static Logger LOGGER = LoggerFactory.getLogger(DBResourceManager.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DBResourceManager.class); + private static final String DATABASE_URL = "org.onap.ccsdk.sli.jdbc.url"; transient boolean terminating = false; transient protected long retryInterval = 10000L; @@ -92,8 +95,8 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } public DBResourceManager(final Properties properties) { - this.configProps = properties; - + this.configProps = processSystemVariables(properties); + // TODO : hack to force classloader to cache mariadb driver. This shouldnt be necessary, // but for some reason it is (without this, dblib throws ClassNotFound on mariadb driver // and fails to load). @@ -102,26 +105,26 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb dvr = null; // get retry interval value - retryInterval = getLongFromProperties(properties, "org.onap.dblib.connection.retry", 10000L); + retryInterval = getLongFromProperties(configProps, "org.onap.dblib.connection.retry", 10000L); // get recovery mode flag - recoveryMode = getBooleanFromProperties(properties, "org.onap.dblib.connection.recovery", true); + recoveryMode = getBooleanFromProperties(configProps, "org.onap.dblib.connection.recovery", true); if(!recoveryMode) { recoveryMode = false; LOGGER.info("Recovery Mode disabled"); } // get time out value for thread cleanup - terminationTimeOut = getLongFromProperties(properties, "org.onap.dblib.termination.timeout", 300000L); + terminationTimeOut = getLongFromProperties(configProps, "org.onap.dblib.termination.timeout", 300000L); // get properties for monitoring - monitorDbResponse = getBooleanFromProperties(properties, "org.onap.dblib.connection.monitor", false); - monitoringInterval = getLongFromProperties(properties, "org.onap.dblib.connection.monitor.interval", 1000L); - monitoringInitialDelay = getLongFromProperties(properties, "org.onap.dblib.connection.monitor.startdelay", 5000L); - expectedCompletionTime = getLongFromProperties(properties, "org.onap.dblib.connection.monitor.expectedcompletiontime", 5000L); - unprocessedFailoverThreshold = getLongFromProperties(properties, "org.onap.dblib.connection.monitor.unprocessedfailoverthreshold", 3L); + monitorDbResponse = getBooleanFromProperties(configProps, "org.onap.dblib.connection.monitor", false); + monitoringInterval = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.interval", 1000L); + monitoringInitialDelay = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.startdelay", 5000L); + expectedCompletionTime = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.expectedcompletiontime", 5000L); + unprocessedFailoverThreshold = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.unprocessedfailoverthreshold", 3L); // initialize performance monitor - PollingWorker.createInistance(properties); + PollingWorker.createInistance(configProps); // initialize recovery thread worker = new RecoveryMgr(); @@ -130,13 +133,49 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb worker.start(); try { - this.config(properties); + this.config(configProps); } catch (final Exception e) { // TODO: config throws Exception which is poor practice. Eliminate this in a separate patch. LOGGER.error("Fatal Exception encountered while configuring DBResourceManager", e); } } + public static Properties processSystemVariables(Properties properties) { + Map hmap = new Properties(); + hmap.putAll(properties); + + Map result = hmap.entrySet().stream() + .filter(map -> map.getValue().toString().startsWith("${")) + .filter(map -> map.getValue().toString().endsWith("}")) + .collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue())); + + result.forEach((name, propEntries) -> { + hmap.put(name, replace(propEntries.toString())); + }); + + if(hmap.containsKey(DATABASE_URL) && hmap.get(DATABASE_URL).toString().contains("${")) { + String url = hmap.get(DATABASE_URL).toString(); + String[] innerChunks = url.split("\\$\\{"); + for(String chunk : innerChunks) { + if(chunk.contains("}")) { + String subChunk = chunk.substring(0, chunk.indexOf("}")); + String varValue = System.getenv(subChunk); + url = url.replace("${"+subChunk+"}", varValue); + } + } + hmap.put(DATABASE_URL, url); + } + return Properties.class.cast(hmap); + } + + + private static String replace(String value) { + String globalVariable = value.substring(2, value.length() -1); + String varValue = System.getenv(globalVariable); + return (varValue != null) ? varValue : value; + } + + private void config(Properties configProps) throws Exception { final ConcurrentLinkedQueue semaphore = new ConcurrentLinkedQueue<>(); final DbConfigPool dbConfig = DBConfigFactory.createConfig(configProps); @@ -204,11 +243,33 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb return -1; } - if(!left.isSlave()) + boolean leftMaster = !left.isSlave(); + if(leftMaster) { + if(left.getIndex() <= right.getIndex()) + return -1; + else { + boolean rightMaster = !right.isSlave(); + if(rightMaster) { + if(left.getIndex() <= right.getIndex()) + return -1; +// if(left.getIndex() > right.getIndex()) + else { + return 1; + } + } else { return -1; + } + } + } if(!right.isSlave()) return 1; + if(left.getIndex() <= right.getIndex()) + return -1; + if(left.getIndex() > right.getIndex()) + return 1; + + } catch (Throwable e) { LOGGER.warn("", e); } @@ -440,12 +501,12 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } } lastException = exc; - LOGGER.error("Generated alarm: "+active.getDbConnectionName(), exc); + LOGGER.error("Generated alarm: {}", active.getDbConnectionName(), exc); handleGetConnectionException(active, exc); } finally { if(LOGGER.isDebugEnabled()){ time = System.currentTimeMillis() - time; - LOGGER.debug("getData processing time : "+ active.getDbConnectionName()+" "+time+" miliseconds."); + LOGGER.debug("getData processing time : {} {} miliseconds.", active.getDbConnectionName(), time); } } } @@ -490,7 +551,7 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb String message = exc.getMessage(); if(message == null) message = exc.getClass().getName(); - LOGGER.error("Generated alarm: "+active.getDbConnectionName()+" - "+message); + LOGGER.error("Generated alarm: {} - {}",active.getDbConnectionName(), message); if(exc instanceof SQLException) throw (SQLException)exc; else { @@ -501,7 +562,7 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } finally { if(LOGGER.isDebugEnabled()){ time = System.currentTimeMillis() - time; - LOGGER.debug(">> getData : "+ active.getDbConnectionName()+" "+time+" miliseconds."); + LOGGER.debug(">> getData : {} {} miliseconds.", active.getDbConnectionName(), time); } } } @@ -570,12 +631,12 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb String message = exc.getMessage(); if(message == null) message = exc.getClass().getName(); - LOGGER.error("Generated alarm: "+active.getDbConnectionName()+" - "+message); + 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()); + LOGGER.warn("retrying due to: {}", sqlExc.getMessage()); this.findMaster(); if(retryAllowed){ retryAllowed = false; @@ -592,7 +653,7 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb } finally { if(LOGGER.isDebugEnabled()){ time = System.currentTimeMillis() - time; - LOGGER.debug("writeData processing time : "+ active.getDbConnectionName()+" "+time+" miliseconds."); + LOGGER.debug("writeData processing time : {} {} miliseconds.", active.getDbConnectionName(), time); } } } @@ -626,6 +687,7 @@ public class DBResourceManager implements DataSource, DataAccessor, DBResourceOb if(!active.isFabric()) { if(this.dsQueue.size() > 1 && active.isSlave()) { + LOGGER.debug("Forcing reorder on: {}", dsQueue.toString()); CachedDataSource master = findMaster(); if(master != null) { active = master; diff --git a/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java index 884f8882..852dda3c 100755 --- a/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java +++ b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java @@ -30,6 +30,7 @@ import org.onap.ccsdk.sli.core.dblib.pm.SQLExecutionMonitorObserver; public class TerminatingCachedDataSource extends CachedDataSource implements SQLExecutionMonitorObserver { private static final int DEFAULT_AVAILABLE_CONNECTIONS = 0; + private static final int DEFAULT_INDEX = -1; public TerminatingCachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException { super(jdbcElem); @@ -49,4 +50,10 @@ public class TerminatingCachedDataSource extends CachedDataSource implements SQL protected int getAvailableConnections() { return DEFAULT_AVAILABLE_CONNECTIONS; } + + @Override + protected int initializeIndex(BaseDBConfiguration jdbcElem) { + return DEFAULT_INDEX; + } + } -- cgit 1.2.3-korg