diff options
| -rw-r--r-- | project2/cgiAppEngine.cpp | 1 | ||||
| -rw-r--r-- | project2/rdbmsDataSource.cpp | 52 | ||||
| -rw-r--r-- | project2/rdbmsDataSource.h | 2 | 
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; | 
