Skip to content

Commit

Permalink
Break uuid_utils header into subcomponents
Browse files Browse the repository at this point in the history
  • Loading branch information
mmore500 committed Feb 8, 2022
1 parent 957679f commit 370b893
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 112 deletions.
35 changes: 35 additions & 0 deletions include/uitsl/utility/generate_random_uuid.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once
#ifndef UITSL_UTILITY_GENERATE_RANDOM_UUID_HPP_INCLUDE
#define UITSL_UTILITY_GENERATE_RANDOM_UUID_HPP_INCLUDE

#include <algorithm>
#include <array>
#include <functional>
#include <random>

#include "../../../third-party/stduuid/include/uuid.h"

namespace uitsl {

uuids::uuid generate_random_uuid() {
thread_local auto random_generator = [](){
// workaround for error encountered when multiprocesses share same node
// > terminate called after throwing an instance of 'std::runtime_error'
// > what(): random_device: rdseed failed
// see https://github.com/xdspacelab/openvslam/issues/319#issuecomment-630225541
// see https://en.cppreference.com/w/cpp/numeric/random/random_device/random_device
std::random_device rd("rdrand");
auto seed_data = std::array<int, std::mt19937::state_size> {};
std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
return std::mt19937(seq);
}();
thread_local uuids::uuid_random_generator uuid_generator( random_generator );

return uuid_generator();

}

} // namespace uitsl

#endif // #ifndef UITSL_UTILITY_GENERATE_RANDOM_UUID_HPP_INCLUDE
101 changes: 101 additions & 0 deletions include/uitsl/utility/get_exec_instance_uuid.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#pragma once
#ifndef UITSL_UTILITY_GET_EXEC_INSTANCE_UUID_HPP_INCLUDE
#define UITSL_UTILITY_GET_EXEC_INSTANCE_UUID_HPP_INCLUDE

#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <string>
#include <string_view>

#include "../../../third-party/Empirical/include/emp/base/always_assert.hpp"
#include "../../../third-party/Empirical/include/emp/base/error.hpp"
#include "../../../third-party/Empirical/include/emp/tools/keyname_utils.hpp"
#include "../../../third-party/Empirical/include/emp/tools/keyname_utils.hpp"
#include "../../../third-party/Empirical/include/emp/tools/string_utils.hpp"
#include "../../../third-party/stduuid/include/uuid.h"

#include "../mpi/comm_utils.hpp"
#include "../mpi/mpi_init_utils.hpp"
#include "../polyfill/filesystem.hpp"

#include "generate_random_uuid.hpp"

namespace uitsl {

uuids::uuid get_exec_instance_uuid() {

static auto uuid = [](){

uuids::uuid res;

// try to set up res uuid using a series of fallback options...
// 1. if not multiprocess, can use random uuid generation
if ( !uitsl::is_multiprocess() ) res = uitsl::generate_random_uuid();
// 2. if user provided UITSL_EXEC_INSTANCE_UUID, verify it and then use it
else if ( const char* seed = std::getenv("UITSL_EXEC_INSTANCE_UUID") ) {
auto parsed = uuids::uuid::from_string(seed);
emp_always_assert(
parsed.has_value(),
"UITSL_EXEC_INSTANCE_UUID must be a valid uuid", seed
);
emp_always_assert(
!parsed->is_nil(),
"UITSL_EXEC_INSTANCE_UUID must be a non-nil uuid", seed, *parsed
);
res = *parsed;
// 3. if PMIX_NAMESPACE is available, use that to make uuid
} else if ( const char* seed = std::getenv("PMIX_NAMESPACE") ) {
// is PMIX_NAMESPACE actually a good uuid seed? not sure
// note: PMIX_NAMESPACE only seems to be provided by OpenMPI
res = uuids::uuid_name_generator{ uuids::uuid{} }(seed);
// 4. no good options left, fail
} else emp_error(
"Need env var UITSL_EXEC_INSTANCE_UUID or PMIX_NAMESPACE "
"for get_multiprocess_exec_instance_uuid.\n"
"Hint: call "
"`export UITSL_EXEC_INSTANCE_UUID=\"$(cat /proc/sys/kernel/random/uuid)\""
" _each time_ prior to launching with mpiexec."
);

// do a quick (non-exhaustive) check for obvious user misuse
// i.e., that uuid is actually unique
const auto reservation_path = std::filesystem::temp_directory_path()
/ emp::keyname::pack({
{"a", "uitsl_exec_instance_uuid"},
{"rank",emp::to_string( uitsl::get_proc_id() )},
{"uid", uuids::to_string( res )},
});
emp_always_assert(
!std::filesystem::exists( reservation_path ),
reservation_path,
uitsl::is_multiprocess(),
std::getenv("UITSL_EXEC_INSTANCE_UUID"),
std::getenv("PMIX_NAMESPACE")
);

// touch reservation_path
// adapted from https://stackoverflow.com/a/54451555
std::ofstream output(reservation_path);

return res;

}();

return uuid;

}

uuids::uuid get_proc_instance_uuid() {
static auto uuid = uitsl::generate_random_uuid();
return uuid;
}

uuids::uuid get_thread_instance_uuid() {
thread_local auto uuid = uitsl::generate_random_uuid();
return uuid;
}

} // namespace uitsl

#endif // #ifndef UITSL_UTILITY_GET_EXEC_INSTANCE_UUID_HPP_INCLUDE
18 changes: 18 additions & 0 deletions include/uitsl/utility/get_proc_instance_uuid.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once
#ifndef UITSL_UTILITY_GET_PROC_INSTANCE_UUID_HPP_INCLUDE
#define UITSL_UTILITY_GET_PROC_INSTANCE_UUID_HPP_INCLUDE

#include "../../../third-party/stduuid/include/uuid.h"

#include "generate_random_uuid.hpp"

namespace uitsl {

uuids::uuid get_proc_instance_uuid() {
static auto uuid = uitsl::generate_random_uuid();
return uuid;
}

} // namespace uitsl

#endif // #ifndef UITSL_UTILITY_GET_PROC_INSTANCE_UUID_HPP_INCLUDE
18 changes: 18 additions & 0 deletions include/uitsl/utility/get_thread_instance_uuid.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once
#ifndef UITSL_UTILITY_GET_THREAD_INSTANCE_UUID_HPP_INCLUDE
#define UITSL_UTILITY_GET_THREAD_INSTANCE_UUID_HPP_INCLUDE

#include "../../../third-party/stduuid/include/uuid.h"

#include "generate_random_uuid.hpp"

namespace uitsl {

uuids::uuid get_thread_instance_uuid() {
thread_local auto uuid = uitsl::generate_random_uuid();
return uuid;
}

} // namespace uitsl

#endif // #ifndef UITSL_UTILITY_GET_THREAD_INSTANCE_UUID_HPP_INCLUDE
116 changes: 4 additions & 112 deletions include/uitsl/utility/uuid_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,117 +2,9 @@
#ifndef UITSL_UTILITY_UUID_UTILS_HPP_INCLUDE
#define UITSL_UTILITY_UUID_UTILS_HPP_INCLUDE

#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <random>
#include <string>
#include <string_view>

#include "../../../third-party/Empirical/include/emp/base/always_assert.hpp"
#include "../../../third-party/Empirical/include/emp/base/error.hpp"
#include "../../../third-party/Empirical/include/emp/tools/keyname_utils.hpp"
#include "../../../third-party/Empirical/include/emp/tools/keyname_utils.hpp"
#include "../../../third-party/Empirical/include/emp/tools/string_utils.hpp"
#include "../../../third-party/stduuid/include/uuid.h"

#include "../mpi/comm_utils.hpp"
#include "../mpi/mpi_init_utils.hpp"
#include "../polyfill/filesystem.hpp"

namespace uitsl {

uuids::uuid generate_random_uuid() {
thread_local auto random_generator = [](){
// workaround for error encountered when multiprocesses share same node
// > terminate called after throwing an instance of 'std::runtime_error'
// > what(): random_device: rdseed failed
// see https://github.com/xdspacelab/openvslam/issues/319#issuecomment-630225541
// see https://en.cppreference.com/w/cpp/numeric/random/random_device/random_device
std::random_device rd("rdrand");
auto seed_data = std::array<int, std::mt19937::state_size> {};
std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
return std::mt19937(seq);
}();
thread_local uuids::uuid_random_generator uuid_generator( random_generator );

return uuid_generator();
}

uuids::uuid get_exec_instance_uuid() {

static auto uuid = [](){

uuids::uuid res;

// try to set up res uuid using a series of fallback options...
// 1. if not multiprocess, can use random uuid generation
if ( !uitsl::is_multiprocess() ) res = uitsl::generate_random_uuid();
// 2. if user provided UITSL_EXEC_INSTANCE_UUID, verify it and then use it
else if ( const char* seed = std::getenv("UITSL_EXEC_INSTANCE_UUID") ) {
auto parsed = uuids::uuid::from_string(seed);
emp_always_assert(
parsed.has_value(),
"UITSL_EXEC_INSTANCE_UUID must be a valid uuid", seed
);
emp_always_assert(
!parsed->is_nil(),
"UITSL_EXEC_INSTANCE_UUID must be a non-nil uuid", seed, *parsed
);
res = *parsed;
// 3. if PMIX_NAMESPACE is available, use that to make uuid
} else if ( const char* seed = std::getenv("PMIX_NAMESPACE") ) {
// is PMIX_NAMESPACE actually a good uuid seed? not sure
// note: PMIX_NAMESPACE only seems to be provided by OpenMPI
res = uuids::uuid_name_generator{ uuids::uuid{} }(seed);
// 4. no good options left, fail
} else emp_error(
"Need env var UITSL_EXEC_INSTANCE_UUID or PMIX_NAMESPACE "
"for get_multiprocess_exec_instance_uuid.\n"
"Hint: call "
"`export UITSL_EXEC_INSTANCE_UUID=\"$(cat /proc/sys/kernel/random/uuid)\""
" _each time_ prior to launching with mpiexec."
);

// do a quick (non-exhaustive) check for obvious user misuse
// i.e., that uuid is actually unique
const auto reservation_path = std::filesystem::temp_directory_path()
/ emp::keyname::pack({
{"a", "uitsl_exec_instance_uuid"},
{"rank",emp::to_string( uitsl::get_proc_id() )},
{"uid", uuids::to_string( res )},
});
emp_always_assert(
!std::filesystem::exists( reservation_path ),
reservation_path,
uitsl::is_multiprocess(),
std::getenv("UITSL_EXEC_INSTANCE_UUID"),
std::getenv("PMIX_NAMESPACE")
);

// touch reservation_path
// adapted from https://stackoverflow.com/a/54451555
std::ofstream output(reservation_path);

return res;

}();

return uuid;

}

uuids::uuid get_proc_instance_uuid() {
static auto uuid = uitsl::generate_random_uuid();
return uuid;
}

uuids::uuid get_thread_instance_uuid() {
thread_local auto uuid = uitsl::generate_random_uuid();
return uuid;
}

} // namespace uitsl
#include "generate_random_uuid.hpp"
#include "get_exec_instance_uuid.hpp"
#include "get_proc_instance_uuid.hpp"
#include "get_thread_instance_uuid.hpp"

#endif // #ifndef UITSL_UTILITY_UUID_UTILS_HPP_INCLUDE

0 comments on commit 370b893

Please sign in to comment.