10 #define PMIXCOMMANDS_H 14 #include <FairMQLogger.h> 15 #include <fairmq/tools/Semaphore.h> 16 #include <fairmq/tools/CppSTL.h> 22 std::array<std::string, 47> typeNames =
60 "PMIX_INFO_DIRECTIVES",
67 "PMIX_COMPRESSED_STRING",
68 "PMIX_ALLOC_DIRECTIVE",
75 enum class Command : int
77 general = PMIX_EXTERNAL_ERR_BASE,
78 error = PMIX_EXTERNAL_ERR_BASE - 1
96 void Subscribe(std::function<
void(
const std::string& msg,
const proc& sender)> callback)
98 using namespace std::placeholders;
100 LOG(debug) <<
"PMIxCommands: Subscribing...";
102 fCallback = callback;
103 std::array<pmix::status, 1> codes;
104 codes[0] =
static_cast<int>(pmix::Command::general);
106 PMIX_INFO_LOAD(&(fInfos[0]), PMIX_EVENT_RETURN_OBJECT,
this, PMIX_POINTER);
108 PMIx_Register_event_handler(codes.data(), codes.size(),
109 fInfos.data(), fInfos.size(),
111 &Commands::EventHandlerRegistration,
114 LOG(debug) <<
"PMIxCommands: Subscribing complete!";
120 LOG(debug) <<
"PMIxCommands: Unsubscribing...";
121 PMIx_Deregister_event_handler(fHandlerRef, &Commands::EventHandlerDeregistration,
this);
123 LOG(debug) <<
"PMIxCommands: Unsubscribing complete!";
125 LOG(debug) <<
"Unsubscribe() is called while no subscription is active";
131 Holder() : fData(
nullptr) {}
132 ~
Holder() { PMIX_DATA_ARRAY_FREE(fData); }
134 std::vector<pmix::info> fInfos;
135 pmix_data_array_t* fData;
138 void Send(
const std::string& msg)
140 std::vector<pmix::info>* infos =
new std::vector<pmix::info>();
141 infos->emplace_back(
"fairmq.cmd", msg);
142 PMIx_Notify_event(static_cast<int>(pmix::Command::general),
144 PMIX_RANGE_NAMESPACE,
145 infos->data(), infos->size(),
146 &Commands::OpCompleteCallback<std::vector<pmix::info>>,
150 void Send(
const std::string& msg,
rank rank)
153 destination.rank = rank;
154 Send(msg, {destination});
157 void Send(
const std::string& msg,
const std::vector<proc>& destination)
159 std::unique_ptr<Holder> holder = fair::mq::tools::make_unique<Holder>();
161 PMIX_DATA_ARRAY_CREATE(holder->fData, destination.size(), PMIX_PROC);
162 memcpy(holder->fData->array, destination.data(), destination.size() *
sizeof(pmix_proc_t));
164 holder->fInfos.emplace_back(PMIX_EVENT_CUSTOM_RANGE, holder->fData);
170 holder->fInfos.emplace_back(
"fairmq.cmd", msg);
175 PMIx_Notify_event(static_cast<int>(pmix::Command::general),
178 holder->fInfos.data(), holder->fInfos.size(),
179 &Commands::OpCompleteCallback<Holder>,
185 static void EventHandlerRegistration(pmix_status_t s,
size_t handlerRef,
void* obj)
187 if (s == PMIX_SUCCESS) {
188 LOG(debug) <<
"Successfully registered event handler, reference = " <<
static_cast<unsigned long>(handlerRef);
189 static_cast<Commands*
>(obj)->fHandlerRef = handlerRef;
190 static_cast<Commands*
>(obj)->fSubscribed =
true;
192 LOG(error) <<
"Could not register PMIx event handler, status = " << s;
194 static_cast<Commands*
>(obj)->fBlocker.Signal();
197 static void EventHandlerDeregistration(pmix_status_t s,
void* obj)
199 if (s == PMIX_SUCCESS) {
200 LOG(debug) <<
"Successfully deregistered event handler, reference = " <<
static_cast<Commands*
>(obj)->fHandlerRef;
201 static_cast<Commands*
>(obj)->fSubscribed =
false;
203 LOG(error) <<
"Could not deregister PMIx event handler, reference = " <<
static_cast<Commands*
>(obj)->fHandlerRef <<
", status = " << s;
205 static_cast<Commands*
>(obj)->fBlocker.Signal();
209 static void OpCompleteCallback(pmix_status_t s,
void* data)
211 if (s == PMIX_SUCCESS) {
214 LOG(error) <<
"Could not complete operation, status = " << s;
218 delete static_cast<T*
>(data);
222 static void Handler(
size_t handlerId,
224 const pmix_proc_t* src,
225 pmix_info_t
info[],
size_t ninfo,
226 pmix_info_t[] ,
size_t nresults,
227 pmix_event_notification_cbfunc_fn_t cbfunc,
230 std::stringstream ss;
231 ss <<
"Event handler called with " 232 <<
"status: " << s <<
", " 233 <<
"source: " << src->nspace <<
"_" << src->rank <<
", " 234 <<
"ninfo: " << ninfo <<
", " 235 <<
"nresults: " << nresults <<
", " 236 <<
"handlerId: " << handlerId;
244 for (
size_t i = 0; i < ninfo; ++i) {
245 ss <<
" [" << i <<
"]: key: '" << info[i].key
246 <<
"', value: '" << pmix::get_value_str(info[i].
value)
247 <<
"', value.type: '" << pmix::typeNames.at(info[i].value.type)
248 <<
"', flags: " << info[i].flags;
250 if (std::strcmp(info[i].key,
"fairmq.cmd") == 0) {
251 msg = pmix::get_value_str(info[i].value);
254 if (std::strcmp(info[i].key, PMIX_EVENT_RETURN_OBJECT) == 0) {
255 obj =
static_cast<Commands*
>(info[i].value.data.ptr);
265 if (obj !=
nullptr) {
266 if (static_cast<Commands*>(obj)->fProcess.rank != src->rank) {
268 static_cast<Commands*
>(obj)->fCallback(msg,
proc(const_cast<char*>(src->nspace), rank(src->rank)));
273 LOG(ERROR) <<
"ERROR";
276 if (cbfunc !=
nullptr) {
277 cbfunc(PMIX_SUCCESS,
nullptr, 0,
nullptr,
nullptr, cbdata);
281 const proc& fProcess;
283 std::function<void(const std::string& msg, const proc& sender)> fCallback;
284 std::array<pmix_info_t, 1> fInfos;
Definition: PMIxCommands.h:129
Definition: PMIxCommands.h:82