00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <iostream>
00041 #include <sstream>
00042 #include <vector>
00043 #include <cstring>
00044
00045 #ifdef WIN32
00046
00047 #include <winsock2.h>
00048 #include <ws2tcpip.h>
00049 #pragma comment(lib, "Ws2_32.lib")
00050 #pragma comment(lib, "Mswsock.lib")
00051 #pragma comment(lib, "AdvApi32.lib")
00052
00053 #include <basetsd.h>
00054 typedef SSIZE_T ssize_t;
00055
00056 #else
00057
00058 #include <netdb.h>
00059 #include <unistd.h>
00060
00061 #endif
00062
00063 namespace Gecode { namespace CPProfiler {
00064
00065 class Node {
00066 NodeUID node_;
00067 NodeUID parent_;
00068 int alt_;
00069 int kids_;
00070
00071 NodeStatus status_;
00072
00073 Option<std::string> label_;
00074 Option<std::string> nogood_;
00075 Option<std::string> info_;
00076
00077 public:
00078 Node(NodeUID node, NodeUID parent,
00079 int alt, int kids, NodeStatus status);
00080 Node& set_node_thread_id(int tid);
00081 const Option<std::string>& label() const;
00082 Node& set_label(const std::string& label);
00083 const Option<std::string>& nogood() const;
00084 Node& set_nogood(const std::string& nogood);
00085 const Option<std::string>& info() const;
00086 Node& set_info(const std::string& info);
00087 int alt() const;
00088 int kids() const;
00089 NodeStatus status() const;
00090 NodeUID nodeUID() const;
00091 NodeUID parentUID() const;
00092 int node_id() const;
00093 int parent_id() const;
00094 int node_thread_id() const;
00095 int node_restart_id() const;
00096 int parent_thread_id() const;
00097 int parent_restart_id() const;
00098 };
00099
00100 class Connector {
00101 private:
00102 MessageMarshalling marshalling;
00103
00104 const unsigned int port;
00105
00106 int sockfd;
00107 bool _connected;
00108
00109 static int sendall(int s, const char* buf, int* len);
00110 void sendOverSocket(void);
00111 void sendRawMsg(const std::vector<char>& buf);
00112 public:
00113 Connector(unsigned int port);
00114
00115 bool connected() const;
00116
00119 void connect(void);
00120
00121
00122 void start(const std::string& file_path = "",
00123 int execution_id = -1, bool has_restarts = false);
00124 void restart(int restart_id = -1);
00125 void done();
00126
00128 void disconnect(void);
00129
00130 void sendNode(const Node& node);
00131 Node createNode(NodeUID node, NodeUID parent,
00132 int alt, int kids, NodeStatus status);
00133 };
00134
00135
00136
00137
00138
00139 inline
00140 Node::Node(NodeUID node, NodeUID parent,
00141 int alt, int kids, NodeStatus status)
00142 : node_{node}, parent_{parent},
00143 alt_(alt), kids_(kids), status_(status) {}
00144
00145 inline Node&
00146 Node::set_node_thread_id(int tid) {
00147 node_.tid = tid;
00148 return *this;
00149 }
00150
00151 inline const Option<std::string>&
00152 Node::label() const { return label_; }
00153
00154 inline Node&
00155 Node::set_label(const std::string& label) {
00156 label_.set(label);
00157 return *this;
00158 }
00159
00160 inline const Option<std::string>&
00161 Node::nogood() const {
00162 return nogood_;
00163 }
00164
00165 inline Node&
00166 Node::set_nogood(const std::string& nogood) {
00167 nogood_.set(nogood);
00168 return *this;
00169 }
00170
00171 inline const Option<std::string>&
00172 Node::info() const { return info_; }
00173
00174 inline Node&
00175 Node::set_info(const std::string& info) {
00176 info_.set(info);
00177 return *this;
00178 }
00179
00180 inline int
00181 Node::alt() const { return alt_; }
00182 inline int
00183 Node::kids() const { return kids_; }
00184
00185 inline NodeStatus
00186 Node::status() const { return status_; }
00187
00188 inline NodeUID
00189 Node::nodeUID() const { return node_; }
00190 inline NodeUID
00191 Node::parentUID() const { return parent_; }
00192
00193 inline int
00194 Node::node_id() const { return node_.nid; }
00195 inline int
00196 Node::parent_id() const { return parent_.nid; }
00197 inline int
00198 Node::node_thread_id() const { return node_.tid; }
00199 inline int
00200 Node::node_restart_id() const { return node_.rid; }
00201 inline int
00202 Node::parent_thread_id() const { return parent_.tid; }
00203 inline int
00204 Node::parent_restart_id() const { return parent_.rid; }
00205
00206
00207
00208
00209
00210 inline
00211 Connector::Connector(unsigned int port) : port(port), _connected(false) {}
00212
00213 inline bool Connector::connected() const { return _connected; }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 inline int
00230 Connector::sendall(int s, const char* buf, int* len) {
00231 int total = 0;
00232 int bytesleft = *len;
00233 ssize_t n;
00234
00235 while (total < *len) {
00236 n = send(s, buf + total, static_cast<size_t>(bytesleft), 0);
00237 if (n == -1) {
00238 break;
00239 }
00240 total += static_cast<int>(n);
00241 bytesleft -= static_cast<int>(n);
00242 }
00243
00244 *len = static_cast<int>(total);
00245
00246 return (n == -1) ? -1 : 0;
00247 }
00248
00249 inline void
00250 Connector::sendRawMsg(const std::vector<char>& buf) {
00251 uint32_t bufSize = static_cast<uint32_t>(buf.size());
00252 int bufSizeLen = sizeof(uint32_t);
00253 sendall(sockfd, reinterpret_cast<char*>(&bufSize), &bufSizeLen);
00254 int bufSizeInt = static_cast<int>(bufSize);
00255 sendall(sockfd, reinterpret_cast<const char*>(buf.data()), &bufSizeInt);
00256 }
00257
00258 inline void
00259 Connector::sendOverSocket(void) {
00260 if (!_connected) return;
00261
00262 std::vector<char> buf = marshalling.serialize();
00263
00264 sendRawMsg(buf);
00265 }
00266
00267 inline void
00268 Connector::connect(void) {
00269 struct addrinfo hints, *servinfo, *p;
00270 int rv;
00271
00272 #ifdef WIN32
00273
00274 WSADATA wsaData;
00275 int startupResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
00276 if (startupResult != 0) {
00277 printf("WSAStartup failed with error: %d\n", startupResult);
00278 }
00279 #endif
00280
00281 memset(&hints, 0, sizeof hints);
00282 hints.ai_family = AF_UNSPEC;
00283 hints.ai_socktype = SOCK_STREAM;
00284
00285 if ((rv = getaddrinfo("localhost", std::to_string(port).c_str(), &hints,
00286 &servinfo)) != 0) {
00287 std::cerr << "getaddrinfo: " << gai_strerror(rv) << "\n";
00288 goto giveup;
00289 }
00290
00291
00292 for (p = servinfo; p != NULL; p = p->ai_next) {
00293 if ((sockfd = static_cast<int>(socket(p->ai_family, p->ai_socktype, p->ai_protocol))) == -1) {
00294
00295 continue;
00296 }
00297
00298 if (::connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
00299 #ifdef WIN32
00300 closesocket(sockfd);
00301 #else
00302 close(sockfd);
00303 #endif
00304
00305 continue;
00306 }
00307
00308 break;
00309 }
00310
00311
00312 if (p == NULL) {
00313 goto giveup;
00314 }
00315
00316 freeaddrinfo(servinfo);
00317
00318 _connected = true;
00319
00320 return;
00321 giveup:
00322 _connected = false;
00323 return;
00324
00325 }
00326
00327 inline void
00328 Connector::start(const std::string& file_path,
00329 int execution_id, bool has_restarts) {
00331 std::string base_name(file_path);
00332 {
00333 size_t pos = base_name.find_last_of('/');
00334 if (pos != static_cast<size_t>(-1)) {
00335 base_name = base_name.substr(pos + 1, base_name.length() - pos - 1);
00336 }
00337 }
00338
00339 std::string info{""};
00340 {
00341 std::stringstream ss;
00342 ss << "{";
00343 ss << "\"has_restarts\": " << (has_restarts ? "true" : "false") << "\n";
00344 ss << ",\"name\": " << "\"" << base_name << "\"" << "\n";
00345 if (execution_id != -1) {
00346 ss << ",\"execution_id\": " << execution_id;
00347 }
00348 ss << "}";
00349 info = ss.str();
00350 }
00351
00352 marshalling.makeStart(info);
00353 sendOverSocket();
00354 }
00355
00356 inline void
00357 Connector::restart(int restart_id) {
00358
00359 std::string info{""};
00360 {
00361 std::stringstream ss;
00362 ss << "{";
00363 ss << "\"restart_id\": " << restart_id << "\n";
00364 ss << "}";
00365 info = ss.str();
00366 }
00367
00368 marshalling.makeRestart(info);
00369 sendOverSocket();
00370 }
00371
00372 inline void
00373 Connector::done() {
00374 marshalling.makeDone();
00375 sendOverSocket();
00376 }
00377
00378 inline void
00379 Connector::disconnect() {
00380 #ifdef WIN32
00381 closesocket(sockfd);
00382 #else
00383 close(sockfd);
00384 #endif
00385 }
00386
00387 inline void
00388 Connector::sendNode(const Node& node) {
00389 if (!_connected) return;
00390
00391 auto& msg = marshalling.makeNode(node.nodeUID(), node.parentUID(),
00392 node.alt(), node.kids(), node.status());
00393
00394 if (node.label().valid()) msg.set_label(node.label().value());
00395 if (node.nogood().valid()) msg.set_nogood(node.nogood().value());
00396 if (node.info().valid()) msg.set_info(node.info().value());
00397
00398 sendOverSocket();
00399 }
00400
00401 inline Node
00402 Connector::createNode(NodeUID node, NodeUID parent,
00403 int alt, int kids, NodeStatus status) {
00404 return Node(node, parent, alt, kids, status);
00405 }
00406
00407 }}
00408
00409