diff --git a/src/ifcopenshell-python/ifcopenshell/__init__.py b/src/ifcopenshell-python/ifcopenshell/__init__.py index cdc82c9c74..07d1f570dd 100644 --- a/src/ifcopenshell-python/ifcopenshell/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/__init__.py @@ -378,15 +378,24 @@ def stream2_from_string(data: str) -> Generator[dict]: yield inst -def convert_path_to_rocksdb(ifcspf_path: Union[Path, str], rocksdb_path: Union[Path, str]) -> None: +def convert_path_to_rocksdb( + ifcspf_path: Union[Path, str], + rocksdb_path: Union[Path, str], + skip_supertypes: Optional[list[str]] = None, +) -> None: """Converts an IFC-SPF file on disk to the IfcOpenShell-specific RocksDB encoding. RocksDB is an embedded key-value store that allows partial reads and is therefore more memory efficient with larger files. :param ifcspf_path: Input file path - needs to exist :param rocksdb_path: RocksDB file path (directory) - may exist, but result may then be invalid + :param skip_supertypes: Optional list of entity type names. Any instance + whose declaration is-a (or subclasses) one of these names will be + omitted from the resulting RocksDB. Note: references to skipped + instances become dangling - reads that walk into them will fail. """ - ser = ifcopenshell_wrapper.RocksDbSerializer(str(ifcspf_path), str(rocksdb_path), True) + skip = list(skip_supertypes) if skip_supertypes else [] + ser = ifcopenshell_wrapper.RocksDbSerializer(str(ifcspf_path), str(rocksdb_path), True, skip) ser.finalize() diff --git a/src/serializers/RocksDbSerializer.cpp b/src/serializers/RocksDbSerializer.cpp index b55e1eadf8..bbc8e38057 100644 --- a/src/serializers/RocksDbSerializer.cpp +++ b/src/serializers/RocksDbSerializer.cpp @@ -23,9 +23,10 @@ RocksDbSerializer::RocksDbSerializer(ifcopenshell::file* file, const std::string output_file_->calculate_unit_factors = false; } -RocksDbSerializer::RocksDbSerializer(const std::string& input_filename, const std::string& rocksdb_filename, bool stream) +RocksDbSerializer::RocksDbSerializer(const std::string& input_filename, const std::string& rocksdb_filename, bool stream, const std::vector& skip_supertypes) : file_(input_filename) , rocksdb_filename_(rocksdb_filename) + , skip_supertypes_(skip_supertypes) { } @@ -144,6 +145,21 @@ void RocksDbSerializer::write_streaming_() { const bool is_header = decl->schema() == &Header_section_schema::get_schema(); + if (!is_header && decl->as_entity() && !skip_supertypes_.empty()) { + bool skip = false; + for (const auto& super : skip_supertypes_) { + if (decl->is(super)) { + skip = true; + break; + } + } + if (skip) { + streamer.references().clear(); + streamer.inverses().clear(); + continue; + } + } + std::vector simple_type_instances; for (size_t i = 0; i < data->storage_->size(); i++) { diff --git a/src/serializers/RocksDbSerializer.h b/src/serializers/RocksDbSerializer.h index 1ff8fec813..66caf3edb2 100644 --- a/src/serializers/RocksDbSerializer.h +++ b/src/serializers/RocksDbSerializer.h @@ -8,17 +8,21 @@ #include +#include +#include + class SERIALIZERS_API RocksDbSerializer : public Serializer { private: rocksdb::DB* db_; std::string rocksdb_filename_; std::variant file_; ifcopenshell::file* output_file_; + std::vector skip_supertypes_; void write_streaming_(); public: RocksDbSerializer(ifcopenshell::file* file, const std::string& rocksdb_filename); - RocksDbSerializer(const std::string& input_filename, const std::string& rocksdb_filename, bool stream); + RocksDbSerializer(const std::string& input_filename, const std::string& rocksdb_filename, bool stream, const std::vector& skip_supertypes = {}); virtual ~RocksDbSerializer() {}