Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Fix the MC wrt the simgrid::Host modification
authorGabriel Corona <gabriel.corona@loria.fr>
Tue, 15 Dec 2015 14:46:58 +0000 (15:46 +0100)
committerGabriel Corona <gabriel.corona@loria.fr>
Wed, 16 Dec 2015 10:55:57 +0000 (11:55 +0100)
include/simgrid/Host.hpp
include/xbt/string.hpp [new file with mode: 0644]
src/mc/ModelChecker.cpp
src/mc/mc_smx.cpp
src/simgrid/host.cpp
src/xbt/string.cpp [new file with mode: 0644]
tools/cmake/DefinePackages.cmake

index d61aefa..e1d2999 100644 (file)
@@ -7,22 +7,24 @@
 #ifndef SIMGRID_HOST_HPP
 #define SIMGRID_HOST_HPP
 
+#include <cstddef>
 #include <memory>
 #include <string>
 #include <vector>
 
 #include <xbt/base.h>
 #include <xbt/Facetable.hpp>
+#include <xbt/string.hpp>
 
 namespace simgrid {
 
 XBT_PUBLIC_CLASS Host : public simgrid::xbt::Facetable<Host> {
 private:
-  std::string id_;
+  simgrid::xbt::string id_;
 public:
-  Host(std::string id);
+  Host(std::string const& id);
   ~Host();
-  std::string const& id() const { return id_; }
+  simgrid::xbt::string const& id() const { return id_; }
   static Host* by_name_or_null(const char* name);
   static Host* by_name_or_create(const char* name);
 };
diff --git a/include/xbt/string.hpp b/include/xbt/string.hpp
new file mode 100644 (file)
index 0000000..30d6737
--- /dev/null
@@ -0,0 +1,288 @@
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef SIMGRIC_XBT_STRING_HPP
+#define SIMGRIC_XBT_STRING_HPP
+
+#ifdef HAVE_MC
+
+#include <stdexcept>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <iterator>
+
+#include <xbt/sysdep.h>
+
+namespace simgrid {
+namespace xbt {
+
+/** POD structure representation of a string
+ */
+struct string_data {
+  char* data;
+  std::size_t len;
+};
+
+/** A std::string with well-known representation
+ *
+ *  This is a (incomplete) drop-in replacement for std::string.
+ *
+ *  This is used for cross-process access to strings
+ *  (when the MC is enabled).
+ */
+XBT_PUBLIC_CLASS string : private string_data {
+  static const char NUL;
+public:
+
+  // Types
+  typedef std::size_t size_type;
+  typedef std::ptrdiff_t difference_type;
+  typedef char& reference;
+  typedef const char& const_reference;
+  typedef char* pointer;
+  typedef const char* const_pointer;
+  typedef char* iterator;
+  typedef const char* const_iterator;
+
+  // Dtor
+  ~string()
+  {
+    if (string_data::data != &NUL)
+      std::free(string_data::data);
+  }
+
+  // Ctors
+  string(const char* s, size_t size)
+  {
+    if (size == 0) {
+      string_data::len = 0;
+      string_data::data = const_cast<char*>(&NUL);
+    } else {
+      string_data::len = size;
+      string_data::data = static_cast<char*>(std::malloc(string_data::len + 1));
+      memcpy(string_data::data, s, string_data::len);
+      string_data::data[string_data::len] = '\0';
+    }
+  }
+  string() : string (nullptr, 0) {}
+  string(const char* s)
+    : string(s, s == nullptr ? 0 : strlen(s))
+  {}
+  string(string const& s) : string(s.c_str(), s.size()) {}
+  string(string&& s)
+  {
+    string_data::len = s.string_data::len;
+    string_data::data = s.string_data::data;
+    s.string_data::len = 0;
+    s.string_data::data = const_cast<char*>(&NUL);
+  }
+  string(std::string const& s) : string(s.c_str(), s.size()) {}
+
+  // Assign
+  void assign(const char* s, size_t size)
+  {
+    if (string_data::data != &NUL)
+      std::free(string_data::data);
+    if (size == 0) {
+      string_data::len = 0;
+      string_data::data = nullptr;
+    } else {
+      string_data::len = size;
+      string_data::data = (char*) std::malloc(string_data::len + 1);
+      memcpy(string_data::data, s, string_data::len);
+      string_data::data[string_data::len] = '\0';
+    }
+  }
+
+  // Copy
+  string& operator=(const char* s)
+  {
+    assign(s, s == nullptr ? 0 : std::strlen(s));
+    return *this;
+  }
+  string& operator=(string& s)
+  {
+    assign(s.c_str(), s.size());
+    return *this;
+  }
+  string& operator=(std::string& s)
+  {
+    assign(s.c_str(), s.size());
+    return *this;
+  }
+
+  // Capacity
+  size_t size() const   { return len; }
+  size_t length() const { return len; }
+  bool empty() const    { return len != 0; }
+  void shrink_to_fit() {}
+
+  // Alement access
+  char* data()              { return string_data::data; }
+  const char* data()  const { return string_data::data; }
+  char* c_str()             { return string_data::data; }
+  const char* c_str() const { return string_data::data; };
+  reference at(size_type i)
+  {
+    if (i >= size())
+      throw std::out_of_range("Out of range");
+    return data()[i];
+  }
+  const_reference at(size_type i) const
+  {
+    if (i >= size())
+      throw std::out_of_range("Out of range");
+    return data()[i];
+  }
+  reference operator[](size_type i)
+  {
+    return data()[i];
+  }
+  const_reference operator[](size_type i) const
+  {
+    return data()[i];
+  }
+  // Conversion
+  operator std::string() const
+  {
+    return std::string(this->c_str(), this->size());
+  }
+
+  // Iterators
+  iterator begin()               { return data(); }
+  iterator end()                 { return data() + size(); }
+  const_iterator begin() const   { return data(); }
+  const_iterator end() const     { return data() + size(); }
+  const_iterator cbegin() const  { return data(); }
+  const_iterator cend() const    { return data() + size(); }
+  // (Missing, reverse iterators)
+
+  // Operations
+  void clear()
+  {
+    string_data::len = 0;
+    string_data::data = (char*) &NUL;
+  }
+
+  // Compare
+  int compare(string const& that) const
+  {
+    size_t n = std::min(this->size(), that.size());
+    int res = memcmp(this->c_str(), that.c_str(), n);
+    if (res != 0)
+      return res;
+    else if (this->size() == that.size())
+      return 0;
+    else if (this->size() < that.size())
+      return -1;
+    else
+      return 1;
+  }
+  bool operator==(string const& that) const
+  {
+    return this->size() == that.size()
+      && std::memcmp(this->c_str(), that.c_str(), this->size()) == 0;
+  }
+  bool operator!=(string const& that) const
+  {
+    return !(*this == that);
+  }
+  bool operator<(string const& that) const
+  {
+    return compare(that) < 0;
+  }
+  bool operator<=(string const& that) const
+  {
+    return compare(that) <= 0;
+  }
+  bool operator>(string const& that) const
+  {
+    return compare(that) > 0;
+  }
+  bool operator>=(string const& that) const
+  {
+    return compare(that) >= 0;
+  }
+
+  // Compare with std::string
+  bool operator==(std::string const& that) const
+  {
+    return this->size() == that.size()
+      && std::memcmp(this->c_str(), that.c_str(), this->size()) == 0;
+  }
+  bool operator!=(std::string const& that) const
+  {
+    return !(*this == that);
+  }
+  bool operator<(std::string const& that) const
+  {
+    return compare(that) < 0;
+  }
+  bool operator<=(std::string const& that) const
+  {
+    return compare(that) <= 0;
+  }
+  bool operator>(std::string const& that) const
+  {
+    return compare(that) > 0;
+  }
+  bool operator>=(std::string const& that) const
+  {
+    return compare(that) >= 0;
+  }
+};
+
+inline
+bool operator==(std::string const& a, string const& b)
+{
+  return b == a;
+}
+inline
+bool operator!=(std::string const& a, string const& b)
+{
+  return b != a;
+}
+inline
+bool operator<(std::string const& a, string const& b)
+{
+  return b > a;
+}
+inline
+bool operator<=(std::string const& a, string const& b)
+{
+  return b >= a;
+}
+inline
+bool operator>(std::string const& a, string const& b)
+{
+  return b < a;
+}
+inline
+bool operator>=(std::string const& a, string const& b)
+{
+  return b <= a;
+}
+
+}
+}
+
+#else
+
+#include <string>
+
+namespace simgrid {
+namespace xbt {
+
+typedef std::string string;
+
+}
+}
+
+#endif
+
+#endif
\ No newline at end of file
index 6e73a2d..5c947d2 100644 (file)
@@ -63,7 +63,6 @@ ModelChecker::~ModelChecker()
 
 const char* ModelChecker::get_host_name(const char* hostname)
 {
-  // FIXME, simgrid::Host
   // Lookup the host name in the dictionary (or create it):
   xbt_dictelm_t elt = xbt_dict_get_elm_or_null(this->hostnames_, hostname);
   if (!elt) {
index 2b051ca..f513359 100644 (file)
@@ -7,6 +7,7 @@
 #include <assert.h>
 
 #include <xbt/log.h>
+#include <xbt/string.hpp>
 
 #include "src/simix/smx_private.h"
 
@@ -179,21 +180,33 @@ const char* MC_smx_process_get_host_name(smx_process_t p)
 
   simgrid::mc::Process* process = &mc_model_checker->process();
 
-  // FIXME, simgrid::Host
-  // Currently, smx_host_t = xbt_dictelm_t.
-  // TODO, add an static_assert on this if switching to C++
-  // The host name is host->key and the host->key_len==strlen(host->key).
-  s_xbt_dictelm_t host_copy;
+  /* Horrible hack to find the offset of the id in the simgrid::Host.
+
+     Offsetof is not supported for non-POD types but this should
+     work in pratice for the targets currently supported by the MC
+     as long as we do not add funny features to the Host class
+     (such as virtual base).
+
+     We are using a (C++11) unrestricted union in order to avoid
+     any construction/destruction of the simgrid::Host.
+  */
+  union fake_host {
+    simgrid::Host host;
+    fake_host() {}
+    ~fake_host() {}
+  };
+  fake_host foo;
+  const size_t offset = (char*) &foo.host.id() - (char*) &foo.host;
+
+  // Read the simgrid::xbt::string in the MCed process:
   mc_smx_process_info_t info = MC_smx_process_get_info(p);
-  if (!info->hostname) {
-
-    // Read the hostname from the MCed process:
-    process->read_bytes(&host_copy, sizeof(host_copy), remote(p->host));
-    int len = host_copy.key_len + 1;
-    char hostname[len];
-    process->read_bytes(hostname, len, remote(host_copy.key));
-    info->hostname = mc_model_checker->get_host_name(hostname);
-  }
+  simgrid::xbt::string_data remote_string;
+  auto remote_string_address = remote(
+    (simgrid::xbt::string_data*) ((char*) p->host + offset));
+  process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
+  char hostname[remote_string.len];
+  process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
+  info->hostname = mc_model_checker->get_host_name(hostname);
   return info->hostname;
 }
 
index 1c3cb95..d7ec5f1 100644 (file)
@@ -202,8 +202,8 @@ int sg_host_get_pstate(sg_host_t host) {
 
 namespace simgrid {
 
-Host::Host(std::string id)
-  : id_(std::move(id))
+Host::Host(std::string const& id)
+  : id_(id)
 {
 }
 
diff --git a/src/xbt/string.cpp b/src/xbt/string.cpp
new file mode 100644 (file)
index 0000000..4489c33
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <simgrid_config.h>
+#include <xbt/string.hpp>
+
+namespace simgrid {
+namespace xbt {
+
+#ifdef HAVE_MC
+
+const char string::NUL = '\0';
+
+#endif
+
+}
+}
index c5b9922..0a8819c 100644 (file)
@@ -272,6 +272,7 @@ set(XBT_SRC
   src/xbt/parmap.cpp
   src/xbt/set.c
   src/xbt/snprintf.c
+  src/xbt/string.cpp
   src/xbt/swag.c
   src/xbt/xbt_log_appender_file.c
   src/xbt/xbt_log_layout_format.c
@@ -740,6 +741,7 @@ set(headers_to_install
   include/xbt/config.h
   include/xbt/cunit.h
   include/xbt/dict.h
+  include/xbt/string.hpp
   include/xbt/dynar.h
   include/xbt/ex.h
   include/xbt/fifo.h