summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project2/cgiAppEngine.cpp1
-rw-r--r--project2/rdbmsDataSource.cpp52
-rw-r--r--project2/rdbmsDataSource.h2
3 files changed, 38 insertions, 17 deletions
diff --git a/project2/cgiAppEngine.cpp b/project2/cgiAppEngine.cpp
index 4f04b7e..363bcb7 100644
--- a/project2/cgiAppEngine.cpp
+++ b/project2/cgiAppEngine.cpp
@@ -5,7 +5,6 @@
#include "cgiEnvironment.h"
#include <libxml/xinclude.h>
#include "xmlObjectLoader.h"
-#include "rdbmsDataSource.h"
#include "iterate.h"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp
index e9c0089..6f3fc92 100644
--- a/project2/rdbmsDataSource.cpp
+++ b/project2/rdbmsDataSource.cpp
@@ -7,6 +7,7 @@
#include <sqlext.h>
_RdbmsDataSource::DBHosts _RdbmsDataSource::dbhosts;
+_RdbmsDataSource::FailedHosts _RdbmsDataSource::failedhosts;
_RdbmsDataSource::_RdbmsDataSource(const xmlpp::Element * p) :
_SourceObject(p),
@@ -53,23 +54,26 @@ _RdbmsDataSource::getReadonly() const
}
if (preferLocal) {
ReadonlyDSNs::const_iterator ro = roDSNs.find(localhost);
- if (ro == roDSNs.end()) {
- syslog(LOG_WARNING, "%s: No database host makes local host name (%s) Will use master DSN",
- __FUNCTION__, localhost.c_str());
- return *connectTo(masterDsn);
+ try {
+ if (ro == roDSNs.end()) {
+ syslog(LOG_WARNING, "%s: No database host makes local host name (%s) Will use master DSN",
+ __FUNCTION__, localhost.c_str());
+ return *connectTo(masterDsn);
+ }
+ return *connectTo(ro->second);
+ }
+ catch (...) {
+ // Failed to connect to a preferred DB... carry on and try the others...
}
- return *connectTo(ro->second);
}
- else {
- BOOST_FOREACH(ReadonlyDSNs::value_type db, roDSNs) {
- try {
- return *connectTo(db.second);
- }
- catch (...) {
- }
+ BOOST_FOREACH(ReadonlyDSNs::value_type db, roDSNs) {
+ try {
+ return *connectTo(db.second);
+ }
+ catch (...) {
}
- return *connectTo(masterDsn);
}
+ return *connectTo(masterDsn);
}
void
@@ -94,6 +98,15 @@ _RdbmsDataSource::rollback()
_RdbmsDataSource::ConnectionPtr
_RdbmsDataSource::connectTo(const std::string & dsn)
{
+ FailedHosts::iterator dbf = failedhosts.find(dsn);
+ if (dbf != failedhosts.end()) {
+ if (time(NULL) - 20 > dbf->second.FailureTime) {
+ failedhosts.erase(dbf);
+ }
+ else {
+ throw dbf->second;
+ }
+ }
DBHosts::const_iterator dbi = dbhosts.find(dsn);
if (dbi != dbhosts.end()) {
try {
@@ -107,8 +120,15 @@ _RdbmsDataSource::connectTo(const std::string & dsn)
syslog(LOG_WARNING, "%s: Cached connection failed", __FUNCTION__);
}
}
- ConnectionPtr db = ConnectionPtr(new ODBC::Connection(dsn));
- dbhosts[dsn] = db;
- return db;
+
+ try {
+ ConnectionPtr db = ConnectionPtr(new ODBC::Connection(dsn));
+ dbhosts[dsn] = db;
+ return db;
+ }
+ catch (const ODBC::ConnectionError & e) {
+ failedhosts.insert(FailedHosts::value_type(dsn, e));
+ throw;
+ }
}
diff --git a/project2/rdbmsDataSource.h b/project2/rdbmsDataSource.h
index 57a607f..a9dad6c 100644
--- a/project2/rdbmsDataSource.h
+++ b/project2/rdbmsDataSource.h
@@ -12,6 +12,7 @@ class _RdbmsDataSource : public _DataSource {
typedef boost::shared_ptr<ODBC::Connection> ConnectionPtr;
typedef std::map<std::string, std::string> ReadonlyDSNs; // Map hostname to DSN string
typedef std::map<std::string, ConnectionPtr> DBHosts; // Map DSN strings to connections
+ typedef std::map<std::string, const ODBC::ConnectionError> FailedHosts; // Map DSN strings to failures
_RdbmsDataSource(const xmlpp::Element * p);
ODBC::Connection & getReadonly() const;
ODBC::Connection & getWritable() const;
@@ -28,6 +29,7 @@ class _RdbmsDataSource : public _DataSource {
private:
mutable std::string localhost;
static DBHosts dbhosts;
+ static FailedHosts failedhosts;
};
typedef boost::shared_ptr<_RdbmsDataSource> RdbmsDataSource;
typedef std::map<std::string, RdbmsDataSource> RdbmsDataSources;