00001
00005
00006
00007
00008
00009 #include <cassert>
00010 #include <sstream>
00011 #include <fstream>
00012 #include <string>
00013 #include <unistd.h>
00014
00015 #include <boost/program_options.hpp>
00016 #include <boost/tokenizer.hpp>
00017
00018 #include <zmq.hpp>
00019
00020 #include <stdair/basic/BasLogParams.hpp>
00021 #include <stdair/basic/BasDBParams.hpp>
00022 #include <stdair/bom/BomJSONImport.hpp>
00023 #include <stdair/bom/BomJSONExport.hpp>
00024 #include <stdair/service/Logger.hpp>
00025
00026 #include <airinv/config/airinv-paths.hpp>
00027 #include <airinv/AIRINV_Master_Service.hpp>
00028
00029
00030 typedef unsigned int ServerPort_T;
00031
00032
00034 const std::string K_AIRINV_DEFAULT_LOG_FILENAME ("airinvServer.log");
00035
00037 const std::string K_AIRINV_DEFAULT_SERVER_PROTOCOL ("tcp://");
00038
00040 const std::string K_AIRINV_DEFAULT_SERVER_ADDRESS ("*");
00041
00043 const ServerPort_T K_AIRINV_DEFAULT_SERVER_PORT (5555);
00044
00046 const std::string K_AIRINV_DEFAULT_INVENTORY_FILENAME (STDAIR_SAMPLE_DIR
00047 "/invdump01.csv");
00049 const std::string K_AIRINV_DEFAULT_SCHEDULE_FILENAME (STDAIR_SAMPLE_DIR
00050 "/schedule01.csv");
00052 const std::string K_AIRINV_DEFAULT_OND_FILENAME (STDAIR_SAMPLE_DIR
00053 "/ond01.csv");
00054
00056 const std::string K_AIRINV_DEFAULT_YIELD_FILENAME (STDAIR_SAMPLE_DIR
00057 "/yield01.csv");
00058
00063 const bool K_AIRINV_DEFAULT_BUILT_IN_INPUT = false;
00064
00069 const bool K_AIRINV_DEFAULT_FOR_SCHEDULE = false;
00070
00074 const int K_AIRINV_EARLY_RETURN_STATUS = 99;
00075
00079 struct Command_T {
00080 typedef enum {
00081 NOP = 0,
00082 QUIT,
00083 DISPLAY,
00084 SELL,
00085 LAST_VALUE
00086 } Type_T;
00087 };
00088
00089
00090
00091 template<class T> std::ostream& operator<< (std::ostream& os,
00092 const std::vector<T>& v) {
00093 std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
00094 return os;
00095 }
00096
00098 int readConfiguration (int argc, char* argv[], std::string& ioServerProtocol,
00099 std::string& ioServerAddress, ServerPort_T& ioServerPort,
00100 bool& ioIsBuiltin, bool& ioIsForSchedule,
00101 stdair::Filename_T& ioInventoryFilename,
00102 stdair::Filename_T& ioScheduleInputFilename,
00103 stdair::Filename_T& ioODInputFilename,
00104 stdair::Filename_T& ioYieldInputFilename,
00105 std::string& ioLogFilename) {
00106
00107 ioIsBuiltin = K_AIRINV_DEFAULT_BUILT_IN_INPUT;
00108
00109
00110 ioIsForSchedule = K_AIRINV_DEFAULT_FOR_SCHEDULE;
00111
00112
00113 boost::program_options::options_description generic ("Generic options");
00114 generic.add_options()
00115 ("prefix", "print installation prefix")
00116 ("version,v", "print version string")
00117 ("help,h", "produce help message");
00118
00119
00120
00121
00122 boost::program_options::options_description config ("Configuration");
00123 config.add_options()
00124 ("builtin,b",
00125 "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")
00126 ("for_schedule,f",
00127 "The BOM tree should be built from a schedule file (instead of from an inventory dump)")
00128 ("inventory,i",
00129 boost::program_options::value< std::string >(&ioInventoryFilename)->default_value(K_AIRINV_DEFAULT_INVENTORY_FILENAME),
00130 "(CVS) input file for the inventory")
00131 ("schedule,s",
00132 boost::program_options::value< std::string >(&ioScheduleInputFilename)->default_value(K_AIRINV_DEFAULT_SCHEDULE_FILENAME),
00133 "(CVS) input file for the schedule")
00134 ("ond,o",
00135 boost::program_options::value< std::string >(&ioODInputFilename)->default_value(K_AIRINV_DEFAULT_OND_FILENAME),
00136 "(CVS) input file for the O&D")
00137 ("yield,y",
00138 boost::program_options::value< std::string >(&ioYieldInputFilename)->default_value(K_AIRINV_DEFAULT_YIELD_FILENAME),
00139 "(CVS) input file for the yield")
00140 ("protocol,t",
00141 boost::program_options::value< std::string >(&ioServerProtocol)->default_value(K_AIRINV_DEFAULT_SERVER_PROTOCOL),
00142 "Server protocol")
00143 ("address,a",
00144 boost::program_options::value< std::string >(&ioServerAddress)->default_value(K_AIRINV_DEFAULT_SERVER_ADDRESS),
00145 "Server address")
00146 ("port,p",
00147 boost::program_options::value< ServerPort_T >(&ioServerPort)->default_value(K_AIRINV_DEFAULT_SERVER_PORT),
00148 "Server port")
00149 ("log,l",
00150 boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_AIRINV_DEFAULT_LOG_FILENAME),
00151 "Filename for the output logs")
00152 ;
00153
00154
00155
00156 boost::program_options::options_description hidden ("Hidden options");
00157 hidden.add_options()
00158 ("copyright",
00159 boost::program_options::value< std::vector<std::string> >(),
00160 "Show the copyright (license)");
00161
00162 boost::program_options::options_description cmdline_options;
00163 cmdline_options.add(generic).add(config).add(hidden);
00164
00165 boost::program_options::options_description config_file_options;
00166 config_file_options.add(config).add(hidden);
00167 boost::program_options::options_description visible ("Allowed options");
00168 visible.add(generic).add(config);
00169
00170 boost::program_options::positional_options_description p;
00171 p.add ("copyright", -1);
00172
00173 boost::program_options::variables_map vm;
00174 boost::program_options::
00175 store (boost::program_options::command_line_parser (argc, argv).
00176 options (cmdline_options).positional(p).run(), vm);
00177
00178 std::ifstream ifs ("airinvServer.cfg");
00179 boost::program_options::store (parse_config_file (ifs, config_file_options),
00180 vm);
00181 boost::program_options::notify (vm);
00182
00183 if (vm.count ("help")) {
00184 std::cout << visible << std::endl;
00185 return K_AIRINV_EARLY_RETURN_STATUS;
00186 }
00187
00188 if (vm.count ("version")) {
00189 std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
00190 return K_AIRINV_EARLY_RETURN_STATUS;
00191 }
00192
00193 if (vm.count ("prefix")) {
00194 std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
00195 return K_AIRINV_EARLY_RETURN_STATUS;
00196 }
00197
00198 if (vm.count ("protocol")) {
00199 ioServerProtocol = vm["protocol"].as< std::string >();
00200 std::cout << "Server protocol is: " << ioServerProtocol << std::endl;
00201 }
00202
00203 if (vm.count ("address")) {
00204 ioServerAddress = vm["address"].as< std::string >();
00205 std::cout << "Server address is: " << ioServerAddress << std::endl;
00206 }
00207
00208 if (vm.count ("port")) {
00209 ioServerPort = vm["port"].as< ServerPort_T >();
00210 std::cout << "Server port is: " << ioServerPort << std::endl;
00211 }
00212
00213 if (vm.count ("builtin")) {
00214 ioIsBuiltin = true;
00215 }
00216 const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
00217 std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
00218
00219 if (vm.count ("for_schedule")) {
00220 ioIsForSchedule = true;
00221 }
00222 const std::string isForScheduleStr = (ioIsForSchedule == true)?"yes":"no";
00223 std::cout << "The BOM should be built from schedule? " << isForScheduleStr
00224 << std::endl;
00225
00226 if (ioIsBuiltin == false) {
00227
00228 if (ioIsForSchedule == false) {
00229
00230 if (vm.count ("inventory")) {
00231 ioInventoryFilename = vm["inventory"].as< std::string >();
00232 std::cout << "Input inventory filename is: " << ioInventoryFilename
00233 << std::endl;
00234
00235 } else {
00236
00237
00238 std::cerr << "Either one among the -b/--builtin, -i/--inventory or "
00239 << " -f/--for_schedule and -s/--schedule options "
00240 << "must be specified" << std::endl;
00241 }
00242
00243 } else {
00244
00245 if (vm.count ("schedule")) {
00246 ioScheduleInputFilename = vm["schedule"].as< std::string >();
00247 std::cout << "Input schedule filename is: " << ioScheduleInputFilename
00248 << std::endl;
00249
00250 } else {
00251
00252
00253 std::cerr << "Either one among the -b/--builtin, -i/--inventory or "
00254 << " -f/--for_schedule and -s/--schedule options "
00255 << "must be specified" << std::endl;
00256 }
00257
00258 if (vm.count ("ond")) {
00259 ioODInputFilename = vm["ond"].as< std::string >();
00260 std::cout << "Input O&D filename is: " << ioODInputFilename << std::endl;
00261 }
00262
00263 if (vm.count ("yield")) {
00264 ioYieldInputFilename = vm["yield"].as< std::string >();
00265 std::cout << "Input yield filename is: " << ioYieldInputFilename << std::endl;
00266 }
00267 }
00268 }
00269
00270 if (vm.count ("log")) {
00271 ioLogFilename = vm["log"].as< std::string >();
00272 std::cout << "Log filename is: " << ioLogFilename << std::endl;
00273 }
00274
00275 return 0;
00276 }
00277
00278
00279
00283 static std::string s_recv (zmq::socket_t& socket) {
00284 zmq::message_t message;
00285 socket.recv (&message);
00286
00287 return std::string (static_cast<char*> (message.data()), message.size());
00288 }
00289
00293 static bool s_send (zmq::socket_t& socket, const std::string& string) {
00294 zmq::message_t message (string.size());
00295 memcpy (message.data(), string.data(), string.size());
00296
00297 bool rc = socket.send (message);
00298 return rc;
00299 }
00300
00301
00302
00303 int main (int argc, char* argv[]) {
00304
00305
00306 std::string ioServerProtocol;
00307 std::string ioServerAddress;
00308 ServerPort_T ioServerPort;
00309
00310
00311
00312 bool isBuiltin;
00313 bool isForSchedule;
00314
00315
00316 stdair::Filename_T lInventoryFilename;
00317 stdair::Filename_T lScheduleInputFilename;
00318 stdair::Filename_T lODInputFilename;
00319 stdair::Filename_T lYieldInputFilename;
00320
00321
00322 stdair::Filename_T lLogFilename;
00323
00324
00325 const int lOptionParserStatus =
00326 readConfiguration (argc, argv, ioServerProtocol, ioServerAddress,
00327 ioServerPort, isBuiltin, isForSchedule,
00328 lInventoryFilename, lScheduleInputFilename,
00329 lODInputFilename, lYieldInputFilename, lLogFilename);
00330
00331 if (lOptionParserStatus == K_AIRINV_EARLY_RETURN_STATUS) {
00332 return 0;
00333 }
00334
00335
00336 std::ofstream logOutputFile;
00337
00338 logOutputFile.open (lLogFilename.c_str());
00339 logOutputFile.clear();
00340
00341
00342 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
00343 AIRINV::AIRINV_Master_Service airinvService (lLogParams);
00344
00345
00346 STDAIR_LOG_DEBUG ("Initialisation of the AirInv server");
00347
00348
00349 if (isBuiltin == true) {
00350
00351
00352 airinvService.buildSampleBom();
00353
00354 } else {
00355 if (isForSchedule == true) {
00356
00357 AIRRAC::YieldFilePath lYieldFilePath (lYieldInputFilename);
00358 airinvService.parseAndLoad (lScheduleInputFilename, lODInputFilename,
00359 lYieldFilePath);
00360
00361 } else {
00362
00363 airinvService.parseAndLoad (lInventoryFilename);
00364 }
00365 }
00366
00367
00368 std::ostringstream oZeroMQBindStream;
00369 oZeroMQBindStream << ioServerProtocol << ioServerAddress
00370 << ":" << ioServerPort;
00371 const std::string lZeroMQBindString (oZeroMQBindStream.str());
00372
00373
00374 zmq::context_t context (1);
00375 zmq::socket_t socket (context, ZMQ_REP);
00376 socket.bind (lZeroMQBindString.c_str());
00377
00378
00379 STDAIR_LOG_DEBUG ("The AirInv server is ready to receive requests...");
00380
00381 while (true) {
00382
00383
00384
00385 const std::string& lFlightDateKeyJSONString = s_recv (socket);
00386
00387
00388 STDAIR_LOG_DEBUG ("Received: '" << lFlightDateKeyJSONString << "'");
00389
00390
00391 stdair::AirlineCode_T lAirlineCode;
00392 stdair::BomJSONImport::jsonImportInventoryKey (lFlightDateKeyJSONString,
00393 lAirlineCode);
00394
00395
00396 stdair::FlightNumber_T lFlightNumber;
00397 stdair::Date_T lDate;
00398 stdair::BomJSONImport::jsonImportFlightDateKey (lFlightDateKeyJSONString,
00399 lFlightNumber, lDate);
00400
00401
00402 STDAIR_LOG_DEBUG ("=> airline code = '" << lAirlineCode
00403 << "', flight number = " << lFlightNumber
00404 << "', departure date = '" << lDate << "'");
00405
00406
00407 const std::string& lFlightDateCSVDump =
00408 airinvService.csvDisplay (lAirlineCode, lFlightNumber, lDate);
00409 STDAIR_LOG_DEBUG (std::endl << lFlightDateCSVDump);
00410
00411
00412 const std::string& lFlightDateJSONDump =
00413 airinvService.jsonExport (lAirlineCode, lFlightNumber, lDate);
00414
00415
00416 STDAIR_LOG_DEBUG ("Send: '" << lFlightDateJSONDump << "'");
00417
00418
00419 s_send (socket, lFlightDateJSONDump);
00420 }
00421
00422 return 0;
00423 }
00424