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