platform/server/ServiceManager.hpp

00001 // ------------------------------------------------------------------------
00002 // Pion is a development platform for building Reactors that process Events
00003 // ------------------------------------------------------------------------
00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
00005 //
00006 // Pion is free software: you can redistribute it and/or modify it under the
00007 // terms of the GNU Affero General Public License as published by the Free
00008 // Software Foundation, either version 3 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Pion is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Affero General Public License
00017 // along with Pion.  If not, see <http://www.gnu.org/licenses/>.
00018 //
00019 
00020 #ifndef __PION_SERVICEMANAGER_HEADER__
00021 #define __PION_SERVICEMANAGER_HEADER__
00022 
00023 #include <list>
00024 #include <string>
00025 #include <boost/thread/mutex.hpp>
00026 #include <pion/PionConfig.hpp>
00027 #include <pion/PionException.hpp>
00028 #include <pion/PionScheduler.hpp>
00029 #include <pion/PluginManager.hpp>
00030 #include <pion/net/HTTPServer.hpp>
00031 #include <pion/net/WebService.hpp>
00032 #include <pion/platform/ConfigManager.hpp>
00033 #include "PlatformService.hpp"
00034 #include <pion/platform/PluginConfig.hpp>
00035 
00036 
00037 namespace pion {        // begin namespace pion
00038 namespace server {      // begin namespace server (Pion Server)
00039     
00040     
00041 // forward declarations to avoid header dependencies
00042 class PlatformConfig;
00043     
00044 
00048 class PION_SERVER_API ServiceManager :
00049     public pion::platform::PluginConfig<PlatformService>
00050 {
00051 public:
00052     
00054     class EmptyServerIdException : public PionException {
00055     public:
00056         EmptyServerIdException(const std::string& config_file)
00057             : PionException("Service configuration file includes a Server without a unique identifier: ", config_file) {}
00058     };
00059 
00061     class EmptyServiceIdException : public PionException {
00062     public:
00063         EmptyServiceIdException(const std::string& server_id)
00064             : PionException("Server configuration includes a Service without a unique identifier: ", server_id) {}
00065     };
00066     
00068     class EmptyServicePluginTypeException : public PionException {
00069     public:
00070         EmptyServicePluginTypeException(const std::string& service_id)
00071             : PionException("Service configuration does not define a plug-in type: ", service_id) {}
00072     };
00073     
00075     class EmptyServiceResourceException : public PionException {
00076     public:
00077         EmptyServiceResourceException(const std::string& service_id)
00078             : PionException("Service configuration does not define a resource: ", service_id) {}
00079     };
00080 
00082     class EmptyServiceServerIdException : public PionException {
00083     public:
00084         EmptyServiceServerIdException(const std::string& config_file)
00085             : PionException("Service configuration file includes a Service without a Server identifier: ", config_file) {}
00086     };
00087 
00089     class EmptyOptionNameException : public PionException {
00090     public:
00091         EmptyOptionNameException(const std::string& service_id)
00092             : PionException("Service configuration option does not define a name: ", service_id) {}
00093     };
00094     
00096     class MissingPortException : public PionException {
00097     public:
00098         MissingPortException(const std::string& server_id)
00099             : PionException("Server configuration does not define a port number: ", server_id) {}
00100     };
00101 
00103     class UnknownAuthTypeException : public PionException {
00104     public:
00105         UnknownAuthTypeException(const std::string& server_id)
00106             : PionException("Server configuration has unknown AuthType parameter: ", server_id) {}
00107     };
00108 
00110     class SSLKeyException : public PionException {
00111     public:
00112         SSLKeyException(const std::string& key_file)
00113             : PionException("Unable to load SSL key file: ", key_file) {}
00114     };
00115 
00117     class RedirectMissingSourceException : public PionException {
00118     public:
00119         RedirectMissingSourceException(const std::string& server_id)
00120             : PionException("Service configuration Redirect element does not specify a Source: ", server_id) {}
00121     };
00122 
00124     class RedirectMissingTargetException : public PionException {
00125     public:
00126         RedirectMissingTargetException(const std::string& server_id)
00127             : PionException("Service configuration Redirect element does not specify a Target: ", server_id) {}
00128     };
00129 
00131     class WebServiceException : public PionException {
00132     public:
00133         WebServiceException(const std::string& service_id, const std::string& error_msg)
00134             : PionException(std::string("Service (") + service_id,
00135                             std::string("): ") + error_msg)
00136         {}
00137     };
00138 
00140     class PlatformServiceNotFoundException : public PionException {
00141     public:
00142         PlatformServiceNotFoundException(const std::string& service_id)
00143             : PionException("No platform service found for identifier: ", service_id) {}
00144     };
00145 
00151     ServiceManager(const pion::platform::VocabularyManager& vocab_mgr, PlatformConfig& platform_config);
00152     
00154     virtual ~ServiceManager() { shutdown(); }
00155     
00157     void shutdown(void);
00158     
00160     virtual void openConfigFile(void);
00161 
00167     virtual void writeServersXML(std::ostream& out) const;
00168     
00175     bool writeServerXML(std::ostream& out, const std::string& server_id) const;
00176 
00182     template<typename WorkFunction>
00183     inline void post(WorkFunction work_func) { m_scheduler.getIOService().post(work_func); }
00184     
00186     inline boost::asio::io_service& getIOService(void) { return m_scheduler.getIOService(); }
00187     
00189     inline boost::uint32_t getNumThreads(void) const { return m_scheduler.getNumThreads(); }
00190     
00192     inline void setNumThreads(const boost::uint32_t n) { m_scheduler.setNumThreads(n); }
00193         
00195     void updateCodecs(void);
00196 
00198     void updateDatabases(void);
00199 
00201     void updateReactors(void);
00202     
00204     unsigned int getPort(void) const;
00205 
00214     std::string addPlatformService(const xmlNodePtr config_ptr);
00215 
00221     void removePlatformService(const std::string& service_id);
00222 
00231     static xmlNodePtr createPlatformServiceConfig(const char *buf, std::size_t len) {
00232         return ConfigManager::createResourceConfig(PLATFORM_SERVICE_ELEMENT_NAME, buf, len);
00233     }
00234 
00235 protected:
00236 
00248     virtual void addPluginNoLock(const std::string& plugin_id,
00249                                  const std::string& plugin_name,
00250                                  const xmlNodePtr config_ptr)
00251     {
00252         try {
00253             PlatformService *new_plugin_ptr = m_plugins.load(plugin_id, plugin_name);
00254             new_plugin_ptr->setId(plugin_id);
00255             new_plugin_ptr->setServiceManager(*this);
00256             new_plugin_ptr->setPlatformConfig(m_platform_config);
00257             if (config_ptr != NULL) {
00258                 pion::platform::VocabularyPtr vocab_ptr(m_vocab_mgr.getVocabulary());
00259                 new_plugin_ptr->setConfig(*vocab_ptr, config_ptr);
00260             }
00261 
00262             pion::net::HTTPServerPtr server_ptr = m_servers[new_plugin_ptr->getServerId()];
00263             server_ptr->addResource(new_plugin_ptr->getResource(), boost::ref(*new_plugin_ptr));
00264         } catch (PionPlugin::PluginNotFoundException&) {
00265             throw;
00266         } catch (std::exception& e) {
00267             throw PluginException(e.what());
00268         }
00269     }
00270 
00271 private:
00272 
00282     void getWebServiceConfig(xmlNodePtr service_node, const std::string& server_id,
00283                              std::string& service_id, std::string& plugin_type,
00284                              std::string& http_resource);
00285     
00293     static void handleServerError(pion::net::HTTPRequestPtr& http_request,
00294                                   pion::net::TCPConnectionPtr& tcp_conn,
00295                                   const std::string& error_msg);
00296 
00297     void addWebService(xmlNodePtr service_node, const std::string& server_id);
00298 
00299     
00301     typedef std::map<std::string, pion::net::HTTPServerPtr>     ServerMap;
00302     
00304     typedef PluginManager<pion::net::WebService>    WebServiceManager;
00305     
00307     typedef PluginManager<PlatformService>          PlatformServiceManager;
00308     
00309     
00311     static const boost::uint32_t    DEFAULT_NUM_THREADS;
00312     
00314     static const std::string        DEFAULT_CONFIG_FILE;
00315 
00317     static const std::string        SERVER_ELEMENT_NAME;
00318 
00320     static const std::string        WEB_SERVICE_ELEMENT_NAME;
00321     
00323     static const std::string        PLATFORM_SERVICE_ELEMENT_NAME;
00324     
00326     static const std::string        PORT_ELEMENT_NAME;
00327 
00329     static const std::string        SSL_KEY_ELEMENT_NAME;
00330 
00332     static const std::string        REDIRECT_ELEMENT_NAME;
00333 
00335     static const std::string        REDIRECT_SOURCE_ELEMENT_NAME;
00336 
00338     static const std::string        REDIRECT_TARGET_ELEMENT_NAME;
00339 
00341     static const std::string        WEB_SERVICE_RESOURCE_ELEMENT_NAME;
00342 
00344     static const std::string        WEB_SERVICE_SERVER_ELEMENT_NAME;
00345 
00347     static const std::string        OPTION_ELEMENT_NAME;
00348     
00350     static const std::string        AUTH_ELEMENT_NAME;
00351     
00353     static const std::string        AUTH_RESTRICT_ELEMENT_NAME;
00354 
00356     static const std::string        AUTH_PERMIT_ELEMENT_NAME;
00357 
00359     static const std::string        AUTH_TYPE_ELEMENT_NAME;
00360 
00362     static const std::string        AUTH_LOGIN_ELEMENT_NAME;
00363 
00365     static const std::string        AUTH_LOGOUT_ELEMENT_NAME;
00366 
00368     static const std::string        AUTH_REDIRECT_ELEMENT_NAME;
00369 
00371     static const std::string        NAME_ATTRIBUTE_NAME;
00372 
00374     PlatformConfig &                m_platform_config;
00375     
00377     PionSingleServiceScheduler      m_scheduler;
00378 
00380     ServerMap                       m_servers;
00381 
00383     WebServiceManager               m_web_services;
00384 
00386     mutable boost::mutex            m_mutex;
00387 };
00388 
00389 
00390 }   // end namespace server
00391 }   // end namespace pion
00392 
00393 #endif

Generated on Wed Apr 13 16:38:34 2011 for pion-platform by  doxygen 1.4.7