diff --git a/Fulcrum.pro b/Fulcrum.pro index 21c000f..144a501 100644 --- a/Fulcrum.pro +++ b/Fulcrum.pro @@ -376,6 +376,7 @@ SOURCES += \ Servers.cpp \ SrvMgr.cpp \ Storage.cpp \ + Storage/Compat.cpp \ Storage/ConcatOperator.cpp \ Storage/DBRecordArray.cpp \ Storage/RecordFile.cpp \ @@ -428,6 +429,7 @@ HEADERS += \ Span.h \ SrvMgr.h \ Storage.h \ + Storage/Compat.h \ Storage/ConcatOperator.h \ Storage/DBRecordArray.h \ Storage/RecordFile.h \ diff --git a/src/Storage.cpp b/src/Storage.cpp index de2d8eb..82a8c40 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -26,6 +26,7 @@ #include "Rpa.h" #include "Span.h" #include "Storage.h" +#include "Storage/Compat.h" #include "Storage/ConcatOperator.h" #include "Storage/DBRecordArray.h" #include "Storage/RecordFile.h" @@ -1661,10 +1662,8 @@ void Storage::openOrCreateDB(bool bulkLoad) } } - rocksdb::DB *db = nullptr; - s = rocksdb::DB::Open(opts, path.toStdString(), colFamDescs, &p->db.columnFamilies, &db); - p->db.db.reset(db); - if (!s.ok() || !db) + s = Compat::DBOpen(opts, path.toStdString(), colFamDescs, &p->db.columnFamilies, &p->db.db); + if (!s.ok() || !p->db.db) throw DatabaseError(QString("Error opening %1 database: %2 (path: %3)") .arg(kDBName, StatusString(s), path)); } @@ -1913,11 +1912,11 @@ bool Storage::checkFulc1xUpgradeDB() if (info.options.merge_operator) dbopts.merge_operator = info.options.merge_operator; dbopts.comparator = info.options.comparator; // should always be default BytewiseComparator, but defensively we ensure that is the case - rocksdb::DB *dbin_raw{}; - if (auto st = rocksdb::DB::Open(dbopts, fname.toStdString(), &dbin_raw); !st.ok()) { + std::unique_ptr dbin; + if (auto st = Compat::DBOpen(dbopts, fname.toStdString(), &dbin); !st.ok()) { throw DatabaseError("rocksdb::DB::Open returned error for " + name + ": " + StatusString(st)); } - std::unique_ptr dbin(dbin_raw); + const bool isMetaTable = info.handle == p->db.meta; std::optional convertedDbMetaSerialization; // upgraded/converted 'kMeta' row (class: Meta) diff --git a/src/Storage.h b/src/Storage.h index 40c2dde..9a6f814 100644 --- a/src/Storage.h +++ b/src/Storage.h @@ -50,8 +50,8 @@ // fwd decls used by Storage private(s) namespace rocksdb { -class DB; class ColumnFamilyHandle; +class DB; class WriteBatch; } diff --git a/src/Storage/Compat.cpp b/src/Storage/Compat.cpp new file mode 100644 index 0000000..a840595 --- /dev/null +++ b/src/Storage/Compat.cpp @@ -0,0 +1,60 @@ +// +// Fulcrum - A fast & nimble SPV Server for Bitcoin Cash +// Copyright (C) 2019-2026 Calin A. Culianu +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program (see LICENSE.txt). If not, see +// . +// +#include "Storage/Compat.h" + +#include +#if ROCKSDB_MAJOR >= 11 +/* RocksDB v11.0.0 or greater may not have the "raw pointer" versions of DB::Open() (which we still must support for + * compatibility with older rocksdb). See: https://github.com/facebook/rocksdb/releases/tag/v11.0.4 + */ +#define USE_RAW_PTR_ROCKSDB_OPEN_FUNC 0 +#else +#define USE_RAW_PTR_ROCKSDB_OPEN_FUNC 1 +#endif + +namespace Compat { + +rocksdb::Status DBOpen(const rocksdb::Options &options, const std::string &name, std::unique_ptr *dbptr) +{ +#if USE_RAW_PTR_ROCKSDB_OPEN_FUNC + rocksdb::DB *raw = nullptr; + rocksdb::Status st = rocksdb::DB::Open(options, name, &raw); + dbptr->reset(raw); // Give the raw DB ptr to the unique ptr + return st; +#else + return rocksdb::DB::Open(options, name, dbptr); +#endif +} + +rocksdb::Status DBOpen(const rocksdb::DBOptions &db_options, const std::string &name, + const std::vector &column_families, + std::vector *handles, + std::unique_ptr *dbptr) +{ +#if USE_RAW_PTR_ROCKSDB_OPEN_FUNC + rocksdb::DB *raw = nullptr; + rocksdb::Status st = rocksdb::DB::Open(db_options, name, column_families, handles, &raw); + dbptr->reset(raw); // Give the raw DB ptr to the unique ptr + return st; +#else + return rocksdb::DB::Open(db_options, name, column_families, handles, dbptr); +#endif +} + +} // namespace Compat diff --git a/src/Storage/Compat.h b/src/Storage/Compat.h new file mode 100644 index 0000000..80444e0 --- /dev/null +++ b/src/Storage/Compat.h @@ -0,0 +1,38 @@ +// +// Fulcrum - A fast & nimble SPV Server for Bitcoin Cash +// Copyright (C) 2019-2026 Calin A. Culianu +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program (see LICENSE.txt). If not, see +// . +// +#pragma once + +#include +#include +#include + +#include +#include +#include + +/// A namespace for encapsulating a "compatibility" layer to smoothe over API differences between various +/// rocksdb versions +namespace Compat { +// rocksdb::DB::Open changed after version v11.0.0 of rocksdb so we smoothe it over with a unified API +rocksdb::Status DBOpen(const rocksdb::Options &options, const std::string &name, std::unique_ptr *dbptr); +rocksdb::Status DBOpen(const rocksdb::DBOptions &db_options, const std::string &name, + const std::vector &column_families, + std::vector *handles, + std::unique_ptr *dbptr); +} // namespace Compat diff --git a/src/Storage/DBRecordArray.cpp b/src/Storage/DBRecordArray.cpp index 8bc2e0f..8e9b6e8 100644 --- a/src/Storage/DBRecordArray.cpp +++ b/src/Storage/DBRecordArray.cpp @@ -20,6 +20,7 @@ #include "ByteView.h" #include "ConcatOperator.h" +#include "Storage/Compat.h" #include "Util.h" #include "bitcoin/serialize.h" @@ -509,13 +510,13 @@ TEST_CASE(gen_hashes) { TEST_CASE(open_db) { TEST_CHECK(tmpDir.isValid()); - rocksdb::DB *dbptr{}; rocksdb::Options opts; opts.create_if_missing = true; opts.merge_operator.reset(new StorageDetail::ConcatOperator); - auto st = rocksdb::DB::Open(opts, tmpDir.path().toStdString(), &dbptr); + std::unique_ptr simple_uptr; + auto st = Compat::DBOpen(opts, tmpDir.path().toStdString(), &simple_uptr); TEST_CHECK_MESSAGE(st.ok(), st.ToString()); - db.reset(dbptr); + db.reset(simple_uptr.release()); TEST_CHECK(db != nullptr); if (!db) throw Exception("DB pointer is null! Cannot proceed!"); cf = db->DefaultColumnFamily();