Savarese Software Research Corporation
WebServiceRunner.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2009 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     https://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00023 #ifndef __SSRC_WSPR_WS_WEB_SERVICE_RUNNER_H
00024 #define __SSRC_WSPR_WS_WEB_SERVICE_RUNNER_H
00025 
00026 #include <ssrc/wispers/ws/service.h>
00027 #include <ssrc/wispers/ws/WebServiceModule.h>
00028 #include <ssrc/wispers/utility/DynamicLibrary.h>
00029 
00030 __BEGIN_NS_SSRC_WSPR_WS
00031 
00032 using NS_SSRC_WSPR_UTILITY::LoadError;
00033 using NS_SSRC_WSPR_UTILITY::DynamicLibrary;
00034 
00035 namespace detail {
00036   extern "C" typedef void fun_delete_module(WebServiceModule *);
00037   extern "C" typedef fun_delete_module* fun_ptr_delete_module;
00038 
00039   class WebServiceModuleDeleter {
00040     fun_ptr_delete_module _delete_module;
00041 
00042   public:
00043     explicit WebServiceModuleDeleter(const fun_ptr_delete_module delete_module) :
00044       _delete_module(delete_module)
00045     { }
00046 
00047     void operator()(WebServiceModule *module) const {
00048       _delete_module(module);
00049     }
00050   };
00051 
00052   template<typename PT = BinaryPackingTraits>
00053   class WebServiceModuleFactory {
00054     typedef NS_SSRC_WISP_PROTOCOL::ContinuationCaller<PT> caller_type;
00055 
00056     // Should really be extern "C", but we can only do that in namespace scope.
00057     typedef WebServiceModule* fun_new_module(const ws_module_context_ptr &);
00058     typedef fun_new_module* fun_ptr_new_module;
00059 
00060     DynamicLibrary _lib;
00061     fun_ptr_new_module _new_module;
00062     fun_ptr_delete_module _delete_module;
00063 
00064   public:
00065 
00066     typedef boost::shared_ptr<WebServiceModule> ws_module_ptr;
00067 
00068 #define WS_MODULE_SYM_NEW "ws_module_new"
00069 #define WS_MODULE_SYM_DELETE "ws_module_delete"
00070 
00071     explicit WebServiceModuleFactory(const string & filename,
00072                                      const DynamicLibrary::Mode mode =
00073                                      DynamicLibrary::NowLocal)
00074       SSRC_DECL_THROW(LoadError) :
00075       _lib(filename, mode),
00076       _new_module(_lib.symbol<fun_ptr_new_module>(WS_MODULE_SYM_NEW)),
00077       _delete_module(_lib.symbol<fun_ptr_delete_module>(WS_MODULE_SYM_DELETE))
00078     { }
00079 
00080 #undef WS_MODULE_SYM_NEW
00081 #undef WS_MODULE_SYM_DELETE
00082 
00083     ws_module_ptr new_module(const ws_module_context_ptr & context) {
00084       if(_new_module && _delete_module)
00085         return
00086           ws_module_ptr(_new_module(context),
00087                         WebServiceModuleDeleter(_delete_module));
00088 
00089       return ws_module_ptr();
00090     }
00091   };
00092 }
00093 
00094 struct WebServiceRunnerInitializer {
00095   typedef std::vector<string> dir_list;
00096   dir_list module_dirs;
00097   Properties actions;
00098 };
00099 
00100 struct WebServiceModuleConfig {
00101   string name;
00102   string module;
00103   string type;
00104   Properties properties;
00105 
00106   WebServiceModuleConfig(const string & name,
00107                          const string & module,
00108                          const string & type,
00109                          const Properties & properties) :
00110     name(name), module(module), type(type), properties(properties)
00111   { }
00112 };
00113 
00114 template<typename container_type>
00115 void get_ws_module_configs(container_type & result, const Properties & modules)
00116 {
00117   const Properties *p = modules.find("Module");
00118 
00119   if(p != 0) {
00120     Properties::child_container_const_iterator && it = p->child_begin();
00121     Properties::child_container_const_iterator && end = p->child_end();
00122 
00123     while(it != end) {
00124       const string & name = it->first;
00125       const Properties *node = it->second;
00126       const string & module = node->get<string>("", "module");
00127       const string & type   = node->get<string>("", "type");
00128       result.push_back(WebServiceModuleConfig(name, module, type,
00129                                               *node->find("properties")));
00130       ++it;
00131     }
00132   }
00133 }
00134 
00135 class WebServiceRunner : public WebService {
00136   typedef WebService super;
00137   friend class NS_SSRC_WISP_SERVICE::ServiceProtocolProcessor<packing_traits>;
00138 
00139   typedef detail::WebServiceModuleFactory<packing_traits> ws_module_factory;
00140   typedef boost::shared_ptr<ws_module_factory> ws_module_factory_ptr;
00141 
00142   WISP_IMPORT(ws_module_factory, ws_module_ptr);
00143 
00144   struct ws_module_entry {
00145     // Important: must be first so it is destroyed after module.
00146     ws_module_factory_ptr factory;
00147     ws_module_ptr module;
00148 
00149     ws_module_entry(const ws_module_factory_ptr & factory,
00150                     const ws_module_ptr & module) :
00151       factory(factory), module(module)
00152     { }
00153   };
00154 
00155   typedef std::unordered_map<string, ws_module_entry> ws_module_map;
00156 
00157   WebServiceRunnerInitializer::dir_list _module_dirs;
00158   std::vector<WebServiceModuleConfig> _module_configs;
00159   ws_module_map _module_map;
00160 
00161   static ws_module_factory_ptr
00162   new_module_factory(const string & filename,
00163                      const DynamicLibrary::Mode mode =
00164                      DynamicLibrary::NowLocal)
00165   {
00166     return
00167       ws_module_factory_ptr(new ws_module_factory(filename, mode));
00168   }
00169 
00170   void load_modules() SSRC_DECL_THROW(LoadError);
00171 
00175   virtual void transition(State state) {
00176     switch(state) {
00177     case Starting:
00178       load_modules();
00179       state = Started;
00180       break;
00181     case Stopping:
00182       state = Stopped;
00183       break;
00184     default:
00185       break;
00186     }
00187 
00188     super::transition(state);
00189   }
00190 
00191 public:
00192 
00193   WebServiceRunner(caller_type & caller,
00194                    const WebServiceRunnerInitializer & initializer) :
00195     super(caller), _module_dirs(initializer.module_dirs)
00196   {
00197     super::add_service_type(WSPR_WS_TYPE("runner"));
00198     get_ws_module_configs(_module_configs, initializer.actions);
00199     get_actions(_actions, initializer.actions);
00200   }
00201 
00202   virtual ~WebServiceRunner() {
00203     // All references to dynamically loaded memory must be removed since
00204     // call handler maps are destroyed after unloading dynamic library.
00205     clear_call_handlers();
00206     clear_request_handlers();
00207     clear_response_handlers();
00208     // Even though these may be redundant because they happen when a
00209     // service enters the stopped state, we want to make sure that no
00210     // continuations or timeouts reference module memory spaces.
00211     clear_timeouts();
00212     _caller.cancel_all();
00213   }
00214 };
00215 
00216 __END_NS_SSRC_WSPR_WS
00217 
00218 #endif

Savarese Software Research Corporation
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.