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