/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2012 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * \file poolworker.cpp * * This file strongly follows the Serialization example from the boost::asio * library (see client.cpp) * * Created on: Feb 28, 2012 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif // boost asio needs specific operator new #include #include "CodePatterns/MemDebug.hpp" #include #include #include #include #include #include #include "atexit.hpp" #include "CodePatterns/Info.hpp" #include "CodePatterns/Log.hpp" #include "Pool/PoolWorker.hpp" //!> global shutdown function boost::function shutdownfunction; //!> global signal vector for later releasing std::vector signals; //!> counter for the number of received signals size_t NoSignalsReceived = 0; //!> maximum number of received signals after which the handlers are released const size_t MAX_NOSIGNALSRECEIVED = 3; void signalhandler(int sig) { // increment received signal counter ++NoSignalsReceived; // shutdown if we have handler if (shutdownfunction) shutdownfunction(sig); if (NoSignalsReceived >= MAX_NOSIGNALSRECEIVED) { // release signal hook again for (std::vector::const_iterator iter = signals.begin(); iter != signals.end(); ++iter) signal(*iter, NULL); } } int main(int argc, char* argv[]) { // from this moment on, we need to be sure to deeinitialize in the correct order // this is handled by the cleanup function atexit(cleanUp); // Declare the supported options. boost::program_options::options_description desc("Allowed options"); desc.add_options() ("help,h", "produce help message") ("verbosity,v", boost::program_options::value(), "set verbosity level") ("signal", boost::program_options::value< std::vector >(), "set signal to catch (can be given multiple times)") ("server", boost::program_options::value< std::string>(), "connect to server at this address (host:port)") ("listen", boost::program_options::value< std::string >(), "listen on this port") ("hostname", boost::program_options::value< std::string>(), "name of host on which this codes runs and which server can resolve") ; boost::program_options::variables_map vm; boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); boost::program_options::notify(vm); if (vm.count("help")) { std::cout << desc << "\n"; return 1; } if (vm.count("verbosity")) { LOG(0, "STATUS: Verbosity level was set to " << vm["verbosity"].as() << "."); setVerbosity(vm["verbosity"].as()); } else { LOG(0, "STATUS: Verbosity level was not set, defaulting to 5."); setVerbosity(5); } std::string server; std::string serverport; if (vm.count("server")) { server = vm["server"].as< std::string >(); serverport = server.substr(server.find_last_of(':')+1, std::string::npos); server = server.substr(0, server.find_last_of(':')); try { boost::lexical_cast(serverport); } catch (boost::bad_lexical_cast) { ELOG(1, "Could not interpret " << serverport << " as server:port."); return 255; } LOG(1, "INFO: Using " << server << ":" << serverport << " as server's address."); } else { ELOG(1, "Requiring server's address (host:port) to connect to."); return 255; } std::string hostname("localhost"); if (vm.count("hostname")) { hostname = vm["hostname"].as< std::string >(); LOG(1, "INFO: Using " << hostname << " as host's name."); } else { char name[1024]; if (gethostname(name, 1023) == 0) { hostname = name; LOG(1, "INFO: Using obtained hostname " << hostname << "."); } else { ELOG(1, "No hostname given and failed to determine automatically."); return 255; } } std::string listenport; if (vm.count("listen")) { try { listenport = vm["listen"].as< std::string >(); } catch (boost::bad_lexical_cast) { ELOG(1, "Could not read " << vm["listen"].as< std::string >() << " as digits."); return 255; } LOG(1, "INFO: Using port " << listenport << " to listen to server connects."); } else { ELOG(1, "Requiring port to listen on ."); return 255; } size_t exitflag = 0; try { boost::asio::io_service io_service; PoolWorker client(io_service, server, serverport, hostname, listenport); // catch ctrl-c and shutdown worker properly shutdownfunction = boost::bind(&PoolWorker::shutdown, boost::ref(client), _1); if (vm.count("signal")) { signals = vm["signal"].as< std::vector >(); for (std::vector::const_iterator iter = signals.begin(); iter != signals.end(); ++iter) { LOG(0, "STATUS: Catching signal " << *iter << " via signal handler."); signal(*iter, &signalhandler); } } else { LOG(0, "STATUS: No signals are caught."); } // process io requests { Info info("io_service"); io_service.run(); } exitflag = client.getFlag(); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return exitflag; }