FairMQ  1.4.33
C++ Message Queuing Library and Framework
PMIx.hpp
1 /********************************************************************************
2  * Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
3  * *
4  * This software is distributed under the terms of the *
5  * GNU Lesser General Public Licence (LGPL) version 3, *
6  * copied verbatim in the file "LICENSE" *
7  ********************************************************************************/
8 
9 #ifndef PMIX_HPP
10 #define PMIX_HPP
11 
12 #include <array>
13 #include <cstring>
14 #include <functional>
15 #include <limits>
16 #include <memory>
17 #include <ostream>
18 #include <pmix.h>
19 #include <sstream>
20 #include <stdexcept>
21 #include <type_traits>
22 #include <utility>
23 #include <vector>
24 
25 // C++ PMIx v2.2 API
26 namespace pmix
27 {
28 
29 struct runtime_error : std::runtime_error
30 {
31  using std::runtime_error::runtime_error;
32 };
33 
34 using status = pmix_status_t;
35 
36 using nspace = pmix_nspace_t;
37 
38 using key = pmix_key_t;
39 
40 using data_type = pmix_data_type_t;
41 
42 struct rank
43 {
44  enum named : pmix_rank_t
45  {
46  undef = PMIX_RANK_UNDEF,
47  wildcard = PMIX_RANK_WILDCARD,
48  local_node = PMIX_RANK_LOCAL_NODE
49  };
50 
51  explicit rank(pmix_rank_t r)
52  : m_value(r)
53  {}
54 
55  operator pmix_rank_t() { return m_value; }
56 
57  private:
58  pmix_rank_t m_value;
59 };
60 
61 struct proc : pmix_proc_t
62 {
63  proc() { PMIX_PROC_CONSTRUCT(static_cast<pmix_proc_t*>(this)); }
64  ~proc() { PMIX_PROC_DESTRUCT(static_cast<pmix_proc_t*>(this)); }
65 
66  proc(pmix::nspace ns, pmix::rank r)
67  {
68  PMIX_PROC_LOAD(static_cast<pmix_proc_t*>(this), ns, static_cast<pmix_rank_t>(r));
69  }
70 
71  friend std::ostream& operator<<(std::ostream& os, const proc& p)
72  {
73  return os << p.nspace << "_" << p.rank;
74  }
75 };
76 
77 struct value : pmix_value_t
78 {
79  value() { PMIX_VALUE_CONSTRUCT(static_cast<pmix_value_t*>(this)); }
80  ~value() { PMIX_VALUE_DESTRUCT(static_cast<pmix_value_t*>(this)); }
81 
82  value(const value& rhs)
83  {
84  status rc;
85  auto lhs(static_cast<pmix_value_t*>(this));
86  PMIX_VALUE_XFER(rc, lhs, static_cast<pmix_value_t*>(const_cast<value*>(&rhs)));
87 
88  if (rc != PMIX_SUCCESS) {
89  throw runtime_error("pmix::value copy ctor failed: rc=" + rc);
90  }
91  }
92 
93  template<typename T>
94  explicit value(T)
95  {
96  throw runtime_error("Given value type not supported or not yet implemented.");
97  }
98 
99  explicit value(const char* val)
100  {
101  PMIX_VALUE_LOAD(static_cast<pmix_value_t*>(this), const_cast<char*>(val), PMIX_STRING);
102  }
103 
104  explicit value(const std::string& val)
105  {
106  PMIX_VALUE_LOAD(
107  static_cast<pmix_value_t*>(this), const_cast<char*>(val.c_str()), PMIX_STRING);
108  }
109 
110  explicit value(int val)
111  {
112  PMIX_VALUE_LOAD(static_cast<pmix_value_t*>(this), &val, PMIX_INT);
113  }
114 
115  explicit value(pmix_data_array_t* val)
116  {
117  PMIX_VALUE_LOAD(static_cast<pmix_value_t*>(this), val, PMIX_DATA_ARRAY);
118  }
119 };
120 
121 struct info : pmix_info_t
122 {
123  info() { PMIX_INFO_CONSTRUCT(static_cast<pmix_info_t*>(this)); }
124  ~info() { PMIX_INFO_DESTRUCT(static_cast<pmix_info_t*>(this)); }
125 
126  template<typename... Args>
127  info(const std::string& k, Args&&... args)
128  {
129  (void)strncpy(key, k.c_str(), PMIX_MAX_KEYLEN);
130  flags = 0;
131 
132  pmix::value rhs(std::forward<Args>(args)...);
133  auto lhs(&value);
134  status rc;
135  PMIX_VALUE_XFER(rc, lhs, static_cast<pmix_value_t*>(&rhs));
136 
137  if (rc != PMIX_SUCCESS) {
138  throw runtime_error("pmix::info ctor failed: rc=" + std::to_string(rc));
139  }
140  }
141 
142  friend std::ostream& operator<<(std::ostream& os, const info& i)
143  {
144  return os << "key=" << i.key << ",value='" << i.value.data.string << "'";
145  }
146 
147  info(const info& rhs)
148  {
149  PMIX_INFO_XFER(static_cast<pmix_info_t*>(this),
150  static_cast<pmix_info_t*>(const_cast<info*>(&rhs)));
151  }
152 };
153 
154 struct pdata : pmix_pdata_t
155 {
156  pdata() { PMIX_PDATA_CONSTRUCT(static_cast<pmix_pdata_t*>(this)); }
157  ~pdata() { PMIX_PDATA_DESTRUCT(static_cast<pmix_pdata_t*>(this)); }
158 
159  pdata(const pdata& rhs)
160  {
161  PMIX_PDATA_XFER(static_cast<pmix_pdata_t*>(this),
162  static_cast<pmix_pdata_t*>(const_cast<pdata*>(&rhs)));
163  }
164 
165  auto set_key(const std::string& new_key) -> void
166  {
167  (void)strncpy(key, new_key.c_str(), PMIX_MAX_KEYLEN);
168  }
169 };
170 
171 auto init(const std::vector<info>& info = {}) -> proc
172 {
173  proc res;
174  status rc;
175 
176  rc = PMIx_Init(&res, const_cast<pmix::info*>(info.data()), info.size());
177  if (rc != PMIX_SUCCESS) {
178  throw runtime_error("pmix::init() failed: rc=" + std::to_string(rc));
179  }
180 
181  return res;
182 }
183 
184 auto initialized() -> bool { return !!PMIx_Initialized(); }
185 
186 auto get_version() -> std::string { return {PMIx_Get_version()}; }
187 
188 auto finalize(const std::vector<info>& info = {}) -> void
189 {
190  status rc;
191 
192  rc = PMIx_Finalize(info.data(), info.size());
193  if (rc != PMIX_SUCCESS) {
194  throw runtime_error("pmix::finalize() failed: rc=" + std::to_string(rc));
195  }
196 }
197 
198 auto publish(const std::vector<info>& info) -> void
199 {
200  status rc;
201 
202  rc = PMIx_Publish(info.data(), info.size());
203  if (rc != PMIX_SUCCESS) {
204  throw runtime_error("pmix::publish() failed: rc=" + std::to_string(rc));
205  }
206 }
207 
208 auto fence(const std::vector<proc>& procs = {}, const std::vector<info>& info = {}) -> void
209 {
210  status rc;
211 
212  rc = PMIx_Fence(procs.data(), procs.size(), info.data(), info.size());
213  if (rc != PMIX_SUCCESS) {
214  throw runtime_error("pmix::fence() failed: rc=" + std::to_string(rc));
215  }
216 }
217 
218 auto lookup(std::vector<pdata>& pdata, const std::vector<info>& info = {}) -> void
219 {
220  status rc;
221 
222  rc = PMIx_Lookup(pdata.data(), pdata.size(), info.data(), info.size());
223  if (rc != PMIX_SUCCESS) {
224  throw runtime_error("pmix::lookup() failed: rc=" + std::to_string(rc));
225  }
226 }
227 
228 std::string get_info(const std::string& name, pmix::proc& process)
229 {
230  pmix_value_t* v;
231 
232  pmix::status rc = PMIx_Get(&process, name.c_str(), nullptr, 0, &v);
233  if (rc == PMIX_SUCCESS) {
234  std::stringstream ss;
235 
236  switch (v->type) {
237  case PMIX_SIZE: ss << static_cast<size_t>(v->data.size) << " (size_t)"; break;
238  case PMIX_INT: ss << static_cast<int>(v->data.integer) << " (int)"; break;
239  case PMIX_INT8: ss << static_cast<int8_t>(v->data.int8) << " (int8_t)"; break;
240  case PMIX_INT16: ss << static_cast<int16_t>(v->data.int16) << " (int16_t)"; break;
241  case PMIX_INT32: ss << static_cast<int32_t>(v->data.int32) << " (int32_t)"; break;
242  case PMIX_INT64: ss << static_cast<int64_t>(v->data.int64) << " (int64_t)"; break;
243  case PMIX_UINT: ss << static_cast<unsigned int>(v->data.uint) << " (unsigned int)"; break;
244  case PMIX_UINT8: ss << static_cast<uint8_t>(v->data.uint8) << " (uint8_t)"; break;
245  case PMIX_UINT16: ss << static_cast<uint16_t>(v->data.uint16) << " (uint16_t)"; break;
246  case PMIX_UINT32: ss << static_cast<uint32_t>(v->data.uint32) << " (uint32_t)"; break;
247  case PMIX_UINT64: ss << static_cast<uint64_t>(v->data.uint64) << " (uint64_t)"; break;
248  case PMIX_FLOAT: ss << static_cast<float>(v->data.fval) << " (float)"; break;
249  case PMIX_DOUBLE: ss << static_cast<double>(v->data.dval) << " (double)"; break;
250  case PMIX_PID: ss << static_cast<pid_t>(v->data.pid) << " (pid_t)"; break;
251  case PMIX_STRING: ss << static_cast<char*>(v->data.string) << " (string)"; break;
252  case PMIX_PROC_RANK: ss << static_cast<uint32_t>(v->data.rank) << " (pmix_rank_t)"; break;
253  case PMIX_PROC: ss << "proc.nspace: " << static_cast<pmix_proc_t*>(v->data.proc)->nspace
254  << ", proc.rank: " << static_cast<pmix_proc_t*>(v->data.proc)->rank << " (pmix_proc_t*)"; break;
255  default:
256  ss << "unknown type: " << v->type;
257  break;
258  }
259 
260  return ss.str();
261  } else if (rc == PMIX_ERR_NOT_FOUND) {
262  // LOG(error) << "PMIx_Get failed: PMIX_ERR_NOT_FOUND";
263  return "";
264  } else {
265  // LOG(error) << "PMIx_Get failed: " << rc;
266  return "<undefined>";
267  }
268 }
269 
270 std::string get_value_str(const pmix_value_t& v)
271 {
272  switch (v.type) {
273  case PMIX_BOOL: return std::to_string(static_cast<bool>(v.data.flag));
274  case PMIX_SIZE: return std::to_string(static_cast<size_t>(v.data.size));
275  case PMIX_INT: return std::to_string(static_cast<int>(v.data.integer));
276  case PMIX_INT8: return std::to_string(static_cast<int8_t>(v.data.int8));
277  case PMIX_INT16: return std::to_string(static_cast<int16_t>(v.data.int16));
278  case PMIX_INT32: return std::to_string(static_cast<int32_t>(v.data.int32));
279  case PMIX_INT64: return std::to_string(static_cast<int64_t>(v.data.int64));
280  case PMIX_UINT: return std::to_string(static_cast<unsigned int>(v.data.uint));
281  case PMIX_UINT8: return std::to_string(static_cast<uint8_t>(v.data.uint8));
282  case PMIX_UINT16: return std::to_string(static_cast<uint16_t>(v.data.uint16));
283  case PMIX_UINT32: return std::to_string(static_cast<uint32_t>(v.data.uint32));
284  case PMIX_UINT64: return std::to_string(static_cast<uint64_t>(v.data.uint64));
285  case PMIX_FLOAT: return std::to_string(static_cast<float>(v.data.fval));
286  case PMIX_DOUBLE: return std::to_string(static_cast<double>(v.data.dval));
287  case PMIX_PID: return std::to_string(static_cast<pid_t>(v.data.pid));
288  case PMIX_STRING: return static_cast<char*>(v.data.string);
289  case PMIX_PROC_RANK: return std::to_string(static_cast<uint32_t>(v.data.rank));
290  case PMIX_POINTER: { std::stringstream ss; ss << static_cast<void*>(v.data.ptr); return ss.str(); }
291  case PMIX_DATA_ARRAY: {
292  if (v.data.darray->type == PMIX_PROC) {
293  std::stringstream ss;
294  ss << "[";
295  for (size_t i = 0; i < v.data.darray->size; ++i) {
296  ss << static_cast<pmix_proc_t*>(static_cast<pmix_data_array_t*>(v.data.darray)->array)[0].nspace;
297  ss << "_";
298  ss << static_cast<pmix_proc_t*>(static_cast<pmix_data_array_t*>(v.data.darray)->array)[0].rank;
299 
300  if (i < v.data.darray->size - 1) {
301  ss << ",";
302  }
303  }
304  ss << "]";
305  return ss.str();
306  } else {
307  return "UNKNOWN TYPE IN DATA ARRAY";
308  }
309  }
310  default: return "UNKNOWN TYPE";
311  }
312 }
313 
314 } /* namespace pmix */
315 
316 #endif /* PMIX_HPP */
pmix::rank
Definition: PMIx.hpp:49
pmix::proc
Definition: PMIx.hpp:68
pmix::info
Definition: PMIx.hpp:128
pmix::runtime_error
Definition: PMIx.hpp:36
pmix::value
Definition: PMIx.hpp:84
pmix::pdata
Definition: PMIx.hpp:161

privacy