5#include <sys/utsname.h>
13#include <boost/algorithm/string.hpp>
29 std::transform(s.begin(), s.end(), s.begin(),
30 [](
unsigned char c){ return std::tolower(c); }
38 auto buffer = std::make_unique<char[]>(bufsize);
39 ret = readlink(
"/proc/self/exe", buffer.get(), bufsize - 1);
41 sprintf(buffer.get(),
"(nullexe)");
43 buffer.get()[ret] =
'\0';
53 char prefix[40] =
"YYYY-MM-ddTHH:mm:ss";
54 char suffix[40] =
"0000 ";
56 localtime_r(&ts.tv_sec, &tm);
57 sprintf(millis,
"%03ld", ts.tv_nsec / 1000000);
58 strftime(prefix,
sizeof(prefix),
"%Y-%m-%dT%H:%M:%S.", &tm);
59 strftime(suffix,
sizeof(suffix),
"%z", &tm);
60 std::string buf = std::string(prefix) + std::string(millis) + std::string(suffix);
68 snprintf(str,
sizeof(str),
"%ld.%09ld",(
long)ts.tv_sec, (
long)ts.tv_nsec);
69 return std::string(str);
80#define CPUINFO_FILE "/proc/cpuinfo"
83 static std::string affinity_all;
84 if (affinity_all.size() < 2) {
88 while (std::getline(in, line)) {
89 size_t cp = line.find(
' ');
90 std::string name = line.substr(0, cp);
91 if (name ==
"processor") {
93 std::istringstream iss(line.substr(cp+1));
99 pmax = (val > pmax ? val : pmax);
104 affinity_all =
"0-1024";
106 std::ostringstream oss;
108 affinity_all = oss.str();
115std::vector< std::string>
get_libs(std::string_view )
117 pid_t pid = getpid();
118 std::ostringstream cmd;
119 cmd <<
"/usr/bin/grep r-xp /proc/" << pid <<
"/maps | /usr/bin/grep '\\.so' | /usr/bin/sed -e 's%.* /%/%g'";
121 std::vector< std::string> libs;
125 std::istringstream nss(proclibs.
output);
127 while (std::getline(nss, line)) {
128 libs.push_back(line);
135 static bool shell_done;
136 static boost::json::object numa_json;
140 size_t numa_node_count = 0;
142 std::vector<std::string> cpulist;
143 std::vector<int64_t> sizes;
144 std::vector<std::string> numa_node;
148 std::istringstream nss(numactl.
output);
149 while (std::getline(nss, line)) {
150 size_t cp = line.find(
':');
151 std::string name = line.substr(0, cp);
152 if (name ==
"available") {
153 std::istringstream iss(line.substr(cp+1));
154 iss >> numa_node_count;
157 if (name.substr(name.length()-4) ==
"cpus" ) {
158 cpulist.push_back(line.substr(cp+2));
161 if (name.substr(name.length()-4) ==
"size" ) {
162 std::istringstream iss(line.substr(cp+1));
168 if (name.substr(name.length()-4) ==
"nces" )
171 if (! numa_node_count || sizes.size() != numa_node_count || cpulist.size() != numa_node_count)
174 numa_json[
"numa_node_count"] = numa_node_count;
175 numa_json[
"numa_cpu_list"] = boost::json::value_from(cpulist);
176 numa_json[
"numa_node_megabyte"] = boost::json::value_from(sizes);
178 boost::json::array na;
179 for (
size_t i = 0; i < numa_node_count; i++) {
180 boost::json::object o = {
182 {
"node_megabytes", sizes[i]},
183 {
"cpu_list", cpulist[i]}
187 numa_json[
"node_list"] = na;
195 static bool shell_done;
196 static boost::json::object gpu_json;
199 std::cerr <<
"add_host_section: doing gpu" <<std::endl;
201 size_t gpu_count = 0;
206 std::cerr <<
"add_host_section: parsing gpu" <<std::endl;
208 std::vector<std::string> vendor;
209 std::vector<std::string> device;
210 std::vector<std::string> rev;
211 std::vector<int32_t> numa_node;
214 std::istringstream nss(lspci.
output);
215 while (std::getline(nss, line)) {
216 if (line.substr(0,1) ==
"-")
218 size_t cp = line.find(
':');
219 std::string name = line.substr(0, cp);
220 if (name ==
"Class") {
221 std::string cname = boost::algorithm::trim_copy(line.substr(cp+1));
222 if (cname ==
"3D controller") {
230 if (name ==
"Vendor" ) {
231 vendor.push_back(boost::algorithm::trim_copy(line.substr(cp+1)));
234 if (name ==
"Device" ) {
235 device.push_back(boost::algorithm::trim_copy(line.substr(cp+1)));
238 if (name ==
"Rev" ) {
239 rev.push_back(boost::algorithm::trim_copy(line.substr(cp+1)));
242 if (name ==
"NUMANode" ) {
243 std::istringstream iss(line.substr(cp+1));
246 numa_node.push_back(nn);
250 if (vendor.size() != gpu_count ||
251 device.size() != gpu_count ||
252 rev.size() != gpu_count ||
253 numa_node.size() != gpu_count) {
254 std::cerr <<
"add_host_section: size mismatch " <<
263 gpu_json[
"gpu_count"] = gpu_count;
264 boost::json::array ga;
265 for (
size_t i = 0; i < gpu_count; i++) {
266 boost::json::object o = {
268 {
"numa_node", numa_node[i]},
269 {
"vendor", vendor[i]},
270 {
"device", device[i]},
275 gpu_json[
"gpulist"] = ga;
279 std::cerr <<
"add_host_section: lspci fail " << lspci.
rc <<std::endl;
286#define MEMINFO_FILE "/proc/meminfo"
295static std::map<std::string, uint64_t> midata = {
300 {
"SReclaimable", 0 },
304 {
"MemAvailable", 0 },
319 while (std::getline(in, line)) {
320 size_t cp = line.find(
':');
321 std::string name = line.substr(0, cp);
322 if (name ==
"MemTotal") {
323 std::istringstream iss(line.substr(cp+1));
345 while (std::getline(in, line)) {
346 size_t cp = line.find(
':');
347 std::string name = line.substr(0, cp);
348 auto it = midata.find(name);
349 if (it != midata.end()) {
350 std::istringstream iss(line.substr(cp+1));
354 std::cerr <<
"error reading value for " << it->first << std::endl;
359#ifdef ADC_MEMINFO_DEBUG
360 std::cerr <<
"parsed meminfo." << name << std::endl;
366 midata[
"MemUsed"] = midata[
"MemTotal"] - midata[
"MemFree"];
367 midata[
"SwapUsed"] = midata[
"SwapTotal"] - midata[
"SwapFree"];
368 midata[
"CachedAll"] = midata[
"Cached"] + midata[
"SReclaimable"];
369 if (midata[
"MemAvailable"] > midata[
"MemTotal"]) {
370 midata[
"MemAvailable"] = midata[
"MemFree"];
377 std::cerr <<
"read meminfo failed" << std::endl;
378 std::cerr <<
"count = " << count << std::endl;
379 std::cerr <<
"mdsize = " << midata.size() << std::endl;
389 uid_t uid = geteuid();
391 struct passwd *pwp = NULL;
392 int bsize = sysconf(_SC_GETPW_R_SIZE_MAX);
396 getpwuid_r(uid, &pw, buf, bsize, &pwp);
401 uname =
"<unknown_user>";
404 clock_gettime(CLOCK_REALTIME, &ts);
408 boost::json::object vv = {
413 uuid_generate_random(uuid);
415 uuid_unparse_lower(uuid, uuidbuf);
416 boost::json::value jv = {
417 {
"adc_api_version", vv },
418 {
"timestamp", ts_ns },
419 {
"datestamp", ts_8601 },
421 {
"uid", std::to_string(uid) },
422 {
"application", application_name},
428std::vector<std::string>
split_string(
const std::string& s,
char delimiter)
430 std::vector<std::string> tokens;
431 std::stringstream ss(s);
433 while (std::getline(ss, token, delimiter)) {
434 if (token.length() > 0) {
435 tokens.push_back(token);
441std::vector<std::string> builder::get_host_env_vars()
443 const char *env = getenv(
"ADC_HOST_SECTION_ENV");
447 std::vector<std::string> s;
451#define ADC_HS_BAD ~(ADC_HS_ALL)
457 std::cerr <<
"bad arg to add_host_section: " << subsections <<std::endl;
461 int uerr = uname(&ubuf);
463 std::cerr <<
"uname failed in add_host_section" <<std::endl;
466 boost::json::object jv = {
467 {
"name", std::string(ubuf.nodename) }
470 jv[
"os_family"] = std::string(ubuf.sysname);
471 jv[
"os_version"] = std::string(ubuf.release);
472 jv[
"os_arch"] = std::string(ubuf.machine);
473 jv[
"os_build"] = std::string(ubuf.version);
476 std::vector<std::string> env_vars = get_host_env_vars();
477 for (
auto it = env_vars.begin();
478 it != env_vars.end(); it++) {
479 const char *s = getenv(it->c_str());
482 jv[*it] = std::string(s);
486 if (midata[
"valid"] == 1) {
487 jv[
"mem_total"] = midata[
"MemTotal"];
490 if (midata[
"valid"] == 1)
491 jv[
"mem_total"] = midata[
"MemTotal"];
497 boost::system::error_code ec;
499 auto cv = boost::json::parse(lscpu, ec);
501 std::cerr <<
"unable to parse ("<< ec <<
") lscpu output: " << lscpu << std::endl;
520 auto app_data_derived = std::dynamic_pointer_cast<builder>(app_data);
521 d[
"app_data"] = app_data_derived->flatten();
526 if (midata[
"valid"] == 0) {
527 boost::json::object jv;
528 d[
"memory_usage"] = jv;
532 boost::json::value jv = {
533 {
"mem_total", midata[
"MemTotal"]},
534 {
"mem_used", midata[
"MemUsed"]},
535 {
"mem_free", midata[
"MemFree"]},
536 {
"mem_shared", midata[
"Shmem"]},
537 {
"mem_buffers", midata[
"Buffers"]},
538 {
"mem_cache", midata[
"CachedAll"]},
539 {
"mem_available", midata[
"MemAvailable"]},
540 {
"swap_total", midata[
"SwapTotal"]},
541 {
"swap_used", midata[
"SwapUsed"]},
542 {
"swap_free", midata[
"SwapFree"]}
544 d[
"memory_usage"] = jv;
551 auto model_data_derived = std::dynamic_pointer_cast<builder>(model_data);
552 d[
"model_data"] = model_data_derived->flatten();
559 std::string fullpath =
get_exe(4096);
560 const char *basename = strrchr(fullpath.c_str(),
'/');
562 basename = fullpath.c_str();
565 std::vector< std::string> libs =
get_libs(fullpath);
566 auto code_details_derived = std::dynamic_pointer_cast<builder>(code_details);
567 auto version_derived = std::dynamic_pointer_cast<builder>(
version);
568 boost::json::value jv = {
570 {
"program", basename},
572 {
"version", version_derived->d},
573 {
"libs", boost::json::value_from(libs) },
574 {
"details", code_details_derived->flatten()}
582 auto build_details_derived = std::dynamic_pointer_cast<builder>(build_details);
583 d[
"code_configuration"] = build_details_derived->flatten();
589 auto status_details_derived = std::dynamic_pointer_cast<builder>(status_details);
590 boost::json::value jv = {
591 {
"return_code", std::to_string(return_code)},
593 {
"details", status_details_derived->flatten()}
602 auto nk = kind(name);
604 auto section_derived = std::dynamic_pointer_cast<builder>(section);
605 sections[std::string(name)] = std::move(section_derived);
611 auto nk = kind(name);
613 return sections[std::string(name)];
615 return std::shared_ptr< builder_api >(NULL);
620 std::vector< std::string > result;
621 for (
auto const& element : sections) {
622 result.push_back(element.first);
631 std::vector< std::string > result;
632 for (
auto const& element : d) {
633 result.push_back(element.key());
640 boost::json::string *s;
644 f.
vp = &std::get< bool >(f.
data);
648 f.
data =
variant(
static_cast<char>(*(v->if_int64())));
649 f.
vp = &std::get< char >(f.
data);
653 f.
data =
variant(
static_cast<char16_t>(*(v->if_uint64())));
654 f.
vp = &std::get< char16_t >(f.
data);
658 f.
data =
variant(
static_cast<char32_t>(*(v->if_uint64())));
659 f.
vp = &std::get< char32_t >(f.
data);
663 f.
data =
variant(
static_cast<uint8_t
>(*(v->if_uint64())));
664 f.
vp = &std::get< uint8_t >(f.
data);
668 f.
data =
variant(
static_cast<uint16_t
>(*(v->if_uint64())));
669 f.
vp = &std::get< uint16_t >(f.
data);
673 f.
data =
variant(
static_cast<uint32_t
>(*(v->if_uint64())));
674 f.
vp = &std::get< uint32_t >(f.
data);
682 std::istringstream iss(ss);
685 f.
vp = &std::get< uint64_t >(f.
data);
690 f.
data =
variant(
static_cast<int8_t
>(*(v->if_int64())));
691 f.
vp = &std::get< int8_t >(f.
data);
695 f.
data =
variant(
static_cast<int16_t
>(*(v->if_int64())));
696 f.
vp = &std::get< int16_t >(f.
data);
700 f.
data =
variant(
static_cast<int32_t
>(*(v->if_int64())));
701 f.
vp = &std::get< int32_t >(f.
data);
706 f.
vp = &std::get< int64_t >(f.
data);
711 f.
vp = &std::get< int64_t >(f.
data);
725#ifdef ADC_GV_STR_DEBUG
726 std::cerr <<
"s c ptr " << (
void*)(s->c_str()) << std::endl;
729#ifdef ADC_GV_STR_DEBUG
730 std::cerr <<
"ss c ptr " << (
void*)(ss.c_str()) << std::endl;
735#ifdef ADC_GV_STR_DEBUG
736 std::cerr <<
"f ptr " << (
void*)&f.
kt << std::endl;
737 std::cerr <<
"f.data " << (
void*)&std::get< std::string >(f.
data) << std::endl;
738 std::cerr <<
"f.data>data " << (
void*)std::get< std::string >(f.
data).data() << std::endl;
740 f.
vp = (&std::get< std::string >(f.
data))->data();
741#ifdef ADC_GV_STR_DEBUG
742 std::cerr <<
"f.vp " << f.
vp << std::endl;
748 f.
data =
variant(
static_cast<float>(*(v->if_double())));
749 f.
vp = &std::get< float >(f.
data);
754 f.
vp = &std::get< double >(f.
data);
757#if ADC_SUPPORT_EXTENDED_FLOATS
762#if ADC_SUPPORT_QUAD_FLOATS
767#if ADC_SUPPORT_GPU_FLOATS
776 std::complex<float> cv(0,0);
778 float re = 0, im = 0;
779 auto a = v->as_array();
781 a[0].is_double() && a[1].is_double() ) {
782 re =
static_cast<float>(a[0].as_double());
783 im =
static_cast<float>(a[1].as_double());
788 f.
vp = &std::get< std::complex<float> >(f.
data);
793 std::complex<double> cv(0,0);
795 double re = 0, im = 0;
796 auto a = v->as_array();
800 re = a[0].as_double();
801 im = a[1].as_double();
806 f.
vp = &std::get< std::complex<double> >(f.
data);
810#if ADC_SUPPORT_EXTENDED_FLOATS
814#if ADC_SUPPORT_QUAD_FLOATS
821 std::array<int64_t, 2> av = {0,0};
823 int64_t sec = 0, subsec = 0;
824 auto a = v->as_array();
828 sec = a[0].as_int64();
829 subsec = a[1].as_int64();
834 f.
vp = &std::get< std::array<int64_t,2> >(f.
data);
850static void fill_array(field& f,
scalar_type st, boost::json::array& a) {
851 auto a_len = a.size();
853 std::shared_ptr<T[]> sa(
new T[a_len]);
856 for (i = 0; i < a_len; i++) {
857 if ( a[i].kind() == json_type) {
858 boost::system::error_code ec;
859 T x = a[i].to_number<T>(ec);
870 f.vp = (std::get< std::shared_ptr<T[]> >(f.data)).get();
874static void fill_array_u64(field& f, boost::json::array& a) {
875 auto a_len = a.size();
877 std::shared_ptr<uint64_t[]> sa(
new uint64_t[a_len]);
879 for (i = 0; i < a_len; i++) {
880 boost::json::string *s = a[i].if_string();
883 std::istringstream iss(ss);
896 f.vp = (std::get< std::shared_ptr<uint64_t[]> >(f.data)).get();
907static void fill_array_complex(field& f, boost::json::array& a) {
908 auto a_len = a.size();
910 std::shared_ptr<std::complex<T>[]> sa(
new std::complex<T>[a_len]);
912 for (i = 0; i < a_len; i++) {
913 if ( a[i].kind() == boost::json::kind::array) {
915 if (pair.as_array().size() != 2) {
919 boost::system::error_code ecr;
920 boost::system::error_code eci;
921 T re = pair.as_array()[0].to_number<T>(ecr);
922 T im = pair.as_array()[1].to_number<T>(eci);
923 if (!(ecr.failed() || eci.failed())) {
933 f.vp = (std::get< std::shared_ptr<std::complex<T>[]> >(f.data)).get();
941 auto a_len = a.size();
943 std::shared_ptr<bool[]> sa(
new bool[a_len]);
945 for (i = 0; i < a_len; i++) {
946 bool* bptr = a[i].if_bool();
954 f.
vp = (std::get< std::shared_ptr<bool[]> >(f.
data)).get();
959 auto a_len = a.size();
961 std::shared_ptr<std::string[]> sa(
new std::string[a_len]);
963 for (i = 0; i < a_len; i++) {
964 boost::json::string* sptr = a[i].if_string();
966 sa[i] = std::string(sptr->c_str());
968 sa[i] = std::string(
"");
972 f.
vp = (std::get< std::shared_ptr<std::string[]> >(f.
data)).get();
976static void get_array(field& f,
scalar_type st, boost::json::value *v)
978 if (!v->is_array()) {
982 auto a = v->as_array();
988 fill_array<char>(f, st, a);
991 fill_array<char16_t>(f, st, a);
994 fill_array<char32_t>(f, st, a);
997 fill_array<uint8_t>(f, st, a);
1000 fill_array<uint16_t>(f, st, a);
1003 fill_array<uint32_t>(f, st, a);
1006 fill_array_u64(f, a);
1009 fill_array<int8_t>(f, st, a);
1012 fill_array<int16_t>(f, st, a);
1015 fill_array<int32_t>(f, st, a);
1018 fill_array<int64_t>(f, st, a);
1031 fill_array<float>(f, st, a);
1034 fill_array<double>(f, st, a);
1036#if ADC_SUPPORT_EXTENDED_FLOATS
1041#if ADC_SUPPORT_QUAD_FLOATS
1046#if ADC_SUPPORT_GPU_FLOATS
1055 fill_array_complex<float>(f, a);
1058 fill_array_complex<double>(f, a);
1060#if ADC_SUPPORT_EXTENDED_FLOATS
1064#if ADC_SUPPORT_QUAD_FLOATS
1080 if (jit.kind() == boost::json::kind::object) {
1081 auto obj = jit.as_object();
1082 auto v = obj.if_contains(
"value");
1083 auto type_name_v = obj.if_contains(
"type");
1084 std::string type_name;
1086 type_name = *(type_name_v->if_string());
1088 if (v && type_name.size()) {
1089 auto c = obj.if_contains(
"container_type");
1093 get_scalar(f, st, v);
1098 get_array(f, st, v);
1103 if (jit.kind() == boost::json::kind::array) {
1107 if (jit.kind() == boost::json::kind::object) {
1111 if (jit.kind() == boost::json::kind::string) {
1114 f.
vp = jit.if_string()->c_str();
1115 f.
count = jit.if_string()->size();
1118 if (jit.kind() == boost::json::kind::bool_) {
1120 f.
vp = jit.if_bool();
1124 if (jit.kind() == boost::json::kind::int64) {
1126 f.
vp = jit.if_int64();
1130 if (jit.kind() == boost::json::kind::uint64) {
1132 f.
vp = jit.if_uint64();
1136 if (jit.kind() == boost::json::kind::double_) {
1138 f.
vp = jit.if_double();
1151void *builder::get_boost_json_value(std::string_view path)
1153 auto sit = sections.find(name);
1154 if (sit != sections.end())
1156 auto jit = d.find(name);
1159 boost::json::value jv = d.at_pointer(path);
1167 std::string commname = std::string(
"mpi_comm_") += name;
1169 if (*(MPI_Comm *)mpi_comm_p == MPI_COMM_NULL)
1171 MPI_Comm *comm = (MPI_Comm *)mpi_comm_p;
1172 boost::json::object jv;
1176 err = MPI_Comm_rank(*comm, &rank);
1178 jv[
"mpi_rank"] = rank;
1184 err = MPI_Comm_size(*comm, &size);
1186 jv[
"mpi_size"] = size;
1191 char name[MPI_MAX_OBJECT_NAME];
1193 err = MPI_Comm_get_name(*comm, name, &len);
1195 jv[
"mpi_name"] = name;
1199 int major=0, minor=0;
1201 err = MPI_Get_version(&major, &minor);
1202 std::ostringstream mversion;
1203 mversion << MPI_VERSION <<
"." << MPI_SUBVERSION;
1205 jv[
"mpi_version"] = mversion.str();
1211 std::ostringstream lversion;
1213#define USE_set_lib_version
1214 lversion <<
"OpenMPI " << OMPI_MAJOR_VERSION <<
"." <<
1215 OMPI_MINOR_VERSION <<
"." << OMPI_RELEASE_VERSION;
1216 goto set_lib_version;
1218#ifdef MVAPICH2_VERSION
1219#define USE_set_lib_version
1220 lversion << MVAPICH2_VERSION;
1221 goto set_lib_version;
1224#define USE_set_lib_version
1225 lversion << MPICH_VERSION;
1226 goto set_lib_version;
1230 char lv[MPI_MAX_LIBRARY_VERSION_STRING];
1232 err = MPI_Get_library_version(lv, &sz);
1234#ifdef USE_set_lib_version
1238 jv[
"mpi_library_version"] = lversion.str();
1244 err = MPI_Comm_rank(*comm, &rank);
1249 err = MPI_Comm_size(*comm, &size);
1253 char *hostnames = (
char *)calloc(size*MPI_MAX_PROCESSOR_NAME, 1);
1255 MPI_Get_processor_name(hostnames + rank * MPI_MAX_PROCESSOR_NAME, &nlen);
1256 MPI_Allgather(hostnames + rank * MPI_MAX_PROCESSOR_NAME,
1257 MPI_MAX_PROCESSOR_NAME,
1260 MPI_MAX_PROCESSOR_NAME,
1264 std::vector<std::string> rh;
1265 for (
auto i = 0; i < size; i++)
1266 rh.push_back(std::string(hostnames + rank * MPI_MAX_PROCESSOR_NAME));
1269 boost::json::array av(rh.begin(), rh.end());
1270 jv[
"mpi_rank_host"] = av;
1274 std::vector<std::string> hl;
1275 std::set<std::string> hm;
1276 for (
auto i = 0; i < size; i++)
1277 hm.insert(std::string(hostnames + rank * MPI_MAX_PROCESSOR_NAME));
1278 for (
auto i = 0; i < size; i++) {
1279 std::string stmp(hostnames + rank * MPI_MAX_PROCESSOR_NAME);
1280 if (hm.count(stmp)) {
1285 boost::json::array hv(hl.begin(), hl.end());
1286 jv[
"mpi_hostlist"] = hv;
1296 boost::json::object jv;
1299 jv[
"mpi_rank"] = rank;
1304 jv[
"mpi_size"] = size;
1308 jv[
"mpi_name"] =
"none";
1312 jv[
"mpi_version"] =
"none";
1316 jv[
"mpi_library_version"] =
"none";
1320 char myhost[HOST_NAME_MAX];
1321 int herr = gethostname(myhost, HOST_NAME_MAX);
1323 sprintf(myhost,
"name_unavailable");
1325 std::vector<std::string> rh;
1326 rh.push_back(myhost);
1327 boost::json::array av(rh.begin(), rh.end());
1330 jv[
"mpi_rank_host"] = av;
1334 jv[
"mpi_hostlist"] = av;
1343 std::vector< std::string >slurmvars;
1349 static std::vector< std::pair<const char *, const char *> > slurm_names =
1351 {
"cluster",
"SLURM_CLUSTER_NAME"},
1352 {
"job_id",
"SLURM_JOB_ID"},
1353 {
"num_nodes",
"SLURM_JOB_NUM_NODES"},
1354 {
"dependency",
"SLURM_JOB_DEPENDENCY"},
1357 boost::json::object jv;
1358 for (
const auto& i : slurm_names) {
1359 const char *val = getenv(i.second);
1365 for (
const auto& i : slurmvars) {
1366 const char *val = getenv(i.c_str());
1377 static std::vector< std::pair<const char *, const char *> > names =
1379 {
"wfid",
"ADC_WFID"},
1380 {
"wfid_parent",
"ADC_WFID_PARENT"},
1381 {
"wfid_path",
"ADC_WFID_PATH"}
1384 boost::json::object jv;
1385 for (
const auto& i : names) {
1386 const char *val = getenv(i.second);
1392 boost::json::array av;
1393 const char *cenv = getenv(
"ADC_WFID_CHILDREN");
1396 std::stringstream ss(cenv);
1399 while (getline(ss, elt, pathsep)) {
1400 if (elt.size() > 0) {
1401#ifdef ADC_WORKFLOW_DEBUG
1402 std::cerr << __func__ <<
": add child " << elt << std::endl;
1404 av.emplace_back(elt);
1408 jv[
"wfid_children"] = av;
1409 d[
"adc_workflow"] = jv;
1414 for (
const auto& v : av) {
1415 if (v.is_string() && v.as_string() == uuid) {
1424 auto wsection = d.if_contains(
"adc_workflow");
1426 std::cerr << __func__ <<
": called before add_workflow_section" << std::endl;
1429 if (! wsection->is_object()) {
1430 std::cerr << __func__ <<
": adc_workflow is not an object. (?!)" << std::endl;
1433 auto haschildren = wsection->as_object().if_contains(
"wfid_children");
1435 std::cerr << __func__ <<
": called before successful add_workflow_section" << std::endl;
1438 auto children = wsection->as_object()[
"wfid_children"];
1439 if (!children.is_array()) {
1440 std::cerr << __func__ <<
": wfid_children is not an array. (?!)" << std::endl;
1443 for (
auto const& uuid : child_uuids) {
1447 wsection->as_object()[
"wfid_children"].as_array().emplace_back(uuid);
1454 static const std::vector<std::string > gitlab_ci_names = {
1456 "CI_RUNNER_VERSION",
1460 "CI_SERVER_VERSION",
1462 "CI_JOB_STARTED_AT",
1464 "CI_PIPELINE_SOURCE",
1468 boost::json::object jv;
1469 for (
const auto& i : gitlab_ci_names) {
1470 const char *val = getenv(i.c_str());
1476 d[
"gitlab_ci"] = jv;
1480 boost::json::value jv = {
1488 boost::json::value jv = {
1496 uint64_t ivalue = value;
1497 boost::json::value jv = {
1505 uint64_t ivalue = value;
1506 boost::json::value jv = {
1515 boost::json::value jv = {
1522 boost::json::value jv = {
1529 boost::json::value jv = {
1536 boost::json::value jv = {
1545 boost::json::value jv = {
1552 boost::json::value jv = {
1559 boost::json::value jv = {
1566 boost::json::value jv = {
1575 boost::json::value jv = {
1583 boost::json::value jv = {
1591 boost::json::value jv = {
1599 boost::json::value jv = {
1606#if ADC_BOOST_JSON_PUBLIC
1607void builder::add(std::string_view name, boost::json::value value) {
1608 boost::json::value jv = {
1618 boost::json::value jv = {
1625 boost::json::value jv = {
1632 boost::json::value jv = {
1639 boost::json::value jv = {
1641 {
"value", std::to_string(value)}
1646 boost::json::value jv = {
1653 boost::json::value jv = {
1660 boost::json::value jv = {
1667 boost::json::value jv = {
1674 boost::json::value jv = {
1680void builder::add(std::string_view name,
const std::complex<float>& value) {
1681 boost::json::value jv = {
1683 {
"value", { value.real(), value.imag() }}
1688 boost::json::value jv = {
1694void builder::add(std::string_view name,
const std::complex<double>& value) {
1695 boost::json::value jv = {
1697 {
"value", { value.real(), value.imag() }}
1704 boost::json::value jv = {
1706 {
"value", { (int64_t)tv.tv_sec, (int64_t)tv.tv_usec }}
1712 boost::json::value jv = {
1714 {
"value", { (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec }}
1720 boost::json::value jv = {
1733 bool *v = (
bool *)p;
1739 char *v = (
char *)p;
1745 char16_t *v = (
char16_t *)p;
1751 char32_t *v = (
char32_t *)p;
1757 char *v = (
char *)p;
1763 char *v = (
char *)p;
1769 char *v = (
char *)p;
1775 char *v = (
char *)p;
1779#if ADC_BOOST_JSON_PUBLIC
1785 char *v = (
char *)p;
1791 char *v = (
char *)p;
1797 uint8_t *v = (uint8_t *)p;
1803 uint16_t *v = (uint16_t *)p;
1809 uint32_t *v = (uint32_t *)p;
1815 uint64_t *v = (uint64_t *)p;
1821 int8_t *v = (int8_t *)p;
1827 int16_t *v = (int16_t *)p;
1833 int32_t *v = (int32_t *)p;
1839 int64_t *v = (int64_t *)p;
1845 float *v = (
float *)p;
1851 double *v = (
double *)p;
1855#if ADC_SUPPORT_EXTENDED_FLOATS
1859 __float80 *v = (__float80 *)p;
1864#if ADC_SUPPORT_QUAD_FLOATS
1867 __float128 *v = (__float128 *)p;
1872#if ADC_SUPPORT_GPU_FLOATS
1896 float *v = (
float *)p;
1897 std::complex<float> c(v[0], v[1]);
1903 double *v = (
double *)p;
1904 std::complex<double> c(v[0], v[1]);
1908#if ADC_SUPPORT_QUAD_FLOATS
1911 __float128 *v = (__float128 *)p;
1912 std::complex<__float128> c(v[0], v[1]);
1917#if ADC_SUPPORT_EXTENDED_FLOATS
1921 __float80 *v = (__float80 *)p;
1922 std::complex<__float80> c(v[0], v[1]);
1929 struct timespec *v = (
struct timespec *)p;
1935 struct timeval *v = (
struct timeval *)p;
1941 int64_t *v = (int64_t *)p;
1951 boost::json::array av(value, value+len);
1952 boost::json::value jv = {
1954 {
"container_type", c},
1961 boost::json::array av(value, value+len);
1962 boost::json::value jv = {
1964 {
"container_type", c},
1971 boost::json::array av(value, value+len);
1972 boost::json::value jv = {
1974 {
"container_type", c},
1981 boost::json::array av(value, value+len);
1982 boost::json::value jv = {
1984 {
"container_type", c},
1991 boost::json::array av(value, value+len);
1992 boost::json::value jv = {
1994 {
"container_type", c},
2000 boost::json::array av(value, value+len);
2001 boost::json::value jv = {
2003 {
"container_type", c},
2009 boost::json::array av(value, value+len);
2010 boost::json::value jv = {
2012 {
"container_type", c},
2018 std::vector<std::string> sv(len);
2019 for (
size_t i = 0; i < len; i++)
2020 sv[i] = std::to_string(value[i]);
2021 boost::json::array av(sv.begin(), sv.end());
2022 boost::json::value jv = {
2024 {
"container_type", c},
2030 boost::json::array av(value, value+len);
2031 boost::json::value jv = {
2033 {
"container_type", c},
2039 boost::json::array av(value, value+len);
2040 boost::json::value jv = {
2042 {
"container_type", c},
2048 boost::json::array av(value, value+len);
2049 boost::json::value jv = {
2051 {
"container_type", c},
2057 boost::json::array av(value, value+len);
2058 boost::json::value jv = {
2060 {
"container_type", c},
2066 boost::json::array av(value, value+len);
2067 boost::json::value jv = {
2069 {
"container_type", c},
2075void builder::add_array(std::string_view name,
const std::complex<float> value[],
size_t len, std::string_view c) {
2076 boost::json::array av(value, value+len);
2077 boost::json::value jv = {
2079 {
"container_type", c},
2080 {
"value", { value.real(), value.imag() }}
2086 boost::json::array av(value, value+len);
2087 boost::json::value jv = {
2089 {
"container_type", c},
2095void builder::add_array(std::string_view name,
const std::complex<double> value[],
size_t len, std::string_view c) {
2096 boost::json::array av(value, value+len);
2097 boost::json::value jv = {
2099 {
"container_type", c},
2100 {
"value", { value.real(), value.imag() }}
2107 boost::json::array av(value, value+len);
2108 boost::json::value jv = {
2110 {
"container_type", c},
2116 boost::json::array av(value, value+len);
2117 boost::json::value jv = {
2119 {
"container_type", c},
2125 boost::json::array av(value, value+len);
2126 boost::json::value jv = {
2128 {
"container_type", c},
2133void builder::add_array(std::string_view name,
const std::string value[],
size_t len, std::string_view c) {
2134 boost::json::array av(value, value+len);
2135 boost::json::value jv = {
2137 {
"container_type", c},
2142void builder::add_array(std::string_view name,
const std::vector<std::string> value, std::string_view c) {
2143 boost::json::value jv = {
2145 {
"container_type", c},
2146 {
"value", boost::json::value_from(value)}
2151 boost::json::value jv = {
2153 {
"container_type", c},
2154 {
"value", boost::json::value_from(value)}
2159 boost::json::value jv = {
2161 {
"container_type", c},
2162 {
"value", boost::json::value_from(value)}
2168 boost::json::array av(value, value+len);
2169 boost::json::value jv = {
2171 {
"container_type", c},
2181boost::json::object builder::flatten()
2183 boost::json::object tot(d);
2184 for (
auto it = sections.begin(); it != sections.end(); it++) {
2185 tot[it->first] = it->second->flatten();
2191 boost::json::object total;
2193 return boost::json::serialize(total);
2196key_type builder::kind(std::string_view name) {
2197 auto sit = sections.find(std::string(name));
2198 if (sit != sections.end())
2200 auto jit = d.find(name);
std::shared_ptr< builder_api > get_section(std::string_view name)
get the existing named section
std::vector< std::string > get_section_names()
get the names of sections
builder(void *mpi_communicator_p=NULL)
void add_json_string(std::string_view name, std::string_view value)
add string which is serialized json.
void add_mpi_section(std::string_view name, void *mpi_comm_p, adc_mpi_field_flags bitflags)
add data about a named mpi communicator. In most applications, "mpi_comm_world" is the recommended na...
void add_code_configuration_section(std::shared_ptr< builder_api > build_details)
Populate build/install "configuration" information such as options enabled.
void add_model_data_section(std::shared_ptr< builder_api > model_data)
populate application run-time physics (re)configuration/result to "model_data" section....
void add_array_json_string(std::string_view name, const std::string value[], size_t len, std::string_view c)
Add Array of strings which are serialized json.
void add_xml_string(std::string_view name, std::string_view value)
add string which is xml.
void add_yaml_string(std::string_view name, std::string_view value)
add string which is yaml.
void add(std::string_view name, bool value)
add a named boolean
void add_host_section(int32_t subsections)
auto-populate the "host" section based on bitflags. There are many optional subsections covering cpus...
const field get_value(std::string_view name)
get the existing named field in the section.
void add_workflow_section()
add data from adc_wfid_ environment variables. The section name is "adc_workflow".
void add_array(std::string_view name, bool value[], size_t len, std::string_view c)
Fixed length arrays of scalar members.
void add_from_pointer_type(std::string_view name, void *, enum scalar_type t)
add data from a c pointer
void add_number_string(std::string_view name, std::string_view value)
add string which is an arbitrary precision decimal number
void add_gitlab_ci_section()
add gitlab_ci environment variable dictionary. The section added is named "gitlab_ci".
void add_section(std::string_view name, std::shared_ptr< builder_api > section)
copy populated generic section into the builder under specified name.
void add_memory_usage_section()
populate "memory_usage" section with current host /proc/meminfo data in the style of free(1).
void add_code_section(std::string tag, std::shared_ptr< builder_api > version, std::shared_ptr< builder_api > code_details)
std::vector< std::string > get_field_names()
get the names of non-section fields in the section
void add_slurm_section()
add slurm output environment variable dictionary elements. The section added is named "slurm".
void add_exit_data_section(int return_code, std::string status, std::shared_ptr< builder_api > status_details)
populate "exit_data" section with code and status stream and user provided details.
void add_epoch(std::string_view name, int64_t epoch)
add unix epoch seconds (gettimeofday)
void add_app_data_section(std::shared_ptr< builder_api > app_data)
create the "app_data" section with data defined by the application writer.
void add_path(std::string_view name, char *value)
add null-terminated string filepath
std::string serialize()
convert object to a json string reflecting the section hierarchy.
void add_workflow_children(std::vector< std::string > &child_uuids)
add list of child uuids to "adc_workflow" section after add_workflow_section has been called....
void add_header_section(std::string_view application_name)
auto-populate the "header" section with application name and required local data
static pipe_data run(const std::string &proc)
std::string get_default_affinity()
std::string format_timespec_utc_ns(struct timespec &ts)
key_type
when expanding scalar_type, always update enum.ipp to match.
scalar_type scalar_type_from_name(const std::string &name)
get the enum representation of a scalar_type string
version enum_version("1.0.0", {"none"})
the version number of enum scalar_type and object_type
std::variant< bool, char, char16_t, char32_t, int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t, float, double, std::complex< float >, std::complex< double >, std::array< int64_t, 2 >, std::string, std::shared_ptr< bool[]>, std::shared_ptr< char[]>, std::shared_ptr< char16_t[]>, std::shared_ptr< char32_t[]>, std::shared_ptr< int8_t[]>, std::shared_ptr< int16_t[]>, std::shared_ptr< int32_t[]>, std::shared_ptr< int64_t[]>, std::shared_ptr< uint8_t[]>, std::shared_ptr< uint16_t[]>, std::shared_ptr< uint32_t[]>, std::shared_ptr< uint64_t[]>, std::shared_ptr< float[]>, std::shared_ptr< double[]>, std::shared_ptr< std::complex< float >[]>, std::shared_ptr< std::complex< double >[]>, std::shared_ptr< std::string[]> > variant
variant for querying builder data.
const std::string to_string(float f)
get string of float using to_chars.
std::string format_timespec_8601(struct timespec &ts)
scalar_type
field types for scientific data encode/decode with json.
@ cp_xml_str
c null-terminated string that contains valid xml
@ cp_epoch
time(NULL) seconds since the epoch (UNIX) as int64_t
@ cp_f16_e8m7
16 bit bfloat (7 mantissa, 8 exponent); requires ADC_SUPPORT_GPU_FLOATS support
@ cp_path
c null-terminated string which names a file-system path
@ cp_json_str
c null-terminated string that contains valid json
@ cp_timespec
(second, nanosecond) as int64_t, int64_t pair from clock_gettime
@ cp_timeval
gettimeofday struct timeval (second, microsecond) as int64_t pair
@ cp_c_f64
complex<double>
@ cp_bool
bool (true/false,1/0)
@ cp_f128
128 bit float; requires ADC_SUPPORT_QUAD_FLOATS support
@ cp_json
json value (object, list, etc)
@ cp_c_f80
complex<extended>; requires ADC_SUPPORT_EXTENDED_FLOATS support
@ cp_number_str
c null-terminated string containing an exact decimal representation of arbitrary precision
@ cp_f80
80 bit float; requires ADC_SUPPORT_EXTENDED_FLOATS support
@ cp_yaml_str
c null-terminated string that contains valid yaml
@ cp_f16_e5m10
16 bit float (10 mantissa, 5 exponent); requires ADC_SUPPORT_GPU_FLOATS support
@ cp_c_f128
complex<quad>; requires ADC_SUPPORT_QUAD_FLOATS support
@ cp_cstr
c null-terminated string
@ cp_f8_e5m2
8 bit float (2 mantissa, 5 exponent); requires ADC_SUPPORT_GPU_FLOATS support
@ cp_f8_e4m3
8 bit float (3 mantissa, 4 exponent); requires ADC_SUPPORT_GPU_FLOATS support
#define ADC_HS_GPU
ADC_HS_GPU collects gpu data available from lspci (requires lspci installed)
#define ADC_HS_RAMSIZE
ADC_HS_RAMSIZE collects MemTotal.
#define ADC_HS_OS
ADC_HS_OS collects other items from uname().
#define ADC_HS_CPU
ADC_HS_CPU collects details from lscpu -J (requires lscpu installed)
#define ADC_HS_NUMA
ADC_HS_NUMA collects numa node, cpu, and per node memory from numactl -H (requires numactl installed)
#define ADC_HS_ENV
ADC_HS_ENV collects env vars listed in env("ADC_HOST_SECTION_ENV") which is :-separated....
#define ADC_MPI_NAME
include "mpi_name" field from mpi_comm_name
#define ADC_MPI_RANK
include "mpi_rank" field from mpi_comm_rank
#define ADC_MPI_VER
include "mpi_version" field from MPI_VERSION.MPI_SUBVERSIUON
#define ADC_MPI_LIB_VER
include mpi_get_library_version result.
int32_t adc_mpi_field_flags
#define ADC_MPI_RANK_HOST
include "mpi_rank_host" subsection from the communicator
#define ADC_MPI_SIZE
include "mpi_size" field from mpi_comm_size
#define ADC_MPI_NONE
include no mpi fields
#define ADC_MPI_HOSTLIST
include "mpi_hostlist" subsection from the communicator
boost::json::object get_gpu_data()
boost::json::kind scalar_type_representation(scalar_type st)
void fill_array_bool(field &f, boost::json::array &a)
std::string get_exe(size_t bufsize)
std::string_view string_view
void fill_array_string(field &f, boost::json::array &a)
std::vector< std::string > get_libs(std::string_view)
boost::json::object get_numa_hardware()
std::vector< std::string > split_string(const std::string &s, char delimiter)
std::string tolower_s(std::string s)
bool array_contains_string(boost::json::array &av, string_view uuid)
std::string container
name of the container variety given to see builder::add_array
scalar_type st
scalar type of the data as published,
size_t count
number of elements in vp.
key_type kt
kind of data associated with the name queried
const void * vp
address of data to be cast according to st for use with c/fortran
A version with tags list.