diff --git a/src/ifcparse/IfcEntityInstanceData.cpp b/src/ifcparse/IfcEntityInstanceData.cpp index da40d96745..3226fa69ab 100644 --- a/src/ifcparse/IfcEntityInstanceData.cpp +++ b/src/ifcparse/IfcEntityInstanceData.cpp @@ -35,7 +35,9 @@ namespace { { if (storage_model_ == 0) { return array_.storage_ptr->get(index_); - } else { + } +#ifdef WITH_ROCKSDB + else { T val; if constexpr ( // the following types cannot be directly deserialized from rocksdb, but need to be constructed @@ -48,6 +50,7 @@ namespace { } return val; } +#endif } template @@ -55,7 +58,9 @@ namespace { { if (storage_model_ == 0) { return array_.storage_ptr->has(index_); - } else { + } +#ifdef WITH_ROCKSDB + else { std::string str; array_.db_ptr->db->Get(rocksdb::ReadOptions{}, (is_entity ? "i|" : "t|") + std::to_string(instance_name_) + "|" + std::to_string(index_), &str); if constexpr (std::is_same_v) { @@ -65,21 +70,24 @@ namespace { } return str[0] == TypeEncoder::encode_type(); } +#endif } inline size_t dispatch_index_(AttributeValue::pointer_type array_, uint8_t storage_model_, size_t instance_name_, bool is_entity, uint8_t index_) { if (storage_model_ == 0) { return array_.storage_ptr->index(index_); - } else { + } +#ifdef WITH_ROCKSDB + else { std::string str; if (!array_.db_ptr->db->Get(rocksdb::ReadOptions{}, (is_entity ? "i|" : "t|") + std::to_string(instance_name_) + "|" + std::to_string(index_), &str).ok()) { return TypeEncoder::encode_type() - 'A'; } return (size_t) str[0] - 'A'; } +#endif } - } AttributeValue::operator int() const @@ -112,7 +120,9 @@ AttributeValue::operator std::string() const // @todo also we don't really need to store a reference to the enumeration type, when this same type is already stored on the definition of the entity and no other value can be provided. if (storage_model_ == 0) { return dispatch_get_(array_, storage_model_, instance_name_, entity_or_type_ == 1 ? true : false, index_).value(); - } else { + } +#ifdef WITH_ROCKSDB + else { std::string str; array_.db_ptr->db->Get(rocksdb::ReadOptions{}, (entity_or_type_ == 1 ? "i|" : "t|") + std::to_string(instance_name_) + "|" + std::to_string(index_), &str); size_t v; @@ -121,6 +131,7 @@ AttributeValue::operator std::string() const memcpy(&v, str.data() + 1 + sizeof(size_t), sizeof(size_t)); return decl->lookup_enum_value(v); } +#endif } return dispatch_get_(array_, storage_model_, instance_name_, entity_or_type_ == 1 ? true : false, index_); } @@ -129,7 +140,9 @@ AttributeValue::operator EnumerationReference() const { if (storage_model_ == 0) { return dispatch_get_(array_, storage_model_, instance_name_, entity_or_type_ == 1 ? true : false, index_); - } else { + } +#ifdef WITH_ROCKSDB + else { std::string str; array_.db_ptr->db->Get(rocksdb::ReadOptions{}, (entity_or_type_ == 1 ? "i|" : "t|") + std::to_string(instance_name_) + "|" + std::to_string(index_), &str); size_t v; @@ -138,6 +151,7 @@ AttributeValue::operator EnumerationReference() const memcpy(&v, str.data() + 1 + sizeof(size_t), sizeof(size_t)); return EnumerationReference(decl, v); } +#endif } AttributeValue::operator boost::dynamic_bitset<>() const @@ -149,7 +163,9 @@ AttributeValue::operator IfcUtil::IfcBaseClass* () const { if (storage_model_ == 0) { return dispatch_get_(array_, storage_model_, instance_name_, entity_or_type_ == 1 ? true : false, index_); - } else { + } +#ifdef WITH_ROCKSDB + else { std::string str; array_.db_ptr->db->Get(rocksdb::ReadOptions{}, (entity_or_type_ == 1 ? "i|" : "t|") + std::to_string(instance_name_) + "|" + std::to_string(index_), &str); size_t v; @@ -160,9 +176,9 @@ AttributeValue::operator IfcUtil::IfcBaseClass* () const } else if (str[1] == 't') { // type reference by Identity return array_.db_ptr->assert_existance(v, IfcParse::impl::rocks_db_file_storage::typedecl_ref); - } - + } } +#endif } AttributeValue::operator std::vector() const @@ -221,6 +237,8 @@ IfcUtil::ArgumentType AttributeValue::type() const return static_cast(dispatch_index_(array_, storage_model_, instance_name_, entity_or_type_ == 1 ? true : false, index_)); } +#ifdef WITH_ROCKSDB + bool impl::serialize(std::string& val, const IfcUtil::IfcBaseClass* t) { auto s = sizeof(size_t); @@ -432,3 +450,5 @@ template bool rocks_db_attribute_storage::has(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index) const; template bool rocks_db_attribute_storage::has(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index) const; template bool rocks_db_attribute_storage::has(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index) const; + +#endif \ No newline at end of file diff --git a/src/ifcparse/IfcEntityInstanceData.h b/src/ifcparse/IfcEntityInstanceData.h index c784261aa6..6333af1796 100644 --- a/src/ifcparse/IfcEntityInstanceData.h +++ b/src/ifcparse/IfcEntityInstanceData.h @@ -25,6 +25,8 @@ #include "aggregate_of_instance.h" #include "IfcSchema.h" +#ifdef WITH_ROCKSDB + #pragma push_macro("Handle") #undef Handle @@ -32,6 +34,8 @@ #pragma pop_macro("Handle") +#endif + #include #include #include @@ -161,6 +165,7 @@ namespace IfcParse { } } +#if WITH_ROCKSDB namespace impl { @@ -275,6 +280,7 @@ namespace impl { bool deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, aggregate_of_aggregate_of_instance::ptr& t); } +#endif // short lived struct AttributeValue { @@ -384,8 +390,10 @@ struct AttributeValue { } }; + struct rocks_db_attribute_storage { public: +#ifdef WITH_ROCKSDB // @todo void* is obviously very ugly here template void set(void* storage, const IfcParse::declaration*, std::size_t identity, std::size_t index, const T& value); @@ -398,6 +406,7 @@ public: // @todo do we need visitation on all data/storage/attribute levels? AttributeValue((IfcParse::impl::rocks_db_file_storage*)storage, identity, decl->as_entity() ? 1 : 0, index).apply_visitor(std::forward(visitor)); } +#endif }; class IFC_PARSE_API IfcEntityInstanceData { @@ -439,27 +448,36 @@ class IFC_PARSE_API IfcEntityInstanceData { void set_attribute_value(void* storage, const IfcParse::declaration* decl, std::size_t identity, std::size_t index, T&& value) { if (storage_) { storage_->set(index, value); - } else { + } +#ifdef WITH_ROCKSDB + else { rocks_db_attribute_storage{}.set(storage, decl, identity, index, value); } +#endif } template bool has_attribute_value(void* storage, const IfcParse::declaration* decl, std::size_t identity, std::size_t index) const { if (storage_) { return storage_->has(index); - } else { + } +#ifdef WITH_ROCKSDB + else { return rocks_db_attribute_storage{}.has(storage, decl, identity, index); } +#endif } template auto apply_visitor(void* storage, const IfcParse::declaration* decl, std::size_t identity, Visitor&& visitor, std::size_t index) const { if (storage_) { return storage_->apply_visitor(std::forward(visitor), index); - } else { + } +#ifdef WITH_ROCKSDB + else { return rocks_db_attribute_storage{}.apply_visitor(storage, decl, identity, index, std::forward(visitor)); } +#endif } void toString(void* storage, const IfcParse::declaration*, std::size_t identity, std::ostream&, bool upper = false) const; diff --git a/src/ifcparse/IfcFile.cpp b/src/ifcparse/IfcFile.cpp index fd4e3bc947..aecd84ae58 100644 --- a/src/ifcparse/IfcFile.cpp +++ b/src/ifcparse/IfcFile.cpp @@ -344,6 +344,7 @@ IfcParse::impl::rocks_db_file_storage::rocksdb_types_iterator::value_type const& } IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::assert_existance(size_t number, instance_ref r) { +#ifdef WITH_ROCKSDB if (r == IfcParse::impl::rocks_db_file_storage::entityinstance_ref) { auto it = instance_cache_.find(number); if (it != instance_cache_.end()) { @@ -388,11 +389,15 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::assert_existance(s } else { throw IfcException("Instance #" + boost::lexical_cast(number) + " not found"); } +#else + throw IfcException("RocksDB support not compiled in"); +#endif } namespace { rocksdb::DB* init_db(const std::string& filepath) { - rocksdb::DB* db; + rocksdb::DB* db = nullptr; +#ifdef WITH_ROCKSDB rocksdb::Options options; // options.disable_auto_compactions = true; options.create_if_missing = true; @@ -401,6 +406,7 @@ namespace { if (!status.ok()) { throw std::runtime_error(status.ToString()); } +#endif // WITH_ROCKSDB# return db; } } @@ -423,6 +429,7 @@ IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(const std::string& IfcParse::impl::rocks_db_file_storage::~rocks_db_file_storage() { +#ifdef WITH_ROCKSDB rocksdb::FlushOptions flush_options; flush_options.allow_write_stall = true; flush_options.wait = true; // Wait until flush completes. @@ -435,6 +442,7 @@ IfcParse::impl::rocks_db_file_storage::~rocks_db_file_storage() db->Close(); delete db; +#endif } @@ -447,6 +455,7 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::instance_by_id(int void IfcParse::impl::rocks_db_file_storage::process_deletion_inverse(IfcUtil::IfcBaseClass* inst) { +#ifdef WITH_ROCKSDB auto id = inst->id(); { @@ -500,6 +509,7 @@ void IfcParse::impl::rocks_db_file_storage::process_deletion_inverse(IfcUtil::If } } } +#endif } IfcUtil::IfcBaseClass* IfcParse::impl::in_memory_file_storage::instance_by_id(int id) diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index 37764ff51e..564ba4b2a7 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -35,7 +35,8 @@ #include #include -#include "rocksdb/merge_operator.h" +#ifdef WITH_ROCKSDB +#include namespace { // @todo move to a proper place @@ -69,6 +70,7 @@ namespace { } }; } +#endif namespace IfcParse { diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index 24b9fc443e..a1fd515b2f 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -791,6 +791,7 @@ namespace { } void IfcParse::impl::rocks_db_file_storage::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, int inst_id, int attribute_index) { +#ifdef WITH_ROCKSDB static std::string s; uint32_t v = id_from; s.resize(sizeof(uint32_t)); @@ -808,9 +809,11 @@ void IfcParse::impl::rocks_db_file_storage::register_inverse(unsigned id_from, c auto new_val = current + s; db->Put(wopts, key, new_val); }*/ +#endif } void IfcParse::impl::rocks_db_file_storage::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) { +#ifdef WITH_ROCKSDB static std::string s; auto inst_id = inst->id(); auto key = "v|" + to_string_fixed_width(inst_id, 10) + "|" + to_string_fixed_width(from_entity->index_in_schema(), 4) + "|" + to_string_fixed_width(attribute_index, 2); @@ -827,10 +830,12 @@ void IfcParse::impl::rocks_db_file_storage::unregister_inverse(unsigned id_from, memcpy(s.data(), vals.data(), s.size()); db->Put(wopts, key, s); } +#endif } void IfcParse::impl::rocks_db_file_storage::add_type_ref(IfcUtil::IfcBaseClass* new_entity) { +#ifdef WITH_ROCKSDB size_t v; std::string s(sizeof(size_t), ' '); @@ -855,10 +860,12 @@ void IfcParse::impl::rocks_db_file_storage::add_type_ref(IfcUtil::IfcBaseClass* v = new_entity->declaration().index_in_schema(); memcpy(s.data(), &v, sizeof(size_t)); db->Put(wopts, (new_entity->declaration().as_entity() ? "i|" : "t|") + std::to_string(new_entity->id() ? new_entity->id() : new_entity->identity()) + "|_", s); +#endif } void IfcParse::impl::rocks_db_file_storage::remove_type_ref(IfcUtil::IfcBaseClass* new_entity) { +#ifdef WITH_ROCKSDB if (new_entity->declaration().as_entity()) { std::string s; auto key = "t|" + std::to_string(new_entity->declaration().index_in_schema()); @@ -873,6 +880,7 @@ void IfcParse::impl::rocks_db_file_storage::remove_type_ref(IfcUtil::IfcBaseClas } db->Delete(wopts, (new_entity->declaration().as_entity() ? "i|" : "t|") + std::to_string(new_entity->id() ? new_entity->id() : new_entity->identity()) + "|_"); +#endif } namespace { @@ -2275,7 +2283,9 @@ aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) { ret->push(instance_by_id(i)); } } - } else if constexpr (std::is_same_v, impl::rocks_db_file_storage>) { + } +#ifdef WITH_ROCKSDB + else if constexpr (std::is_same_v, impl::rocks_db_file_storage>) { // @todo no lower/upper_bounds() implemented yet auto prefix = "v|" + std::to_string(t) + "|"; auto it = x.db->NewIterator(rocksdb::ReadOptions()); @@ -2288,7 +2298,9 @@ aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) { } it->Next(); } - } else { + } +#endif + else { throw std::runtime_error("Storage not initialized"); } }, storage_); @@ -2482,7 +2494,9 @@ aggregate_of_instance::ptr IfcFile::getInverse(int instance_id, const IfcParse:: } } } - } else if constexpr (std::is_same_v, impl::rocks_db_file_storage>) { + } +#ifdef WITH_ROCKSDB + else if constexpr (std::is_same_v, impl::rocks_db_file_storage>) { if (attribute_index == -1) { // @todo no lower/upper_bounds() implemented yet auto prefix = "v|" + std::to_string(instance_id) + "|" + std::to_string(ent->index_in_schema()) + "|"; @@ -2505,6 +2519,7 @@ aggregate_of_instance::ptr IfcFile::getInverse(int instance_id, const IfcParse:: } } } +#endif }, storage_); }); @@ -2717,6 +2732,7 @@ AttributeValue IfcEntityInstanceData::get_attribute_value(void* storage, const I } bool IfcParse::impl::rocks_db_file_storage::read_schema(const IfcParse::schema_definition*& schema) { +#ifdef WITH_ROCKSDB std::string value; auto key = "h|file_schema|0"; db->Get(rocksdb::ReadOptions{}, key, &value); @@ -2725,6 +2741,7 @@ bool IfcParse::impl::rocks_db_file_storage::read_schema(const IfcParse::schema_d schema = schema_by_name(strings[0]); return true; } +#endif return false; } diff --git a/src/ifcparse/rocksdb_map_adapter.h b/src/ifcparse/rocksdb_map_adapter.h index 9a01777bd6..fc92f9aa59 100644 --- a/src/ifcparse/rocksdb_map_adapter.h +++ b/src/ifcparse/rocksdb_map_adapter.h @@ -17,8 +17,14 @@ * * ********************************************************************************/ +#ifndef ROCKSDB_MAP_ADAPTER_H +#define ROCKSDB_MAP_ADAPTER_H + +#ifdef WITH_ROCKSDB #include #include +#endif + #include #include #include @@ -217,6 +223,7 @@ public: iterator(const iterator& other) : db_(other.db_), prefix_(other.prefix_), codec_(other.codec_) { +#ifdef WITH_ROCKSDB if (other.it_) { std::string curr = other.it_->key().ToString(); it_.reset(db_->NewIterator(rocksdb::ReadOptions{})); @@ -224,9 +231,11 @@ public: if (!it_->Valid() || it_->key().ToString() != curr) it_.reset(); } +#endif } iterator& operator=(const iterator& other) { +#ifdef WITH_ROCKSDB if (this != &other) { db_ = other.db_; prefix_ = other.prefix_; @@ -241,14 +250,19 @@ public: it_.reset(); } } +#endif return *this; } value_type operator*() const { +#ifdef WITH_ROCKSDB std::string full_key = it_->key().ToString(); std::string key_without_prefix = full_key.substr(prefix_.size()); std::string value_str = it_->value().ToString(); return { key_from_string(key_without_prefix), codec_.decode(value_str) }; +#else + return cached_value_; +#endif } // operator-> uses a mutable cache to return a pointer to the current value. @@ -258,10 +272,12 @@ public: } iterator& operator++() { +#if WITH_ROCKSDB if (it_) { it_->Next(); check_valid(); } +#endif return *this; } @@ -272,9 +288,11 @@ public: } bool operator==(const iterator& other) const { +#ifdef WITH_ROCKSDB if (!it_ && !other.it_) return true; if (it_ && other.it_) return it_->key().ToString() == other.it_->key().ToString(); +#endif return false; } @@ -284,11 +302,13 @@ public: }; iterator begin() const { +#ifdef WITH_ROCKSDB auto iter = std::unique_ptr(db_->NewIterator(rocksdb::ReadOptions{})); iter->Seek(prefix_); if (iter->Valid() && iter->key().starts_with(prefix_)) { return iterator(db_, prefix_, std::move(iter), codec_); } +#endif return end(); } @@ -297,23 +317,30 @@ public: } iterator find(const key_type& key) const { +#ifdef WITH_ROCKSDB std::string key_str = key_to_string(key); std::string full_key = prefix_ + key_str; auto iter = std::unique_ptr(db_->NewIterator(rocksdb::ReadOptions{})); iter->Seek(full_key); if (iter->Valid() && iter->key().ToString() == full_key) return iterator(db_, prefix_, std::move(iter), codec_); +#endif return end(); } size_t erase(const key_type& key) { +#ifdef WITH_ROCKSDB std::string key_str = key_to_string(key); std::string full_key = prefix_ + key_str; rocksdb::Status s = db_->Delete(rocksdb::WriteOptions{}, full_key); return s.ok() ? 1 : 0; +#else + return 0; +#endif } std::pair insert(const value_type& val) { +#ifdef WITH_ROCKSDB std::string key_str = key_to_string(val.first); std::string full_key = prefix_ + key_str; std::string existing; @@ -327,6 +354,9 @@ public: if (!s.ok()) { return { end(), false }; } +#endif return { find(val.first), true }; } }; + +#endif \ No newline at end of file diff --git a/src/ifcparse/rocksdb_set_view.h b/src/ifcparse/rocksdb_set_view.h index c90d59678e..e9e1906e81 100644 --- a/src/ifcparse/rocksdb_set_view.h +++ b/src/ifcparse/rocksdb_set_view.h @@ -17,8 +17,14 @@ * * ********************************************************************************/ +#ifndef ROCKSDB_SET_VIEW_H +#define ROCKSDB_SET_VIEW_H + +#ifdef WITH_ROCKSDB #include #include +#endif + #include #include #include @@ -60,11 +66,15 @@ public: // Helper: extract the key (i.e. the value) from the current RocksDB key. value_type extract_current_value() const { +#ifdef WITH_ROCKSDB std::string full_key = it_->key().ToString(); std::string remainder = full_key.substr(prefix_.size()); size_t pos = remainder.find('|'); std::string key_str = (pos != std::string::npos) ? remainder.substr(0, pos) : remainder; return key_from_string(key_str); +#else + return cached_value_; +#endif } // Validates the current iterator state. @@ -86,6 +96,7 @@ public: iterator(const iterator& other) : db_(other.db_), prefix_(other.prefix_) { +#ifdef WITH_ROCKSDB if (other.it_) { std::string curr = other.it_->key().ToString(); it_.reset(db_->NewIterator(rocksdb::ReadOptions{})); @@ -93,9 +104,11 @@ public: if (!it_->Valid() || it_->key().ToString() != curr) it_.reset(); } +#endif } iterator& operator=(const iterator& other) { +#ifdef WITH_ROCKSDB if (this != &other) { db_ = other.db_; prefix_ = other.prefix_; @@ -109,6 +122,7 @@ public: it_.reset(); } } +#endif return *this; } @@ -125,6 +139,7 @@ public: // Pre-increment: advance the iterator and skip over any duplicate keys. iterator& operator++() { +#ifdef WITH_ROCKSDB if (it_) { // Record the current key value. value_type curr = extract_current_value(); @@ -135,6 +150,7 @@ public: if (!it_ || !it_->Valid() || !it_->key().starts_with(prefix_)) it_.reset(); } +#endif return *this; } @@ -145,10 +161,12 @@ public: } bool operator==(const iterator& other) const { +#ifdef WITH_ROCKSDB if (!it_ && !other.it_) return true; if (it_ && other.it_) return it_->key().ToString() == other.it_->key().ToString(); +#endif return false; } @@ -159,10 +177,12 @@ public: // Returns an iterator to the first element in the key-space (or end() if none exist). iterator begin() const { +#ifdef WITH_ROCKSDB auto iter = std::unique_ptr(db_->NewIterator(rocksdb::ReadOptions{})); iter->Seek(prefix_); if (iter->Valid() && iter->key().starts_with(prefix_)) return iterator(db_, prefix_, std::move(iter)); +#endif return end(); } @@ -173,6 +193,7 @@ public: // Read-only find: returns an iterator to the element with the given key if it exists. iterator find(const key_type& key) const { +#ifdef WITH_ROCKSDB std::string key_str = key_to_string(key); // Construct the search key: prefix + key_str + separator. std::string start_key = prefix_ + key_str + "|"; @@ -186,6 +207,7 @@ public: if (key_from_string(found_key_str) == key) return iterator(db_, prefix_, std::move(iter)); } +#endif return end(); } @@ -193,3 +215,5 @@ public: // @todo } }; + +#endif \ No newline at end of file diff --git a/src/ifcparse/storage.h b/src/ifcparse/storage.h index dc3c1aa599..c3a5c4853a 100644 --- a/src/ifcparse/storage.h +++ b/src/ifcparse/storage.h @@ -1,6 +1,19 @@ #ifndef STORAGE_H #define STORAGE_H +#ifndef WITH_ROCKSDB + +namespace rocksdb { + class DB {}; + class Options {}; + class WriteOptions {}; + class ReadOptions {}; + class Iterator {}; + class Status {}; +} + +#endif + #include "rocksdb_map_adapter.h" #include "rocksdb_set_view.h" #include "map_variant.h" @@ -436,6 +449,7 @@ namespace IfcParse { static constexpr char prefix_[] = "t|"; boost::optional read_id_() const { +#ifdef WITH_ROCKSDB auto sv = state_->key().ToStringView(); auto ii = sv.find("|", 2); if (ii != decltype(sv)::npos) { @@ -445,6 +459,7 @@ namespace IfcParse { return (size_t)result; } } +#endif return boost::none; } public: @@ -464,15 +479,18 @@ namespace IfcParse { rocksdb_types_iterator(const rocks_db_file_storage* fs) : storage_(fs) { +#ifdef WITH_ROCKSDB state_ = fs->db->NewIterator(rocksdb::ReadOptions()); state_->Seek(prefix_); if (!state_->Valid() || !state_->key().starts_with(prefix_)) { delete state_; state_ = nullptr; } +#endif } rocksdb_types_iterator& operator++() { +#ifdef WITH_ROCKSDB if (!state_) { return *this; } @@ -490,6 +508,7 @@ namespace IfcParse { } } return *this; +#endif } rocksdb_types_iterator operator++(int) {