Generated on Wed Jul 21 2021 00:00:00 for Gecode by doxygen 1.9.1
connector.hpp
Go to the documentation of this file.
1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /*
3  * Main authors:
4  * Maxim Shishmarev <maxim.shishmarev@monash.edu>
5  *
6  * Contributing authors:
7  * Kevin Leo <kevin.leo@monash.edu>
8  * Christian Schulte <schulte@gecode.org>
9  *
10  * Copyright:
11  * Kevin Leo, 2017
12  * Christian Schulte, 2017
13  * Maxim Shishmarev, 2017
14  *
15  * This file is part of Gecode, the generic constraint
16  * development environment:
17  * http://www.gecode.org
18  *
19  * Permission is hereby granted, free of charge, to any person obtaining
20  * a copy of this software and associated documentation files (the
21  * "Software"), to deal in the Software without restriction, including
22  * without limitation the rights to use, copy, modify, merge, publish,
23  * distribute, sublicense, and/or sell copies of the Software, and to
24  * permit persons to whom the Software is furnished to do so, subject to
25  * the following conditions:
26  *
27  * The above copyright notice and this permission notice shall be
28  * included in all copies or substantial portions of the Software.
29  *
30  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37  *
38  */
39 
40 #include <iostream>
41 #include <sstream>
42 #include <vector>
43 #include <cstring>
44 
45 #ifdef WIN32
46 
47 #include <winsock2.h>
48 #include <ws2tcpip.h>
49 #pragma comment(lib, "Ws2_32.lib")
50 #pragma comment(lib, "Mswsock.lib")
51 #pragma comment(lib, "AdvApi32.lib")
52 
53 #include <basetsd.h>
54 typedef SSIZE_T ssize_t;
55 
56 #else
57 
58 #include <netdb.h>
59 #include <unistd.h>
60 
61 #endif
62 
63 namespace Gecode { namespace CPProfiler {
64 
65  class Node {
66  NodeUID node_;
67  NodeUID parent_;
68  int alt_;
69  int kids_;
70 
71  NodeStatus status_;
72 
73  Option<std::string> label_;
74  Option<std::string> nogood_;
75  Option<std::string> info_;
76 
77  public:
78  Node(NodeUID node, NodeUID parent,
79  int alt, int kids, NodeStatus status);
80  Node& set_node_thread_id(int tid);
81  const Option<std::string>& label() const;
82  Node& set_label(const std::string& label);
83  const Option<std::string>& nogood() const;
84  Node& set_nogood(const std::string& nogood);
85  const Option<std::string>& info() const;
86  Node& set_info(const std::string& info);
87  int alt() const;
88  int kids() const;
89  NodeStatus status() const;
90  NodeUID nodeUID() const;
91  NodeUID parentUID() const;
92  int node_id() const;
93  int parent_id() const;
94  int node_thread_id() const;
95  int node_restart_id() const;
96  int parent_thread_id() const;
97  int parent_restart_id() const;
98  };
99 
100  class Connector {
101  private:
102  MessageMarshalling marshalling;
103 
104  const unsigned int port;
105 
106  int sockfd;
107  bool _connected;
108 
109  static int sendall(int s, const char* buf, int* len);
110  void sendOverSocket(void);
111  void sendRawMsg(const std::vector<char>& buf);
112  public:
113  Connector(unsigned int port);
114 
115  bool connected() const;
116 
119  void connect(void);
120 
121  // sends START_SENDING message to the Profiler with a model name
122  void start(const std::string& file_path = "",
123  int execution_id = -1, bool has_restarts = false);
124  void restart(int restart_id = -1);
125  void done();
126 
128  void disconnect(void);
129 
130  void sendNode(const Node& node);
131  Node createNode(NodeUID node, NodeUID parent,
132  int alt, int kids, NodeStatus status);
133  };
134 
135 
136  /*
137  * Nodes
138  */
139  inline
140  Node::Node(NodeUID node, NodeUID parent,
141  int alt, int kids, NodeStatus status)
142  : node_{node}, parent_{parent},
143  alt_(alt), kids_(kids), status_(status) {}
144 
145  inline Node&
147  node_.tid = tid;
148  return *this;
149  }
150 
151  inline const Option<std::string>&
152  Node::label() const { return label_; }
153 
154  inline Node&
155  Node::set_label(const std::string& label) {
156  label_.set(label);
157  return *this;
158  }
159 
160  inline const Option<std::string>&
161  Node::nogood() const {
162  return nogood_;
163  }
164 
165  inline Node&
166  Node::set_nogood(const std::string& nogood) {
167  nogood_.set(nogood);
168  return *this;
169  }
170 
171  inline const Option<std::string>&
172  Node::info() const { return info_; }
173 
174  inline Node&
175  Node::set_info(const std::string& info) {
176  info_.set(info);
177  return *this;
178  }
179 
180  inline int
181  Node::alt() const { return alt_; }
182  inline int
183  Node::kids() const { return kids_; }
184 
185  inline NodeStatus
186  Node::status() const { return status_; }
187 
188  inline NodeUID
189  Node::nodeUID() const { return node_; }
190  inline NodeUID
191  Node::parentUID() const { return parent_; }
192 
193  inline int
194  Node::node_id() const { return node_.nid; }
195  inline int
196  Node::parent_id() const { return parent_.nid; }
197  inline int
198  Node::node_thread_id() const { return node_.tid; }
199  inline int
200  Node::node_restart_id() const { return node_.rid; }
201  inline int
202  Node::parent_thread_id() const { return parent_.tid; }
203  inline int
204  Node::parent_restart_id() const { return parent_.rid; }
205 
206 
207  /*
208  * Connector
209  */
210  inline
211  Connector::Connector(unsigned int port) : port(port), _connected(false) {}
212 
213  inline bool Connector::connected() const { return _connected; }
214 
215 
216  /*
217  * The following code is taken from:
218  * Beej's Guide to Network Programming
219  * http://beej.us/guide/bgnet/
220  * with the folloiwng license:
221  *
222  * Beej's Guide to Network Programming is Copyright © 2015 Brian "Beej Jorgensen" Hall.
223  * With specific exceptions for source code and translations, below, this work is licensed under the Creative Commons Attribution- Noncommercial- No Derivative Works 3.0 License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
224  * One specific exception to the "No Derivative Works" portion of the license is as follows: this guide may be freely translated into any language, provided the translation is accurate, and the guide is reprinted in its entirety. The same license restrictions apply to the translation as to the original guide. The translation may also include the name and contact information for the translator.
225  * The C source code presented in this document is hereby granted to the public domain, and is completely free of any license restriction.
226  * Educators are freely encouraged to recommend or supply copies of this guide to their students.
227  * Contact beej@beej.us for more information.
228  */
229  inline int
230  Connector::sendall(int s, const char* buf, int* len) {
231  int total = 0; // how many bytes we've sent
232  int bytesleft = *len; // how many we have left to send
233  ssize_t n;
234 
235  while (total < *len) {
236  n = send(s, buf + total, static_cast<size_t>(bytesleft), 0);
237  if (n == -1) {
238  break;
239  }
240  total += static_cast<int>(n);
241  bytesleft -= static_cast<int>(n);
242  }
243 
244  *len = static_cast<int>(total); // return number actually sent here
245 
246  return (n == -1) ? -1 : 0; // return -1 on failure, 0 on success
247  }
248 
249  inline void
250  Connector::sendRawMsg(const std::vector<char>& buf) {
251  uint32_t bufSize = static_cast<uint32_t>(buf.size());
252  int bufSizeLen = sizeof(uint32_t);
253  sendall(sockfd, reinterpret_cast<char*>(&bufSize), &bufSizeLen);
254  int bufSizeInt = static_cast<int>(bufSize);
255  sendall(sockfd, reinterpret_cast<const char*>(buf.data()), &bufSizeInt);
256  }
257 
258  inline void
259  Connector::sendOverSocket(void) {
260  if (!_connected) return;
261 
262  std::vector<char> buf = marshalling.serialize();
263 
264  sendRawMsg(buf);
265  }
266 
267  inline void
269  struct addrinfo hints, *servinfo, *p;
270  int rv;
271 
272 #ifdef WIN32
273  // Initialise Winsock.
274  WSADATA wsaData;
275  int startupResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
276  if (startupResult != 0) {
277  printf("WSAStartup failed with error: %d\n", startupResult);
278  }
279 #endif
280 
281  memset(&hints, 0, sizeof hints);
282  hints.ai_family = AF_UNSPEC;
283  hints.ai_socktype = SOCK_STREAM;
284 
285  if ((rv = getaddrinfo("localhost", std::to_string(port).c_str(), &hints,
286  &servinfo)) != 0) {
287  std::cerr << "getaddrinfo: " << gai_strerror(rv) << "\n";
288  goto giveup;
289  }
290 
291  // loop through all the results and connect to the first we can
292  for (p = servinfo; p != NULL; p = p->ai_next) {
293  if ((sockfd = static_cast<int>(socket(p->ai_family, p->ai_socktype, p->ai_protocol))) == -1) {
294  // errno is set here, but we don't examine it.
295  continue;
296  }
297 
298  if (::connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
299 #ifdef WIN32
300  closesocket(sockfd);
301 #else
302  close(sockfd);
303 #endif
304  // errno is set here, but we don't examine it.
305  continue;
306  }
307 
308  break;
309  }
310 
311  // Connection failed; give up.
312  if (p == NULL) {
313  goto giveup;
314  }
315 
316  freeaddrinfo(servinfo); // all done with this structure
317 
318  _connected = true;
319 
320  return;
321  giveup:
322  _connected = false;
323  return;
324 
325  }
326 
327  inline void
328  Connector::start(const std::string& file_path,
329  int execution_id, bool has_restarts) {
331  std::string base_name(file_path);
332  {
333  size_t pos = base_name.find_last_of('/');
334  if (pos != static_cast<size_t>(-1)) {
335  base_name = base_name.substr(pos + 1, base_name.length() - pos - 1);
336  }
337  }
338 
339  std::string info{""};
340  {
341  std::stringstream ss;
342  ss << "{";
343  ss << "\"has_restarts\": " << (has_restarts ? "true" : "false") << "\n";
344  ss << ",\"name\": " << "\"" << base_name << "\"" << "\n";
345  if (execution_id != -1) {
346  ss << ",\"execution_id\": " << execution_id;
347  }
348  ss << "}";
349  info = ss.str();
350  }
351 
352  marshalling.makeStart(info);
353  sendOverSocket();
354  }
355 
356  inline void
357  Connector::restart(int restart_id) {
358 
359  std::string info{""};
360  {
361  std::stringstream ss;
362  ss << "{";
363  ss << "\"restart_id\": " << restart_id << "\n";
364  ss << "}";
365  info = ss.str();
366  }
367 
368  marshalling.makeRestart(info);
369  sendOverSocket();
370  }
371 
372  inline void
374  marshalling.makeDone();
375  sendOverSocket();
376  }
377 
378  inline void
380 #ifdef WIN32
381  closesocket(sockfd);
382 #else
383  close(sockfd);
384 #endif
385  }
386 
387  inline void
388  Connector::sendNode(const Node& node) {
389  if (!_connected) return;
390 
391  auto& msg = marshalling.makeNode(node.nodeUID(), node.parentUID(),
392  node.alt(), node.kids(), node.status());
393 
394  if (node.label().valid()) msg.set_label(node.label().value());
395  if (node.nogood().valid()) msg.set_nogood(node.nogood().value());
396  if (node.info().valid()) msg.set_info(node.info().value());
397 
398  sendOverSocket();
399  }
400 
401  inline Node
403  int alt, int kids, NodeStatus status) {
404  return Node(node, parent, alt, kids, status);
405  }
406 
407 }}
408 
409 // STATISTICS: search-trace
int p
Number of positive literals for node type.
Definition: bool-expr.cpp:232
int n
Number of negative literals for node type.
Definition: bool-expr.cpp:234
Node createNode(NodeUID node, NodeUID parent, int alt, int kids, NodeStatus status)
Definition: connector.hpp:402
void sendNode(const Node &node)
Definition: connector.hpp:388
void start(const std::string &file_path="", int execution_id=-1, bool has_restarts=false)
Definition: connector.hpp:328
void disconnect(void)
disconnect from a socket
Definition: connector.hpp:379
Connector(unsigned int port)
Definition: connector.hpp:211
void connect(void)
connect to a socket via port specified in the construction (6565 by default)
Definition: connector.hpp:268
void restart(int restart_id=-1)
Definition: connector.hpp:357
Message & makeNode(NodeUID node, NodeUID parent, int32_t alt, int32_t kids, NodeStatus status)
Definition: message.hpp:291
void makeStart(const std::string &info)
Definition: message.hpp:306
void makeRestart(const std::string &info)
Definition: message.hpp:313
void set_label(const std::string &label)
Definition: message.hpp:167
Node & set_nogood(const std::string &nogood)
Definition: connector.hpp:166
NodeUID nodeUID() const
Definition: connector.hpp:189
const Option< std::string > & nogood() const
Definition: connector.hpp:161
Node(NodeUID node, NodeUID parent, int alt, int kids, NodeStatus status)
Definition: connector.hpp:140
int parent_restart_id() const
Definition: connector.hpp:204
Node & set_info(const std::string &info)
Definition: connector.hpp:175
int parent_thread_id() const
Definition: connector.hpp:202
const Option< std::string > & info() const
Definition: connector.hpp:172
const Option< std::string > & label() const
Definition: connector.hpp:152
NodeUID parentUID() const
Definition: connector.hpp:191
NodeStatus status() const
Definition: connector.hpp:186
Node & set_node_thread_id(int tid)
Definition: connector.hpp:146
int node_thread_id() const
Definition: connector.hpp:198
int node_restart_id() const
Definition: connector.hpp:200
Node & set_label(const std::string &label)
Definition: connector.hpp:155
bool valid(void) const
Check whether value is present.
Definition: message.hpp:89
void set(const T &t)
Set value to t.
Definition: message.hpp:94
const T & value(void) const
Access value.
Definition: message.hpp:104
NodeStatus
Types of nodes for CP Profiler.
Definition: message.hpp:51
bool pos(const View &x)
Test whether x is postive.
Definition: mult.hpp:41
Unique identifier for a node.
Definition: message.hpp:114
int32_t nid
Node number.
Definition: message.hpp:116
int32_t rid
Restart id.
Definition: message.hpp:118
int32_t tid
Thread id.
Definition: message.hpp:120