LCOV - code coverage report
Current view: top level - src/restart - RestartableDataWriter.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: d8769b Lines: 60 66 90.9 %
Date: 2025-11-07 20:01:30 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14