Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:19:36

0001 #include "ODBCInterface.h"
0002 
0003 #include <odbc++/connection.h>
0004 #include <odbc++/drivermanager.h>
0005 #include <odbc++/resultset.h>
0006 #include <odbc++/statement.h>  // for Statement
0007 #include <odbc++/types.h>
0008 
0009 #include <cassert>
0010 #include <chrono>
0011 #include <cmath>
0012 #include <iostream>
0013 #include <random>  // For retrying connections
0014 #include <string>
0015 #include <thread>
0016 
0017 ODBCInterface *ODBCInterface::__instance{nullptr};
0018 
0019 ODBCInterface *ODBCInterface::instance()
0020 {
0021   if (!__instance)
0022   {
0023     __instance = new ODBCInterface();
0024   }
0025   return __instance;
0026 }
0027 
0028 ODBCInterface::~ODBCInterface()
0029 {
0030   ODBCInterface::Disconnect();
0031   __instance = nullptr;
0032   return;
0033 }
0034 
0035 odbc::Connection *ODBCInterface::getDBConnection(const std::string &dbname)
0036 {
0037   auto coniter = m_OdbcConnectionMap.find(dbname);
0038   if (coniter != m_OdbcConnectionMap.end())
0039   {
0040     return coniter->second;
0041   }
0042   m_NumConnection[dbname]++;
0043   std::random_device ran_dev;
0044   std::seed_seq seeds{ran_dev(), ran_dev(), ran_dev()};  //...
0045   std::mt19937_64 mersenne_twister(seeds);
0046   std::uniform_int_distribution<> uniform(m_MIN_SLEEP_DUR, m_MAX_SLEEP_DUR);
0047   odbc::Connection *dbcon{nullptr};
0048   for (int num_tries = 0; num_tries < m_MAX_NUM_RETRIES; ++num_tries)
0049   {
0050     try
0051     {
0052       dbcon = odbc::DriverManager::getConnection(dbname, "", "");
0053     }
0054     catch (odbc::SQLException &e)
0055     {
0056       std::cout  << ": SQL Exception: " << e.getMessage() << std::endl;
0057     }
0058 
0059     if (dbcon)
0060     {
0061       break;
0062     }
0063     ++m_ConnectionTries;
0064     int sleep_time_ms = uniform(mersenne_twister);
0065     std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time_ms));
0066     m_SleepMS += sleep_time_ms;
0067 
0068     if (0 < Verbosity())
0069     {
0070       std::cout  << "Connection unsuccessful, Sleeping for addtional "
0071         << sleep_time_ms << " ms" << std::endl;
0072     }
0073   }
0074   if (1 < Verbosity())
0075   {
0076     std::cout  << ": Connection successful (" << m_ConnectionTries
0077           << " attempts, " << m_SleepMS << " ms)" << std::endl;
0078   }
0079   if (!dbcon)
0080   {
0081     std::cout  << ": DB Connection failed after " << m_MAX_NUM_RETRIES
0082           << " retries, abandoning query" << std::endl;
0083     return nullptr;
0084   }
0085   m_CurrentConnections++;
0086   m_OdbcConnectionMap.insert(std::make_pair(dbname, dbcon));
0087   return dbcon;
0088 }
0089 
0090 odbc::Statement *ODBCInterface::getStatement(const std::string &dbname)
0091 {
0092   m_NumStatementUse[dbname]++;
0093   auto statiter = m_OdbcStatementMap.find(dbname);
0094   if (statiter != m_OdbcStatementMap.end())
0095   {
0096     return statiter->second;
0097   }
0098   odbc::Connection *dbcon = getDBConnection(dbname);
0099   odbc::Statement *statement = dbcon->createStatement();
0100   m_OdbcStatementMap.insert(std::make_pair(dbname, statement));
0101   return statement;
0102 }
0103 
0104 
0105 void ODBCInterface::Print(const std::string & /*what*/) const
0106 {
0107   if (m_NumConnection.empty())
0108   {
0109     std::cout << "No ODBC connections cached" << std::endl;
0110   }
0111   else
0112   {
0113     std::cout << "Odbc Connections Opened: " << std::endl;
0114     for (auto const &iter: m_NumConnection)
0115     {
0116       std::cout << "db: " << iter.first << ", opened: " << iter.second << std::endl;
0117     }
0118   }
0119   if (m_NumStatementUse.empty())
0120   {
0121     std::cout << "No odbc::Statements cached" << std::endl;
0122   }
0123   else
0124   {
0125     std::cout << "Odbc Statement use: " << std::endl;
0126     for (auto const &iter: m_NumStatementUse)
0127     {
0128       std::cout << "db: " << iter.first << ", Statement use: " << iter.second << std::endl;
0129     }
0130   }
0131   return;
0132 }
0133 
0134 void ODBCInterface::Disconnect()
0135 {
0136     if (!m_OdbcConnectionMap.empty())
0137   {
0138     for (const auto& iter : m_OdbcConnectionMap)
0139     {
0140       delete iter.second;
0141     }
0142     m_OdbcConnectionMap.clear();
0143   }
0144   if (!m_OdbcStatementMap.empty())
0145   {
0146     m_OdbcStatementMap.clear();
0147   }
0148   m_CurrentConnections = 0;
0149 }