Skip to content
Snippets Groups Projects
Commit 660072df authored by Steven Murray's avatar Steven Murray
Browse files

Bare minimum database reconnect logic

parent 33069a9c
No related branches found
No related tags found
No related merge requests found
...@@ -67,5 +67,19 @@ void Conn::executeNonQuery(const std::string &sql, const Stmt::AutocommitMode au ...@@ -67,5 +67,19 @@ void Conn::executeNonQuery(const std::string &sql, const Stmt::AutocommitMode au
} }
} }
//------------------------------------------------------------------------------
// setHealthy
//------------------------------------------------------------------------------
void Conn::setHealthy(const bool value) {
m_healthy = value;
}
//------------------------------------------------------------------------------
// getHealthy
//------------------------------------------------------------------------------
bool Conn::getHealthy() const {
return m_healthy;
}
} // namespace rdbms } // namespace rdbms
} // namespace cta } // namespace cta
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "Stmt.hpp" #include "Stmt.hpp"
#include <atomic>
#include <list> #include <list>
#include <memory> #include <memory>
#include <string> #include <string>
...@@ -93,6 +94,29 @@ public: ...@@ -93,6 +94,29 @@ public:
*/ */
virtual std::list<std::string> getTableNames() = 0; virtual std::list<std::string> getTableNames() = 0;
/**
* Returns true if the connection is healthy.
*
* @return True if the connection is healthy.
*/
bool getHealthy() const;
protected:
/**
* Sets the status of the connection to be either healthy or not healthy.
*
* @param value True if the connection is healthy.
*/
void setHealthy(const bool value);
private:
/**
* True if the connection's state is healthy.
*/
std::atomic<bool> m_healthy{true};
}; // class Conn }; // class Conn
} // namespace rdbms } // namespace rdbms
......
...@@ -69,10 +69,24 @@ PooledConn ConnPool::getConn() { ...@@ -69,10 +69,24 @@ PooledConn ConnPool::getConn() {
// returnConn // returnConn
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void ConnPool::returnConn(Conn *const conn) { void ConnPool::returnConn(Conn *const conn) {
conn->commit(); // If the connection is healthy
std::unique_lock<std::mutex> lock(m_connsMutex); if(conn->getHealthy()) {
m_conns.emplace_back(conn);
m_connsCv.notify_one(); // Commit the connection and put it back in the pool
conn->commit();
std::unique_lock<std::mutex> lock(m_connsMutex);
m_conns.emplace_back(conn);
m_connsCv.notify_one();
// Else the connection is not healthy
} else {
// Close the connection and put a brand new one in the pool
delete conn;
std::unique_lock<std::mutex> lock(m_connsMutex);
m_conns.push_back(m_connFactory.create());
m_connsCv.notify_one();
}
} }
} // namespace rdbms } // namespace rdbms
......
...@@ -60,8 +60,11 @@ private: ...@@ -60,8 +60,11 @@ private:
friend PooledConn; friend PooledConn;
/** /**
* Calls commit on the specified database connection and returns it to the * If the specified database connection is healthy, then this method calls
* pool. * commit on the connection and returns it to the pool.
*
* If the specified database connection is no healthy, then this method
* closes the connection and creates a new one in the connection pool.
* *
* @param conn The connection to be commited and returned to the pool. * @param conn The connection to be commited and returned to the pool.
*/ */
......
...@@ -138,5 +138,40 @@ std::list<std::string> OcciConn::getTableNames() { ...@@ -138,5 +138,40 @@ std::list<std::string> OcciConn::getTableNames() {
} }
} }
//------------------------------------------------------------------------------
// updateHealth
//------------------------------------------------------------------------------
void OcciConn::updateHealth(const oracle::occi::SQLException &ex) {
using namespace oracle;
// Error codes that identify an unhealthy connection
// The majority of these error codes were learnt from CASTOR
switch(ex.getErrorCode()) {
case 28:
case 1003:
case 1008:
case 1012:
case 1033:
case 1089:
case 2392:
case 2399:
case 3113:
case 3114:
case 3135:
case 12170:
case 12541:
case 12571:
case 24338:
case 12537:
case 25401:
case 25409:
case 32102:
setHealthy(false);
break;
default:
break;
};
}
} // namespace rdbms } // namespace rdbms
} // namespace cta } // namespace cta
...@@ -105,6 +105,8 @@ public: ...@@ -105,6 +105,8 @@ public:
private: private:
friend OcciStmt;
/** /**
* Mutex used to serialize access to this object. * Mutex used to serialize access to this object.
*/ */
...@@ -120,6 +122,14 @@ private: ...@@ -120,6 +122,14 @@ private:
*/ */
oracle::occi::Connection *m_conn; oracle::occi::Connection *m_conn;
/**
* Determines whether or not the specified Oracle exception affects the status
* of the database connection and updates it accordingly.
*
* @param ex The Oracle exception.
*/
void updateHealth(const oracle::occi::SQLException &ex);
}; // class OcciConn }; // class OcciConn
} // namespace rdbms } // namespace rdbms
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "rdbms/OcciStmt.hpp" #include "rdbms/OcciStmt.hpp"
#include <cstring> #include <cstring>
#include <iostream>
#include <map> #include <map>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
...@@ -181,11 +180,9 @@ std::unique_ptr<Rset> OcciStmt::executeQuery() { ...@@ -181,11 +180,9 @@ std::unique_ptr<Rset> OcciStmt::executeQuery() {
try { try {
return cta::make_unique<OcciRset>(*this, m_stmt->executeQuery()); return cta::make_unique<OcciRset>(*this, m_stmt->executeQuery());
} catch(exception::Exception &ex) { } catch(occi::SQLException &ex) {
throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + getSql() + ": " + m_conn.updateHealth(ex);
ex.getMessage().str()); throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + getSql() + ": " + ex.what());
} catch(std::exception &se) {
throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + getSql() + ": " + se.what());
} }
} }
...@@ -197,11 +194,9 @@ void OcciStmt::executeNonQuery() { ...@@ -197,11 +194,9 @@ void OcciStmt::executeNonQuery() {
try { try {
m_stmt->executeUpdate(); m_stmt->executeUpdate();
} catch(exception::Exception &ex) { } catch(occi::SQLException &ex) {
throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + getSql() + ": " + m_conn.updateHealth(ex);
ex.getMessage().str()); throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + getSql() + ": " + ex.what());
} catch(std::exception &se) {
throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + getSql() + ": " + se.what());
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment