8 #include <fmt/format.h> 
    9 #include <log4cplus/loggingmacros.h> 
   18         return source.GetKeywordRuleProcessor().Process(source.
GetKeywords(),
 
   21         auto msg = fmt::format(
"Processing keyword rules failed for JSON keywords source '{}'",
 
   23         LOG4CPLUS_ERROR(ops.
logger, msg);
 
   24         std::throw_with_nested(std::runtime_error(msg));
 
   29     auto logger = log4cplus::Logger::getInstance(
"dpm.merge");
 
   32     result.reserve(literal_kws.size());
 
   33     std::copy(std::make_move_iterator(literal_kws.begin()),
 
   34               std::make_move_iterator(literal_kws.end()),
 
   35               std::back_inserter(result));
 
   38         return source.GetKeywordRuleProcessor().Process(result,
 
   41         auto msg = fmt::format(
"Processing keyword rules failed for FITS file keywords source '{}'",
 
   42                                source.GetFilePath().string());
 
   43         LOG4CPLUS_ERROR(logger, msg);
 
   44         std::throw_with_nested(std::runtime_error(msg));
 
   53                                               std::vector<SourceTypes> 
const& sources) {
 
   54     auto logger = log4cplus::Logger::getInstance(
"dpm.merge");
 
   55     constexpr 
const int primary_hdu_num = 1;
 
   58     LOG4CPLUS_DEBUG(logger, 
"Read keywords from " << target.GetFilePath());
 
   59     std::for_each(std::begin(literal_kws), std::end(literal_kws), [&](
auto const& kw) {
 
   60         LOG4CPLUS_DEBUG(logger, kw);
 
   62     result.reserve(literal_kws.size());
 
   63     std::copy(std::begin(literal_kws), std::end(literal_kws), std::back_inserter(result));
 
   67         result = target.GetKeywordRuleProcessor().Process(result,
 
   69         LOG4CPLUS_DEBUG(logger, 
"Result after keyword processing: " << target.GetFilePath());
 
   70         std::for_each(std::begin(result), std::end(result), [&](
auto const& kw) {
 
   71             LOG4CPLUS_DEBUG(logger, kw);
 
   74         auto msg = fmt::format(
"Processing keyword rules failed for target FITS file '{}'",
 
   75                                target.GetFilePath().string());
 
   76         LOG4CPLUS_ERROR(logger, msg);
 
   77         std::throw_with_nested(std::runtime_error(msg));
 
   80     for (
auto const& source : sources) {
 
   81         std::string path_or_name;
 
   82         auto kws = std::visit(
 
   84                 using T = std::decay_t<decltype(source)>;
 
   85                 if constexpr (std::is_same_v<T, FitsKeywordsSource>) {
 
   86                     path_or_name = fmt::format(
"{}: (keyword list)", source.GetName());
 
   88                 } 
else if constexpr (std::is_same_v<T, FitsFileSource>) {
 
   90                         fmt::format(
"{}: {}", source.GetName(), source.GetFilePath().native());
 
   95         LOG4CPLUS_DEBUG(logger, 
"Updating with keywords from : " << path_or_name);
 
   97             std::begin(kws), std::end(kws), [&](
auto const& kw) { LOG4CPLUS_DEBUG(logger, kw); });
 
  105 std::vector<fits::LiteralKeyword> 
FormatKeywords(fits::KeywordVector::const_iterator begin,
 
  106                                                  fits::KeywordVector::const_iterator end,
 
  108     auto const& logger = log4cplus::Logger::getInstance(
"dpm.merge");
 
  109     std::vector<fits::LiteralKeyword> result;
 
  110     LOG4CPLUS_DEBUG(logger, 
"Formatting keywords ...");
 
  113             LOG4CPLUS_DEBUG(logger, 
"Formatting keyword input:  \"" << kw << 
"\"");
 
  115             LOG4CPLUS_DEBUG(logger, 
"Formatting keyword result: \"" << formatted << 
"\"");
 
  118     LOG4CPLUS_DEBUG(logger, 
"Formatting keywords done.");
 
  122 template <
class Container>
 
  123 void LogKeywords(log4cplus::Logger 
const& logger, Container 
const& keywords) {
 
  124     std::for_each(std::begin(keywords), std::end(keywords), [&](
auto const& kw) {
 
  125         LOG4CPLUS_DEBUG(logger, kw);
 
  132                              std::vector<SourceTypes> 
const& sources,
 
  134     auto const& logger = ops.
logger;
 
  135     LOG4CPLUS_INFO(logger, 
"Merge primary HDU keywords");
 
  136     LOG4CPLUS_INFO(logger, 
"Compile primary keywords");
 
  137     constexpr 
const int primary_hdu_num = 1;
 
  142     mandatory.emplace_back(std::in_place_type<fits::ValueKeyword>, 
"ORIGFILE", params.
origfile);
 
  143     mandatory.emplace_back(std::in_place_type<fits::ValueKeyword>, 
"ARCFILE", params.
arcfile);
 
  145         primary_hdu_keywords, primary_hdu_keywords.end(), mandatory.begin(), mandatory.end());
 
  147     LOG4CPLUS_INFO(logger, 
"Format keywords");
 
  149         std::begin(primary_hdu_keywords), std::end(primary_hdu_keywords), ops.
keyword_formatter);
 
  151         LOG4CPLUS_INFO(logger, 
"Sort keywords");
 
  153         LOG4CPLUS_DEBUG(logger, 
"Sorted keywords");
 
  160         LOG4CPLUS_INFO(logger, 
"Clear keywords to make room for writing back sorted keywords.");
 
  162         LOG4CPLUS_INFO(logger, 
"Writing keywords");
 
  163         std::optional<ssize_t> remaining_size;
 
  165         if (remaining_size) {
 
  166             if (*remaining_size < 0) {
 
  167                 auto needed = -*remaining_size;
 
  169                 auto msg = fmt::format(
 
  170                     "Writing keywords required resizing of primary HDU: Add space for at least {} " 
  171                     "keywords to avoid resize",
 
  175                 auto msg = fmt::format(
"Primary HDU keyword space remaining: {} ", *remaining_size);
 
  176                 LOG4CPLUS_INFO(logger, msg);
 
  180         LOG4CPLUS_INFO(logger, 
"Writing keywords SKIPPED (dry-run)");
 
  191     auto const& logger = ops.
logger;
 
  194         "Merging HDU extensions from " << source.GetName() << 
"(" << source.GetFilePath() << 
")");
 
  197     fitsfile* source_fits = source.GetFitsFile();
 
  198     fitsfile* target_fits = target.GetFitsFile();
 
  200     fits_get_num_hdus(source_fits, &num_hdus, &status);
 
  203             fmt::format(
"Failed to get number of HDUs from '{}'", target.GetFilePath().c_str());
 
  204         LOG4CPLUS_ERROR(logger, msg);
 
  211         LOG4CPLUS_INFO(ops.
logger,
 
  212                        "Note: No HDU extensions to merge from " << source.GetFilePath());
 
  220         int previous = 
false;
 
  222         int following = 
true;
 
  223         fits_copy_file(source_fits, target_fits, previous, current, following, &status);
 
  225             auto const msg = 
"FITS function fits_copy_file failed";
 
  226             LOG4CPLUS_ERROR(logger, msg);
 
  230         LOG4CPLUS_INFO(logger,
 
  231                        "Merging HDU extensions from " << source.GetName() << 
"(" 
  232                                                       << source.GetFilePath()
 
  233                                                       << 
") SKIPPED (dry-run)");
 
  239                         std::vector<SourceTypes> 
const& sources,
 
  241     auto const& logger = ops.
logger;
 
  242     LOG4CPLUS_INFO(logger, 
"Merging HDU extensions");
 
  244     for (
auto const& source_var : sources) {
 
  245         if (!std::holds_alternative<FitsFileSource>(source_var)) {
 
  248         FitsFileSource const& source = std::get<FitsFileSource>(source_var);
 
  252             std::throw_with_nested(
 
  253                 std::runtime_error(fmt::format(
"Failed to copy HDU extensions from '{}' to '{}'",
 
  254                                                source.GetFilePath().c_str(),
 
  255                                                target.GetFilePath().c_str())));
 
  258     LOG4CPLUS_INFO(logger, 
"Merging HDU extensions completed successfully");
 
  262     auto const& logger = ops.
logger;
 
  263     LOG4CPLUS_INFO(logger, 
"Updating checksums for all HDUs");
 
  265     fitsfile* target_fits = target.GetFitsFile();
 
  267     fits_get_num_hdus(target_fits, &num_hdus, &status);
 
  270             fmt::format(
"Failed to get number of HDUs from '{}'", target.GetFilePath().c_str());
 
  271         LOG4CPLUS_ERROR(logger, msg);
 
  276         for (
int hdu_num = 1; hdu_num <= num_hdus; ++hdu_num) {
 
  277             LOG4CPLUS_DEBUG(logger, 
"Updating checksum for HDU " << hdu_num);
 
  281         LOG4CPLUS_INFO(logger, 
"Updating checkum keywords SKIPPED (dry-run)");
 
  283     LOG4CPLUS_INFO(logger, 
"Updating checkum keywords completed for all HDUs successfully");
 
  289            std::vector<SourceTypes> 
const& sources,
 
  291     auto const& logger = ops.
logger;
 
  308     LOG4CPLUS_INFO(logger, 
"Starting merge operation");
 
  312         std::throw_with_nested(std::runtime_error(
"Failed to merge primary HDU keywords"));
 
  318         std::throw_with_nested(std::runtime_error(
"Failed to merge primary HDU keywords"));
 
  323         std::throw_with_nested(std::runtime_error(
"Failed to update checksums"));
 
  326     LOG4CPLUS_INFO(logger, 
"Completed successfully");