/Users/eugenesiegel/btc/bitcoin/src/flatfile.cpp
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2009-2010 Satoshi Nakamoto | 
| 2 |  | // Copyright (c) 2009-2022 The Bitcoin Core developers | 
| 3 |  | // Distributed under the MIT software license, see the accompanying | 
| 4 |  | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | 
| 5 |  |  | 
| 6 |  | #include <stdexcept> | 
| 7 |  |  | 
| 8 |  | #include <flatfile.h> | 
| 9 |  | #include <logging.h> | 
| 10 |  | #include <tinyformat.h> | 
| 11 |  | #include <util/fs_helpers.h> | 
| 12 |  |  | 
| 13 |  | FlatFileSeq::FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size) : | 
| 14 | 102k |     m_dir(std::move(dir)), | 
| 15 | 102k |     m_prefix(prefix), | 
| 16 | 102k |     m_chunk_size(chunk_size) | 
| 17 | 102k | { | 
| 18 | 102k |     if (chunk_size == 0) { | 
| 19 | 0 |         throw std::invalid_argument("chunk_size must be positive"); | 
| 20 | 0 |     } | 
| 21 | 102k | } | 
| 22 |  |  | 
| 23 |  | std::string FlatFilePos::ToString() const | 
| 24 | 0 | { | 
| 25 | 0 |     return strprintf("FlatFilePos(nFile=%i, nPos=%i)", nFile, nPos);| Line | Count | Source |  | 1172 | 0 | #define strprintf tfm::format | 
 | 
| 26 | 0 | } | 
| 27 |  |  | 
| 28 |  | fs::path FlatFileSeq::FileName(const FlatFilePos& pos) const | 
| 29 | 1.03M | { | 
| 30 | 1.03M |     return m_dir / fs::u8path(strprintf("%s%05u.dat", m_prefix, pos.nFile));| Line | Count | Source |  | 1172 | 1.03M | #define strprintf tfm::format | 
 | 
| 31 | 1.03M | } | 
| 32 |  |  | 
| 33 |  | FILE* FlatFileSeq::Open(const FlatFilePos& pos, bool read_only) const | 
| 34 | 1.03M | { | 
| 35 | 1.03M |     if (pos.IsNull()) { | 
| 36 | 0 |         return nullptr; | 
| 37 | 0 |     } | 
| 38 | 1.03M |     fs::path path = FileName(pos); | 
| 39 | 1.03M |     fs::create_directories(path.parent_path()); | 
| 40 | 1.03M |     FILE* file = fsbridge::fopen(path, read_only ? "rb"975k: "rb+"59.1k); | 
| 41 | 1.03M |     if (!file && !read_only0) | 
| 42 | 0 |         file = fsbridge::fopen(path, "wb+"); | 
| 43 | 1.03M |     if (!file) { | 
| 44 | 0 |         LogPrintf("Unable to open file %s\n", fs::PathToString(path));| Line | Count | Source |  | 361 | 0 | #define LogPrintf(...) LogInfo(__VA_ARGS__) | Line | Count | Source |  | 356 | 0 | #define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
 | 
| 45 | 0 |         return nullptr; | 
| 46 | 0 |     } | 
| 47 | 1.03M |     if (pos.nPos && fseek(file, pos.nPos, SEEK_SET)973k) { | 
| 48 | 0 |         LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, fs::PathToString(path));| Line | Count | Source |  | 361 | 0 | #define LogPrintf(...) LogInfo(__VA_ARGS__) | Line | Count | Source |  | 356 | 0 | #define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
 | 
| 49 | 0 |         if (fclose(file) != 0) { | 
| 50 | 0 |             LogError("Unable to close file %s", fs::PathToString(path));| Line | Count | Source |  | 358 | 0 | #define LogError(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Error, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 51 | 0 |         } | 
| 52 | 0 |         return nullptr; | 
| 53 | 0 |     } | 
| 54 | 1.03M |     return file; | 
| 55 | 1.03M | } | 
| 56 |  |  | 
| 57 |  | size_t FlatFileSeq::Allocate(const FlatFilePos& pos, size_t add_size, bool& out_of_space) const | 
| 58 | 50.0k | { | 
| 59 | 50.0k |     out_of_space = false; | 
| 60 |  |  | 
| 61 | 50.0k |     unsigned int n_old_chunks = (pos.nPos + m_chunk_size - 1) / m_chunk_size; | 
| 62 | 50.0k |     unsigned int n_new_chunks = (pos.nPos + add_size + m_chunk_size - 1) / m_chunk_size; | 
| 63 | 50.0k |     if (n_new_chunks > n_old_chunks) { | 
| 64 | 0 |         size_t old_size = pos.nPos; | 
| 65 | 0 |         size_t new_size = n_new_chunks * m_chunk_size; | 
| 66 | 0 |         size_t inc_size = new_size - old_size; | 
| 67 |  | 
 | 
| 68 | 0 |         if (CheckDiskSpace(m_dir, inc_size)) { | 
| 69 | 0 |             FILE *file = Open(pos); | 
| 70 | 0 |             if (file) { | 
| 71 | 0 |                 LogDebug(BCLog::VALIDATION, "Pre-allocating up to position 0x%x in %s%05u.dat\n", new_size, m_prefix, pos.nFile); | Line | Count | Source |  | 381 | 0 | #define LogDebug(category, ...) LogPrintLevel(category, BCLog::Level::Debug, __VA_ARGS__) | Line | Count | Source |  | 373 | 0 |     do {                                                              \ |  | 374 | 0 |         if (LogAcceptCategory((category), (level))) {                 \ |  | 375 | 0 |             bool rate_limit{level >= BCLog::Level::Info};             \ |  | 376 | 0 |             LogPrintLevel_(category, level, rate_limit, __VA_ARGS__); \ | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 |  | 377 | 0 |         }                                                             \ |  | 378 | 0 |     } while (0) | 
 | 
 | 
| 72 | 0 |                 AllocateFileRange(file, pos.nPos, inc_size); | 
| 73 | 0 |                 if (fclose(file) != 0) { | 
| 74 | 0 |                     LogError("Cannot close file %s%05u.dat after extending it with %u bytes", m_prefix, pos.nFile, new_size);| Line | Count | Source |  | 358 | 0 | #define LogError(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Error, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 75 | 0 |                     return 0; | 
| 76 | 0 |                 } | 
| 77 | 0 |                 return inc_size; | 
| 78 | 0 |             } | 
| 79 | 0 |         } else { | 
| 80 | 0 |             out_of_space = true; | 
| 81 | 0 |         } | 
| 82 | 0 |     } | 
| 83 | 50.0k |     return 0; | 
| 84 | 50.0k | } | 
| 85 |  |  | 
| 86 |  | bool FlatFileSeq::Flush(const FlatFilePos& pos, bool finalize) const | 
| 87 | 9.16k | { | 
| 88 | 9.16k |     FILE* file = Open(FlatFilePos(pos.nFile, 0)); // Avoid fseek to nPos | 
| 89 | 9.16k |     if (!file) { | 
| 90 | 0 |         LogError("%s: failed to open file %d\n", __func__, pos.nFile);| Line | Count | Source |  | 358 | 0 | #define LogError(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Error, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 91 | 0 |         return false; | 
| 92 | 0 |     } | 
| 93 | 9.16k |     if (finalize && !TruncateFile(file, pos.nPos)0) { | 
| 94 | 0 |         LogError("%s: failed to truncate file %d\n", __func__, pos.nFile);| Line | Count | Source |  | 358 | 0 | #define LogError(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Error, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 95 | 0 |         if (fclose(file) != 0) { | 
| 96 | 0 |             LogError("Failed to close file %d", pos.nFile);| Line | Count | Source |  | 358 | 0 | #define LogError(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Error, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 97 | 0 |         } | 
| 98 | 0 |         return false; | 
| 99 | 0 |     } | 
| 100 | 9.16k |     if (!FileCommit(file)) { | 
| 101 | 0 |         LogError("%s: failed to commit file %d\n", __func__, pos.nFile);| Line | Count | Source |  | 358 | 0 | #define LogError(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Error, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 102 | 0 |         if (fclose(file) != 0) { | 
| 103 | 0 |             LogError("Failed to close file %d", pos.nFile);| Line | Count | Source |  | 358 | 0 | #define LogError(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Error, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 104 | 0 |         } | 
| 105 | 0 |         return false; | 
| 106 | 0 |     } | 
| 107 | 9.16k |     DirectoryCommit(m_dir); | 
| 108 |  |  | 
| 109 | 9.16k |     if (fclose(file) != 0) { | 
| 110 | 0 |         LogError("Failed to close file %d after flush", pos.nFile);| Line | Count | Source |  | 358 | 0 | #define LogError(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Error, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 0 | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 111 | 0 |         return false; | 
| 112 | 0 |     } | 
| 113 | 9.16k |     return true; | 
| 114 | 9.16k | } |