summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2010-07-05 15:13:40 +0000
committerrandomdan <randomdan@localhost>2010-07-05 15:13:40 +0000
commit9c120965dce08b7ed0517d80dd4d5c9f800d3c54 (patch)
treeee0130ac28f9c061dec68e2ac4032b4a3589225a
parentFix parameter lookup (diff)
downloadproject2-9c120965dce08b7ed0517d80dd4d5c9f800d3c54.tar.bz2
project2-9c120965dce08b7ed0517d80dd4d5c9f800d3c54.tar.xz
project2-9c120965dce08b7ed0517d80dd4d5c9f800d3c54.zip
Implement connection caching and checking (requires ODBCv3 driver)
Implement preferLocal DB access
-rw-r--r--project2/rdbmsDataSource.cpp85
-rw-r--r--project2/rdbmsDataSource.h12
2 files changed, 82 insertions, 15 deletions
diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp
index 1a55fb8..ab515a1 100644
--- a/project2/rdbmsDataSource.cpp
+++ b/project2/rdbmsDataSource.cpp
@@ -1,48 +1,105 @@
#include "rdbmsDataSource.h"
#include "xmlObjectLoader.h"
#include <libxml++/nodes/textnode.h>
+#include <sys/utsname.h>
+#include <syslog.h>
+#include <errno.h>
+#include <sqlext.h>
+
+_RdbmsDataSource::DBHosts _RdbmsDataSource::dbhosts;
_RdbmsDataSource::_RdbmsDataSource(const xmlpp::Element * p) :
_SourceObject(p),
_DataSource(p),
- masterDsn(xmlChildText(p, "masterdsn"))
+ masterDsn(xmlChildText(p, "masterdsn")),
+ preferLocal(p->get_attribute_value("preferlocal") != "false")
{
+ BOOST_FOREACH(const xmlpp::Node * node, p->find("readonly/dsn")) {
+ const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node);
+ if (elem) {
+ roDSNs[elem->get_attribute_value("host")] = elem->get_child_text()->get_content();
+ }
+ }
}
ODBC::Connection &
_RdbmsDataSource::getWritable() const
{
- if (!database) {
- database = boost::shared_ptr<ODBC::Connection>(new ODBC::Connection(masterDsn));
+ ConnectionPtr master = connectTo(masterDsn);
+ if (!master->inTx()) {
+ master->beginTx();
}
- if (!database->inTx()) {
- database->beginTx();
- }
- return *database;
+ return *master;
}
ODBC::Connection &
_RdbmsDataSource::getReadonly() const
{
- if (!database) {
- database = boost::shared_ptr<ODBC::Connection>(new ODBC::Connection(masterDsn));
+ if (localhost.length() == 0 && preferLocal) {
+ struct utsname name;
+ if (uname(&name)) {
+ syslog(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)", __FUNCTION__, errno, strerror(errno));
+ localhost = "unknown";
+ }
+ else {
+ localhost = name.nodename;
+ }
+ }
+ 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);
+ }
+ return *connectTo(ro->second);
+ }
+ else {
+ BOOST_FOREACH(ReadonlyDSNs::value_type db, roDSNs) {
+ try {
+ return *connectTo(db.second);
+ }
+ catch (...) {
+ }
+ }
+ return *connectTo(masterDsn);
}
- return *database;
}
void
_RdbmsDataSource::commit()
{
- if (database && database->inTx()) {
- database->commitTx();
+ DBHosts::const_iterator m = dbhosts.find(masterDsn);
+ if (m != dbhosts.end() && m->second->inTx()) {
+ m->second->commitTx();
}
}
void
_RdbmsDataSource::rollback()
{
- if (database && database->inTx()) {
- database->rollbackTx();
+ DBHosts::const_iterator m = dbhosts.find(masterDsn);
+ if (m != dbhosts.end() && m->second->inTx()) {
+ m->second->rollbackTx();
+ }
+}
+_RdbmsDataSource::ConnectionPtr
+_RdbmsDataSource::connectTo(const std::string & dsn)
+{
+ DBHosts::const_iterator dbi = dbhosts.find(dsn);
+ if (dbi != dbhosts.end()) {
+ try {
+ SQLINTEGER dead = dbi->second->getAttrInt(SQL_ATTR_CONNECTION_DEAD);
+ if (dead == SQL_CD_FALSE) {
+ return dbi->second;
+ }
+ }
+ catch (...) {
+ // Connection in failed state
+ syslog(LOG_WARNING, "%s: Cached connection failed", __FUNCTION__);
+ }
}
+ ConnectionPtr db = ConnectionPtr(new ODBC::Connection(dsn));
+ dbhosts[dsn] = db;
+ return db;
}
diff --git a/project2/rdbmsDataSource.h b/project2/rdbmsDataSource.h
index ee75550..e5709b7 100644
--- a/project2/rdbmsDataSource.h
+++ b/project2/rdbmsDataSource.h
@@ -9,14 +9,24 @@
class _RdbmsDataSource : public _DataSource {
public:
+ 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
_RdbmsDataSource(const xmlpp::Element * p);
ODBC::Connection & getReadonly() const;
ODBC::Connection & getWritable() const;
virtual void commit();
virtual void rollback();
const std::string masterDsn;
+ const bool preferLocal;
+
+ protected:
+ static ConnectionPtr connectTo(const std::string & dsn);
+ ReadonlyDSNs roDSNs;
+
private:
- mutable boost::shared_ptr<ODBC::Connection> database;
+ mutable std::string localhost;
+ static DBHosts dbhosts;
};
typedef boost::shared_ptr<_RdbmsDataSource> RdbmsDataSource;
typedef std::map<std::string, RdbmsDataSource> RdbmsDataSources;