Savarese Software Research Corporation
service_main.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2008 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  *     http://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 
00022 #ifndef __SSRC_WISP_UTILITY_SERVICE_MAIN_H
00023 #define __SSRC_WISP_UTILITY_SERVICE_MAIN_H
00024 
00025 #include <ssrc/wisp/service.h>
00026 #include <ssrc/wisp/utility/ServiceOptions.h>
00027 #include <ssrc/wisp/utility/ServiceMainOptions.h>
00028 
00029 #include <iostream>
00030 
00031 __BEGIN_NS_SSRC_WISP_UTILITY
00032 
00033 template<typename service_type, typename options_type>
00034 SSRC_UNIQUE_PTR<service_type> new_service(const options_type & options) {
00035   return SSRC_UNIQUE_PTR<service_type>(new service_type(options.connection,
00036                                            options.name,
00037                                            options.capacity));
00038 }
00039 
00040 template<typename service_type, typename options_type, typename init_type>
00041 SSRC_UNIQUE_PTR<service_type> new_service(const options_type & options,
00042                                         const init_type & initializer)
00043 {
00044   return SSRC_UNIQUE_PTR<service_type>(new service_type(initializer,
00045                                            options.connection,
00046                                            options.name,
00047                                            options.capacity));
00048 }
00049 
00050 template<typename service_type, typename options_type, bool has_initializer>
00051 struct ServiceFactory;
00052 
00053 template<typename service_type, typename options_type>
00054 struct ServiceFactory<service_type, options_type, false> {
00055   typedef SSRC_UNIQUE_PTR<service_type> service_ptr;
00056   SSRC_UNIQUE_PTR<service_type> operator()(const options_type & options) {
00057     return new_service<service_type>(options);
00058   }
00059 };
00060 
00061 template<typename service_type, typename options_type>
00062 struct ServiceFactory<service_type, options_type, true> {
00063   typedef SSRC_UNIQUE_PTR<service_type> service_ptr;
00064   SSRC_UNIQUE_PTR<service_type> operator()(const options_type & options) {
00065     return new_service<service_type>(options, options.initializer);
00066   }
00067 };
00068 
00069 struct ServiceMainOptionsProcessor {
00070   template<typename CustomOptions>
00071   static int process_options(const CustomOptions & options) {
00072     if(options.help) {
00073       std::cout << options.description << std::endl;
00074       return 0;
00075     } else if(options.wisp_version) {
00076       std::cout << "Wisp version: " << WISP_VERSION << std::endl;
00077       return 0;
00078     } else if(options.arg_error) {
00079       std::cerr << "Service option error: " << options.arg_error_msg
00080                 << std::endl;
00081       return 1;
00082     }
00083 
00084     if(options.connection.empty()) {
00085       std::cerr << "Service error: You must specify a connection.\n";
00086       return 1;
00087     }
00088 
00089     if(options.locale.size() > 0)
00090       std::locale::global(std::locale(std::locale::classic(),
00091                                       options.locale.c_str(),
00092                                       std::locale::ctype));
00093     return -1;
00094   }
00095 };
00096 
00097 template<typename ProtocolProcessor,
00098          template <typename PP> class EH,
00099          typename CustomOptions,
00100          typename CustomOptionsProcessor,
00101          bool has_initializer>
00102 int service_main(int argc, char *argv[]) {
00103   using namespace NS_SSRC_WISP;
00104   using namespace NS_SSRC_WISP_SERVICE;
00105   using NS_SSRC_WISP_UTILITY::ServiceOptions;
00106 
00107   typedef ServiceOptions<CustomOptions> Options;
00108   typedef boost::scoped_ptr<Options> options_ptr;
00109   typedef boost::scoped_ptr<CustomOptionsProcessor> options_processor_ptr;
00110   typedef Service<EH<ProtocolProcessor> > service_type;
00111   typedef
00112     ServiceFactory<service_type, Options, has_initializer> service_factory;
00113 
00114   WISP_IMPORT_T(ProtocolProcessor, packing_traits);
00115 
00116   string service_name;
00117 
00118   try {
00119     options_processor_ptr options_processor(new CustomOptionsProcessor);
00120     options_ptr options(new Options(argc, argv));
00121     int exit_code = options_processor->process_options(*options);
00122 
00123     if(exit_code != -1) {
00124       return exit_code;
00125     } else {
00126       service_factory new_service;
00127       typename service_factory::service_ptr service = new_service(*options);
00128       EventLoop loop;
00129       service_name = service->name();
00130       service->start(loop, options->call_timeout);
00131       // Free extra memory used by options and options_processor.
00132       options.reset();
00133       options_processor.reset();
00134       loop.start();
00135     }
00136   } catch(const NS_SSRC_SPREAD::Error & spread_error) {
00137     std::cerr << "Service error: " << service_name
00138               << " : Caught ssrc::spread::Error\n";
00139     spread_error.print();
00140     return 1;
00141   } catch(const std::exception & std_error) {
00142     std::cerr << "Service error: " << service_name << " : "
00143               << std_error.what() << std::endl;
00144     return 1;
00145   } catch(...) {
00146     std::cerr << "Service error: " << service_name
00147               << " : Caught unknown exception!\n";
00148     throw;
00149   }
00150 
00151   return 0;
00152 }
00153 
00154 #define WISP_EMPTY_INIT_CODE
00155 
00156 #define WISP_CUSTOM_SERVICE_MAIN_WITH_INIT(service_type, handler_type, options_type, options_processor_type, has_initializer, init_code) \
00157 int main(int argc, char *argv[]) { \
00158   init_code \
00159   return NS_SSRC_WISP_UTILITY::service_main<service_type, handler_type, options_type, options_processor_type, has_initializer>(argc, argv); \
00160 }
00161 
00162 #define WISP_CUSTOM_SERVICE_MAIN(service_type, handler_type, options_type, options_processor_type, has_initializer) \
00163   WISP_CUSTOM_SERVICE_MAIN_WITH_INIT(service_type, handler_type, options_type, options_processor_type, has_initializer, WISP_EMPTY_INIT_CODE)
00164 
00165 #define WISP_SERVICE_MAIN_WITH_INIT(service_type, init_code)                  \
00166   WISP_CUSTOM_SERVICE_MAIN_WITH_INIT(service_type,                            \
00167                            NS_SSRC_WISP_SERVICE::ServiceEventHandler,         \
00168                            NS_SSRC_WISP_UTILITY::ServiceMainOptions,          \
00169                            NS_SSRC_WISP_UTILITY::ServiceMainOptionsProcessor, \
00170                            false, init_code)
00171 
00172 #define WISP_SERVICE_MAIN(service_type)                                 \
00173   WISP_SERVICE_MAIN_WITH_INIT(service_type, WISP_EMPTY_INIT_CODE)
00174 
00175 __END_NS_SSRC_WISP_UTILITY
00176 
00177 #endif

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