leveldb: pull upstream C++23 changes #31766

pull fanquake wants to merge 3 commits into bitcoin:master from fanquake:leveldb_cpp23 changing 4 files +23 −13
  1. fanquake commented at 2:01 PM on January 30, 2025: member

    Cherry-picks two commits from upstream (https://github.com/google/leveldb/commit/302786e211d1f2e6fd260261f642d03a91e5922c, https://github.com/google/leveldb/commit/e829478c6a3a55d8e5c1227e2678dcc18d518609), which remove the usage of std::aligned_storage/std::aligned_union.

    Note the first cherry-pick is not clean, because due to Google tooling issues, it accidently contained a revert of the prior two commits. See https://github.com/google/leveldb/pull/1249 for more details.

    Also see https://issues.chromium.org/issues/388068052, although note that they reverted the roll to latest leveldb. I'm guessing due to the acidental reversion issue above.

  2. DrahtBot commented at 2:01 PM on January 30, 2025: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31766.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK darosior, dergoegge, l0rinc

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    No conflicts as of last run.

  3. DrahtBot commented at 3:00 PM on January 30, 2025: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Debug: https://github.com/bitcoin/bitcoin/runs/36420557428</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  4. DrahtBot added the label CI failed on Jan 30, 2025
  5. victorvianna commented at 5:48 PM on January 30, 2025: none

    FYI the upstream PR landed

  6. fanquake force-pushed on Mar 7, 2025
  7. fanquake renamed this:
    [WIP] leveldb: pull upstream C++23 changes
    leveldb: pull upstream C++23 changes
    on Mar 7, 2025
  8. fanquake commented at 5:10 PM on March 7, 2025: member

    Updated now that the changes have landed upstream in https://github.com/bitcoin-core/leveldb-subtree/pull/47.

  9. fanquake marked this as ready for review on Mar 7, 2025
  10. DrahtBot removed the label CI failed on Mar 7, 2025
  11. Squashed 'src/leveldb/' changes from 04b5790928..4188247086
    4188247086 Merge bitcoin-core/leveldb-subtree#47: Fix C++23 compilation errors in leveldb
    183e79a495 Fix speculatively some "placement new" issues in leveldb
    82c31046ed Fix C++23 compilation errors in leveldb
    
    git-subtree-dir: src/leveldb
    git-subtree-split: 41882470862df219f74cdd38354007b91eb98191
    a130bbd154
  12. Update leveldb subtree to latest upstream 24fd0235e4
  13. ci: remove -Wno-error=deprecated-declarations from ASAN
    This is no-longer needed after the changes to leveldb.
    c8fab35617
  14. fanquake force-pushed on Mar 17, 2025
  15. fanquake requested review from dergoegge on Mar 18, 2025
  16. fanquake requested review from darosior on Mar 18, 2025
  17. darosior approved
  18. darosior commented at 12:27 AM on March 19, 2025: member

    ACK c8fab356171a0e283d5716647e3243c04810ac51 -- checked it's a clean subtree pull from https://github.com/bitcoin-core/leveldb-subtree/tree/bitcoin-fork

  19. dergoegge approved
  20. dergoegge commented at 2:00 PM on March 19, 2025: member

    utACK c8fab356171a0e283d5716647e3243c04810ac51

  21. l0rinc commented at 2:22 PM on March 19, 2025: contributor

    I have first compared every modified file completely against the latest versions of https://github.com/google/leveldb/blob/main/util/env_posix.cc, https://github.com/google/leveldb/blob/main/util/env_windows.cc and https://github.com/google/leveldb/blob/main/util/no_destructor.h, but realized we're too far behind.

    <details> <summary>Full diff</summary>

    diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc
    index 86571059ba..25399f9745 100644
    --- a/src/leveldb/util/env_posix.cc
    +++ b/src/leveldb/util/env_posix.cc
    @@ -4,9 +4,10 @@
     
     #include <dirent.h>
     #include <fcntl.h>
    -#include <pthread.h>
     #include <sys/mman.h>
    +#ifndef __Fuchsia__
     #include <sys/resource.h>
    +#endif
     #include <sys/stat.h>
     #include <sys/time.h>
     #include <sys/types.h>
    @@ -42,14 +43,14 @@ namespace {
     // Set by EnvPosixTestHelper::SetReadOnlyMMapLimit() and MaxOpenFiles().
     int g_open_read_only_file_limit = -1;
     
    -// Up to 4096 mmap regions for 64-bit binaries; none for 32-bit.
    -constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 4096 : 0;
    +// Up to 1000 mmap regions for 64-bit binaries; none for 32-bit.
    +constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0;
     
     // Can be set using EnvPosixTestHelper::SetReadOnlyMMapLimit().
     int g_mmap_limit = kDefaultMmapLimit;
     
     // Common flags defined for all posix open operations
    -#if HAVE_O_CLOEXEC
    +#if defined(HAVE_O_CLOEXEC)
     constexpr const int kOpenBaseFlags = O_CLOEXEC;
     #else
     constexpr const int kOpenBaseFlags = 0;
    @@ -72,7 +73,14 @@ Status PosixError(const std::string& context, int error_number) {
     class Limiter {
      public:
       // Limit maximum number of resources to |max_acquires|.
    -  Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}
    +  Limiter(int max_acquires)
    +      :
    +#if !defined(NDEBUG)
    +        max_acquires_(max_acquires),
    +#endif  // !defined(NDEBUG)
    +        acquires_allowed_(max_acquires) {
    +    assert(max_acquires >= 0);
    +  }
     
       Limiter(const Limiter&) = delete;
       Limiter operator=(const Limiter&) = delete;
    @@ -85,15 +93,35 @@ class Limiter {
     
         if (old_acquires_allowed > 0) return true;
     
    -    acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
    +    int pre_increment_acquires_allowed =
    +        acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
    +
    +    // Silence compiler warnings about unused arguments when NDEBUG is defined.
    +    (void)pre_increment_acquires_allowed;
    +    // If the check below fails, Release() was called more times than acquire.
    +    assert(pre_increment_acquires_allowed < max_acquires_);
    +
         return false;
       }
     
       // Release a resource acquired by a previous call to Acquire() that returned
       // true.
    -  void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }
    +  void Release() {
    +    int old_acquires_allowed =
    +        acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
    +
    +    // Silence compiler warnings about unused arguments when NDEBUG is defined.
    +    (void)old_acquires_allowed;
    +    // If the check below fails, Release() was called more times than acquire.
    +    assert(old_acquires_allowed < max_acquires_);
    +  }
     
      private:
    +#if !defined(NDEBUG)
    +  // Catches an excessive number of Release() calls.
    +  const int max_acquires_;
    +#endif  // !defined(NDEBUG)
    +
       // The number of available resources.
       //
       // This is a counter and is not tied to the invariants of any other class, so
    @@ -108,7 +136,7 @@ class Limiter {
     class PosixSequentialFile final : public SequentialFile {
      public:
       PosixSequentialFile(std::string filename, int fd)
    -      : fd_(fd), filename_(filename) {}
    +      : fd_(fd), filename_(std::move(filename)) {}
       ~PosixSequentialFile() override { close(fd_); }
     
       Status Read(size_t n, Slice* result, char* scratch) override {
    @@ -135,8 +163,6 @@ class PosixSequentialFile final : public SequentialFile {
         return Status::OK();
       }
     
    -  virtual std::string GetName() const override { return filename_; }
    -
      private:
       const int fd_;
       const std::string filename_;
    @@ -197,8 +223,6 @@ class PosixRandomAccessFile final : public RandomAccessFile {
         return status;
       }
     
    -  virtual std::string GetName() const override { return filename_; }
    -
      private:
       const bool has_permanent_fd_;  // If false, the file is opened on every read.
       const int fd_;                 // -1 if has_permanent_fd_ is false.
    @@ -218,7 +242,7 @@ class PosixMmapReadableFile final : public RandomAccessFile {
       // over the ownership of the region.
       //
       // |mmap_limiter| must outlive this instance. The caller must have already
    -  // aquired the right to use one mmap region, which will be released when this
    +  // acquired the right to use one mmap region, which will be released when this
       // instance is destroyed.
       PosixMmapReadableFile(std::string filename, char* mmap_base, size_t length,
                             Limiter* mmap_limiter)
    @@ -243,8 +267,6 @@ class PosixMmapReadableFile final : public RandomAccessFile {
         return Status::OK();
       }
     
    -  virtual std::string GetName() const override { return filename_; }
    -
      private:
       char* const mmap_base_;
       const size_t length_;
    @@ -325,7 +347,7 @@ class PosixWritableFile final : public WritableFile {
           return status;
         }
     
    -    return SyncFd(fd_, filename_, false);
    +    return SyncFd(fd_, filename_);
       }
     
      private:
    @@ -360,7 +382,7 @@ class PosixWritableFile final : public WritableFile {
         if (fd < 0) {
           status = PosixError(dirname_, errno);
         } else {
    -      status = SyncFd(fd, dirname_, true);
    +      status = SyncFd(fd, dirname_);
           ::close(fd);
         }
         return status;
    @@ -372,7 +394,7 @@ class PosixWritableFile final : public WritableFile {
       //
       // The path argument is only used to populate the description string in the
       // returned Status if an error occurs.
    -  static Status SyncFd(int fd, const std::string& fd_path, bool syncing_dir) {
    +  static Status SyncFd(int fd, const std::string& fd_path) {
     #if HAVE_FULLFSYNC
         // On macOS and iOS, fsync() doesn't guarantee durability past power
         // failures. fcntl(F_FULLFSYNC) is required for that purpose. Some
    @@ -392,11 +414,6 @@ class PosixWritableFile final : public WritableFile {
         if (sync_success) {
           return Status::OK();
         }
    -    // Do not crash if filesystem can't fsync directories
    -    // (see [#10000](/bitcoin-bitcoin/10000/))
    -    if (syncing_dir && errno == EINVAL) {
    -      return Status::OK();
    -    }
         return PosixError(fd_path, errno);
       }
     
    @@ -437,8 +454,6 @@ class PosixWritableFile final : public WritableFile {
         return Basename(filename).starts_with("MANIFEST");
       }
     
    -  virtual std::string GetName() const override { return filename_; }
    -
       // buf_[0, pos_ - 1] contains data to be written to fd_.
       char buf_[kWritableFileBufferSize];
       size_t pos_;
    @@ -600,7 +615,7 @@ class PosixEnv : public Env {
         return Status::OK();
       }
     
    -  Status DeleteFile(const std::string& filename) override {
    +  Status RemoveFile(const std::string& filename) override {
         if (::unlink(filename.c_str()) != 0) {
           return PosixError(filename, errno);
         }
    @@ -614,7 +629,7 @@ class PosixEnv : public Env {
         return Status::OK();
       }
     
    -  Status DeleteDir(const std::string& dirname) override {
    +  Status RemoveDir(const std::string& dirname) override {
         if (::rmdir(dirname.c_str()) != 0) {
           return PosixError(dirname, errno);
         }
    @@ -741,7 +756,7 @@ class PosixEnv : public Env {
       // Instances are constructed on the thread calling Schedule() and used on the
       // background thread.
       //
    -  // This structure is thread-safe beacuse it is immutable.
    +  // This structure is thread-safe because it is immutable.
       struct BackgroundWorkItem {
         explicit BackgroundWorkItem(void (*function)(void* arg), void* arg)
             : function(function), arg(arg) {}
    @@ -770,6 +785,10 @@ int MaxOpenFiles() {
       if (g_open_read_only_file_limit >= 0) {
         return g_open_read_only_file_limit;
       }
    +#ifdef __Fuchsia__
    +  // Fuchsia doesn't implement getrlimit.
    +  g_open_read_only_file_limit = 50;
    +#else
       struct ::rlimit rlim;
       if (::getrlimit(RLIMIT_NOFILE, &rlim)) {
         // getrlimit failed, fallback to hard-coded default.
    @@ -780,6 +799,7 @@ int MaxOpenFiles() {
         // Allow use of 20% of available file descriptors for read-only files.
         g_open_read_only_file_limit = rlim.rlim_cur / 5;
       }
    +#endif
       return g_open_read_only_file_limit;
     }
     
    @@ -906,4 +926,4 @@ Env* Env::Default() {
       return env_container.env();
     }
     
    -}  // namespace leveldb
    +}  // namespace leveldb
    \ No newline at end of file
    diff --git a/src/leveldb/util/env_windows.cc b/src/leveldb/util/env_windows.cc
    index 0a48c3fb52..4b68efdd33 100644
    --- a/src/leveldb/util/env_windows.cc
    +++ b/src/leveldb/util/env_windows.cc
    @@ -33,10 +33,6 @@
     #include "util/mutexlock.h"
     #include "util/windows_logger.h"
     
    -#if defined(DeleteFile)
    -#undef DeleteFile
    -#endif  // defined(DeleteFile)
    -
     namespace leveldb {
     
     namespace {
    @@ -118,7 +114,14 @@ class ScopedHandle {
     class Limiter {
      public:
       // Limit maximum number of resources to |max_acquires|.
    -  Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}
    +  Limiter(int max_acquires)
    +      :
    +#if !defined(NDEBUG)
    +        max_acquires_(max_acquires),
    +#endif  // !defined(NDEBUG)
    +        acquires_allowed_(max_acquires) {
    +    assert(max_acquires >= 0);
    +  }
     
       Limiter(const Limiter&) = delete;
       Limiter operator=(const Limiter&) = delete;
    @@ -137,9 +140,22 @@ class Limiter {
     
       // Release a resource acquired by a previous call to Acquire() that returned
       // true.
    -  void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }
    +  void Release() {
    +    int old_acquires_allowed =
    +        acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
    +
    +    // Silence compiler warnings about unused arguments when NDEBUG is defined.
    +    (void)old_acquires_allowed;
    +    // If the check below fails, Release() was called more times than acquire.
    +    assert(old_acquires_allowed < max_acquires_);
    +  }
     
      private:
    +#if !defined(NDEBUG)
    +  // Catches an excessive number of Release() calls.
    +  const int max_acquires_;
    +#endif  // !defined(NDEBUG)
    +
       // The number of available resources.
       //
       // This is a counter and is not tied to the invariants of any other class, so
    @@ -177,8 +193,6 @@ class WindowsSequentialFile : public SequentialFile {
         return Status::OK();
       }
     
    -  std::string GetName() const override { return filename_; }
    -
      private:
       const ScopedHandle handle_;
       const std::string filename_;
    @@ -194,7 +208,7 @@ class WindowsRandomAccessFile : public RandomAccessFile {
       Status Read(uint64_t offset, size_t n, Slice* result,
                   char* scratch) const override {
         DWORD bytes_read = 0;
    -    OVERLAPPED overlapped = {};
    +    OVERLAPPED overlapped = {0};
     
         overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
         overlapped.Offset = static_cast<DWORD>(offset);
    @@ -211,8 +225,6 @@ class WindowsRandomAccessFile : public RandomAccessFile {
         return Status::OK();
       }
     
    -  std::string GetName() const override { return filename_; }
    -
      private:
       const ScopedHandle handle_;
       const std::string filename_;
    @@ -244,8 +256,6 @@ class WindowsMmapReadableFile : public RandomAccessFile {
         return Status::OK();
       }
     
    -  std::string GetName() const override { return filename_; }
    -
      private:
       char* const mmap_base_;
       const size_t length_;
    @@ -315,8 +325,6 @@ class WindowsWritableFile : public WritableFile {
         return Status::OK();
       }
     
    -  std::string GetName() const override { return filename_; }
    -
      private:
       Status FlushBuffer() {
         Status status = WriteUnbuffered(buf_, pos_);
    @@ -387,9 +395,8 @@ class WindowsEnv : public Env {
         *result = nullptr;
         DWORD desired_access = GENERIC_READ;
         DWORD share_mode = FILE_SHARE_READ;
    -    auto wFilename = toUtf16(filename);
    -    ScopedHandle handle = ::CreateFileW(
    -        wFilename.c_str(), desired_access, share_mode,
    +    ScopedHandle handle = ::CreateFileA(
    +        filename.c_str(), desired_access, share_mode,
             /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
             /*hTemplateFile=*/nullptr);
         if (!handle.is_valid()) {
    @@ -405,9 +412,8 @@ class WindowsEnv : public Env {
         *result = nullptr;
         DWORD desired_access = GENERIC_READ;
         DWORD share_mode = FILE_SHARE_READ;
    -    auto wFilename = toUtf16(filename);
         ScopedHandle handle =
    -        ::CreateFileW(wFilename.c_str(), desired_access, share_mode,
    +        ::CreateFileA(filename.c_str(), desired_access, share_mode,
                           /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING,
                           FILE_ATTRIBUTE_READONLY,
                           /*hTemplateFile=*/nullptr);
    @@ -427,7 +433,7 @@ class WindowsEnv : public Env {
         }
     
         ScopedHandle mapping =
    -        ::CreateFileMappingW(handle.get(),
    +        ::CreateFileMappingA(handle.get(),
                                  /*security attributes=*/nullptr, PAGE_READONLY,
                                  /*dwMaximumSizeHigh=*/0,
                                  /*dwMaximumSizeLow=*/0,
    @@ -452,9 +458,8 @@ class WindowsEnv : public Env {
                              WritableFile** result) override {
         DWORD desired_access = GENERIC_WRITE;
         DWORD share_mode = 0;  // Exclusive access.
    -    auto wFilename = toUtf16(filename);
    -    ScopedHandle handle = ::CreateFileW(
    -        wFilename.c_str(), desired_access, share_mode,
    +    ScopedHandle handle = ::CreateFileA(
    +        filename.c_str(), desired_access, share_mode,
             /*lpSecurityAttributes=*/nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
             /*hTemplateFile=*/nullptr);
         if (!handle.is_valid()) {
    @@ -470,9 +475,8 @@ class WindowsEnv : public Env {
                                WritableFile** result) override {
         DWORD desired_access = FILE_APPEND_DATA;
         DWORD share_mode = 0;  // Exclusive access.
    -    auto wFilename = toUtf16(filename);
    -    ScopedHandle handle = ::CreateFileW(
    -        wFilename.c_str(), desired_access, share_mode,
    +    ScopedHandle handle = ::CreateFileA(
    +        filename.c_str(), desired_access, share_mode,
             /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
             /*hTemplateFile=*/nullptr);
         if (!handle.is_valid()) {
    @@ -485,16 +489,14 @@ class WindowsEnv : public Env {
       }
     
       bool FileExists(const std::string& filename) override {
    -    auto wFilename = toUtf16(filename);
    -    return GetFileAttributesW(wFilename.c_str()) != INVALID_FILE_ATTRIBUTES;
    +    return GetFileAttributesA(filename.c_str()) != INVALID_FILE_ATTRIBUTES;
       }
     
       Status GetChildren(const std::string& directory_path,
                          std::vector<std::string>* result) override {
         const std::string find_pattern = directory_path + "\\*";
    -    WIN32_FIND_DATAW find_data;
    -    auto wFind_pattern = toUtf16(find_pattern);
    -    HANDLE dir_handle = ::FindFirstFileW(wFind_pattern.c_str(), &find_data);
    +    WIN32_FIND_DATAA find_data;
    +    HANDLE dir_handle = ::FindFirstFileA(find_pattern.c_str(), &find_data);
         if (dir_handle == INVALID_HANDLE_VALUE) {
           DWORD last_error = ::GetLastError();
           if (last_error == ERROR_FILE_NOT_FOUND) {
    @@ -506,12 +508,11 @@ class WindowsEnv : public Env {
           char base_name[_MAX_FNAME];
           char ext[_MAX_EXT];
     
    -      auto find_data_filename = toUtf8(find_data.cFileName);
    -      if (!_splitpath_s(find_data_filename.c_str(), nullptr, 0, nullptr, 0,
    -                        base_name, ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {
    +      if (!_splitpath_s(find_data.cFileName, nullptr, 0, nullptr, 0, base_name,
    +                        ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {
             result->emplace_back(std::string(base_name) + ext);
           }
    -    } while (::FindNextFileW(dir_handle, &find_data));
    +    } while (::FindNextFileA(dir_handle, &find_data));
         DWORD last_error = ::GetLastError();
         ::FindClose(dir_handle);
         if (last_error != ERROR_NO_MORE_FILES) {
    @@ -520,25 +521,22 @@ class WindowsEnv : public Env {
         return Status::OK();
       }
     
    -  Status DeleteFile(const std::string& filename) override {
    -    auto wFilename = toUtf16(filename);
    -    if (!::DeleteFileW(wFilename.c_str())) {
    +  Status RemoveFile(const std::string& filename) override {
    +    if (!::DeleteFileA(filename.c_str())) {
           return WindowsError(filename, ::GetLastError());
         }
         return Status::OK();
       }
     
       Status CreateDir(const std::string& dirname) override {
    -    auto wDirname = toUtf16(dirname);
    -    if (!::CreateDirectoryW(wDirname.c_str(), nullptr)) {
    +    if (!::CreateDirectoryA(dirname.c_str(), nullptr)) {
           return WindowsError(dirname, ::GetLastError());
         }
         return Status::OK();
       }
     
    -  Status DeleteDir(const std::string& dirname) override {
    -    auto wDirname = toUtf16(dirname);
    -    if (!::RemoveDirectoryW(wDirname.c_str())) {
    +  Status RemoveDir(const std::string& dirname) override {
    +    if (!::RemoveDirectoryA(dirname.c_str())) {
           return WindowsError(dirname, ::GetLastError());
         }
         return Status::OK();
    @@ -546,8 +544,7 @@ class WindowsEnv : public Env {
     
       Status GetFileSize(const std::string& filename, uint64_t* size) override {
         WIN32_FILE_ATTRIBUTE_DATA file_attributes;
    -    auto wFilename = toUtf16(filename);
    -    if (!::GetFileAttributesExW(wFilename.c_str(), GetFileExInfoStandard,
    +    if (!::GetFileAttributesExA(filename.c_str(), GetFileExInfoStandard,
                                     &file_attributes)) {
           return WindowsError(filename, ::GetLastError());
         }
    @@ -561,9 +558,7 @@ class WindowsEnv : public Env {
       Status RenameFile(const std::string& from, const std::string& to) override {
         // Try a simple move first. It will only succeed when |to| doesn't already
         // exist.
    -    auto wFrom = toUtf16(from);
    -    auto wTo = toUtf16(to);
    -    if (::MoveFileW(wFrom.c_str(), wTo.c_str())) {
    +    if (::MoveFileA(from.c_str(), to.c_str())) {
           return Status::OK();
         }
         DWORD move_error = ::GetLastError();
    @@ -572,7 +567,7 @@ class WindowsEnv : public Env {
         // succeed when |to| does exist. When writing to a network share, we may not
         // be able to change the ACLs. Ignore ACL errors then
         // (REPLACEFILE_IGNORE_MERGE_ERRORS).
    -    if (::ReplaceFileW(wTo.c_str(), wFrom.c_str(), /*lpBackupFileName=*/nullptr,
    +    if (::ReplaceFileA(to.c_str(), from.c_str(), /*lpBackupFileName=*/nullptr,
                            REPLACEFILE_IGNORE_MERGE_ERRORS,
                            /*lpExclude=*/nullptr, /*lpReserved=*/nullptr)) {
           return Status::OK();
    @@ -592,9 +587,8 @@ class WindowsEnv : public Env {
       Status LockFile(const std::string& filename, FileLock** lock) override {
         *lock = nullptr;
         Status result;
    -    auto wFilename = toUtf16(filename);
    -    ScopedHandle handle = ::CreateFileW(
    -        wFilename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
    +    ScopedHandle handle = ::CreateFileA(
    +        filename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
             /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
             nullptr);
         if (!handle.is_valid()) {
    @@ -634,11 +628,10 @@ class WindowsEnv : public Env {
           return Status::OK();
         }
     
    -    wchar_t wtmp_path[MAX_PATH];
    -    if (!GetTempPathW(ARRAYSIZE(wtmp_path), wtmp_path)) {
    +    char tmp_path[MAX_PATH];
    +    if (!GetTempPathA(ARRAYSIZE(tmp_path), tmp_path)) {
           return WindowsError("GetTempPath", ::GetLastError());
         }
    -    std::string tmp_path = toUtf8(std::wstring(wtmp_path));
         std::stringstream ss;
         ss << tmp_path << "leveldbtest-" << std::this_thread::get_id();
         *result = ss.str();
    @@ -649,8 +642,7 @@ class WindowsEnv : public Env {
       }
     
       Status NewLogger(const std::string& filename, Logger** result) override {
    -    auto wFilename = toUtf16(filename);
    -    std::FILE* fp = _wfopen(wFilename.c_str(), L"w");
    +    std::FILE* fp = std::fopen(filename.c_str(), "wN");
         if (fp == nullptr) {
           *result = nullptr;
           return WindowsError(filename, ::GetLastError());
    @@ -689,7 +681,7 @@ class WindowsEnv : public Env {
       // Instances are constructed on the thread calling Schedule() and used on the
       // background thread.
       //
    -  // This structure is thread-safe beacuse it is immutable.
    +  // This structure is thread-safe because it is immutable.
       struct BackgroundWorkItem {
         explicit BackgroundWorkItem(void (*function)(void* arg), void* arg)
             : function(function), arg(arg) {}
    @@ -706,31 +698,6 @@ class WindowsEnv : public Env {
           GUARDED_BY(background_work_mutex_);
     
       Limiter mmap_limiter_;  // Thread-safe.
    -
    -  // Converts a Windows wide multi-byte UTF-16 string to a UTF-8 string.
    -  // See http://utf8everywhere.org/#windows
    -  std::string toUtf8(const std::wstring& wstr) {
    -    if (wstr.empty()) return std::string();
    -    int size_needed = WideCharToMultiByte(
    -        CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
    -    std::string strTo(size_needed, 0);
    -    WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0],
    -                        size_needed, NULL, NULL);
    -    return strTo;
    -  }
    -
    -  // Converts a UTF-8 string to a Windows UTF-16 multi-byte wide character
    -  // string.
    -  // See http://utf8everywhere.org/#windows
    -  std::wstring toUtf16(const std::string& str) {
    -    if (str.empty()) return std::wstring();
    -    int size_needed =
    -        MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    -    std::wstring strTo(size_needed, 0);
    -    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &strTo[0],
    -                        size_needed);
    -    return strTo;
    -  }
     };
     
     // Return the maximum number of concurrent mmaps.
    @@ -849,4 +816,4 @@ Env* Env::Default() {
       return env_container.env();
     }
     
    -}  // namespace leveldb
    +}  // namespace leveldb
    \ No newline at end of file
    diff --git a/src/leveldb/util/no_destructor.h b/src/leveldb/util/no_destructor.h
    index c28a107313..1836d2029c 100644
    --- a/src/leveldb/util/no_destructor.h
    +++ b/src/leveldb/util/no_destructor.h
    @@ -16,35 +16,35 @@ namespace leveldb {
     // This is intended for use with function-level static variables.
     template <typename InstanceType>
     class NoDestructor {
    - public:
    -  template <typename... ConstructorArgTypes>
    -  explicit NoDestructor(ConstructorArgTypes&&... constructor_args) {
    -    static_assert(sizeof(instance_storage_) >= sizeof(InstanceType),
    -                  "instance_storage_ is not large enough to hold the instance");
    -    static_assert(std::is_standard_layout_v<NoDestructor<InstanceType>>);
    -    static_assert(
    -        offsetof(NoDestructor, instance_storage_) % alignof(InstanceType) == 0,
    -        "instance_storage_ does not meet the instance's alignment requirement");
    -    static_assert(
    -        alignof(NoDestructor<InstanceType>) % alignof(InstanceType) == 0,
    -        "instance_storage_ does not meet the instance's alignment requirement");
    -    new (instance_storage_)
    -        InstanceType(std::forward<ConstructorArgTypes>(constructor_args)...);
    -  }
    -
    -  ~NoDestructor() = default;
    -
    -  NoDestructor(const NoDestructor&) = delete;
    -  NoDestructor& operator=(const NoDestructor&) = delete;
    -
    -  InstanceType* get() {
    -    return reinterpret_cast<InstanceType*>(&instance_storage_);
    -  }
    -
    - private:
    -  alignas(InstanceType) char instance_storage_[sizeof(InstanceType)];
    +public:
    +    template <typename... ConstructorArgTypes>
    +    explicit NoDestructor(ConstructorArgTypes&&... constructor_args) {
    +        static_assert(sizeof(instance_storage_) >= sizeof(InstanceType),
    +                      "instance_storage_ is not large enough to hold the instance");
    +        static_assert(std::is_standard_layout_v<NoDestructor<InstanceType>>);
    +        static_assert(
    +            offsetof(NoDestructor, instance_storage_) % alignof(InstanceType) == 0,
    +            "instance_storage_ does not meet the instance's alignment requirement");
    +        static_assert(
    +            alignof(NoDestructor<InstanceType>) % alignof(InstanceType) == 0,
    +            "instance_storage_ does not meet the instance's alignment requirement");
    +        new (instance_storage_)
    +            InstanceType(std::forward<ConstructorArgTypes>(constructor_args)...);
    +    }
    +
    +    ~NoDestructor() = default;
    +
    +    NoDestructor(const NoDestructor&) = delete;
    +    NoDestructor& operator=(const NoDestructor&) = delete;
    +
    +    InstanceType* get() {
    +        return reinterpret_cast<InstanceType*>(&instance_storage_);
    +    }
    +
    +private:
    +    alignas(InstanceType) char instance_storage_[sizeof(InstanceType)];
     };
     
     }  // namespace leveldb
     
    -#endif  // STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_
    +#endif  // STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_
    \ No newline at end of file
    

    </details>

    After that I have compared the modified codeparts only against latest and they match exactly.

    Build failure is known and unrelated. Build and tests are passing locally for a rebased version against latest master.

    ACK c8fab356171a0e283d5716647e3243c04810ac51

    edit: running a full reindex-chainstate for a rebased version to validate the change

  22. fanquake merged this on Mar 20, 2025
  23. fanquake closed this on Mar 20, 2025

  24. fanquake deleted the branch on Mar 20, 2025
  25. l0rinc commented at 9:13 AM on March 20, 2025: contributor

    reindex-chainstate finished successfully

    <details> <summary>Details</summary>

    COMMITS="5e934ebc82ca239cd98eed1689f7cdc2c672a9ae"; \
    STOP_HEIGHT=888000; DBCACHE=5000; \
    C_COMPILER=gcc; CXX_COMPILER=g++; \
    git fetch --all -q && (for c in $COMMITS; do git log -1 --oneline $c || exit 1; done) && \
    hyperfine \
      --export-json "/mnt/my_storage/rdx-${COMMITS// /-}-${STOP_HEIGHT}-${DBCACHE}-${C_COMPILER}.json" \
      --runs 1 \
      --parameter-list COMMIT ${COMMITS// /,} \
      --prepare "killall bitcoind || true; rm -f /mnt/my_storage/BitcoinData/debug.log; git checkout {COMMIT}; git clean -fxd; git reset --hard; cmake -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_WALLET=OFF -DCMAKE_C_COMPILER=$C_COMPILER -DCMAKE_CXX_COMPILER=$CXX_COMPILER && cmake --build build -j$(nproc) --target bitcoind && ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=$STOP_HEIGHT -dbcache=10000 -printtoconsole=0 || true" \
      --cleanup "cp /mnt/my_storage/BitcoinData/debug.log /mnt/my_storage/logs/debug-{COMMIT}-$(date +%s).log || true" \
      "COMPILER=$C_COMPILER COMMIT={COMMIT} ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=$STOP_HEIGHT -dbcache=$DBCACHE -blocksonly -reindex-chainstate -connect=0 -printtoconsole=0"
    
    5e934ebc82 (l0rinc/detached179) ci: remove -Wno-error=deprecated-declarations from ASAN
    Benchmark 1: COMPILER=gcc COMMIT=5e934ebc82ca239cd98eed1689f7cdc2c672a9ae ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=888000 -dbcache=5000 -blocksonly -reindex-chainstate -connect=0 -printtoconsole=0
      Time (abs ≡):        24720.986 s               [User: 22604.063 s, System: 1067.193 s]
    

    </details>


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-26 06:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me