The Sparta Modeling Framework
Loading...
Searching...
No Matches
BinaryOArchive.hpp
1// <BinaryOArchive> -*- C++ -*-
2
3#pragma once
4
5#include "sparta/statistics/dispatch/archives/ArchiveSink.hpp"
6#include "sparta/statistics/dispatch/archives/RootArchiveNode.hpp"
7#include "sparta/statistics/dispatch/archives/ArchiveNode.hpp"
8
9#include <fstream>
10#include <filesystem>
11
12#include <boost/archive/binary_oarchive.hpp>
13
14namespace sparta {
15namespace statistics {
16
22{
23public:
24 //One-time initialization. Open output files and serialize
25 //the archive tree to a metadata file for future use.
26 void initialize() override {
27 const std::string & path = getPath();
28 const std::string & subpath = getSubpath();
29 createArchiveDirectory_(path, subpath);
30 openBinaryArchiveFile_(path, subpath);
31
32 //If this sink has a root archive node attached
33 //to it, we should serialize it to disk now. This
34 //will let us reconstruct the same archive tree later
35 //on when we want to attach to an archive outside of
36 //a simulation.
37 RootArchiveNode * root = getRoot_();
38 if (root) {
39 serializeArchiveTree_(*root, path, subpath);
40 }
41 }
42
43 //Copy metadata files from one archive to another. This may
44 //occur during actions such as saving/re-saving an archive to
45 //a different directory.
46 void copyMetadataFrom(const ArchiveStream * stream) override
47 {
48 const std::string & source_path = stream->getPath();
49 const std::string & source_subpath = stream->getSubpath();
50 const std::string source_full_path = source_path + "/" + source_subpath;
51
52 const std::string source_tree_filename = source_full_path + "/archive_tree.bin";
53 if (!std::filesystem::exists(source_tree_filename)) {
54 throw SpartaException(
55 "Metadata file not available for read: ") << source_tree_filename;
56 }
57
58 const std::string & dest_path = getPath();
59 const std::string & dest_subpath = getSubpath();
60 const std::string dest_full_path = dest_path + "/" + dest_subpath;
61
62 const std::string dest_tree_filename = dest_full_path + "/archive_tree.bin";
63 if (std::filesystem::exists(dest_tree_filename)) {
64 std::filesystem::remove(dest_tree_filename);
65 }
66
67 std::filesystem::copy_file(source_tree_filename, dest_tree_filename);
68 }
69
70 //Put one vector of statistics data values into the binary file
71 void sendToSink(const std::vector<double> & values) override {
72 if (!values.empty()) {
73 binary_fout_.write(reinterpret_cast<const char*>(
74 &values[0]), values.size() * sizeof(double));
75 }
76 }
77
78 //Flush the file buffer. This action is performed whenever the
79 //archive system needs to synchronize all data sources/sinks,
80 //for example if a call is made to one of the "getData()" methods
81 //during a live simulation.
82 void flush() override {
83 binary_fout_.flush();
84 }
85
86private:
87 void createArchiveDirectory_(const std::string & path,
88 const std::string & subpath) const
89 {
90 std::filesystem::create_directories(path + "/" + subpath);
91 }
92
93 void openBinaryArchiveFile_(const std::string & path,
94 const std::string & subpath)
95 {
96 const std::string binary_filename = path + "/" + subpath + "/values.bin";
97 if (std::filesystem::exists(binary_filename)) {
98 std::filesystem::remove(binary_filename);
99 }
100
101 binary_fout_.open(binary_filename, std::ios::binary);
102 if (!binary_fout_) {
103 throw SpartaException(
104 "Unable to open archive file for write: ") << binary_filename;
105 }
106
107 auto root = getRoot_();
108 if (root) {
109 root->setMetadataValue("output_filename", binary_filename);
110 }
111 }
112
113 //Serialize the root archive node (and all of its children
114 //and metadata) to an auxiliary file in the archive directory.
115 //We need this metadata later in order to rebuild this tree
116 //when we connect to archives offline (no simulation, no
117 //streaming statistics... just a Python shell, for instance)
118 void serializeArchiveTree_(const RootArchiveNode & root,
119 const std::string & path,
120 const std::string & subpath) const
121 {
122 const std::string filename = path + "/" + subpath + "/archive_tree.bin";
123 if (std::filesystem::exists(filename)) {
124 std::filesystem::remove(filename);
125 }
126
127 std::ofstream fout(filename, std::ios::binary);
128 if (!fout) {
129 throw SpartaException(
130 "Unable to open archive file for write: ") << filename;
131 }
132
133 boost::archive::binary_oarchive oa(fout);
134 oa << root;
135 }
136
137 std::ofstream binary_fout_;
138};
139
140} // namespace statistics
141} // namespace sparta
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Generic statistic sink base class for report archives.
Generic statistic stream base class for sources and sinks in the report archive system.
Use a binary archive file as a destination for statistics values.
There is one of these root node objects at the top of each report's archive. The hierarchy looks like...
Macros for handling exponential backoff.