Support RocksDB shared library and new unique_ptr DB::Open API

Some distributions (e.g. Fedora) ship only a shared RocksDB that exports
RocksDB::rocksdb-shared rather than RocksDB::rocksdb. The CMake target
selection now falls back to the shared target when the static one is absent.

Newer RocksDB also changed DB::Open and DB::OpenForReadOnly to take
std::unique_ptr<DB>* instead of DB**. IfcFile.cpp uses SFINAE tag dispatch
to build against both old and new APIs without version detection.
This commit is contained in:
Bruno Postle
2026-06-04 22:31:02 +01:00
committed by Thomas Krijnen
parent eacff93945
commit 365be8fb52
2 changed files with 35 additions and 5 deletions
+28 -2
View File
@@ -7,6 +7,8 @@
#endif
#include <fstream>
#include <memory>
#include <utility>
#include <sys/types.h>
#include <sys/stat.h>
@@ -410,6 +412,26 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::assert_existance(s
}
namespace {
#ifdef IFOPSH_WITH_ROCKSDB
// Newer RocksDB releases (e.g. the one shipped by Fedora rawhide) changed
// DB::Open / DB::OpenForReadOnly to take a std::unique_ptr<DB>* and removed
// the raw DB** overloads. These helpers select whichever signature the
// installed RocksDB exposes, so the code builds against both old and new
// headers. The int/long tag prefers the unique_ptr form when both exist.
template <typename Fn>
auto rocksdb_open(Fn&& open, rocksdb::DB*& db, int)
-> decltype(open(std::declval<std::unique_ptr<rocksdb::DB>*>())) {
std::unique_ptr<rocksdb::DB> owned;
auto status = open(&owned);
db = owned.release();
return status;
}
template <typename Fn>
auto rocksdb_open(Fn&& open, rocksdb::DB*& db, long)
-> decltype(open(std::declval<rocksdb::DB**>())) {
return open(&db);
}
#endif
rocksdb::DB* init_db(const std::string& filepath, bool readonly) {
rocksdb::DB* db = nullptr;
#ifdef IFOPSH_WITH_ROCKSDB
@@ -446,9 +468,13 @@ namespace {
rocksdb::Status status;
if (readonly) {
status = rocksdb::DB::OpenForReadOnly(options, filepath, &db);
status = rocksdb_open([&](auto* dbptr) -> decltype(rocksdb::DB::OpenForReadOnly(options, filepath, dbptr)) {
return rocksdb::DB::OpenForReadOnly(options, filepath, dbptr);
}, db, 0);
} else {
status = rocksdb::DB::Open(options, filepath, &db);
status = rocksdb_open([&](auto* dbptr) -> decltype(rocksdb::DB::Open(options, filepath, dbptr)) {
return rocksdb::DB::Open(options, filepath, dbptr);
}, db, 0);
}
if (!status.ok()) {
return nullptr;