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 9833 : RestartableDataWriter::RestartableDataWriter(MooseApp & app, RestartableDataMap & data) 19 9833 : : RestartableDataIO(app, data) 20 : { 21 9833 : } 22 : 23 45214 : RestartableDataWriter::RestartableDataWriter(MooseApp & app, std::vector<RestartableDataMap> & data) 24 45214 : : RestartableDataIO(app, data) 25 : { 26 45214 : } 27 : 28 : void 29 55047 : RestartableDataWriter::write(std::ostream & header_stream, std::ostream & data_stream) 30 : { 31 : // Set everything as not stored 32 113670 : for (const auto tid : make_range(dataSize())) 33 2056736 : for (auto & value : currentData(tid)) 34 1998113 : value.setNotStored({}); 35 : 36 : // Header 37 55047 : char id[] = {'R', 'D'}; 38 55047 : header_stream.write(id, 2); 39 : 40 : // File version 41 55047 : auto file_version = CURRENT_BACKUP_FILE_VERSION; 42 55047 : dataStore(header_stream, file_version, nullptr); 43 : 44 : // Type hash for basic hash 45 55047 : std::size_t compare_hash_code = typeid(COMPARE_HASH_CODE_TYPE).hash_code(); 46 55047 : dataStore(header_stream, compare_hash_code, nullptr); 47 : 48 : // Number of procs 49 55047 : auto n_procs = n_processors(); 50 55047 : dataStore(header_stream, n_procs, nullptr); 51 : 52 : // Number of data 53 55047 : auto num_data = dataSize(); 54 55047 : dataStore(header_stream, num_data, nullptr); 55 : 56 : // Size of data for each thread 57 113670 : for (const auto tid : make_range(dataSize())) 58 : { 59 58623 : std::size_t n_data = currentData(tid).size(); 60 58623 : dataStore(header_stream, n_data, nullptr); 61 : } 62 : 63 : // Write out the RestartableData header, and store the actual data separately 64 113665 : for (const auto tid : make_range(dataSize())) 65 2056683 : for (auto & data : currentData(tid)) 66 : { 67 : // Store the data 68 1998065 : const std::size_t data_start_position = static_cast<std::size_t>(data_stream.tellp()); 69 1998065 : data.store(data_stream); 70 1998061 : 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 1998061 : std::string name = data.name(); 75 1998061 : std::string type = data.typeId().name(); 76 1998061 : std::size_t type_hash_code = data.typeId().hash_code(); 77 1998061 : bool has_context = data.hasContext(); 78 1998061 : dataStore(header_stream, name, nullptr); 79 1998061 : dataStore(header_stream, data_size, nullptr); 80 1998061 : dataStore(header_stream, type_hash_code, nullptr); 81 1998061 : dataStore(header_stream, type, nullptr); 82 1998061 : dataStore(header_stream, has_context, nullptr); 83 1998061 : } 84 55043 : } 85 : 86 : std::vector<std::filesystem::path> 87 20708 : RestartableDataWriter::write(const std::filesystem::path & folder_base) 88 : { 89 20708 : const auto header_file = restartableHeaderFile(folder_base); 90 20708 : const auto data_file = restartableDataFile(folder_base); 91 : 92 : // Make the folder if it doesn't exist 93 20708 : const auto dir = header_file.parent_path(); 94 : mooseAssert(dir == data_file.parent_path(), "Inconsistent directories"); 95 20708 : if (!std::filesystem::exists(dir)) 96 : { 97 18906 : std::error_code err; 98 18906 : 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 20708 : std::vector<std::filesystem::path> paths; 108 : 109 : // Helper for opening a stream for use 110 82832 : auto open = [&paths](const std::filesystem::path & filename) 111 : { 112 41416 : std::ofstream stream; 113 41416 : stream.open(filename.c_str(), std::ios::out | std::ios::binary); 114 41416 : if (!stream.is_open()) 115 0 : mooseError( 116 0 : "Unable to open restart file ", std::filesystem::absolute(filename), " for writing"); 117 41416 : paths.push_back(filename); 118 41416 : return stream; 119 0 : }; 120 : 121 : // Open and write 122 20708 : auto header_stream = open(header_file); 123 20708 : auto data_stream = open(data_file); 124 20708 : 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 20704 : const auto data_write_time = std::filesystem::last_write_time(header_file); 129 20704 : std::filesystem::last_write_time(dir, data_write_time); 130 : 131 41408 : return paths; 132 20704 : }