← Documentation
ADS-IDAC Engine 5.0.0
RestartTrim.h
Go to the documentation of this file.
1
40#pragma once
41
42#include <cstdint>
43#include <cstring>
44#include <vector>
45
46namespace adsidac {
47
51 std::size_t header_end = 0;
52 std::size_t base = 0;
53 std::size_t base_end = 0;
54 std::size_t target = 0;
55 std::size_t target_end = 0;
56 bool have_header = false;
57 bool have_base = false;
58 bool have_target = false;
59};
60
70inline RestartLayout scan_restart(const std::vector<char>& buf, std::int32_t want)
71{
72 auto rd32 = [](const char* p) { std::int32_t v; std::memcpy(&v, p, 4); return v; };
74 std::size_t p = 0, prev = 0;
75
76 while (p + 8 <= buf.size()) {
77 const std::int32_t reclen = rd32(&buf[p]);
78 if (reclen < 0 || p + 8 + static_cast<std::size_t>(reclen) > buf.size()) break;
79
80 if (reclen == 24 && std::memcmp(&buf[p + 4], "restart ", 8) == 0) {
81 // The dump starts at the 8-byte header record just before this one.
82 const std::size_t start = prev;
83 const bool complete = (rd32(&buf[p + 4 + 8]) & 16) != 0;
84 if (!L.have_header) { L.header_end = start; L.have_header = true; }
85 if (L.have_base && L.base_end == 0) L.base_end = start;
86 if (L.have_target && L.target_end == 0) L.target_end = start;
87 if (complete && !L.have_base) { L.base = start; L.have_base = true; L.base_end = 0; }
88 if (want >= 0 && rd32(&buf[p + 4 + 16]) == want && !L.have_target) {
89 L.target = start; L.have_target = true; L.target_end = 0;
90 }
91 }
92 prev = p;
93 p += 8 + static_cast<std::size_t>(reclen);
94 }
95 if (L.have_base && L.base_end == 0) L.base_end = buf.size();
96 if (L.have_target && L.target_end == 0) L.target_end = buf.size();
97 return L;
98}
99
105inline bool has_complete_restart(const std::vector<char>& buf)
106{
107 return scan_restart(buf, -1).have_base;
108}
109
113inline std::vector<char> extract_header_and_base(const std::vector<char>& buf)
114{
115 const RestartLayout L = scan_restart(buf, -1);
116 if (!L.have_header || !L.have_base) return {};
117 std::vector<char> out;
118 out.reserve(L.header_end + (L.base_end - L.base));
119 out.insert(out.end(), buf.begin(), buf.begin() + L.header_end);
120 out.insert(out.end(), buf.begin() + L.base, buf.begin() + L.base_end);
121 return out;
122}
123
132inline std::vector<char> extract_record_no_base(const std::vector<char>& buf, std::int32_t want)
133{
134 const RestartLayout L = scan_restart(buf, want);
135 if (!L.have_header || !L.have_target) return {};
136 if (L.target_end <= L.target || L.target_end > buf.size()) return {};
137 std::vector<char> out;
138 out.reserve(L.header_end + (L.target_end - L.target));
139 out.insert(out.end(), buf.begin(), buf.begin() + L.header_end);
140 out.insert(out.end(), buf.begin() + L.target, buf.begin() + L.target_end);
141 return out;
142}
143
150inline std::vector<char> splice_base(const std::vector<char>& hdr_base,
151 const std::vector<char>& body)
152{
153 const RestartLayout B = scan_restart(body, -1);
154 if (!B.have_header) return {};
155 std::vector<char> out;
156 out.reserve(hdr_base.size() + (body.size() - B.header_end));
157 out.insert(out.end(), hdr_base.begin(), hdr_base.end());
158 out.insert(out.end(), body.begin() + B.header_end, body.end());
159 return out;
160}
161
168inline std::vector<char> extract_restart_record(const std::vector<char>& buf, std::int32_t want)
169{
170 const RestartLayout L = scan_restart(buf, want);
171 if (!L.have_header || !L.have_target || !L.have_base) return {};
172 if (L.target_end <= L.target || L.target_end > buf.size()) return {};
173 if (L.base_end <= L.base || L.base_end > buf.size()) return {};
174
175 const bool target_is_base = (L.target == L.base);
176 std::vector<char> out;
177 out.reserve(L.header_end + (L.base_end - L.base)
178 + (target_is_base ? 0 : L.target_end - L.target));
179 out.insert(out.end(), buf.begin(), buf.begin() + L.header_end);
180 out.insert(out.end(), buf.begin() + L.base, buf.begin() + L.base_end);
181 if (!target_is_base)
182 out.insert(out.end(), buf.begin() + L.target, buf.begin() + L.target_end);
183 return out;
184}
185
186} // namespace adsidac
RestartLayout scan_restart(const std::vector< char > &buf, std::int32_t want)
Walk the record chain and locate the header, the base dump and the target dump.
Definition: RestartTrim.h:70
std::vector< char > extract_restart_record(const std::vector< char > &buf, std::int32_t want)
[header][complete base][target]: self-contained, no cache needed.
Definition: RestartTrim.h:168
std::vector< char > splice_base(const std::vector< char > &hdr_base, const std::vector< char > &body)
Put the cached base back in front of a base-less transfer.
Definition: RestartTrim.h:150
std::vector< char > extract_record_no_base(const std::vector< char > &buf, std::int32_t want)
[header][target], the wire payload with the base omitted.
Definition: RestartTrim.h:132
std::vector< char > extract_header_and_base(const std::vector< char > &buf)
[header][complete base], the run-wide constant that is cached per rank and published as <project>/res...
Definition: RestartTrim.h:113
bool has_complete_restart(const std::vector< char > &buf)
Does this buffer contain a complete restart dump (the base)?
Definition: RestartTrim.h:105
Byte offsets of the structural landmarks in a restart buffer. An offset is meaningful only when its h...
Definition: RestartTrim.h:50
std::size_t base
start of the first COMPLETE restart dump
Definition: RestartTrim.h:52
std::size_t base_end
one past it (start of the next dump, or the buffer size)
Definition: RestartTrim.h:53
bool have_header
at least one dump was found
Definition: RestartTrim.h:56
bool have_base
a complete restart dump was found
Definition: RestartTrim.h:57
std::size_t target
start of the first dump whose ncount equals want
Definition: RestartTrim.h:54
bool have_target
a dump with ncount == want was found
Definition: RestartTrim.h:58
std::size_t header_end
end of header + plot-id block = start of first dump
Definition: RestartTrim.h:51
std::size_t target_end
one past it (start of the next dump, or the buffer size)
Definition: RestartTrim.h:55