this repo has no description
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 * Guido Tack <tack@gecode.org> 8 * Kevin Leo <kevin.leo@monash.edu> 9 * 10 * Copyright: 11 * Maxim Shishmarev, 2017 12 * Guido Tack, 2017 13 * Kevin Leo, 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 <vector> 41#include <string> 42#include <cassert> 43#include <cstdint> 44 45namespace Gecode { namespace CPProfiler { 46 47 /// Version of CPProfiler protocol 48 static const int32_t PROFILER_PROTOCOL_VERSION = 3; 49 50 /// Types of nodes for CP Profiler 51 enum NodeStatus { 52 SOLVED = 0, ///< Node representing a solution 53 FAILED = 1, ///< Node representing failure 54 BRANCH = 2, ///< Node representing a branch 55 SKIPPED = 3 ///< Node skipped by backjumping 56 }; 57 58 /// Types of messages for CP Profiler 59 enum class MsgType { 60 NODE = 0, 61 DONE = 1, 62 START = 2, 63 RESTART = 3 64 }; 65 66 /// Optional value class 67 template <class T> 68 class Option { 69 protected: 70 /// A value, potentially not initialized 71 T value_; 72 /// Whether value is present 73 bool present{false}; 74 public: 75 /// Check whether value is present 76 bool valid(void) const; 77 /// Set value to \a t 78 void set(const T& t); 79 /// Disregard value 80 void unset(void); 81 /// Access value 82 const T& value(void) const; 83 /// Access value 84 T& value(void); 85 }; 86 87 template <class T> 88 forceinline bool 89 Option<T>::valid(void) const { 90 return present; 91 } 92 template <class T> 93 forceinline void 94 Option<T>::set(const T& t) { 95 present = true; value_ = t; 96 } 97 template <class T> 98 forceinline void 99 Option<T>::unset(void) { 100 present = false; 101 } 102 template <class T> 103 forceinline const T& 104 Option<T>::value(void) const { 105 assert(present); return value_; 106 } 107 template <class T> 108 forceinline T& 109 Option<T>::value(void) { 110 assert(present); return value_; 111 } 112 113 /// Unique identifier for a node 114 struct NodeUID { 115 /// Node number 116 int32_t nid; 117 /// Restart id 118 int32_t rid; 119 /// Thread id 120 int32_t tid; 121 }; 122 123 /// Message for the CP Profiler 124 class Message { 125 protected: 126 MsgType _type; 127 128 NodeUID _node; 129 NodeUID _parent; 130 int32_t _alt; 131 int32_t _kids; 132 NodeStatus _status; 133 134 bool _have_label{false}; 135 std::string _label; 136 137 bool _have_nogood{false}; 138 std::string _nogood; 139 140 bool _have_info{false}; 141 std::string _info; 142 143 bool _have_version{false}; 144 int32_t _version; // PROFILER_PROTOCOL_VERSION; 145 146 public: 147 bool isNode(void) const { return _type == MsgType::NODE; } 148 bool isDone(void) const { return _type == MsgType::DONE; } 149 bool isStart(void) const { return _type == MsgType::START; } 150 bool isRestart(void) const { return _type == MsgType::RESTART; } 151 152 NodeUID nodeUID(void) const { return _node; } 153 void set_nodeUID(const NodeUID& n) { _node = n; } 154 155 NodeUID parentUID(void) const { return _parent; } 156 void set_parentUID(const NodeUID& p) { _parent = p; } 157 158 int32_t alt(void) const { return _alt; } 159 void set_alt(int32_t alt) { _alt = alt; } 160 161 int32_t kids(void) const { return _kids; } 162 void set_kids(int32_t kids) { _kids = kids; } 163 164 NodeStatus status(void) const { return _status; } 165 void set_status(NodeStatus status) { _status = status; } 166 167 void set_label(const std::string& label) { 168 _have_label = true; 169 _label = label; 170 } 171 172 void set_info(const std::string& info) { 173 _have_info = true; 174 _info = info; 175 } 176 177 void set_nogood(const std::string& nogood) { 178 _have_nogood = true; 179 _nogood = nogood; 180 } 181 182 void set_version(int32_t v) { 183 _have_version = true; 184 _version = v; 185 } 186 187 bool has_version(void) const { return _have_version; } 188 int32_t version(void) const { return _version; } 189 190 bool has_label(void) const { return _have_label; } 191 const std::string& label() const { return _label; } 192 193 bool has_nogood(void) const { return _have_nogood; } 194 const std::string& nogood(void) const { return _nogood; } 195 196 // generic optional fields 197 bool has_info(void) const { return _have_info; } 198 const std::string& info(void) const { return _info; } 199 200 void set_type(MsgType type) { _type = type; } 201 MsgType type(void) const { return _type; } 202 203 void reset(void) { 204 _have_label = false; 205 _have_nogood = false; 206 _have_info = false; 207 _have_version = false; 208 } 209 }; 210 211 212 class MessageMarshalling { 213 private: 214 /// Only optional fields are listed here, if node (no need for field id) 215 enum Field { 216 LABEL = 0, 217 NOGOOD = 1, 218 INFO = 2, 219 VERSION = 3 220 }; 221 222 Message msg; 223 224 typedef char* iter; 225 226 static void serializeType(std::vector<char>& data, MsgType f) { 227 data.push_back(static_cast<char>(f)); 228 } 229 230 static void serializeField(std::vector<char>& data, Field f) { 231 data.push_back(static_cast<char>(f)); 232 } 233 234 static void serialize(std::vector<char>& data, int32_t i) { 235 data.push_back(static_cast<char>((i & 0xFF000000) >> 24)); 236 data.push_back(static_cast<char>((i & 0xFF0000) >> 16)); 237 data.push_back(static_cast<char>((i & 0xFF00) >> 8)); 238 data.push_back(static_cast<char>((i & 0xFF))); 239 } 240 241 static void serialize(std::vector<char>& data, NodeStatus s) { 242 data.push_back(static_cast<char>(s)); 243 } 244 245 static void serialize(std::vector<char>& data, const std::string& s) { 246 serialize(data, static_cast<int32_t>(s.size())); 247 for (char c : s) { 248 data.push_back(c); 249 } 250 } 251 252 static MsgType deserializeMsgType(iter& it) { 253 auto m = static_cast<MsgType>(*it); 254 ++it; 255 return m; 256 } 257 258 static Field deserializeField(iter& it) { 259 auto f = static_cast<Field>(*it); 260 ++it; 261 return f; 262 } 263 264 static int32_t deserializeInt(iter& it) { 265 auto b1 = static_cast<uint32_t>(reinterpret_cast<uint8_t&>(*it++)); 266 auto b2 = static_cast<uint32_t>(reinterpret_cast<uint8_t&>(*it++)); 267 auto b3 = static_cast<uint32_t>(reinterpret_cast<uint8_t&>(*it++)); 268 auto b4 = static_cast<uint32_t>(reinterpret_cast<uint8_t&>(*it++)); 269 270 return static_cast<int32_t>(b1 << 24 | b2 << 16 | b3 << 8 | b4); 271 } 272 273 static NodeStatus deserializeStatus(iter& it) { 274 auto f = static_cast<NodeStatus>(*it); 275 ++it; 276 return f; 277 } 278 279 static std::string deserializeString(iter& it) { 280 std::string result; 281 int32_t size = deserializeInt(it); 282 result.reserve(static_cast<size_t>(size)); 283 for (int32_t i = 0; i < size; i++) { 284 result += *it; 285 ++it; 286 } 287 return result; 288 } 289 290 public: 291 Message& makeNode(NodeUID node, NodeUID parent, 292 int32_t alt, int32_t kids, NodeStatus status) { 293 msg.reset(); 294 msg.set_type(MsgType::NODE); 295 296 msg.set_nodeUID(node); 297 msg.set_parentUID(parent); 298 299 msg.set_alt(alt); 300 msg.set_kids(kids); 301 msg.set_status(status); 302 303 return msg; 304 } 305 306 void makeStart(const std::string& info) { 307 msg.reset(); 308 msg.set_type(MsgType::START); 309 msg.set_version(PROFILER_PROTOCOL_VERSION); 310 msg.set_info(info); /// info containts name, has_restarts, execution id 311 } 312 313 void makeRestart(const std::string& info) { 314 msg.reset(); 315 msg.set_type(MsgType::RESTART); 316 msg.set_info(info); /// info contains restart_id (-1 default) 317 } 318 319 void makeDone(void) { 320 msg.reset(); 321 msg.set_type(MsgType::DONE); 322 } 323 324 const Message& get_msg(void) { return msg; } 325 326 std::vector<char> serialize(void) const { 327 std::vector<char> data; 328 size_t dataSize = 1 + (msg.isNode() ? 4 * 8 + 1 : 0) + 329 (msg.has_label() ? 1 + 4 + msg.label().size() : 0) + 330 (msg.has_nogood() ? 1 + 4 + msg.nogood().size() : 0) + 331 (msg.has_info() ? 1 + 4 + msg.info().size() : 0); 332 data.reserve(dataSize); 333 334 serializeType(data, msg.type()); 335 if (msg.isNode()) { 336 // serialize NodeId node 337 auto n_uid = msg.nodeUID(); 338 serialize(data, n_uid.nid); 339 serialize(data, n_uid.rid); 340 serialize(data, n_uid.tid); 341 // serialize NodeId parent 342 auto p_uid = msg.parentUID(); 343 serialize(data, p_uid.nid); 344 serialize(data, p_uid.rid); 345 serialize(data, p_uid.tid); 346 // Other Data 347 serialize(data, msg.alt()); 348 serialize(data, msg.kids()); 349 serialize(data, msg.status()); 350 } 351 352 if(msg.has_version()) { 353 serializeField(data, VERSION); 354 serialize(data, msg.version()); 355 } 356 if (msg.has_label()) { 357 serializeField(data, LABEL); 358 serialize(data, msg.label()); 359 } 360 if (msg.has_nogood()) { 361 serializeField(data, NOGOOD); 362 serialize(data, msg.nogood()); 363 } 364 if (msg.has_info()) { 365 serializeField(data, INFO); 366 serialize(data, msg.info()); 367 } 368 return data; 369 } 370 371 void deserialize(char* data, size_t size) { 372 char *end = data + size; 373 msg.set_type(deserializeMsgType(data)); 374 if (msg.isNode()) { 375 int32_t nid = deserializeInt(data); 376 int32_t rid = deserializeInt(data); 377 int32_t tid = deserializeInt(data); 378 379 msg.set_nodeUID({nid, rid, tid}); 380 381 nid = deserializeInt(data); 382 rid = deserializeInt(data); 383 tid = deserializeInt(data); 384 385 msg.set_parentUID({nid, rid, tid}); 386 387 msg.set_alt(deserializeInt(data)); 388 msg.set_kids(deserializeInt(data)); 389 msg.set_status(deserializeStatus(data)); 390 } 391 392 msg.reset(); 393 394 while (data != end) { 395 MessageMarshalling::Field f = deserializeField(data); 396 switch (f) { 397 case VERSION: 398 msg.set_version(deserializeInt(data)); break; 399 case LABEL: 400 msg.set_label(deserializeString(data)); break; 401 case NOGOOD: 402 msg.set_nogood(deserializeString(data)); break; 403 case INFO: 404 msg.set_info(deserializeString(data)); break; 405 default: 406 break; 407 } 408 } 409 } 410 }; 411 412}} 413 414// STATISTICS: search-trace