diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index c454c0e394c..c9c30e21d88 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -29,6 +29,7 @@ #include #include +#include #include // std::unique_ptr #include // memcpy @@ -1324,6 +1325,54 @@ BlockchainLMDB::BlockchainLMDB(bool batch_transactions): BlockchainDB() m_hardfork = nullptr; } +#ifdef WIN32 +static bool disable_ntfs_compression(const boost::filesystem::path& filepath) +{ + DWORD file_attributes = ::GetFileAttributesW(filepath.c_str()); + if (file_attributes == INVALID_FILE_ATTRIBUTES) + { + MERROR("Failed to get " << filepath.string() << " file attributes. Error: " << ::GetLastError()); + return false; + } + + if (!(file_attributes & FILE_ATTRIBUTE_COMPRESSED)) + return true; // not compressed + + LOG_PRINT_L1("Disabling NTFS compression for " << filepath.string()); + HANDLE file_handle = ::CreateFileW( + filepath.c_str(), + GENERIC_READ | GENERIC_WRITE, + 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.string() << ". 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 + void BlockchainLMDB::open(const std::string& filename, const int db_flags) { int result; @@ -1352,12 +1401,13 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) #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)) + if (!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()); + boost::filesystem::ofstream(datafile.string()).close(); // touch the file to ensure it exists + if (!disable_ntfs_compression(datafile)) + throw DB_ERROR("Database file is NTFS compressend and compression could not be disabled"); #endif boost::optional is_hdd_result = tools::is_hdd(filename.c_str()); @@ -1701,54 +1751,6 @@ 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 d5eb0aab420..6eeb942dc25 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -32,7 +32,6 @@ #include "cryptonote_basic/blobdatatype.h" // for type blobdata #include "ringct/rctTypes.h" #include -#include #include @@ -203,10 +202,6 @@ 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;