You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

613 lines
15 KiB

/******************************************************************************
*
* Copyright: Intellectual Property of Four Elements Capital Pte Ltd, Singapore.
* All rights reserved.
*
******************************************************************************/
package com.fourelementscapital.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.jcs.JCS;
import org.apache.commons.jcs.access.CacheAccess;
import org.apache.commons.jcs.engine.behavior.IElementAttributes;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.fourelementscapital.db.mariadb.BBSyncDBMariaDB;
import com.fourelementscapital.db.mariadb.ConstructQueryDBMariaDB;
import com.fourelementscapital.db.mariadb.ContractDBMariaDB;
import com.fourelementscapital.db.mariadb.DBManagerDBMariaDB;
import com.fourelementscapital.db.mariadb.FlexiFieldDBMariaDB;
import com.fourelementscapital.db.mariadb.IExecDBMariaDB;
import com.fourelementscapital.db.mariadb.InfrastructureDBMariaDB;
import com.fourelementscapital.db.mariadb.RFunctionDBMariaDB;
import com.fourelementscapital.db.mariadb.ReferenceDBMariaDB;
import com.fourelementscapital.db.mariadb.SchedulerDBMariaDB;
import com.fourelementscapital.db.mariadb.UtilDBMariaDB;
import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;
import com.jolbox.bonecp.Statistics;
/**
* Super class of all db classes
*/
public class SuperDB {
// get db name from config file :
public static final String DB_NAME_BBSYNC = "bbsync";
//public static final String DB_NAME_R_FUNCTION = "rfunction";
public static final String DB_NAME_R_FUNCTION = "quantlib";
public static final String DB_NAME_TRADING = "trading";
public static final String DB_NAME_TRADINGREF = "tradingRef";
public static final String DB_NAME_IEXEC = "iexec";
public static final String DB_NAME_INFRASTRUCTURE = "infrastructure";
public static boolean CONNECTION_POOL_ACTIVE=false;
public static boolean CONNECTION_POOL_CONN_COUNT=true;
private static int db_close_timeout = 5; // default : 5 minutes
private Connection con = null;
private String db=null;
private String driver = "com.mysql.jdbc.Driver";
private static ConcurrentHashMap<String,BoneCP> connPools=new ConcurrentHashMap<String,BoneCP>();
private static Vector<SuperDB> connections=new Vector<SuperDB>();
private Date connectedDate=null;
private String callStack=null;
public static String MY_SQL_DRIVER="com.mysql.jdbc.Driver";
private String tablename=null;
private Logger log=LogManager.getLogger(SuperDB.class.getName());
//private Logger log = LogManager.getLogger(ExecuteRMgmt.class.getName());
private static long count=0;
private static long delays=0;
//private static JCS cache=null;
private static CacheAccess<String, String> cache=null;
/**
* Get DB close timeout
* @return timeout
*/
public static int getDbCloseTimeout() {
if(Config.getString("db_close_timeout") != null) {
db_close_timeout = Integer.parseInt(Config.getString("db_close_timeout"));
}
return db_close_timeout;
}
/**
* Get connected date
* @return connected date
*/
public Date getConnectedDate() {
return connectedDate;
}
/**
* Set connected date
* @param connectedDate connected date
*/
public void setConnectedDate(Date connectedDate) {
this.connectedDate = connectedDate;
}
/**
* Get call stack
* @return call stack
*/
public String getCallStack() {
return callStack;
}
/**
* Set call stack
* @param callStack call stack
*/
public void setCallStack(String callStack) {
this.callStack = callStack;
}
/**
* Connect to specific database
* @param db database
* @throws Exception
*/
public void connectDB(String db) throws Exception {
// Establish the connection.
this.db=db;
Date start=new Date();
String marketConnectionURL = Utils.getConfig4E(".CONFIG4E_JDBC_CONNECTIONSTRING_" + db.toUpperCase()); // throw exception
// add parameter to prevent timestamp converting error
marketConnectionURL += "&useUnicode=true&useFastDateParsing=false&characterEncoding=UTF-8";
// replace driver if marketConnectionURL contains 'sqlserver'. i.e. 'jdbc:sqlserver://10.153.64.3:1433;databaseName=infrastructure;integratedSecurity=false;user=dbuser;password=dbuser'
if (marketConnectionURL.contains("sqlserver")) {
this.driver="com.microsoft.sqlserver.jdbc.SQLServerDriver";
}
if(CONNECTION_POOL_ACTIVE){
if(connPools.get(db)==null){
setupConnectionPool(marketConnectionURL);
}
if(this.con!=null && !this.con.isClosed()) {
//don't assing new
printOrphanConns();
}else{
this.con=connPools.get(db).getAsyncConnection().get();
this.setCallStack(collectErrorStack(new Exception().getStackTrace()));
this.setConnectedDate(new Date());
//connPools.get(db).getAsyncConnection()
connections.add(this);
}
}else{
Class.forName(this.driver);
log.debug("marketConnectionURL:"+marketConnectionURL);
if(this.con!=null && !this.con.isClosed()) {
//don't assing new
//System.out.println("~~~SuperDB.connectDB(): Reuse connection, Already connection is active");
printOrphanConns();
}else{
this.con = DriverManager.getConnection(marketConnectionURL);
connections.add(this);
this.setCallStack(collectErrorStack(new Exception().getStackTrace()));
this.setConnectedDate(new Date());
//DatabaseMetaData md=this.con.getMetaData();
//md.get
}
}
//log.debug("conn opened in "+diff+" ms" +" counter:"+count);
if(CONNECTION_POOL_CONN_COUNT) {
Date end=new Date();
long diff=end.getTime()-start.getTime();
delays+=diff;
count++;
}
}
/**
* Get cache
* @return cache
* @throws Exception
*/
private static CacheAccess getCache() throws Exception {
if(cache==null) cache=JCS.getInstance("SuperDB-cache");
return cache;
}
/**
* Print orphan connections
* @throws Exception
*/
private void printOrphanConns() throws Exception {
if(getCache().get("delayPrint")!=null){
System.out.println("~~~SuperDB.connectDB(): Reuse connection, Already connection is active");
}else{
IElementAttributes att= getCache().getDefaultElementAttributes();
att.setMaxLife(600);
getCache().put("delayPrint","delay",att);
try{
System.out.println("=====SuperDB.connectDB(): Reuse connection, Already connection is active====\n"+collectErrorStack(new Exception().getStackTrace()));
//Thread.dumpStack();
}catch(Exception e){
//e.printStackTrace();
}
}
}
/**
* Setup connection pool
* @param marketConnectionURL market connection URL
* @throws Exception
*/
private synchronized void setupConnectionPool(String marketConnectionURL) throws Exception {
Class.forName(this.driver); // load the DB driver
BoneCPConfig config = new BoneCPConfig(); // create a new configuration object
config.setJdbcUrl(marketConnectionURL); // set the JDBC url
config.setMinConnectionsPerPartition(1);
config.setMaxConnectionsPerPartition(25);
config.setPartitionCount(2); //set connectinos returned to pool lives very short
//config.setAcquireIncrement(1);
config.setMaxConnectionAgeInSeconds(10);
config.setLogStatementsEnabled(true);
connPools.put(db, new BoneCP(config));
}
/**
* Close all connections
*/
public static void closeAllConnections(){
for(Iterator it=connPools.keySet().iterator();it.hasNext();) {
String key=(String)it.next();
BoneCP bcp=(BoneCP)connPools.get(key);
bcp.shutdown();
connPools.remove(key);
}
}
/**
* Get connection count
* @return connection count
*/
public static String getConnectionCount() {
String t="Total Conn:"+count+" total delay:"+delays+" average:"+(delays/count)+" ms";
return t;
}
/**
* Get connection objects
* @return connection objects
*/
public static List<SuperDB> getConnectionObjs() {
return connections;
}
/**
* Reset connection count
*/
public static void connectionCountReset() {
count=0;
delays=0;
}
/**
* Get connection status
* @return connection status
*/
public static String getConnStatus(){
String t="\n";
for(Iterator it=connPools.keySet().iterator();it.hasNext();) {
String key=(String)it.next();
BoneCP bcp=(BoneCP)connPools.get(key);
Statistics st=bcp.getStatistics();
t+="Db:"+key+" --->";
t+=" Total Conn:"+st.getTotalCreatedConnections()+" Free:"+st.getTotalFree()+" Cached hits:"+st.getCacheHits()+" Cached miss:"+st.getCacheMiss()+" Req Conn:"+st.getConnectionsRequested()+" Leased:"+st.getTotalLeased();
t+="\n";
//bcp.shutdown();
//connPools.remove(key);
}
return t;
}
/**
* Get opened connections
* @return connection count
*/
public static String getOpenedConnections() {
return "Size:"+connections.size();
}
/**
* Collect error stack
* @return error stack
* @throws Exception
*/
public static String collectStack() throws Exception {
return collectErrorStack(new Exception().getStackTrace());
}
/**
* Kill connections
* @param minsbefore minutes before
* @throws Exception
*/
public static void killConnections(int minsbefore) throws Exception {
Logger log=LogManager.getLogger(SuperDB.class.getName());
Vector<SuperDB> v=new Vector();
synchronized(connections) {
//System.out.println("------" );
for(SuperDB sdb: connections) {
Calendar opened=Calendar.getInstance(); opened.setTime(sdb.getConnectedDate());
Calendar now=Calendar.getInstance(); now.setTime(new Date());
now.add(Calendar.MINUTE, -minsbefore);
long diff=new Date().getTime()-sdb.getConnectedDate().getTime();
diff=diff/1000;
SimpleDateFormat sdf=new SimpleDateFormat("dd-MMM HH:mm:ss");
//System.out.println("Opened at:"+sdf.format(sdb.getConnectedDate())+" now:"+sdf.format(new Date())+"con id: is expired:"+now.after(opened)+" diff:"+diff+" seconds" );
if(now.after(opened)){
//System.out.println("closing connection: as it is expired");
//sdb.closeDB();
v.add(sdb);
}
}
}
if(v.size()>0){
log.error("~~~~~~Closing "+v.size()+" connections after "+minsbefore+" minutes");
}
for(SuperDB sdb: v) {
sdb.closeDB();
}
}
/**
* Collect error stack
* @return error stack
* @throws Exception
*/
private static String collectErrorStack(StackTraceElement[] sts) throws Exception {
String rtn="";
SimpleDateFormat sdf=new SimpleDateFormat("dd-MMM HH:mm:ss.SSS ");
rtn+="\n-- "+sdf.format(new Date())+" Thread:"+Thread.currentThread().getId()+" - "+Thread.currentThread().getName()+" --\n";
for(int loop=0;loop<sts.length;loop++){
if(sts[loop].getClassName().contains("com.fourelementscapital.")){
rtn+=" " +sts[loop].getClassName()+"."+sts[loop].getMethodName()+"\n";
}
}
return rtn;
}
/**
* Collect all stack
* @return stack
* @throws Exception
*/
public static String collectStack4All() throws Exception {
String rtn="";
for(SuperDB sdb: connections){
rtn+=sdb.getCallStack()+"\n";
}
return rtn;
}
//public BoneCP getConnectionPool(){
// return connPools.get(this.db);
//}
/**
* Set database
* @param db database
*/
public void setDb(String db){
this.db=db;
}
/**
* Get database
* @return database
*/
public String getDb(){
return this.db;
}
/**
* Get driver
* @param db database
* @return driver
*/
public String getDriver(String db) {
return Config.getValue(db+".db_driver");
}
/**
* Get connection
* @return connection
*/
public Connection connection(){
return this.con;
}
/**
* Set read only
* @param flag flag
* @throws Exception
*/
public void setReadOnly(boolean flag) throws Exception {
this.con.setReadOnly(flag);
}
/**
* Check whether read only
* @return true if read only
* @throws Exception
*/
public boolean isReadOnly() throws Exception {
return this.con.isReadOnly();
}
/**
* Close database
* @throws Exception
*/
public void closeDB() throws Exception {
if(this.con!=null){
//if(CONNECTION_POOL_ACTIVE){
//}else{
connections.remove(this);
this.con.close();
this.con=null;
//}
}
}
/**
* Check whether driver is MySQL
* @return true if driver is MySQL
*/
public boolean isMySQLDriver(){
if(this.db!=null && getDriver(this.db)!=null && getDriver(this.db).equals(MY_SQL_DRIVER)){
return true;
}else{
return false;
}
}
/**
* Get contract database class
* @param tablename table name
* @param db database
* @return contract database class
*/
public final ContractDB getContractDB(String tablename, String db) {
this.tablename=tablename;
this.db=db;
//if(this.db!=null && getDriver(this.db)!=null && getDriver(this.db).equals(MY_SQL_DRIVER)){
ContractDBMariaDB cdb=new ContractDBMariaDB(this.tablename);
cdb.setDb(db);
return cdb;
/*
}else{
return null;
}
*/
}
//public final ContractDB getContractDB(String tablename) {
// return null;
//}
/**
* Get utility database class
* @param db database
* @return utility database class
*/
public final UtilDB getUtilDB(String db) {
//return this.utilDB;
this.db=db;
//if(this.db!=null && getDriver(this.db)!=null && getDriver(this.db).equals(MY_SQL_DRIVER)){
UtilDBMariaDB udsql=new UtilDBMariaDB();
udsql.setDb(db);
return udsql;
/*
}else{
return null;
}
*/
}
/**
* Get BBSync database class
* @return BBSync database class
*/
public static BBSyncDB getBBSyncDB() {
return new BBSyncDBMariaDB();
}
/**
* Get Flexi Field database class
* @return Flexi Field database class
*/
public static FlexiFieldDB getFlexiFieldDB() {
return new FlexiFieldDBMariaDB();
}
/**
* Get Reference database class
* @return Reference database class
*/
public static ReferenceDB getReferenceDB() {
return new ReferenceDBMariaDB();
}
/**
* Get Scheduler database class
* @return Scheduler database class
*/
public static SchedulerDB getSchedulerDB() {
return new SchedulerDBMariaDB();
}
/**
* Get RFunction database class
* @return RFunction database class
*/
public static RFunctionDB getRFunctionDB() {
return new RFunctionDBMariaDB();
}
/**
* Get IExec database class
* @return IExec database class
*/
public static IExecDB getIExcecDB() {
return new IExecDBMariaDB();
}
/**
* Get DBManager database class
* @return DBManager database class
*/
public static DBManagerDB getDBManagerDB(){
return new DBManagerDBMariaDB();
}
/**
* Get Util database class
* @return Util database class
*/
public static UtilDB getUtilDB4SQLServer() {
return new UtilDBMariaDB();
}
/**
* Get ConstructQuery database class
* @return ConstructQuery database class
*/
public static ConstructQueryDB getConstructQueryDB() {
return new ConstructQueryDBMariaDB();
}
/**
* Get Infrastructure database class
* @return Infrastructure database class
*/
public static InfrastructureDB getInfrastructureDB() {
return new InfrastructureDBMariaDB();
}
}