14#include "../Branch/BranchRecord.h"
15#include "../ParallelExec/ParallelGlobal.h"
17#include <boost/archive/binary_oarchive.hpp>
18#include <boost/archive/binary_iarchive.hpp>
19#include <boost/serialization/map.hpp>
20#include <boost/serialization/vector.hpp>
21#include <boost/serialization/string.hpp>
22#include <boost/serialization/shared_ptr.hpp>
31 template<
class Archive>
112 template<
class Archive>
152 std::ostringstream oss(std::ios::binary);
153 boost::archive::binary_oarchive oa(oss);
163 boost::archive::binary_iarchive ia(iss);
184 auto v =
lz4_compress(s.data(),
static_cast<int>(s.size()));
185 return std::string(v.data(), v.size());
191 return std::string(v.data(), v.size());
196 std::ostringstream oss(std::ios::binary);
198 boost::archive::binary_oarchive oa(oss);
206 static std::shared_ptr<RestartNodeInfo>
unpack_rinfo(
const std::string& blob) {
207 auto ri = std::make_shared<RestartNodeInfo>();
209 std::istringstream iss(raw, std::ios::binary);
210 boost::archive::binary_iarchive ia(iss);
227 void save(
const std::string& path) {
235 std::map<const RestartNodeInfo*, int> idx;
236 auto pack_of = [&](
const std::shared_ptr<RestartNodeInfo>& ri) ->
int {
238 auto it = idx.find(ri.get());
239 if (it != idx.end())
return it->second;
242 idx.emplace(ri.get(), i);
257 if (blob.empty())
continue;
258 auto c =
lz4_compress(blob.data(),
static_cast<int>(blob.size()));
270 const std::string tmp_path = path +
".tmp";
272 std::ofstream ofs(tmp_path, std::ios::binary);
274 std::cerr <<
"ERROR: cannot open checkpoint file for writing: " << tmp_path << std::endl;
277 boost::archive::binary_oarchive oa(ofs);
281 std::cerr <<
"ERROR: checkpoint write failed (disk full?): " << tmp_path << std::endl;
284 std::filesystem::remove(tmp_path, ec);
289 std::filesystem::rename(tmp_path, path, ec);
291 std::cerr <<
"ERROR: cannot move checkpoint into place: " << ec.message() << std::endl;
294 std::cout <<
"[CHECKPOINT] Saved: " << path
314 std::ifstream ifs(path, std::ios::binary);
318 std::cerr <<
"FATAL: cannot open checkpoint file for reading: " << path << std::endl;
322 boost::archive::binary_iarchive ia(ifs);
324 }
catch (
const std::exception& ex) {
325 std::cerr <<
"FATAL: checkpoint file is corrupt or truncated: " << path
326 <<
" (" << ex.what() <<
")" << std::endl;
329 const int stored_version = ckpt.
version;
331 std::cerr <<
"FATAL: checkpoint version " << stored_version
332 <<
" is older than the format this binary reads (version "
334 <<
" be read by this binary. Finish that run with the binary that\n"
335 <<
" wrote it, or start a fresh run." << std::endl;
342 if (stored_version >= 7) {
343 std::vector<std::shared_ptr<RestartNodeInfo>> uniques;
349 (ref >= 0 && ref < (int)uniques.size()) ? uniques[ref] :
nullptr;
354 (ref >= 0 && ref < (
int)uniques.size()) ? uniques[ref] :
nullptr);
366 if (blob.empty())
continue;
367 auto d =
lz4_decompress(blob.data(),
static_cast<int>(blob.size()));
std::vector< char > lz4_compress(const char *data, int size)
LZ4-compress a buffer with a 4-byte original-size header.
std::vector< char > lz4_decompress(const char *data, int size)
LZ4-decompress a buffer that has a 4-byte original-size header.
Checkpoint/restart state snapshot — captures entire C++ simulation state at a branching point.
Complete state of a dynamic event tree run at a sequence boundary.
static std::string pack_rinfo(const RestartNodeInfo &ri)
Serialize one snapshot (Boost binary archive) and LZ4-compress it.
std::vector< int > task_state_pack_ref
task position -> packed index (-1 = null)
static std::string lz4_unpack_string(const std::string &s)
Inverse of lz4_pack_string(). Exits the process (lz4_decompress) if s does not decompress to its reco...
std::map< int, std::string > branch_record_blobs
cid -> serialized BranchRecord of the holding client; filled by the MPI writer only and used there to...
std::map< int, std::vector< char > > source_blobs
source key -> restart blob
static std::shared_ptr< RestartNodeInfo > unpack_rinfo(const std::string &blob)
Inverse of pack_rinfo(). Deserialization pre-seeds the snapshot from the process-local shared masters...
bool config_matches(uint64_t current) const
Does this checkpoint's configuration digest match current, the digest of the running process (g_sim....
std::vector< SequenceReport > completed_reports
Reports of finished sequences (filled only when the visualization server is on)
static bool version_supported(int v)
Whether load() accepts a file with stored version v.
void serialize(Archive &ar, unsigned int)
Boost serialization of the archive layout.
static std::string lz4_pack_string(const std::string &s)
LZ4-compress s with the 4-byte size header of lz4_compress().
int sequences_completed
Sequences finished when the checkpoint was taken.
std::string branch_center_blob
uint64_t config_fingerprint
void save(const std::string &path)
Write the checkpoint to path.
std::vector< PendingBranch > pending_tasks
Unexplored branches.
static constexpr int VERSION
std::vector< std::string > packed_rinfos
lz4(serialized rinfo), one per unique snapshot
std::map< int, std::shared_ptr< RestartNodeInfo > > restart_states
cid -> snapshot; read by serial resume
void capture_branch_center(const BranchRecord &br)
Serialize br (Boost binary archive) into branch_center_blob, replacing its previous content.
void restore_branch_center(BranchRecord &br) const
Deserialize branch_center_blob into br. The blob must be uncompressed, as load() leaves it; a Boost a...
static DETCheckpoint load(const std::string &path)
Read a checkpoint file.
std::map< int, int > cid_source
int version
Format version stored in the archive.
std::vector< std::shared_ptr< RestartNodeInfo > > task_restart_states
Snapshot per pending task (null = none); read by MPI resume.
std::map< int, int > restart_state_pack_ref
cid -> packed index (-1 = null entry)
std::vector< std::string > task_branch_blobs
Always empty; resume dispatches branch_center_blob.
One unexplored branch recorded in a checkpoint.
void serialize(Archive &ar, unsigned int)
int cid
Branch cluster ID the branch belongs to.
int sequence_id
Global sequence ID already assigned by the MPI server; 0 = assign at dispatch (serial checkpoints)
int parent_sequence_id
Sequence that generated the branch point (-1 = unknown)
int branch_index
Index of the alternative within the cluster (1..N-1)