Branch data Line data Source code
1 : : /* Copyright 2006-2013 Savarese Software Research Corporation
2 : : *
3 : : * Licensed under the Apache License, Version 2.0 (the "License");
4 : : * you may not use this file except in compliance with the License.
5 : : * You may obtain a copy of the License at
6 : : *
7 : : * http://www.savarese.com/software/ApacheLicense-2.0
8 : : *
9 : : * Unless required by applicable law or agreed to in writing, software
10 : : * distributed under the License is distributed on an "AS IS" BASIS,
11 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : * See the License for the specific language governing permissions and
13 : : * limitations under the License.
14 : : */
15 : :
16 : : /**
17 : : * @file
18 : : * This header defines the service_main utility function template.
19 : : */
20 : :
21 : : #ifndef __SSRC_WISP_UTILITY_SERVICE_MAIN_H
22 : : #define __SSRC_WISP_UTILITY_SERVICE_MAIN_H
23 : :
24 : : #include <ssrc/wisp/service.h>
25 : : #include <ssrc/wisp/utility/ServiceOptions.h>
26 : : #include <ssrc/wisp/utility/ServiceMainOptions.h>
27 : :
28 : : #include <iostream>
29 : :
30 : : __BEGIN_NS_SSRC_WISP_UTILITY
31 : :
32 : : template<typename service_type, typename options_type>
33 : 3 : std::unique_ptr<service_type> new_service(const options_type & options) {
34 : : return std::make_unique<service_type>(options.connection,
35 : : options.name,
36 : 3 : options.capacity);
37 : : }
38 : :
39 : : template<typename service_type, typename options_type, typename init_type>
40 : : std::unique_ptr<service_type> new_service(const options_type & options,
41 : : const init_type & initializer)
42 : : {
43 : : return std::make_unique<service_type>(initializer,
44 : : options.connection,
45 : : options.name,
46 : : options.capacity);
47 : : }
48 : :
49 : : template<typename service_type, typename options_type, bool has_initializer>
50 : : struct ServiceFactory;
51 : :
52 : : template<typename service_type, typename options_type>
53 : : struct ServiceFactory<service_type, options_type, false> {
54 : : typedef std::unique_ptr<service_type> service_ptr;
55 : 3 : std::unique_ptr<service_type> operator()(const options_type & options) {
56 : 3 : return new_service<service_type>(options);
57 : : }
58 : : };
59 : :
60 : : template<typename service_type, typename options_type>
61 : : struct ServiceFactory<service_type, options_type, true> {
62 : : typedef std::unique_ptr<service_type> service_ptr;
63 : : std::unique_ptr<service_type> operator()(const options_type & options) {
64 : : return new_service<service_type>(options, options.initializer);
65 : : }
66 : : };
67 : :
68 : : struct ServiceMainOptionsProcessor {
69 : : template<typename CustomOptions>
70 : : static int process_options(const CustomOptions & options) {
71 : : if(options.help) {
72 : : std::cout << options.description << std::endl;
73 : : return 0;
74 : : } else if(options.wisp_version) {
75 : : std::cout << "Wisp version: " << WISP_VERSION << std::endl;
76 : : return 0;
77 : : } else if(options.arg_error) {
78 : : std::cerr << "Service option error: " << options.arg_error_msg
79 : : << std::endl;
80 : : return 1;
81 : : }
82 : :
83 : : if(options.connection.empty()) {
84 : : std::cerr << "Service error: You must specify a connection.\n";
85 : : return 1;
86 : : }
87 : :
88 : : if(options.locale.size() > 0)
89 : : std::locale::global(std::locale(std::locale::classic(),
90 : : options.locale.c_str(),
91 : : std::locale::ctype));
92 : : return -1;
93 : : }
94 : : };
95 : :
96 : : template<typename ProtocolProcessor,
97 : : template <typename PP, typename...> class EH,
98 : : typename CustomOptions,
99 : : typename CustomOptionsProcessor,
100 : : bool has_initializer>
101 : : int service_main(int argc, char *argv[]) {
102 : : using namespace NS_SSRC_WISP;
103 : : using namespace NS_SSRC_WISP_SERVICE;
104 : : using NS_SSRC_WISP_UTILITY::ServiceOptions;
105 : :
106 : : typedef ServiceOptions<CustomOptions> Options;
107 : : typedef std::unique_ptr<Options> options_ptr;
108 : : typedef std::unique_ptr<CustomOptionsProcessor> options_processor_ptr;
109 : : typedef Service<EH<ProtocolProcessor> > service_type;
110 : : typedef
111 : : ServiceFactory<service_type, Options, has_initializer> service_factory;
112 : :
113 : : WISP_IMPORT_T(ProtocolProcessor, packing_traits);
114 : :
115 : : std::string service_name;
116 : :
117 : : try {
118 : : options_processor_ptr options_processor(make_smart_ptr<options_processor_ptr>());
119 : : options_ptr options(make_smart_ptr<options_ptr>(argc, argv));
120 : : int exit_code = options_processor->process_options(*options);
121 : :
122 : : if(exit_code != -1) {
123 : : return exit_code;
124 : : } else {
125 : : service_factory new_service;
126 : : typename service_factory::service_ptr service = new_service(*options);
127 : : EventLoop loop;
128 : : service_name = service->name();
129 : : service->start(loop, options->call_timeout);
130 : : // Free extra memory used by options and options_processor.
131 : : options.reset();
132 : : options_processor.reset();
133 : : loop.start();
134 : : }
135 : : } catch(const NS_SSRC_SPREAD::Error & spread_error) {
136 : : std::cerr << "Service error: " << service_name
137 : : << " : Caught ssrc::spread::Error\n";
138 : : spread_error.print();
139 : : return 1;
140 : : } catch(const std::exception & std_error) {
141 : : std::cerr << "Service error: " << service_name << " : "
142 : : << std_error.what() << std::endl;
143 : : return 1;
144 : : } catch(...) {
145 : : std::cerr << "Service error: " << service_name
146 : : << " : Caught unknown exception!\n";
147 : : throw;
148 : : }
149 : :
150 : : return 0;
151 : : }
152 : :
153 : : #define WISP_EMPTY_INIT_CODE
154 : :
155 : : #define WISP_CUSTOM_SERVICE_MAIN_WITH_INIT(service_type, handler_type, options_type, options_processor_type, has_initializer, init_code) \
156 : : int main(int argc, char *argv[]) { \
157 : : init_code \
158 : : return NS_SSRC_WISP_UTILITY::service_main<service_type, handler_type, options_type, options_processor_type, has_initializer>(argc, argv); \
159 : : }
160 : :
161 : : #define WISP_CUSTOM_SERVICE_MAIN(service_type, handler_type, options_type, options_processor_type, has_initializer) \
162 : : WISP_CUSTOM_SERVICE_MAIN_WITH_INIT(service_type, handler_type, options_type, options_processor_type, has_initializer, WISP_EMPTY_INIT_CODE)
163 : :
164 : : #define WISP_SERVICE_MAIN_WITH_INIT(service_type, init_code) \
165 : : WISP_CUSTOM_SERVICE_MAIN_WITH_INIT(service_type, \
166 : : NS_SSRC_WISP_SERVICE::ServiceEventHandler, \
167 : : NS_SSRC_WISP_UTILITY::ServiceMainOptions, \
168 : : NS_SSRC_WISP_UTILITY::ServiceMainOptionsProcessor, \
169 : : false, init_code)
170 : :
171 : : #define WISP_SERVICE_MAIN(service_type) \
172 : : WISP_SERVICE_MAIN_WITH_INIT(service_type, WISP_EMPTY_INIT_CODE)
173 : :
174 : : __END_NS_SSRC_WISP_UTILITY
175 : :
176 : : #endif
|