AirInv Logo  1.00.12
C++ Simulated Airline Inventory Management System Library
Loading...
Searching...
No Matches
AirInvServer.cpp
Go to the documentation of this file.
1
5// //////////////////////////////////////////////////////////////////////
6// Import section
7// //////////////////////////////////////////////////////////////////////
8// STL
9#include <cassert>
10#include <sstream>
11#include <fstream>
12#include <string>
13#include <unistd.h>
14// Boost (Extended STL)
15#include <boost/program_options.hpp>
16#include <boost/tokenizer.hpp>
17// ZeroMQ
18#include <zmq.hpp>
19// StdAir
20#include <stdair/basic/BasLogParams.hpp>
21#include <stdair/basic/BasDBParams.hpp>
22#include <stdair/service/Logger.hpp>
23#include <stdair/stdair_json.hpp>
24// AirInvServer
25#include <airinv/config/airinv-paths.hpp>
27
28// ///////// Type definitions //////////
29typedef unsigned int ServerPort_T;
30
31// //////// Constants //////
33const std::string K_AIRINV_DEFAULT_LOG_FILENAME ("airinvServer.log");
34
36const std::string K_AIRINV_DEFAULT_SERVER_PROTOCOL ("tcp://");
37
39const std::string K_AIRINV_DEFAULT_SERVER_ADDRESS ("*");
40
42const ServerPort_T K_AIRINV_DEFAULT_SERVER_PORT (5555);
43
45const std::string K_AIRINV_DEFAULT_INVENTORY_FILENAME (STDAIR_SAMPLE_DIR
46 "/invdump01.csv");
48const std::string K_AIRINV_DEFAULT_SCHEDULE_FILENAME (STDAIR_SAMPLE_DIR
49 "/schedule01.csv");
51const std::string K_AIRINV_DEFAULT_OND_FILENAME (STDAIR_SAMPLE_DIR
52 "/ond01.csv");
54const std::string K_AIRINV_DEFAULT_FRAT5_INPUT_FILENAME (STDAIR_SAMPLE_DIR
55 "/frat5.csv");
57const std::string K_AIRINV_DEFAULT_FF_DISUTILITY_INPUT_FILENAME (STDAIR_SAMPLE_DIR
58 "/ffDisutility.csv");
59
61const std::string K_AIRINV_DEFAULT_YIELD_FILENAME (STDAIR_SAMPLE_DIR
62 "/yield01.csv");
63
68const bool K_AIRINV_DEFAULT_BUILT_IN_INPUT = false;
69
74const bool K_AIRINV_DEFAULT_FOR_SCHEDULE = false;
75
79const int K_AIRINV_EARLY_RETURN_STATUS = 99;
80
84struct Command_T {
85 typedef enum {
86 NOP = 0,
87 QUIT,
88 DISPLAY,
89 SELL,
90 LAST_VALUE
91 } Type_T;
92};
93
94// ///////// Parsing of Options & Configuration /////////
95// A helper function to simplify the main part.
96template<class T> std::ostream& operator<< (std::ostream& os,
97 const std::vector<T>& v) {
98 std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
99 return os;
100}
101
103int readConfiguration (int argc, char* argv[], std::string& ioServerProtocol,
104 std::string& ioServerAddress, ServerPort_T& ioServerPort,
105 bool& ioIsBuiltin, bool& ioIsForSchedule,
106 stdair::Filename_T& ioInventoryFilename,
107 stdair::Filename_T& ioScheduleInputFilename,
108 stdair::Filename_T& ioODInputFilename,
109 stdair::Filename_T& ioFRAT5Filename,
110 stdair::Filename_T& ioFFDisutilityFilename,
111 stdair::Filename_T& ioYieldInputFilename,
112 std::string& ioLogFilename) {
113 // Default for the built-in input
114 ioIsBuiltin = K_AIRINV_DEFAULT_BUILT_IN_INPUT;
115
116 // Default for the inventory or schedule option
117 ioIsForSchedule = K_AIRINV_DEFAULT_FOR_SCHEDULE;
118
119 // Declare a group of options that will be allowed only on command line
120 boost::program_options::options_description generic ("Generic options");
121 generic.add_options()
122 ("prefix", "print installation prefix")
123 ("version,v", "print version string")
124 ("help,h", "produce help message");
125
126 // Declare a group of options that will be allowed both on command
127 // line and in config file
128
129 boost::program_options::options_description config ("Configuration");
130 config.add_options()
131 ("builtin,b",
132 "The sample BOM tree can be either built-in or parsed from an input file. That latter must then be given with the -i/--inventory or -s/--schedule option")
133 ("for_schedule,f",
134 "The BOM tree should be built from a schedule file (instead of from an inventory dump)")
135 ("inventory,i",
136 boost::program_options::value< std::string >(&ioInventoryFilename)->default_value(K_AIRINV_DEFAULT_INVENTORY_FILENAME),
137 "(CVS) input file for the inventory")
138 ("schedule,s",
139 boost::program_options::value< std::string >(&ioScheduleInputFilename)->default_value(K_AIRINV_DEFAULT_SCHEDULE_FILENAME),
140 "(CVS) input file for the schedule")
141 ("ond,o",
142 boost::program_options::value< std::string >(&ioODInputFilename)->default_value(K_AIRINV_DEFAULT_OND_FILENAME),
143 "(CVS) input file for the O&D")
144 ("frat5,r",
145 boost::program_options::value< std::string >(&ioFRAT5Filename)->default_value(K_AIRINV_DEFAULT_FRAT5_INPUT_FILENAME),
146 "(CSV) input file for the FRAT5 Curve")
147 ("ff_disutility,d",
148 boost::program_options::value< std::string >(&ioFFDisutilityFilename)->default_value(K_AIRINV_DEFAULT_FF_DISUTILITY_INPUT_FILENAME),
149 "(CSV) input file for the FF disutility Curve")
150 ("yield,y",
151 boost::program_options::value< std::string >(&ioYieldInputFilename)->default_value(K_AIRINV_DEFAULT_YIELD_FILENAME),
152 "(CVS) input file for the yield")
153 ("protocol,t",
154 boost::program_options::value< std::string >(&ioServerProtocol)->default_value(K_AIRINV_DEFAULT_SERVER_PROTOCOL),
155 "Server protocol")
156 ("address,a",
157 boost::program_options::value< std::string >(&ioServerAddress)->default_value(K_AIRINV_DEFAULT_SERVER_ADDRESS),
158 "Server address")
159 ("port,p",
160 boost::program_options::value< ServerPort_T >(&ioServerPort)->default_value(K_AIRINV_DEFAULT_SERVER_PORT),
161 "Server port")
162 ("log,l",
163 boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_AIRINV_DEFAULT_LOG_FILENAME),
164 "Filename for the output logs")
165 ;
166
167 // Hidden options, will be allowed both on command line and
168 // in config file, but will not be shown to the user.
169 boost::program_options::options_description hidden ("Hidden options");
170 hidden.add_options()
171 ("copyright",
172 boost::program_options::value< std::vector<std::string> >(),
173 "Show the copyright (license)");
174
175 boost::program_options::options_description cmdline_options;
176 cmdline_options.add(generic).add(config).add(hidden);
177
178 boost::program_options::options_description config_file_options;
179 config_file_options.add(config).add(hidden);
180 boost::program_options::options_description visible ("Allowed options");
181 visible.add(generic).add(config);
182
183 boost::program_options::positional_options_description p;
184 p.add ("copyright", -1);
185
186 boost::program_options::variables_map vm;
187 boost::program_options::
188 store (boost::program_options::command_line_parser (argc, argv).
189 options (cmdline_options).positional(p).run(), vm);
190
191 std::ifstream ifs ("airinvServer.cfg");
192 boost::program_options::store (parse_config_file (ifs, config_file_options),
193 vm);
194 boost::program_options::notify (vm);
195
196 if (vm.count ("help")) {
197 std::cout << visible << std::endl;
198 return K_AIRINV_EARLY_RETURN_STATUS;
199 }
200
201 if (vm.count ("version")) {
202 std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
203 return K_AIRINV_EARLY_RETURN_STATUS;
204 }
205
206 if (vm.count ("prefix")) {
207 std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
208 return K_AIRINV_EARLY_RETURN_STATUS;
209 }
210
211 if (vm.count ("protocol")) {
212 ioServerProtocol = vm["protocol"].as< std::string >();
213 std::cout << "Server protocol is: " << ioServerProtocol << std::endl;
214 }
215
216 if (vm.count ("address")) {
217 ioServerAddress = vm["address"].as< std::string >();
218 std::cout << "Server address is: " << ioServerAddress << std::endl;
219 }
220
221 if (vm.count ("port")) {
222 ioServerPort = vm["port"].as< ServerPort_T >();
223 std::cout << "Server port is: " << ioServerPort << std::endl;
224 }
225
226 if (vm.count ("builtin")) {
227 ioIsBuiltin = true;
228 }
229 const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
230 std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
231
232 if (vm.count ("for_schedule")) {
233 ioIsForSchedule = true;
234 }
235 const std::string isForScheduleStr = (ioIsForSchedule == true)?"yes":"no";
236 std::cout << "The BOM should be built from schedule? " << isForScheduleStr
237 << std::endl;
238
239 if (ioIsBuiltin == false) {
240
241 if (ioIsForSchedule == false) {
242 // The BOM tree should be built from parsing an inventory dump
243 if (vm.count ("inventory")) {
244 ioInventoryFilename = vm["inventory"].as< std::string >();
245 std::cout << "Input inventory filename is: " << ioInventoryFilename
246 << std::endl;
247
248 } else {
249 // The built-in option is not selected. However, no inventory dump
250 // file is specified
251 std::cerr << "Either one among the -b/--builtin, -i/--inventory or "
252 << " -f/--for_schedule and -s/--schedule options "
253 << "must be specified" << std::endl;
254 }
255
256 } else {
257 // The BOM tree should be built from parsing a schedule (and O&D) file
258 if (vm.count ("schedule")) {
259 ioScheduleInputFilename = vm["schedule"].as< std::string >();
260 std::cout << "Input schedule filename is: " << ioScheduleInputFilename
261 << std::endl;
262
263 } else {
264 // The built-in option is not selected. However, no schedule file
265 // is specified
266 std::cerr << "Either one among the -b/--builtin, -i/--inventory or "
267 << " -f/--for_schedule and -s/--schedule options "
268 << "must be specified" << std::endl;
269 }
270
271 if (vm.count ("ond")) {
272 ioODInputFilename = vm["ond"].as< std::string >();
273 std::cout << "Input O&D filename is: " << ioODInputFilename << std::endl;
274 }
275
276 if (vm.count ("frat5")) {
277 ioFRAT5Filename = vm["frat5"].as< std::string >();
278 std::cout << "FRAT5 input filename is: " << ioFRAT5Filename << std::endl;
279
280 }
281
282 if (vm.count ("ff_disutility")) {
283 ioFFDisutilityFilename = vm["ff_disutility"].as< std::string >();
284 std::cout << "FF disutility input filename is: "
285 << ioFFDisutilityFilename << std::endl;
286
287 }
288
289 if (vm.count ("yield")) {
290 ioYieldInputFilename = vm["yield"].as< std::string >();
291 std::cout << "Input yield filename is: " << ioYieldInputFilename << std::endl;
292 }
293 }
294 }
295
296 if (vm.count ("log")) {
297 ioLogFilename = vm["log"].as< std::string >();
298 std::cout << "Log filename is: " << ioLogFilename << std::endl;
299 }
300
301 return 0;
302}
303
304
305// ///////// Utility functions on top of the ZeroMQ library /////////
309static std::string s_recv (zmq::socket_t& socket) {
310 zmq::message_t message;
311
312 zmq::recv_result_t rc = socket.recv (message);
313
314 // DEBUG
315 if (rc.has_value()) {
316 const unsigned int rc_val = rc.value();
317 std::cout << "Receive status: " << rc_val << std::endl;
318 }
319
320 return std::string (static_cast<char*> (message.data()), message.size());
321}
322
326static zmq::send_result_t s_send (zmq::socket_t& socket, const std::string& string) {
327 zmq::message_t message (string.size());
328 memcpy (message.data(), string.data(), string.size());
329
330 zmq::send_flags flags = zmq::send_flags::none;
331
332 zmq::send_result_t rc = socket.send (message, flags);
333 return rc;
334}
335
336
337// /////////////////////// M A I N ////////////////////////
338int main (int argc, char* argv[]) {
339
340 // Server parameters (for ZeroMQ)
341 std::string ioServerProtocol;
342 std::string ioServerAddress;
343 ServerPort_T ioServerPort;
344
345 // State whether the BOM tree should be built-in or parsed from an
346 // input file
347 bool isBuiltin;
348 bool isForSchedule;
349
350 // Input file names
351 stdair::Filename_T lInventoryFilename;
352 stdair::Filename_T lScheduleInputFilename;
353 stdair::Filename_T lODInputFilename;
354 stdair::Filename_T lFRAT5InputFilename;
355 stdair::Filename_T lFFDisutilityInputFilename;
356 stdair::Filename_T lYieldInputFilename;
357
358 // Output log File
359 stdair::Filename_T lLogFilename;
360
361 // Call the command-line option parser
362 const int lOptionParserStatus =
363 readConfiguration (argc, argv, ioServerProtocol, ioServerAddress,
364 ioServerPort, isBuiltin, isForSchedule,
365 lInventoryFilename, lScheduleInputFilename,
366 lODInputFilename, lFRAT5InputFilename,
367 lFFDisutilityInputFilename, lYieldInputFilename,
368 lLogFilename);
369
370 if (lOptionParserStatus == K_AIRINV_EARLY_RETURN_STATUS) {
371 return 0;
372 }
373
374 // Set the log parameters
375 std::ofstream logOutputFile;
376 // Open and clean the log outputfile
377 logOutputFile.open (lLogFilename.c_str());
378 logOutputFile.clear();
379
380 // Initialise the inventory service
381 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
382 AIRINV::AIRINV_Master_Service airinvService (lLogParams);
383
384 // DEBUG
385 STDAIR_LOG_DEBUG ("Initialisation of the AirInv server");
386
387 // Check wether or not a (CSV) input file should be read
388 if (isBuiltin == true) {
389
390 // Build the sample BOM tree for RMOL
391 airinvService.buildSampleBom();
392
393 } else {
394 if (isForSchedule == true) {
395 // Build the BOM tree from parsing a schedule file (and O&D list)
396 stdair::ScheduleFilePath lScheduleFilePath (lScheduleInputFilename);
397 stdair::ODFilePath lODFilePath (lODInputFilename);
398 stdair::FRAT5FilePath lFRAT5FilePath (lFRAT5InputFilename);
399 stdair::FFDisutilityFilePath lFFDisutilityFilePath (lFFDisutilityInputFilename);
400 AIRRAC::YieldFilePath lYieldFilePath (lYieldInputFilename);
401 airinvService.parseAndLoad (lScheduleFilePath, lODFilePath,
402 lFRAT5FilePath, lFFDisutilityFilePath,
403 lYieldFilePath);
404
405 } else {
406 // Build the BOM tree from parsing an inventory dump file
407 AIRINV::InventoryFilePath lInventoryFilePath (lInventoryFilename);
408 airinvService.parseAndLoad (lInventoryFilePath);
409 }
410 }
411
412 // Build the connection string (e.g., "tcp://*:5555", which is the default)
413 std::ostringstream oZeroMQBindStream;
414 oZeroMQBindStream << ioServerProtocol << ioServerAddress
415 << ":" << ioServerPort;
416 const std::string lZeroMQBindString (oZeroMQBindStream.str());
417
418 // Prepare the context and socket of the server
419 zmq::context_t context (1);
420 zmq::socket_t socket (context, ZMQ_REP);
421 socket.bind (lZeroMQBindString.c_str());
422
423 // DEBUG
424 STDAIR_LOG_DEBUG ("The AirInv server is ready to receive requests...");
425
426 while (true) {
427
428 // Wait for next request from client, which is expected to give
429 // a JSON-ified command.
430 const std::string& lReceivedString = s_recv (socket);
431
432 // DEBUG
433 STDAIR_LOG_DEBUG ("Received: '" << lReceivedString << "'");
434
435 const stdair::JSONString lJSONCommandString (lReceivedString);
436 const std::string& lJSONDump =
437 airinvService.jsonHandler (lJSONCommandString);
438
439 // DEBUG
440 STDAIR_LOG_DEBUG ("Send: '" << lJSONDump << "'");
441
442 // Send back the answer details to the client
443 zmq::send_result_t rc = s_send (socket, lJSONDump);
444
445 // DEBUG
446 if (rc.has_value()) {
447 const unsigned int rc_val = rc.value();
448 std::cout << "Send status: " << rc_val << std::endl;
449 }
450 }
451
452 return 0;
453}
454
int main(int argc, char *argv[])
std::basic_ostream< charT, traits > & operator<<(std::basic_ostream< charT, traits > &ioOut, const AIRINV::BomAbstract &iBom)
Interface for the AIRINV Services.