From a1269f80d17fd09705a61dee39451fea392e0f56 Mon Sep 17 00:00:00 2001 From: randomdan Date: Sat, 11 Jun 2011 03:00:47 +0000 Subject: Make named types code totally generic Convert RDBMS DB types to new named types system and remove all the hacky mess previous used --- project2/Jamfile.jam | 31 +++++++++++------- project2/rdbmsDataSource.cpp | 42 +++--------------------- project2/rdbmsDataSource.h | 19 ++++++++++- project2/sql-modODBC.cpp | 4 +++ project2/sql-modPQ.cpp | 4 +++ project2/xmlObjectLoader.cpp | 78 +++++++++++++------------------------------- project2/xmlObjectLoader.h | 68 ++++++++++++++++++++++++++++++-------- 7 files changed, 127 insertions(+), 119 deletions(-) create mode 100644 project2/sql-modODBC.cpp create mode 100644 project2/sql-modPQ.cpp diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index caf94fd..5b9799a 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -126,28 +126,35 @@ lib p2xmlSession : p2common ; -obj rdbmsDataSource : - rdbmsDataSource.cpp : - yes:WITH_ODBC - yes:WITH_PQ - yes:../libodbcpp//odbcpp - yes:../libpqpp//pqpp +explicit object sql-modODBC ; +obj sql-modODBC : + sql-modODBC.cpp : + ../libodbcpp//odbcpp libxmlpp ../libmisc + : : + ../libodbcpp//odbcpp + ; + +explicit object sql-modPQ ; +obj sql-modPQ : + sql-modPQ.cpp : + ../libpqpp//pqpp + libxmlpp + ../libmisc + : : + ../libpqpp//pqpp ; lib p2sql : - [ glob sql*.cpp ] tablepatch.cpp rdbmsDataSource + sqlCheck.cpp sqlTask.cpp sqlMergeTask.cpp sqlRows.cpp sqlVariableBinder.cpp tablepatch.cpp rdbmsDataSource.cpp ../libdbpp//dbpp : - yes:../libodbcpp//odbcpp - yes:../libpqpp//pqpp + yes:sql-modODBC + yes:sql-modPQ libxmlpp p2common ../libmisc - : : - yes:../libodbcpp//odbcpp - yes:../libpqpp//pqpp ; lib p2url : diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp index 1b0ab3c..f21c737 100644 --- a/project2/rdbmsDataSource.cpp +++ b/project2/rdbmsDataSource.cpp @@ -1,5 +1,4 @@ #include "rdbmsDataSource.h" -#include "xmlObjectLoader.h" #include #include #include "logger.h" @@ -7,16 +6,6 @@ #include #include -static const int NOTSET = 0; -#ifdef WITH_PQ -#include "../libpqpp/connection.h" -static const int PQ_TYPEID = 1; -#endif -#ifdef WITH_ODBC -#include "../libodbcpp/connection.h" -static const int ODBC_TYPEID = 2; -#endif - SimpleMessageException(UnknownConnectionProvider); /// Specialized ElementLoader for instances of RdbmsDataSource; handles persistent DB connections @@ -209,41 +198,18 @@ RdbmsDataSource::RdbmsConnection::isExpired() const return (time(NULL) > lastUsedTime + keepAliveTime); } -RdbmsDataSource::ConnectionInfo::ConnectionInfo(const xmlpp::Element * n) : - typeId(NOTSET) +RdbmsDataSource::ConnectionInfo::ConnectionInfo(const xmlpp::Element * n) { -#if WITH_ODBC - BOOST_FOREACH(const xmlpp::Node * node, n->find("odbc")) { - typeId = ODBC_TYPEID; - dsn = dynamic_cast(node)->get_child_text()->get_content(); - } -#endif -#if WITH_PQ - BOOST_FOREACH(const xmlpp::Node * node, n->find("postgresql")) { - typeId = PQ_TYPEID; + BOOST_FOREACH(const xmlpp::Node * node, n->get_children()) { + typeId = LoaderBase::getLoader(node->get_name()); dsn = dynamic_cast(node)->get_child_text()->get_content(); } -#endif - if (typeId == NOTSET || dsn.empty()) { - throw UnknownConnectionProvider(n->get_path()); - } } DB::Connection * RdbmsDataSource::ConnectionInfo::connect() const { -#if WITH_ODBC - if (typeId == ODBC_TYPEID) { - return new ODBC::Connection(dsn); - } -#endif -#if WITH_PQ - if (typeId == PQ_TYPEID) { - return new PQ::Connection(dsn); - } -#endif - // This should never happen if the object was constructed correctly - throw UnknownConnectionProvider(__PRETTY_FUNCTION__); + return typeId->connect(dsn); } bool diff --git a/project2/rdbmsDataSource.h b/project2/rdbmsDataSource.h index 857173b..0e175e7 100644 --- a/project2/rdbmsDataSource.h +++ b/project2/rdbmsDataSource.h @@ -8,6 +8,23 @@ #include "dataSource.h" #include "../libdbpp/connection.h" #include "../libdbpp/error.h" +#include "xmlObjectLoader.h" + +/// Base class to implement DB connection type modules +class ConnectionLoader : public ComponentLoader { + public: + virtual DB::Connection * connect(const std::string & dsn) const = 0; +}; + +/// Helper implemention for specific DB types +template +class ConnectionLoaderImpl : public ConnectionLoader { + public: + virtual DB::Connection * connect(const std::string & dsn) const + { + return new DBType(dsn); + } +}; /// Project2 component to provide access to transactional RDBMS data sources class RdbmsDataSource : public DataSource { @@ -37,7 +54,7 @@ class RdbmsDataSource : public DataSource { private: std::string dsn; - int typeId; + boost::shared_ptr typeId; }; typedef boost::shared_ptr ConnectionPtr; diff --git a/project2/sql-modODBC.cpp b/project2/sql-modODBC.cpp new file mode 100644 index 0000000..ca57731 --- /dev/null +++ b/project2/sql-modODBC.cpp @@ -0,0 +1,4 @@ +#include "rdbmsDataSource.h" +#include "../libodbcpp/connection.h" +typedef ODBC::Connection ODBCConnection; +DECLARE_COMPONENT_LOADER("odbc", ODBCConnection, ConnectionLoader) diff --git a/project2/sql-modPQ.cpp b/project2/sql-modPQ.cpp new file mode 100644 index 0000000..499d8e7 --- /dev/null +++ b/project2/sql-modPQ.cpp @@ -0,0 +1,4 @@ +#include "rdbmsDataSource.h" +#include "../libpqpp/connection.h" +typedef PQ::Connection PQConnection; +DECLARE_COMPONENT_LOADER("postgresql", PQConnection, ConnectionLoader) diff --git a/project2/xmlObjectLoader.cpp b/project2/xmlObjectLoader.cpp index 9187c82..372081b 100644 --- a/project2/xmlObjectLoader.cpp +++ b/project2/xmlObjectLoader.cpp @@ -11,15 +11,6 @@ unsigned int LoaderBase::depth = 0; std::set LoaderBase::loadedObjects; typedef std::map > ElementLoaderMap; -ElementLoaderMap * & -objLoaders() -{ - static ElementLoaderMap * _objLoaders = NULL; - if (!_objLoaders) { - _objLoaders = new ElementLoaderMap(); - } - return _objLoaders; -} LoaderBase::LoaderBase(bool r) : recursive(r), @@ -50,27 +41,21 @@ LoaderBase::collectAll(const xmlpp::Element * node, bool childrenOnly, Unsupport if (!childrenOnly && node->get_namespace_uri() == ns) { Glib::ustring name = node->get_name(); unsigned int stored = 0; - ElementLoaderMap::const_iterator i = objLoaders()->find(name); - if (i != objLoaders()->end()) { - SourceObjectPtr o = i->second->go(node); - created += 1; - loadedObjects.insert(o); - BOOST_FOREACH(std::set >::value_type s, supportedStorers) { - if (s->save(o, node)) { - stored += 1; - } - } - if (stored < 1) { - if (uh == ErrorOnUnsupported) { - throw NotSupported(name); - } - else if (uh == WarnOnUnsupported) { - Logger()->messagef(LOG_WARNING, "'%s' unsupported in this location", name.c_str()); - } + SourceObjectPtr o = getLoader(name)->go(node); + created += 1; + loadedObjects.insert(o); + BOOST_FOREACH(std::set >::value_type s, supportedStorers) { + if (s->save(o, node)) { + stored += 1; } } - else { - throw NotSupported(name); + if (stored < 1) { + if (uh == ErrorOnUnsupported) { + throw NotSupported(name); + } + else if (uh == WarnOnUnsupported) { + Logger()->messagef(LOG_WARNING, "'%s' unsupported in this location", name.c_str()); + } } } if (created == 0 && (recursive || childrenOnly)) { @@ -94,27 +79,10 @@ LoaderBase::collectAll(const CommonObjects * co, const xmlpp::Element * node, bo loadedObjects.clear(); } -void -LoaderBase::newLoader(const std::string & n, ElementLoader * l) -{ - objLoaders()->insert(ElementLoaderMap::value_type(n, boost::shared_ptr(l))); -} - -void -LoaderBase::removeLoader(const std::string & n) -{ - ElementLoaderMap * & o = objLoaders(); - o->erase(n); - if (o->empty()) { - delete o; - o = NULL; - } -} - void LoaderBase::onIdle() { - BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) { + BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) { l.second->onIdle(); } } @@ -126,7 +94,7 @@ LoaderBase::onIteration() depth = 0; loadedObjects.clear(); - BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) { + BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) { l.second->onIteration(); } } @@ -134,16 +102,11 @@ LoaderBase::onIteration() void LoaderBase::onPeriodic() { - BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) { + BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) { l.second->onPeriodic(); } } -void -ElementLoader::onIdle() -{ -} - Glib::ustring xmlChildText(const xmlpp::Node * p, const Glib::ustring & t) { @@ -161,12 +124,17 @@ xmlChildText(const xmlpp::Node * p, const Glib::ustring & t) } void -ElementLoader::onIteration() +ComponentLoader::onIdle() +{ +} + +void +ComponentLoader::onIteration() { } void -ElementLoader::onPeriodic() +ComponentLoader::onPeriodic() { } diff --git a/project2/xmlObjectLoader.h b/project2/xmlObjectLoader.h index fb0ac16..e68a390 100644 --- a/project2/xmlObjectLoader.h +++ b/project2/xmlObjectLoader.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "intrusivePtrBase.h" #include "sourceObject.h" #include "exceptions.h" @@ -34,8 +35,44 @@ class LoaderBase { static void onIteration(); static void onPeriodic(); - static void newLoader(const std::string & N, ElementLoader * L); - static void removeLoader(const std::string & N); + template + static std::map > * & objLoaders() + { + static std::map > * _objLoaders = NULL; + if (!_objLoaders) { + _objLoaders = new std::map >(); + } + return _objLoaders; + } + + template + static void newLoader(const std::string & n, T * l) + { + objLoaders()->insert(std::pair >(n, boost::shared_ptr(l))); + } + + template + static void removeLoader(const std::string & n) + { + std::map > * & o = objLoaders(); + o->erase(n); + if (o->empty()) { + delete o; + o = NULL; + } + } + + template + static boost::shared_ptr getLoader(const std::string & n) + { + typename std::map >::const_iterator i = objLoaders()->find(n); + if (i != objLoaders()->end()) { + return i->second; + } + else { + throw E(n); + } + } private: static unsigned int depth; @@ -47,25 +84,30 @@ class LoaderBase { const Glib::ustring ns; }; +#define DECLARE_CUSTOM_COMPONENT_LOADER(N, I, T, B) \ + static void init_loader_##I() __attribute__ ((constructor(201))); \ + static void init_loader_##I() { LoaderBase::newLoader(N, new T()); } \ + static void kill_loader_##I() __attribute__ ((destructor(201))); \ + static void kill_loader_##I() { LoaderBase::removeLoader(N); } #define DECLARE_CUSTOM_LOADER(N, T) \ - static void init_loader_##T() __attribute__ ((constructor(201))); \ - static void init_loader_##T() { LoaderBase::newLoader(N, new T()); } \ - static void kill_loader_##T() __attribute__ ((destructor(201))); \ - static void kill_loader_##T() { LoaderBase::removeLoader(N); } + DECLARE_CUSTOM_COMPONENT_LOADER(N, T, T, ElementLoader) +#define DECLARE_COMPONENT_LOADER(N, T, B) \ + DECLARE_CUSTOM_COMPONENT_LOADER(N, T, B##Impl, B) #define DECLARE_LOADER(N, T) \ - static void init_loader_##T() __attribute__ ((constructor(201))); \ - static void init_loader_##T() { LoaderBase::newLoader(N, new ElementLoaderImpl()); } \ - static void kill_loader_##T() __attribute__ ((destructor(201))); \ - static void kill_loader_##T() { LoaderBase::removeLoader(N); } + DECLARE_COMPONENT_LOADER(N, T, ElementLoader) -/// Helper for loading and maintaining Project2 script components -class ElementLoader { +/// Helper for loading and maintaining Project2 components +class ComponentLoader { public: - virtual SourceObjectPtr go(const xmlpp::Element * xml) const = 0; virtual void onIdle(); // When the app engine goes idle virtual void onIteration(); // When the app engine has completed an iteration virtual void onPeriodic(); // When the app engine feels like it }; +/// Helper for loading and maintaining Project2 script components +class ElementLoader : public ComponentLoader { + public: + virtual SourceObjectPtr go(const xmlpp::Element * xml) const = 0; +}; /// Helper for loading and maintaining Project2 script components (typed implementation) template -- cgit v1.2.3