mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
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:
@@ -258,10 +258,14 @@ if(WITH_ROCKSDB)
|
||||
set(ROCKSDB_LIBRARIES "IFCOPENSHELL_RocksDB")
|
||||
target_compile_definitions(IFCOPENSHELL_RocksDB INTERFACE IFOPSH_WITH_ROCKSDB)
|
||||
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_ROCKSDB)
|
||||
# Shared binaries for `rocksdb` only support limited API (only `c.h`), but we use `db.h` API.
|
||||
# So rocksdb supported only as a static library.
|
||||
# See https://github.com/facebook/rocksdb/issues/981.
|
||||
target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb)
|
||||
if(TARGET RocksDB::rocksdb)
|
||||
target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb)
|
||||
elseif(TARGET RocksDB::rocksdb-shared)
|
||||
target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb-shared)
|
||||
else()
|
||||
message(FATAL_ERROR "RocksDB found but neither RocksDB::rocksdb nor RocksDB::rocksdb-shared target exists")
|
||||
endif()
|
||||
|
||||
if(WITH_ZSTD)
|
||||
# @todo do we actually need the zstd include dir or rather just pass
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user