From ce2154972f81921d40c4a3900c7d2f0f9a11735e Mon Sep 17 00:00:00 2001 From: eversinc33 Date: Wed, 1 Jan 2025 21:54:50 +0100 Subject: [PATCH] unset NTFS compression on database files --- src/blockchain_db/lmdb/db_lmdb.cpp | 63 +++++++++++++++++++++++++++++- src/blockchain_db/lmdb/db_lmdb.h | 5 +++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index d01119249cc..c454c0e394c 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -27,12 +27,15 @@ #include "db_lmdb.h" -#include #include #include #include // std::unique_ptr #include // memcpy +#ifdef WIN32 +#include +#endif + #include "string_tools.h" #include "file_io_utils.h" #include "common/util.h" @@ -1347,6 +1350,16 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) throw DB_ERROR("Database could not be opened"); } +#ifdef WIN32 + // ensure NTFS compression is disabled on the directory and database file to avoid corruption of the blockchain + if (boost::filesystem::exists(filename) && !disable_ntfs_compression(filename)) + LOG_PRINT_L0("Failed to disable NTFS compression on folder: " << filename << ". Error: " << ::GetLastError()); + boost::filesystem::path datafile(filename); + datafile /= CRYPTONOTE_BLOCKCHAINDATA_FILENAME; + if (boost::filesystem::exists(datafile) && !disable_ntfs_compression(datafile)) + LOG_PRINT_L0("Failed to disable NTFS compression on database file: " << datafile << ". Error: " << ::GetLastError()); +#endif + boost::optional is_hdd_result = tools::is_hdd(filename.c_str()); if (is_hdd_result) { @@ -1688,6 +1701,54 @@ std::string BlockchainLMDB::get_db_name() const return std::string("lmdb"); } +#ifdef WIN32 +bool BlockchainLMDB::disable_ntfs_compression(const boost::filesystem::path& filepath) const +{ + DWORD file_attributes = ::GetFileAttributesW(filepath.c_str()); + if (file_attributes == INVALID_FILE_ATTRIBUTES) + { + MERROR("Failed to get '" << filepath << "' file attributes. Error code: " << ::GetLastError()); + return false; + } + + if (!(file_attributes & FILE_ATTRIBUTE_COMPRESSED)) + return true; // not compressed + + LOG_PRINT_L1("Disabling NTFS compression for " << filepath); + HANDLE file_handle = ::CreateFileW( + filepath.c_str(), + GENERIC_ALL, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, + OPEN_EXISTING, + boost::filesystem::is_directory(filepath) ? FILE_FLAG_BACKUP_SEMANTICS : 0, // Needed to open handles to directories + nullptr + ); + + if (file_handle == INVALID_HANDLE_VALUE) + { + MERROR("Failed to open handle: " << filepath << ". Error: " << ::GetLastError()); + return false; + } + + USHORT compression_state = COMPRESSION_FORMAT_NONE; + DWORD bytes_returned; + BOOL ok = DeviceIoControl( + file_handle, + FSCTL_SET_COMPRESSION, + &compression_state, + sizeof(compression_state), + nullptr, + 0, + &bytes_returned, + nullptr + ); + + CloseHandle(file_handle); + return ok; +} +#endif + // The below two macros are for DB access within block add/remove, whether // regular batch txn is in use or not. m_write_txn is used as a batch txn, even // if it's only within block add/remove. diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 6eeb942dc25..d5eb0aab420 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -32,6 +32,7 @@ #include "cryptonote_basic/blobdatatype.h" // for type blobdata #include "ringct/rctTypes.h" #include +#include #include @@ -202,6 +203,10 @@ class BlockchainLMDB : public BlockchainDB virtual std::string get_db_name() const; +#ifdef WIN32 + virtual bool disable_ntfs_compression(const boost::filesystem::path& filepath) const; +#endif + virtual bool block_exists(const crypto::hash& h, uint64_t *height = NULL) const; virtual uint64_t get_block_height(const crypto::hash& h) const;