preCICE v3.1.1
Loading...
Searching...
No Matches
ConnectionInfoPublisher.cpp
Go to the documentation of this file.
1#include <algorithm>
2#include <boost/algorithm/string/trim.hpp>
3#include <boost/uuid/name_generator.hpp>
4#include <boost/uuid/string_generator.hpp>
5#include <boost/uuid/uuid_io.hpp>
6
7#include <chrono>
8#include <filesystem>
9#include <fstream>
10#include <stdexcept>
11#include <thread>
12
14#include "logging/LogMacros.hpp"
16#include "utils/assertion.hpp"
17
18namespace fs = std::filesystem;
19namespace precice::com {
20
21namespace {
22
23std::string preciceFancyHash(std::string_view s)
24try {
25 boost::uuids::string_generator ns_gen;
26 auto ns = ns_gen("af7ce8f2-a9ee-46cb-38ee-71c318aa3580"); // md5 hash of precice.org as namespace
27
28 boost::uuids::name_generator gen{ns};
29 return boost::uuids::to_string(gen(s.data(), s.size()));
30
31} catch (const std::runtime_error &e) {
32 PRECICE_UNREACHABLE("preCICE hashing failed", e.what());
33 return "";
34}
35} // namespace
36
38{
39 constexpr int firstLevelLen = 2;
40 std::string const s = std::string(acceptorName).append(tag).append(requesterName).append(std::to_string(rank));
41 std::string hash = preciceFancyHash(s);
42 hash.erase(std::remove(hash.begin(), hash.end(), '-'), hash.end());
43
44 auto p = fs::path(hash.substr(0, firstLevelLen)) / hash.substr(firstLevelLen);
45
46 return p.string();
47}
48
50{
51 std::string directional = std::string(acceptorName).append("-").append(requesterName);
52
53 auto p = fs::path(addressDirectory.begin(), addressDirectory.end()) / "precice-run" / directional;
54
55 return p.string();
56}
57
62
64{
65 auto local = getLocalDirectory();
67 auto p = fs::path(getLocalDirectory()) / hashed;
68
69 return p.string();
70}
71
73{
74 auto path = getFilename();
75
76 PRECICE_DEBUG("Waiting for connection file \"{}\"", path);
77 const auto waitdelay = std::chrono::milliseconds(1);
78 while (!fs::exists(path)) {
80 }
82 PRECICE_DEBUG("Found connection file \"{}\"", path);
83
84 std::ifstream ifs(path);
85 PRECICE_CHECK(ifs,
86 "Unable to establish connection as the connection file \"{}\" couldn't be opened.",
87 path);
88 std::string addressData;
89 std::getline(ifs, addressData);
90 PRECICE_CHECK(!addressData.empty(),
91 "Unable to establish connection as the connection file \"{}\" is empty. "
92 "Please report this bug to the preCICE developers.",
93 path);
94 boost::algorithm::trim_right(addressData);
95 return addressData;
96}
97
99{
100 fs::path path(getFilename());
101 if (!fs::exists(path)) {
102 PRECICE_WARN("Cannot clean-up the connection file \"{}\" as it doesn't exist. "
103 "In case of connection problems, please report this to the preCICE developers.",
104 path.generic_string());
105 return;
106 }
107 PRECICE_DEBUG("Deleting connection file \"{}\"", path.generic_string());
108 try {
109 fs::remove(path);
111 fs::exists(path),
112 "The connection file \"{}\" wasn't properly removed. "
113 "Make sure to delete the \"precice-run\" directory before restarting the simulation.",
114 path.generic_string());
115 } catch (const fs::filesystem_error &e) {
116 PRECICE_WARN("Unable to clean-up connection file due to error: {}. "
117 "Make sure to delete the \"precice-run\" directory before restarting the simulation.",
118 e.what());
119 }
120}
121
123{
124 auto path = getFilename();
125 auto tmp = fs::path(path + "~");
126
127 {
128 auto message = "Unable to establish connection as a {}connection file already exists at \"{}\". "
129 "This is likely a leftover of a previous crash or stop during communication build-up. "
130 "Please remove the \"precice-run\" directory and restart the simulation.";
131 PRECICE_CHECK(!fs::exists(path), message, "", path);
132 PRECICE_CHECK(!fs::exists(tmp), message, "temporary ");
133 }
134
135 PRECICE_DEBUG("Writing temporary connection file \"{}\"", tmp.generic_string());
136 fs::create_directories(tmp.parent_path());
137 {
138 std::ofstream ofs(tmp.string());
139 PRECICE_CHECK(ofs, "Unable to establish connection as the temporary connection file \"{}\" couldn't be opened.", tmp.generic_string());
140 fmt::print(ofs,
141 "{}\nAcceptor: {}, Requester: {}, Tag: {}, Rank: {}",
143 }
145 "Unable to establish connection as the temporary connection file \"{}\" was written, but doesn't exist on disk. "
146 "Please report this bug to the preCICE developers.",
147 tmp.generic_string());
148
149 PRECICE_DEBUG("Publishing connection file \"{}\"", path);
150 fs::rename(tmp, path);
152 fs::exists(tmp),
153 "The temporary connection file \"{}\" wasn't properly removed. "
154 "Make sure to delete the \"precice-run\" directory before restarting the simulation.",
155 tmp.generic_string());
157 "Unable to establish connection as the connection file \"{}\" doesn't exist on disk. "
158 "Please report this bug to the preCICE developers.",
159 path);
160}
161
162} // namespace precice::com
#define PRECICE_WARN_IF(condition,...)
Definition LogMacros.hpp:21
#define PRECICE_WARN(...)
Definition LogMacros.hpp:11
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:64
#define PRECICE_CHECK(check,...)
Definition LogMacros.hpp:35
T append(T... args)
#define PRECICE_ASSERT(...)
Definition assertion.hpp:87
#define PRECICE_UNREACHABLE(...)
Definition assertion.hpp:95
T begin(T... args)
std::string getLocalDirectory() const
Returns the local directory which is used to store the hashed part.
std::string getFilename() const
Returns the full path to the hashed filename.
std::string read() const
Reads the info from the connection info file. Will block, if the the file is not present.
void write(std::string_view info) const
Write the string info, e.g. IP:port to the connection info file.
~ConnectionInfoWriter()
Removes the connection info file and the directories ./precice-run/[hash], is empty.
T create_directories(T... args)
T data(T... args)
T empty(T... args)
T end(T... args)
T erase(T... args)
T exists(T... args)
T generic_string(T... args)
T getline(T... args)
std::string hashedFilePath(std::string_view acceptorName, std::string_view requesterName, std::string_view meshName, Rank rank)
Returns the file name for the connection information.
std::string localDirectory(std::string_view acceptorName, std::string_view requesterName, std::string_view addressDirectory)
contains the data communication abstraction layer.
int Rank
Definition Types.hpp:37
T remove(T... args)
T rename(T... args)
T size(T... args)
T sleep_for(T... args)
T substr(T... args)
T to_string(T... args)
T what(T... args)