Skip to content

Commit da4e86a

Browse files
committed
Exploration of using rocksdb as file+instance storage
1 parent cdcbc2a commit da4e86a

16 files changed

Lines changed: 1982 additions & 517 deletions

src/ifcparse/IfcBaseClass.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface {
117117

118118
void unset_attribute_value(size_t i);
119119

120+
AttributeValue get_attribute_value(size_t index) const;
121+
120122
uint32_t identity() const { return identity_; }
121123

122124
uint32_t id() const { return id_; }
@@ -131,7 +133,7 @@ class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass {
131133
IfcBaseEntity(IfcEntityInstanceData&& data);
132134

133135
IfcBaseEntity(size_t n)
134-
: IfcBaseClass(IfcEntityInstanceData(storage_t(n)))
136+
: IfcBaseClass(IfcEntityInstanceData(in_memory_attribute_storage(n)))
135137
{}
136138

137139
virtual const IfcParse::declaration& declaration() const = 0;
@@ -172,7 +174,7 @@ class IFC_PARSE_API IfcBaseType : public IfcBaseClass {
172174
{}
173175

174176
IfcBaseType()
175-
: IfcBaseClass(IfcEntityInstanceData(storage_t(1)))
177+
: IfcBaseClass(IfcEntityInstanceData(in_memory_attribute_storage(1)))
176178
{}
177179

178180
virtual const IfcParse::declaration& declaration() const = 0;
Lines changed: 223 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "IfcEntityInstanceData.h"
22
#include "IfcBaseClass.h"
3+
#include "IfcFile.h"
34

45
// @todo is size() still needed?
56
class SizeVisitor {
@@ -28,100 +29,300 @@ class SizeVisitor {
2829
int operator()(const aggregate_of_aggregate_of_instance::ptr& i) const { return i->size(); }
2930
};
3031

32+
namespace {
33+
34+
// Trait to detect contiguous containers (vector / string)
35+
template <typename T>
36+
struct is_contiguous_container : std::false_type {};
37+
template <typename T, typename Alloc>
38+
struct is_contiguous_container<std::vector<T, Alloc>> : std::true_type {};
39+
template <typename CharT, typename Traits, typename Alloc>
40+
struct is_contiguous_container<std::basic_string<CharT, Traits, Alloc>> : std::true_type {};
41+
42+
template <typename T>
43+
bool serialize(std::string& val, const T& t) {
44+
return false;
45+
}
46+
47+
template <typename T, typename std::enable_if<is_contiguous_container<T>::value, int>::type = 0>
48+
bool serialize(std::string& val, const T& t) {
49+
auto s = sizeof(typename T::value_type) * t.size();
50+
val.resize(s);
51+
val[0] = TypeEncoder::encode_type<T>();
52+
memcpy(val.data() + 1, t.data(), s);
53+
return true;
54+
}
55+
56+
bool serialize(std::string& val, const IfcUtil::IfcBaseClass* t) {
57+
auto s = sizeof(size_t);
58+
val.resize(s + 2);
59+
val[0] = TypeEncoder::encode_type<IfcUtil::IfcBaseClass*>();
60+
// 1 = entity - stored by id (entity name)
61+
// 2 = type - stored by identity (internal counter in class)
62+
val[1] = t->declaration().as_entity() ? 1 : 2;
63+
size_t iden = t->declaration().as_entity() ? t->id() : t->identity();
64+
memcpy(val.data() + 2, &iden, s);
65+
return true;
66+
}
67+
68+
69+
bool serialize(std::string& val, const EnumerationReference& v) {
70+
auto s = sizeof(size_t);
71+
val.resize(s * 2 + 1);
72+
val[0] = TypeEncoder::encode_type<EnumerationReference>();
73+
size_t vv = v.enumeration()->index_in_schema();
74+
memcpy(val.data() + 1, &vv, sizeof(size_t));
75+
vv = v.index();
76+
memcpy(val.data() + 1, &vv, sizeof(size_t));
77+
return true;
78+
}
79+
80+
bool serialize(std::string& val, aggregate_of_instance::ptr& t) {
81+
std::vector<size_t> ids;
82+
// @nb this has to be identity, because needs to work for typedecls as well
83+
std::transform(t->begin(), t->end(), std::back_inserter(ids), [](auto& x) { return x->identity(); });
84+
return false;
85+
}
86+
87+
bool serialize(std::string& val, aggregate_of_aggregate_of_instance::ptr& t) {
88+
return false;
89+
}
90+
91+
/*
92+
template <typename T>
93+
bool deserialize(std::string& val, const T& t) {}
94+
*/
95+
96+
template <typename T, typename std::enable_if<is_contiguous_container<T>::value, int>::type = 0>
97+
bool deserialize(std::string& val, T& t) {
98+
// @todo vector of vector
99+
if (val[0] != TypeEncoder::encode_type<T>()) {
100+
return false;
101+
}
102+
auto s = (val.size() - 1) / sizeof(typename T::value_type);
103+
t.resize(s);
104+
memcpy(t.data(), val.data() + 1, s * sizeof(typename T::value_type));
105+
return true;
106+
}
107+
108+
template <typename T, typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T>, int>::type = 0>
109+
bool deserialize(std::string& val, T& t) {
110+
if (val[0] != TypeEncoder::encode_type<T>()) {
111+
return false;
112+
}
113+
auto s = (val.size() - 1) / sizeof(T);
114+
memcpy(&t, val.data() + 1, sizeof(T));
115+
return true;
116+
}
117+
118+
bool deserialize(std::string& val, boost::logic::tribool& t) {
119+
if (val[0] != TypeEncoder::encode_type<boost::logic::tribool>()) {
120+
return false;
121+
}
122+
if (val[1] == 0) {
123+
t = false;
124+
} else if (val[1] == 1) {
125+
t = true;
126+
} else if (val[1] == 2) {
127+
t = boost::logic::indeterminate;
128+
} else {
129+
return false;
130+
}
131+
}
132+
133+
bool deserialize(std::string& val, boost::dynamic_bitset<>& t) {
134+
if (val[0] != TypeEncoder::encode_type<boost::dynamic_bitset<>>()) {
135+
return false;
136+
}
137+
t = boost::dynamic_bitset<>(val.substr(1));
138+
return true;
139+
}
140+
141+
bool deserialize(std::string& val, aggregate_of_instance::ptr& t) {
142+
return false;
143+
}
144+
145+
bool deserialize(std::string& val, aggregate_of_aggregate_of_instance::ptr& t) {
146+
return false;
147+
}
148+
}
149+
150+
namespace {
151+
template<typename T>
152+
inline T dispatch_get_(AttributeValue::pointer_type array_, uint8_t storage_model_, size_t instance_name_, uint8_t index_)
153+
{
154+
if (storage_model_ == 0) {
155+
return array_.storage_ptr->get<T>(index_);
156+
} else {
157+
T val;
158+
if constexpr (
159+
// the following types cannot be directly deserialized from rocksdb, but need to be constructed
160+
!std::is_same_v<T, EnumerationReference> &&
161+
!std::is_same_v<std::remove_cv_t<std::remove_pointer_t<T>>, IfcUtil::IfcBaseClass>)
162+
{
163+
std::string str;
164+
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
165+
deserialize(str, val);
166+
}
167+
return val;
168+
}
169+
}
170+
171+
template<typename T>
172+
inline bool dispatch_has_(AttributeValue::pointer_type array_, uint8_t storage_model_, size_t instance_name_, uint8_t index_)
173+
{
174+
if (storage_model_ == 0) {
175+
return array_.storage_ptr->has<T>(index_);
176+
} else {
177+
std::string str;
178+
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
179+
return str[0] == TypeEncoder::encode_type<T>();
180+
}
181+
}
182+
183+
inline size_t dispatch_index_(AttributeValue::pointer_type array_, uint8_t storage_model_, size_t instance_name_, uint8_t index_)
184+
{
185+
if (storage_model_ == 0) {
186+
return array_.storage_ptr->index(index_);
187+
} else {
188+
std::string str;
189+
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
190+
return (size_t) str[0] - 'A';
191+
}
192+
}
193+
194+
}
195+
31196
AttributeValue::operator int() const
32197
{
33-
return array_->get<int>(index_);
198+
return dispatch_get_<int>(array_, storage_model_, instance_name_, index_);
34199
}
35200

36201
AttributeValue::operator bool() const
37202
{
38-
return array_->get<bool>(index_);
203+
return dispatch_get_<bool>(array_, storage_model_, instance_name_, index_);
39204
}
40205

41206
AttributeValue::operator double() const
42207
{
43-
return array_->get<double>(index_);
208+
return dispatch_get_<double>(array_, storage_model_, instance_name_, index_);
44209
}
45210

46211
AttributeValue::operator boost::logic::tribool() const
47212
{
48-
if (array_->has<bool>(index_)) {
49-
return array_->get<bool>(index_);
213+
if (dispatch_has_<bool>(array_, storage_model_, instance_name_, index_)) {
214+
return dispatch_get_<bool>(array_, storage_model_, instance_name_, index_);
50215
}
51-
return array_->get<boost::logic::tribool>(index_);
216+
return dispatch_get_<boost::logic::tribool>(array_, storage_model_, instance_name_, index_);
52217
}
53218

54219
AttributeValue::operator std::string() const
55220
{
56-
if (array_->has<EnumerationReference>(index_)) {
221+
if (dispatch_has_<EnumerationReference>(array_, storage_model_, instance_name_, index_)) {
57222
// @todo this is silly, but the way things currently work,
58223
// @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.
59-
return array_->get<EnumerationReference>(index_).value();
224+
if (storage_model_ == 0) {
225+
return dispatch_get_<EnumerationReference>(array_, storage_model_, instance_name_, index_).value();
226+
} else {
227+
std::string str;
228+
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
229+
size_t v;
230+
memcpy(&v, str.data() + 1, sizeof(size_t));
231+
auto decl = schema_->declarations()[v]->as_enumeration_type();
232+
memcpy(&v, str.data() + 5, sizeof(size_t));
233+
return decl->lookup_enum_value(v);
234+
}
235+
}
236+
return dispatch_get_<std::string>(array_, storage_model_, instance_name_, index_);
237+
}
238+
239+
AttributeValue::operator EnumerationReference() const
240+
{
241+
if (storage_model_ == 0) {
242+
return dispatch_get_<EnumerationReference>(array_, storage_model_, instance_name_, index_);
243+
} else {
244+
std::string str;
245+
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
246+
size_t v;
247+
memcpy(&v, str.data() + 1, sizeof(size_t));
248+
auto decl = schema_->declarations()[v]->as_enumeration_type();
249+
memcpy(&v, str.data() + 5, sizeof(size_t));
250+
return EnumerationReference(decl, v);
60251
}
61-
return array_->get<std::string>(index_);
62252
}
63253

64254
AttributeValue::operator boost::dynamic_bitset<>() const
65255
{
66-
return array_->get<boost::dynamic_bitset<>>(index_);
256+
return dispatch_get_<boost::dynamic_bitset<>>(array_, storage_model_, instance_name_, index_);
67257
}
68258

69259
AttributeValue::operator IfcUtil::IfcBaseClass* () const
70260
{
71-
return array_->get<IfcUtil::IfcBaseClass*>(index_);
261+
if (storage_model_ == 0) {
262+
return dispatch_get_<IfcUtil::IfcBaseClass*>(array_, storage_model_, instance_name_, index_);
263+
} else {
264+
std::string str;
265+
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
266+
size_t v;
267+
memcpy(&v, str.data() + 1, sizeof(size_t));
268+
auto decl = schema_->declarations()[v]->as_enumeration_type();
269+
memcpy(&v, str.data() + 5, sizeof(size_t));
270+
return array_.db_ptr->assert_existance(v);
271+
}
72272
}
73273

74274
AttributeValue::operator std::vector<int>() const
75275
{
76-
return array_->get<std::vector<int>>(index_);
276+
return dispatch_get_<std::vector<int>>(array_, storage_model_, instance_name_, index_);
77277
}
78278

79279
AttributeValue::operator std::vector<double>() const
80280
{
81-
return array_->get<std::vector<double>>(index_);
281+
return dispatch_get_<std::vector<double>>(array_, storage_model_, instance_name_, index_);
82282
}
83283

84284
AttributeValue::operator std::vector<std::string>() const
85285
{
86-
return array_->get<std::vector<std::string>>(index_);
286+
return dispatch_get_<std::vector<std::string>>(array_, storage_model_, instance_name_, index_);
87287
}
88288

89289
AttributeValue::operator std::vector<boost::dynamic_bitset<>>() const
90290
{
91-
return array_->get<std::vector<boost::dynamic_bitset<>>>(index_);
291+
return dispatch_get_<std::vector<boost::dynamic_bitset<>>>(array_, storage_model_, instance_name_, index_);
92292
}
93293

94294
AttributeValue::operator boost::shared_ptr<aggregate_of_instance>() const
95295
{
96-
return array_->get<boost::shared_ptr<aggregate_of_instance>>(index_);
296+
return dispatch_get_<boost::shared_ptr<aggregate_of_instance>>(array_, storage_model_, instance_name_, index_);
97297
}
98298

99299
AttributeValue::operator std::vector<std::vector<int>>() const
100300
{
101-
return array_->get<std::vector<std::vector<int>>>(index_);
301+
return dispatch_get_<std::vector<std::vector<int>>>(array_, storage_model_, instance_name_, index_);
102302
}
103303

104304
AttributeValue::operator std::vector<std::vector<double>>() const
105305
{
106-
return array_->get<std::vector<std::vector<double>>>(index_);
306+
return dispatch_get_<std::vector<std::vector<double>>>(array_, storage_model_, instance_name_, index_);
107307
}
108308

109309
AttributeValue::operator boost::shared_ptr<aggregate_of_aggregate_of_instance>() const
110310
{
111-
return array_->get<boost::shared_ptr<aggregate_of_aggregate_of_instance>>(index_);
311+
return dispatch_get_<boost::shared_ptr<aggregate_of_aggregate_of_instance>>(array_, storage_model_, instance_name_, index_);
112312
}
113313

114314
bool AttributeValue::isNull() const
115315
{
116-
return array_->has<Blank>(index_);
316+
return dispatch_has_<Blank>(array_, storage_model_, instance_name_, index_);
117317
}
118318

119319
unsigned int AttributeValue::size() const
120320
{
121-
return array_->apply_visitor(SizeVisitor{}, index_);
321+
// @todo
322+
return array_.storage_ptr->apply_visitor(SizeVisitor{}, index_);
122323
}
123324

124325
IfcUtil::ArgumentType AttributeValue::type() const
125326
{
126-
return static_cast<IfcUtil::ArgumentType>(array_->index(index_));
327+
return static_cast<IfcUtil::ArgumentType>(dispatch_index_(array_, storage_model_, instance_name_, index_));
127328
}

0 commit comments

Comments
 (0)