Getting closer to working SPF again

This commit is contained in:
Thomas Krijnen
2025-02-24 20:46:29 +01:00
parent b4d0cfe0c8
commit 048f77cfed
4 changed files with 130 additions and 18 deletions
+3 -1
View File
@@ -330,6 +330,8 @@ if (WITH_ROCKSDB)
add_definitions(-DWITH_ROCKSDB)
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_ROCKSDB)
set(RPCRT_LIBRARIES "rpcrt4.lib" "shlwapi.lib")
endif()
# Find Boost: On win32 the (hardcoded) default is to use static libraries and
@@ -967,7 +969,7 @@ endforeach()
set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
add_library(IfcParse ${IFCPARSE_FILES})
target_link_libraries(IfcParse ${ROCKSDB_LIBRARY})
target_link_libraries(IfcParse ${ROCKSDB_LIBRARY} ${RPCRT_LIBRARIES})
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
if(WASM_BUILD)
+55 -1
View File
@@ -391,7 +391,6 @@ namespace {
}
// @todo naming
IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(const std::string& filepath, IfcParse::IfcFile* ffile)
: file(ffile)
@@ -413,6 +412,61 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::instance_by_id(int
return assert_existance(id);
}
void IfcParse::impl::rocks_db_file_storage::process_deletion_inverse(IfcUtil::IfcBaseClass* inst)
{
auto id = inst->id();
{
// compute next prefix that does not start with v|{id}
auto prefix = "v|" + id;
auto it = db->NewIterator(rocksdb::ReadOptions());
it->Seek(prefix);
while (it->Valid()) {
it->Next();
if (!it->key().starts_with(prefix)) {
break;
}
}
rocksdb::WriteBatch batch;
batch.DeleteRange(prefix, it->key());
db->Write(rocksdb::WriteOptions{}, &batch);
}
// This is based on traversal which needs instances to still be contained in the map.
// another option would be to keep byid intact for the remainder of this loop
aggregate_of_instance::ptr entity_attributes = traverse(inst, 1);
for (aggregate_of_instance::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
IfcUtil::IfcBaseClass* entity_attribute = *it;
if (entity_attribute == inst) {
continue;
}
const unsigned int name = entity_attribute->id();
// Do not update inverses for simple types (which have id()==0 in IfcOpenShell).
if (name != 0) {
// Find instances entity -> other
// and update inverses from entity into other
{
auto prefix = "v|" + name;
auto it = db->NewIterator(rocksdb::ReadOptions());
it->Seek(prefix);
while (it->Valid() && it->key().starts_with(prefix)) {
std::string s = it->value().ToString();
// Iterator are snapshotted? So don't get invalidated?
std::vector<size_t> vals(s.size() / sizeof(size_t));
memcpy(vals.data(), s.data(), s.size());
vals.erase(std::find(vals.begin(), vals.end(), (size_t)id));
s.resize(vals.size() * sizeof(size_t));
memcpy(s.data(), vals.data(), s.size());
db->Put(rocksdb::WriteOptions{}, it->key(), s);
}
}
}
}
}
IfcUtil::IfcBaseClass* IfcParse::impl::in_memory_file_storage::instance_by_id(int id)
{
auto it = byid_.find(id);
+14 -5
View File
@@ -206,8 +206,6 @@ namespace impl {
typedef map_transformer<identity_by_id_t, std::function<IfcUtil::IfcBaseClass* (size_t)>, std::function<size_t(IfcUtil::IfcBaseClass*)>> entity_by_id_t;
typedef entity_by_id_t::iterator iterator;
identity_by_id_t idenbyid_;
in_memory_file_storage()
: byid_(
&idenbyid_,
@@ -216,6 +214,9 @@ namespace impl {
)
{}
in_memory_file_storage(const in_memory_file_storage&) = delete;
in_memory_file_storage(const in_memory_file_storage&&) = delete;
class type_iterator : private entities_by_type_t::const_iterator {
public:
using iterator_category = std::forward_iterator_tag;
@@ -260,7 +261,6 @@ namespace impl {
static bool guid_map() { return guid_map_; }
static void guid_map(bool b) { guid_map_ = b; }
entity_by_id_t byid_;
// this is for simple types
entity_by_iden_t byidentity_;
// entities_by_type_t bytype_;
@@ -268,6 +268,8 @@ namespace impl {
// entities_by_ref_t byref_;
entities_by_ref_t byref_excl_;
entity_by_guid_t byguid_;
identity_by_id_t idenbyid_;
entity_by_id_t byid_;
void load(unsigned entity_instance_name, const IfcParse::entity* entity, parse_context&, int attribute_index = -1);
void try_read_semicolon() const;
@@ -291,7 +293,14 @@ namespace impl {
bytype_excl_[ty]->push(new_entity);
}
void remove_type_ref(IfcUtil::IfcBaseClass* new_entity) {
// @todo
auto ty = new_entity->declaration().as_entity();
auto it = bytype_excl_.find(ty);
if (it != bytype_excl_.end()) {
it->second->remove(new_entity);
if (it->second->size() == 0) {
bytype_excl_.erase(ty);
}
}
}
void add_inverse_ref(IfcUtil::IfcBaseClass* new_entity) {
@@ -509,6 +518,7 @@ namespace impl {
const IfcParse::declaration* operator*() const;
};
// @todo rocksdb_instance_iterator?
using const_iterator = rocksdb_types_iterator;
void register_inverse(unsigned, const IfcParse::entity* from_entity, int inst_id, int attribute_index);
@@ -707,7 +717,6 @@ private:
void build_inverses();
// @todo variant apply_visitor
void register_inverse(unsigned, const IfcParse::entity* from_entity, int inst_id, int attribute_index);
void unregister_inverse(unsigned, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass*, int attribute_index);
+58 -11
View File
@@ -811,6 +811,28 @@ void IfcParse::impl::rocks_db_file_storage::unregister_inverse(unsigned id_from,
}
}
void IfcParse::impl::rocks_db_file_storage::add_type_ref(IfcUtil::IfcBaseClass* new_entity)
{
size_t v = new_entity->identity();
std::string s(sizeof(size_t), ' ');
memcpy(s.data(), &v, sizeof(size_t));
db->Merge(rocksdb::WriteOptions{}, "t|" + std::to_string(new_entity->declaration().index_in_schema()), s);
}
void IfcParse::impl::rocks_db_file_storage::remove_type_ref(IfcUtil::IfcBaseClass* new_entity)
{
std::string s;
auto key = "t|" + std::to_string(new_entity->declaration().index_in_schema());
if (db->Get(rocksdb::ReadOptions{}, key, &s).ok()) {
std::vector<size_t> vals(s.size() / sizeof(size_t));
memcpy(vals.data(), s.data(), s.size());
vals.erase(std::find(vals.begin(), vals.end(), (size_t)new_entity->identity()));
s.resize(vals.size() * sizeof(size_t));
memcpy(s.data(), vals.data(), s.size());
db->Put(rocksdb::WriteOptions{}, key, s);
}
}
namespace {
class StringBuilderVisitor : public boost::static_visitor<void> {
private:
@@ -1231,7 +1253,9 @@ IfcFile::IfcFile(const std::string& path, filetype ty) {
// @todo allow for rocksdb from path
if (ty == ifcspf) {
IfcSpfStream s(path);
storage_ = impl::in_memory_file_storage{};
storage_.emplace<1>(); // impl::in_memory_file_storage{};
// @todo assign in constructor
std::get<impl::in_memory_file_storage>(storage_).file = this;
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
} else {
storage_ = impl::rocks_db_file_storage(path, this);
@@ -1243,20 +1267,20 @@ IfcFile::IfcFile(const std::string& path, filetype ty) {
IfcFile::IfcFile(std::istream& stream, int length) {
IfcSpfStream s(stream, length);
storage_ = impl::in_memory_file_storage{};
storage_.emplace<1>();
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
}
IfcFile::IfcFile(void* data, int length) {
IfcSpfStream s(data, length);
storage_ = impl::in_memory_file_storage{};
storage_.emplace<1>();
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
}
IfcFile::IfcFile(IfcParse::IfcSpfStream* s) {
storage_ = impl::in_memory_file_storage{};
storage_.emplace<1>();
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(s, schema_, max_id_);
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
}
@@ -1266,7 +1290,7 @@ IfcFile::IfcFile(const IfcParse::schema_definition* schema)
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
, max_id_(0)
{
storage_ = impl::in_memory_file_storage{};
storage_.emplace<1>();
setDefaultHeaderValues();
}
@@ -1283,7 +1307,8 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
return;
}
tokens = new IfcSpfLexer(stream, file);
// @todo file ptr arg removed?
tokens = new IfcSpfLexer(stream, nullptr);
std::vector<std::string> schemas;
@@ -2014,7 +2039,7 @@ void IfcParse::impl::in_memory_file_storage::process_deletion_inverse(IfcUtil::I
ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end());
}
}
}
}
}
namespace {
@@ -2102,7 +2127,7 @@ aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) {
}
IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) {
std::visit([id](auto& x) {
return std::visit([id](auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::monostate>) {
throw std::runtime_error("Storage not initialized");
return (IfcUtil::IfcBaseClass*) nullptr;
@@ -2185,7 +2210,7 @@ std::ostream& operator<<(std::ostream& out, const IfcParse::IfcFile& file) {
typedef std::vector<IfcUtil::IfcBaseClass*> vector_t;
vector_t sorted;
std::transform(file.begin(), file.end(), std::back_inserter(sorted), [file](const auto& x) { return file.byidentity_.find(x.second)->second; });
std::transform(file.begin(), file.end(), std::back_inserter(sorted), [&file](const auto& x) { return file.byidentity_.find(x.second)->second; });
std::sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b) { return a->id() < b->id(); });
for (auto& e : sorted) {
@@ -2436,6 +2461,28 @@ void IfcParse::IfcFile::build_inverses() {
}
}
void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, int inst_id, int attribute_index)
{
std::visit([id_from, from_entity, inst_id, attribute_index](auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::monostate>) {
throw std::runtime_error("Storage not initialized");
} else {
return x.register_inverse(id_from, from_entity, inst_id, attribute_index);
}
}, storage_);
}
void IfcParse::IfcFile::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index)
{
std::visit([id_from, from_entity, inst, attribute_index](auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::monostate>) {
throw std::runtime_error("Storage not initialized");
} else {
return x.unregister_inverse(id_from, from_entity, inst, attribute_index);
}
}, storage_);
}
std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_(0);
// bool IfcParse::IfcFile::guid_map_ = true;
@@ -2497,9 +2544,9 @@ IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& data)
AttributeValue IfcEntityInstanceData::get_attribute_value(size_t index) const
{
return std::visit([index](const auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, IfcParse::impl::in_memory_file_storage>) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, in_memory_attribute_storage>) {
return AttributeValue(&x, (uint8_t)index);
} else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, IfcParse::impl::rocks_db_file_storage>) {
} else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, rocks_db_attribute_storage>) {
// @todo
return AttributeValue{};
} else {