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 : #include "RestartableDataWriter.h" 11 : 12 : #include "DataIO.h" 13 : #include "RestartableDataMap.h" 14 : 15 : #include <fstream> 16 : #include <system_error> 17 : 18 9573 : RestartableDataWriter::RestartableDataWriter(MooseApp & app, RestartableDataMap & data) 19 9573 : : RestartableDataIO(app, data) 20 : { 21 9573 : } 22 : 23 41839 : RestartableDataWriter::RestartableDataWriter(MooseApp & app, std::vector<RestartableDataMap> & data) 24 41839 : : RestartableDataIO(app, data) 25 : { 26 41839 : } 27 : 28 : void 29 51412 : RestartableDataWriter::write(std::ostream & header_stream, std::ostream & data_stream) 30 : { 31 : // Set everything as not stored 32 106420 : for (const auto tid : make_range(dataSize())) 33 1864759 : for (auto & value : currentData(tid)) 34 1809751 : value.setNotStored({}); 35 : 36 : // Header 37 51412 : char id[] = {'R', 'D'}; 38 51412 : header_stream.write(id, 2); 39 : 40 : // File version 41 51412 : auto file_version = CURRENT_BACKUP_FILE_VERSION; 42 51412 : dataStore(header_stream, file_version, nullptr); 43 : 44 : // Type hash for basic hash 45 51412 : std::size_t compare_hash_code = typeid(COMPARE_HASH_CODE_TYPE).hash_code(); 46 51412 : dataStore(header_stream, compare_hash_code, nullptr); 47 : 48 : // Number of procs 49 51412 : auto n_procs = n_processors(); 50 51412 : dataStore(header_stream, n_procs, nullptr); 51 : 52 : // Number of data 53 51412 : auto num_data = dataSize(); 54 51412 : dataStore(header_stream, num_data, nullptr); 55 : 56 : // Size of data for each thread 57 106420 : for (const auto tid : make_range(dataSize())) 58 : { 59 55008 : std::size_t n_data = currentData(tid).size(); 60 55008 : dataStore(header_stream, n_data, nullptr); 61 : } 62 : 63 : // Write out the RestartableData header, and store the actual data separately 64 106415 : for (const auto tid : make_range(dataSize())) 65 1864710 : for (auto & data : currentData(tid)) 66 : { 67 : // Store the data 68 1809707 : const std::size_t data_start_position = static_cast<std::size_t>(data_stream.tellp()); 69 1809707 : data.store(data_stream); 70 1809703 : std::size_t data_size = static_cast<std::size_t>(data_stream.tellp()) - data_start_position; 71 : 72 : // Store name, size, type hash, and type in the header 73 : mooseAssert(data.name().size(), "Empty name"); 74 1809703 : std::string name = data.name(); 75 1809703 : std::string type = data.typeId().name(); 76 1809703 : std::size_t type_hash_code = data.typeId().hash_code(); 77 1809703 : bool has_context = data.hasContext(); 78 1809703 : dataStore(header_stream, name, nullptr); 79 1809703 : dataStore(header_stream, data_size, nullptr); 80 1809703 : dataStore(header_stream, type_hash_code, nullptr); 81 1809703 : dataStore(header_stream, type, nullptr); 82 1809703 : dataStore(header_stream, has_context, nullptr); 83 1809703 : } 84 51408 : } 85 : 86 : std::vector<std::filesystem::path> 87 20179 : RestartableDataWriter::write(const std::filesystem::path & folder_base) 88 : { 89 20179 : const auto header_file = restartableHeaderFile(folder_base); 90 20179 : const auto data_file = restartableDataFile(folder_base); 91 : 92 : // Make the folder if it doesn't exist 93 20179 : const auto dir = header_file.parent_path(); 94 : mooseAssert(dir == data_file.parent_path(), "Inconsistent directories"); 95 20179 : if (!std::filesystem::exists(dir)) 96 : { 97 18596 : std::error_code err; 98 18596 : if (!std::filesystem::create_directory(dir, err)) 99 0 : mooseError("Unable to create restart directory\n", 100 0 : std::filesystem::absolute(dir), 101 : "\n\n", 102 0 : err.message()); 103 : } 104 : 105 : // We want to keep track of the paths that we create so that we can 106 : // return them for file management later (primarily removing old checkpoints) 107 20179 : std::vector<std::filesystem::path> paths; 108 : 109 : // Helper for opening a stream for use 110 80716 : auto open = [&paths](const std::filesystem::path & filename) 111 : { 112 40358 : std::ofstream stream; 113 40358 : stream.open(filename.c_str(), std::ios::out | std::ios::binary); 114 40358 : if (!stream.is_open()) 115 0 : mooseError( 116 0 : "Unable to open restart file ", std::filesystem::absolute(filename), " for writing"); 117 40358 : paths.push_back(filename); 118 40358 : return stream; 119 0 : }; 120 : 121 : // Open and write 122 20179 : auto header_stream = open(header_file); 123 20179 : auto data_stream = open(data_file); 124 20179 : write(header_stream, data_stream); 125 : 126 : // Update the folder's modified time to now for consistency 127 : // (this used in checking for the latest checkpoint) 128 20175 : const auto data_write_time = std::filesystem::last_write_time(header_file); 129 20175 : std::filesystem::last_write_time(dir, data_write_time); 130 : 131 40350 : return paths; 132 20175 : }