1 | /*
|
---|
2 | * Project: MoleCuilder
|
---|
3 | * Description: creates and alters molecular systems
|
---|
4 | * Copyright (C) 2012 University of Bonn. All rights reserved.
|
---|
5 | * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
|
---|
6 | */
|
---|
7 |
|
---|
8 | /*
|
---|
9 | * \file poolworker.cpp
|
---|
10 | *
|
---|
11 | * This file strongly follows the Serialization example from the boost::asio
|
---|
12 | * library (see client.cpp)
|
---|
13 | *
|
---|
14 | * Created on: Feb 28, 2012
|
---|
15 | * Author: heber
|
---|
16 | */
|
---|
17 |
|
---|
18 |
|
---|
19 | // include config.h
|
---|
20 | #ifdef HAVE_CONFIG_H
|
---|
21 | #include <config.h>
|
---|
22 | #endif
|
---|
23 |
|
---|
24 | // boost asio needs specific operator new
|
---|
25 | #include <boost/asio.hpp>
|
---|
26 |
|
---|
27 | #include "CodePatterns/MemDebug.hpp"
|
---|
28 |
|
---|
29 | #include <iostream>
|
---|
30 | #include <boost/program_options.hpp>
|
---|
31 | #include <boost/lexical_cast.hpp>
|
---|
32 | #include <signal.h>
|
---|
33 | #include <unistd.h>
|
---|
34 | #include <vector>
|
---|
35 |
|
---|
36 | #include "Fragmentation/Automation/atexit.hpp"
|
---|
37 | #include "CodePatterns/Info.hpp"
|
---|
38 | #include "CodePatterns/Log.hpp"
|
---|
39 | #include "Fragmentation/Automation/Pool/PoolWorker.hpp"
|
---|
40 |
|
---|
41 | //!> global shutdown function
|
---|
42 | boost::function<void (int)> shutdownfunction;
|
---|
43 | //!> global signal vector for later releasing
|
---|
44 | std::vector<size_t> signals;
|
---|
45 | //!> counter for the number of received signals
|
---|
46 | size_t NoSignalsReceived = 0;
|
---|
47 | //!> maximum number of received signals after which the handlers are released
|
---|
48 | const size_t MAX_NOSIGNALSRECEIVED = 3;
|
---|
49 |
|
---|
50 | void signalhandler(int sig)
|
---|
51 | {
|
---|
52 | // increment received signal counter
|
---|
53 | ++NoSignalsReceived;
|
---|
54 |
|
---|
55 | // shutdown if we have handler
|
---|
56 | if (shutdownfunction)
|
---|
57 | shutdownfunction(sig);
|
---|
58 |
|
---|
59 | if (NoSignalsReceived >= MAX_NOSIGNALSRECEIVED) {
|
---|
60 | // release signal hook again
|
---|
61 | for (std::vector<size_t>::const_iterator iter = signals.begin();
|
---|
62 | iter != signals.end(); ++iter)
|
---|
63 | signal(*iter, NULL);
|
---|
64 | }
|
---|
65 | }
|
---|
66 |
|
---|
67 | int main(int argc, char* argv[])
|
---|
68 | {
|
---|
69 | // from this moment on, we need to be sure to deeinitialize in the correct order
|
---|
70 | // this is handled by the cleanup function
|
---|
71 | atexit(cleanUp);
|
---|
72 |
|
---|
73 | // Declare the supported options.
|
---|
74 | boost::program_options::options_description desc("Allowed options");
|
---|
75 | desc.add_options()
|
---|
76 | ("help,h", "produce help message")
|
---|
77 | ("verbosity,v", boost::program_options::value<size_t>(), "set verbosity level")
|
---|
78 | ("signal", boost::program_options::value< std::vector<size_t> >(), "set signal to catch (can be given multiple times)")
|
---|
79 | ("server", boost::program_options::value< std::string>(), "connect to server at this address (host:port)")
|
---|
80 | ("listen", boost::program_options::value< std::string >(), "listen on this port")
|
---|
81 | ("hostname", boost::program_options::value< std::string>(), "name of host on which this codes runs and which server can resolve")
|
---|
82 | ;
|
---|
83 |
|
---|
84 | boost::program_options::variables_map vm;
|
---|
85 | boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
|
---|
86 | boost::program_options::notify(vm);
|
---|
87 |
|
---|
88 | if (vm.count("help")) {
|
---|
89 | std::cout << desc << "\n";
|
---|
90 | return 1;
|
---|
91 | }
|
---|
92 |
|
---|
93 | if (vm.count("verbosity")) {
|
---|
94 | LOG(0, "STATUS: Verbosity level was set to " << vm["verbosity"].as<size_t>() << ".");
|
---|
95 | setVerbosity(vm["verbosity"].as<size_t>());
|
---|
96 | } else {
|
---|
97 | LOG(0, "STATUS: Verbosity level was not set, defaulting to 5.");
|
---|
98 | setVerbosity(5);
|
---|
99 | }
|
---|
100 |
|
---|
101 | std::string server;
|
---|
102 | std::string serverport;
|
---|
103 | if (vm.count("server")) {
|
---|
104 | server = vm["server"].as< std::string >();
|
---|
105 | serverport = server.substr(server.find_last_of(':')+1, std::string::npos);
|
---|
106 | server = server.substr(0, server.find_last_of(':'));
|
---|
107 | try {
|
---|
108 | boost::lexical_cast<size_t>(serverport);
|
---|
109 | } catch (boost::bad_lexical_cast) {
|
---|
110 | ELOG(1, "Could not interpret " << serverport << " as server:port.");
|
---|
111 | return 255;
|
---|
112 | }
|
---|
113 | LOG(1, "INFO: Using " << server << ":" << serverport << " as server's address.");
|
---|
114 | } else {
|
---|
115 | ELOG(1, "Requiring server's address (host:port) to connect to.");
|
---|
116 | return 255;
|
---|
117 | }
|
---|
118 |
|
---|
119 | std::string hostname("localhost");
|
---|
120 | if (vm.count("hostname")) {
|
---|
121 | hostname = vm["hostname"].as< std::string >();
|
---|
122 | LOG(1, "INFO: Using " << hostname << " as host's name.");
|
---|
123 | } else {
|
---|
124 | char name[1024];
|
---|
125 | if (gethostname(name, 1023) == 0) {
|
---|
126 | hostname = name;
|
---|
127 | LOG(1, "INFO: Using obtained hostname " << hostname << ".");
|
---|
128 | } else {
|
---|
129 | ELOG(1, "No hostname given and failed to determine automatically.");
|
---|
130 | return 255;
|
---|
131 | }
|
---|
132 | }
|
---|
133 |
|
---|
134 | std::string listenport;
|
---|
135 | if (vm.count("listen")) {
|
---|
136 | try {
|
---|
137 | listenport = vm["listen"].as< std::string >();
|
---|
138 | } catch (boost::bad_lexical_cast) {
|
---|
139 | ELOG(1, "Could not read " << vm["listen"].as< std::string >() << " as digits.");
|
---|
140 | return 255;
|
---|
141 | }
|
---|
142 | LOG(1, "INFO: Using port " << listenport << " to listen to server connects.");
|
---|
143 | } else {
|
---|
144 | ELOG(1, "Requiring port to listen on .");
|
---|
145 | return 255;
|
---|
146 | }
|
---|
147 |
|
---|
148 | size_t exitflag = 0;
|
---|
149 | try
|
---|
150 | {
|
---|
151 | boost::asio::io_service io_service;
|
---|
152 | PoolWorker client(io_service, server, serverport, hostname, listenport);
|
---|
153 |
|
---|
154 | // catch ctrl-c and shutdown worker properly
|
---|
155 | shutdownfunction = boost::bind(&PoolWorker::shutdown, boost::ref(client), _1);
|
---|
156 | if (vm.count("signal")) {
|
---|
157 | signals = vm["signal"].as< std::vector<size_t> >();
|
---|
158 | for (std::vector<size_t>::const_iterator iter = signals.begin();
|
---|
159 | iter != signals.end(); ++iter) {
|
---|
160 | LOG(0, "STATUS: Catching signal " << *iter << " via signal handler.");
|
---|
161 | signal(*iter, &signalhandler);
|
---|
162 | }
|
---|
163 | } else {
|
---|
164 | LOG(0, "STATUS: No signals are caught.");
|
---|
165 | }
|
---|
166 |
|
---|
167 | // process io requests
|
---|
168 | {
|
---|
169 | Info info("io_service");
|
---|
170 | io_service.run();
|
---|
171 | }
|
---|
172 | exitflag = client.getFlag();
|
---|
173 | }
|
---|
174 | catch (std::exception& e)
|
---|
175 | {
|
---|
176 | std::cerr << e.what() << std::endl;
|
---|
177 | }
|
---|
178 |
|
---|
179 |
|
---|
180 | return exitflag;
|
---|
181 | }
|
---|