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
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(); |
|
} |
|
|
|
} |
|
|
|
|
|
|