Generated on Thu Apr 11 13:59:17 2019 for Gecode by doxygen 1.6.3

message.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Maxim Shishmarev <maxim.shishmarev@monash.edu>
00005  *
00006  *  Contributing authors:
00007  *     Guido Tack <tack@gecode.org>
00008  *     Kevin Leo <kevin.leo@monash.edu>
00009  *
00010  *  Copyright:
00011  *     Maxim Shishmarev, 2017
00012  *     Guido Tack, 2017
00013  *     Kevin Leo, 2017
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00037  *
00038  */
00039 
00040 #include <vector>
00041 #include <string>
00042 #include <cassert>
00043 #include <cstdint>
00044 
00045 namespace Gecode { namespace CPProfiler {
00046 
00048   static const int32_t PROFILER_PROTOCOL_VERSION = 3;
00049 
00051   enum NodeStatus {
00052     SOLVED  = 0, 
00053     FAILED  = 1, 
00054     BRANCH  = 2, 
00055     SKIPPED = 3  
00056   };
00057   
00059   enum class MsgType {
00060     NODE    = 0,
00061     DONE    = 1,
00062     START   = 2,
00063     RESTART = 3
00064   };
00065   
00067   template <class T>
00068   class Option {
00069   protected:
00071     T value_;
00073     bool present{false};
00074   public:
00076     bool valid(void) const;
00078     void set(const T& t);
00080     void unset(void);
00082     const T& value(void) const;
00084     T& value(void);
00085   };
00086 
00087   template <class T>
00088   forceinline bool
00089   Option<T>::valid(void) const {
00090     return present;
00091   }
00092   template <class T>
00093   forceinline void
00094   Option<T>::set(const T& t) {
00095     present = true; value_ = t;
00096   }
00097   template <class T>
00098   forceinline void
00099   Option<T>::unset(void) {
00100     present = false;
00101   }
00102   template <class T>
00103   forceinline const T&
00104   Option<T>::value(void) const {
00105     assert(present); return value_;
00106   }
00107   template <class T>
00108   forceinline T&
00109   Option<T>::value(void) {
00110     assert(present); return value_;
00111   }
00112   
00114   struct NodeUID {
00116     int32_t nid;
00118     int32_t rid;
00120     int32_t tid;
00121   };
00122   
00124   class Message {
00125   protected:
00126     MsgType _type;
00127     
00128     NodeUID _node;
00129     NodeUID _parent;
00130     int32_t _alt;
00131     int32_t _kids;
00132     NodeStatus _status;
00133     
00134     bool _have_label{false};
00135     std::string _label;
00136     
00137     bool _have_nogood{false};
00138     std::string _nogood;
00139     
00140     bool _have_info{false};
00141     std::string _info;
00142     
00143     bool _have_version{false};
00144     int32_t _version; // PROFILER_PROTOCOL_VERSION;
00145     
00146   public:
00147     bool isNode(void) const { return _type == MsgType::NODE; }
00148     bool isDone(void) const { return _type == MsgType::DONE; }
00149     bool isStart(void) const { return _type == MsgType::START; }
00150     bool isRestart(void) const { return _type == MsgType::RESTART; }
00151     
00152     NodeUID nodeUID(void) const { return _node; }
00153     void set_nodeUID(const NodeUID& n) { _node = n; }
00154     
00155     NodeUID parentUID(void) const { return _parent; }
00156     void set_parentUID(const NodeUID& p) { _parent = p; }
00157     
00158     int32_t alt(void) const { return _alt; }
00159     void set_alt(int32_t alt) { _alt = alt; }
00160     
00161     int32_t kids(void) const { return _kids; }
00162     void set_kids(int32_t kids) { _kids = kids; }
00163     
00164     NodeStatus status(void) const { return _status; }
00165     void set_status(NodeStatus status) { _status = status; }
00166     
00167     void set_label(const std::string& label) {
00168       _have_label = true;
00169       _label = label;
00170     }
00171     
00172     void set_info(const std::string& info) {
00173       _have_info = true;
00174       _info = info;
00175     }
00176     
00177     void set_nogood(const std::string& nogood) {
00178       _have_nogood = true;
00179       _nogood = nogood;
00180     }
00181     
00182     void set_version(int32_t v) {
00183       _have_version = true;
00184       _version = v;
00185     }
00186     
00187     bool has_version(void) const { return _have_version; }
00188     int32_t version(void) const { return _version; }
00189     
00190     bool has_label(void) const { return _have_label; }
00191     const std::string& label() const { return _label; }
00192     
00193     bool has_nogood(void) const { return _have_nogood; }
00194     const std::string& nogood(void) const { return _nogood; }
00195     
00196     // generic optional fields
00197     bool has_info(void) const { return _have_info; }
00198     const std::string& info(void) const { return _info; }
00199 
00200     void set_type(MsgType type) { _type = type; }
00201     MsgType type(void) const { return _type; }
00202     
00203     void reset(void) {
00204       _have_label = false;
00205       _have_nogood = false;
00206       _have_info = false;
00207       _have_version = false;
00208     }
00209   };
00210 
00211 
00212   class MessageMarshalling {
00213   private:
00215     enum Field {
00216       LABEL = 0,
00217       NOGOOD = 1,
00218       INFO = 2,
00219       VERSION = 3
00220     };
00221     
00222     Message msg;
00223     
00224     typedef char* iter;
00225     
00226     static void serializeType(std::vector<char>& data, MsgType f) {
00227       data.push_back(static_cast<char>(f));
00228     }
00229     
00230     static void serializeField(std::vector<char>& data, Field f) {
00231       data.push_back(static_cast<char>(f));
00232     }
00233     
00234     static void serialize(std::vector<char>& data, int32_t i) {
00235       data.push_back(static_cast<char>((i & 0xFF000000) >> 24));
00236       data.push_back(static_cast<char>((i & 0xFF0000) >> 16));
00237       data.push_back(static_cast<char>((i & 0xFF00) >> 8));
00238       data.push_back(static_cast<char>((i & 0xFF)));
00239     }
00240     
00241     static void serialize(std::vector<char>& data, NodeStatus s) {
00242       data.push_back(static_cast<char>(s));
00243     }
00244     
00245     static void serialize(std::vector<char>& data, const std::string& s) {
00246       serialize(data, static_cast<int32_t>(s.size()));
00247       for (char c : s) {
00248         data.push_back(c);
00249       }
00250     }
00251     
00252     static MsgType deserializeMsgType(iter& it) {
00253       auto m = static_cast<MsgType>(*it);
00254       ++it;
00255       return m;
00256     }
00257     
00258     static Field deserializeField(iter& it) {
00259       auto f = static_cast<Field>(*it);
00260       ++it;
00261       return f;
00262     }
00263     
00264     static int32_t deserializeInt(iter& it) {
00265       auto b1 = static_cast<uint32_t>(reinterpret_cast<uint8_t&>(*it++));
00266       auto b2 = static_cast<uint32_t>(reinterpret_cast<uint8_t&>(*it++));
00267       auto b3 = static_cast<uint32_t>(reinterpret_cast<uint8_t&>(*it++));
00268       auto b4 = static_cast<uint32_t>(reinterpret_cast<uint8_t&>(*it++));
00269       
00270       return static_cast<int32_t>(b1 << 24 | b2 << 16 | b3 << 8 | b4);
00271     }
00272     
00273     static NodeStatus deserializeStatus(iter& it) {
00274       auto f = static_cast<NodeStatus>(*it);
00275       ++it;
00276       return f;
00277     }
00278     
00279     static std::string deserializeString(iter& it) {
00280       std::string result;
00281       int32_t size = deserializeInt(it);
00282       result.reserve(static_cast<size_t>(size));
00283       for (int32_t i = 0; i < size; i++) {
00284         result += *it;
00285         ++it;
00286       }
00287       return result;
00288     }
00289     
00290   public:
00291     Message& makeNode(NodeUID node, NodeUID parent,
00292                       int32_t alt, int32_t kids, NodeStatus status) {
00293       msg.reset();
00294       msg.set_type(MsgType::NODE);
00295       
00296       msg.set_nodeUID(node);
00297       msg.set_parentUID(parent);
00298       
00299       msg.set_alt(alt);
00300       msg.set_kids(kids);
00301       msg.set_status(status);
00302       
00303       return msg;
00304     }
00305     
00306     void makeStart(const std::string& info) {
00307       msg.reset();
00308       msg.set_type(MsgType::START);
00309       msg.set_version(PROFILER_PROTOCOL_VERSION);
00310       msg.set_info(info); 
00311         }
00312     
00313     void makeRestart(const std::string& info) {
00314       msg.reset();
00315       msg.set_type(MsgType::RESTART);
00316       msg.set_info(info); 
00317         }
00318     
00319     void makeDone(void) {
00320       msg.reset();
00321       msg.set_type(MsgType::DONE);
00322     }
00323     
00324     const Message& get_msg(void) { return msg; }
00325     
00326     std::vector<char> serialize(void) const {
00327       std::vector<char> data;
00328       size_t dataSize = 1 + (msg.isNode() ? 4 * 8 + 1 : 0) +
00329         (msg.has_label() ? 1 + 4 + msg.label().size() : 0) +
00330         (msg.has_nogood() ? 1 + 4 + msg.nogood().size() : 0) +
00331         (msg.has_info() ? 1 + 4 + msg.info().size() : 0);
00332       data.reserve(dataSize);
00333       
00334       serializeType(data, msg.type());
00335       if (msg.isNode()) {
00336         // serialize NodeId node
00337         auto n_uid = msg.nodeUID();
00338         serialize(data, n_uid.nid);
00339         serialize(data, n_uid.rid);
00340         serialize(data, n_uid.tid);
00341         // serialize NodeId parent
00342         auto p_uid = msg.parentUID();
00343         serialize(data, p_uid.nid);
00344         serialize(data, p_uid.rid);
00345         serialize(data, p_uid.tid);
00346         // Other Data
00347         serialize(data, msg.alt());
00348         serialize(data, msg.kids());
00349         serialize(data, msg.status());
00350       }
00351       
00352       if(msg.has_version()) {
00353         serializeField(data, VERSION);
00354         serialize(data, msg.version());
00355       }
00356       if (msg.has_label()) {
00357         serializeField(data, LABEL);
00358         serialize(data, msg.label());
00359       }
00360       if (msg.has_nogood()) {
00361         serializeField(data, NOGOOD);
00362         serialize(data, msg.nogood());
00363       }
00364       if (msg.has_info()) {
00365         serializeField(data, INFO);
00366         serialize(data, msg.info());
00367       }
00368       return data;
00369     }
00370     
00371     void deserialize(char* data, size_t size) {
00372       char *end = data + size;
00373       msg.set_type(deserializeMsgType(data));
00374       if (msg.isNode()) {
00375         int32_t nid = deserializeInt(data);
00376         int32_t rid = deserializeInt(data);
00377         int32_t tid = deserializeInt(data);
00378         
00379         msg.set_nodeUID({nid, rid, tid});
00380         
00381         nid = deserializeInt(data);
00382         rid = deserializeInt(data);
00383         tid = deserializeInt(data);
00384         
00385         msg.set_parentUID({nid, rid, tid});
00386         
00387         msg.set_alt(deserializeInt(data));
00388         msg.set_kids(deserializeInt(data));
00389         msg.set_status(deserializeStatus(data));
00390       }
00391       
00392       msg.reset();
00393       
00394       while (data != end) {
00395         MessageMarshalling::Field f = deserializeField(data);
00396         switch (f) {
00397         case VERSION:
00398           msg.set_version(deserializeInt(data)); break;
00399         case LABEL:
00400           msg.set_label(deserializeString(data)); break;
00401         case NOGOOD:
00402           msg.set_nogood(deserializeString(data)); break;
00403         case INFO:
00404           msg.set_info(deserializeString(data)); break;
00405         default:
00406           break;
00407         }
00408       }
00409     }
00410   };
00411 
00412 }}
00413 
00414 // STATISTICS: search-trace