Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #pragma once 11 : 12 : #include "RestartableDataIO.h" 13 : 14 : #include "RestartableData.h" 15 : #include "InputStream.h" 16 : #include "MoosePassKey.h" 17 : 18 : #include <sstream> 19 : #include <utility> 20 : 21 : /** 22 : * Reader for restartable data written by the RestartableDataWriter. 23 : */ 24 : class RestartableDataReader : public RestartableDataIO 25 : { 26 : public: 27 : RestartableDataReader(MooseApp & app, RestartableDataMap & data, const bool force = false); 28 : RestartableDataReader(MooseApp & app, 29 : std::vector<RestartableDataMap> & data, 30 : const bool force = false); 31 : 32 : /** 33 : * Structure that contains the input streams for the reader. 34 : * One for the header and one for the data. 35 : */ 36 : struct InputStreams 37 : { 38 : std::unique_ptr<InputStream> header; 39 : std::unique_ptr<InputStream> data; 40 : }; 41 : 42 : /** 43 : * Sets the input stream for reading from the stringstreams \p header_stream 44 : * and \p data_stream for the header and data, respectively. 45 : */ 46 : void setInput(std::unique_ptr<std::stringstream> header_stream, 47 : std::unique_ptr<std::stringstream> data_stream); 48 : /** 49 : * Sets the input stream for reading to the file with the folder base \p folder_base 50 : */ 51 : void setInput(const std::filesystem::path & folder_base); 52 : 53 : /** 54 : * @return Whether or not this reader is currently restoring 55 : */ 56 96003 : bool isRestoring() const { return _streams.data != nullptr; } 57 : 58 : /** 59 : * Restores \p value in place from the open reader if it is present in the checkpoint and 60 : * has not yet been loaded. Used to recover data (e.g. reporter values) that is declared 61 : * after the bulk restore pass while the reader window is still open. 62 : * 63 : * Requires that restore() has been called. 64 : * 65 : * @return Whether or not the value was restored 66 : */ 67 : bool restoreDataIfAvailable(RestartableDataValue & value, 68 : const THREAD_ID tid, 69 : Moose::PassKey<MooseApp>); 70 : 71 : /** 72 : * Clears the contents of the reader (header stream, data stream, header) 73 : * 74 : * This returns ownership of the resulting input in the event that 75 : * it should be retained 76 : */ 77 : InputStreams clear(); 78 : 79 : /** 80 : * Restores the restartable data. The input must be set via setInput() first. 81 : * 82 : * A handle to the input is still kept after this restore is called! In order to 83 : * remove that handle, you must call clear()! 84 : * 85 : * @param filter_names A list of data names to only restore. If not provided, 86 : * restores all. 87 : */ 88 : void restore(const DataNames & filter_names = {}); 89 : 90 : /** 91 : * Restores the data with name \p data_name of type T. 92 : * 93 : * This is used to restore data that was never declared in the restart, 94 : * but was stored in the backup. You cannot call this if the data has 95 : * already been declared or restored. 96 : * 97 : * Requires that restore() is called first to load the headers. 98 : * 99 : * @param data_name The name of the data 100 : * @param tid The thread 101 : * @param context The data context (if any) 102 : * @param args Arguments to forward to the constructor of the object 103 : * @return The restored data 104 : */ 105 : template <typename T, typename... Args> 106 : T & restoreData(const std::string & data_name, 107 : const THREAD_ID tid = 0, 108 : void * const context = nullptr, 109 : Args &&... args); 110 : 111 : ///@{ 112 : /* 113 : * Enable/Disable errors to allow meta data to be created/loaded on different number or 114 : * processors 115 : * 116 : * See LoadSurrogateModelAction for use case 117 : */ 118 3580 : void setErrorOnLoadWithDifferentNumberOfProcessors(bool value) 119 : { 120 3580 : _error_on_different_number_of_processors = value; 121 3580 : } 122 : ///@} 123 : 124 : /** 125 : * @return Whether or not restartable data is available in the folder \p folder_base 126 : * 127 : * Will error if the header is available and the data is not, or if the data is 128 : * and the header is not. 129 : */ 130 : static bool isAvailable(const std::filesystem::path & folder_base); 131 : 132 : /** 133 : * @return Whether or not data exists in the headers with the name 134 : * \p data_name with type T on thread \p tid 135 : * 136 : * Requires that restore() is called first to load the headers. 137 : */ 138 : template <typename T> 139 42 : bool hasData(const std::string & data_name, const THREAD_ID tid = 0) const 140 : { 141 42 : return hasData(data_name, typeid(T), tid); 142 : } 143 : 144 : private: 145 : /** 146 : * Struct that describes data in the header 147 : */ 148 : struct HeaderEntry 149 : { 150 : /// The position in the stream at which this data is 151 : std::streampos position; 152 : /// The size of this data 153 : std::size_t size; 154 : /// The hash code for this data (typeid(T).hash_code()) 155 : std::size_t type_hash_code; 156 : /// The type for this data 157 : std::string type; 158 : /// Whether or not this data had context 159 : bool has_context; 160 : }; 161 : 162 : /** 163 : * @return Whether or not data exists in the headers with the name 164 : * \p data_name with type \p type on thread \p tid 165 : * 166 : * Requires that restore() is called first to load the headers. 167 : */ 168 : bool 169 : hasData(const std::string & data_name, const std::type_info & type, const THREAD_ID tid) const; 170 : 171 : /** 172 : * Internal method for reading the header (stored by RestartableDataWriter) 173 : */ 174 : std::vector<std::unordered_map<std::string, HeaderEntry>> 175 : readHeader(InputStream & header_input) const; 176 : 177 : /** 178 : * Internal method for deserializing (restoring from backup into a value) 179 : */ 180 : void deserializeValue(InputStream & data_input, 181 : RestartableDataValue & value, 182 : const HeaderEntry & header_entry) const; 183 : 184 : /** 185 : * Checks whether or not we're currently restoring and errors if not 186 : */ 187 : void requireRestoring() const; 188 : 189 : /** 190 : * @return The header entry for the data with name \p data_name on thread \p tid 191 : * if it exists, and nullptr otherwise. 192 : * 193 : * Requires that restore() is called first to load the headers. 194 : */ 195 : const HeaderEntry * queryHeader(const std::string & data_name, const THREAD_ID tid) const; 196 : /** 197 : * @return The header entry for the data with name \p data_name on thread \p tid. 198 : * 199 : * Requires that restore() is called first to load the headers. 200 : */ 201 : const HeaderEntry & getHeader(const std::string & data_name, const THREAD_ID tid) const; 202 : 203 : /** 204 : * @returns Whether or not the type \p type is the same as the type in \p header_entry 205 : * 206 : * We need this because this check depends on whether or not we do a string comparison 207 : */ 208 : bool isSameType(const HeaderEntry & header_entry, const std::type_info & type) const; 209 : 210 : /** 211 : * Internal method for restoring a new data value 212 : */ 213 : RestartableDataValue & restoreData(const std::string & data_name, 214 : std::unique_ptr<RestartableDataValue> value, 215 : const THREAD_ID tid); 216 : /// The inputs for reading 217 : InputStreams _streams; 218 : 219 : /// The loaded headers from the restart 220 : std::vector<std::unordered_map<std::string, HeaderEntry>> _header; 221 : 222 : /// Whether or not we're currently restoring 223 : bool _is_restoring; 224 : 225 : /// Whether or not to error with a different number of processors 226 : bool _error_on_different_number_of_processors; 227 : 228 : /// Whether or not to forcefully attempt to read despite incompatibilities 229 : const bool _force; 230 : }; 231 : 232 : template <typename T, typename... Args> 233 : T & 234 20 : RestartableDataReader::restoreData(const std::string & data_name, 235 : const THREAD_ID tid /* = 0 */, 236 : void * const context /* = nullptr */, 237 : Args &&... args) 238 : { 239 20 : std::unique_ptr<RestartableDataValue> T_data = 240 : std::make_unique<RestartableData<T>>(data_name, context, std::forward<Args>(args)...); 241 30 : auto & value = restoreData(data_name, std::move(T_data), tid); 242 10 : auto T_value = dynamic_cast<RestartableData<T> *>(&value); 243 : mooseAssert(T_value, "Bad cast"); 244 20 : return T_value->set(); 245 20 : }