Alpha version of label indexes.
Squashed messages from 9 commits:
9.
Properties now uses PropertyFamily and contained classes.
Fetching,seting,clearing properties can be done with PropertyFamilyKey or PropertyTypeKey.
Hierarchy of newly added clases is:
Vertices -n-> PropertyFamily {name: String} <-1-n-> PropertyType {type: Property::Flags}
Edges -n-> PropertyFamily {name: String} <-1-n-> PropertyType {type: Property::Flags}
PropertyFamilyKey -> PropertyType
PropertyTypeKey -> PropertyType
PropertyType t0,t1;
let t0!=t1 be true
let t0.family==t1.family be true
then next is true
PropertyTypeKey{&t0}!=PropertyTypeKey{&t1}
PropertyFamilyKey{&t0}==PropertyFamilyKey{&t1}
PropertyFamilyKey{&t0}==PropertyTypeKey{&t1}
PropertyTypeKey{&t0}==PropertyFamilyKey{&t1}
8.
Intermedate commit.
Noticed that integration queries throw SEGFAULT.
7.
Defined interface for indexes.
Fixed three memory leaks.
Fixed integration_queries test which now passes.
6.
Commit which return Xorshift128plus to valid shape.
5.
Tmp commit.
4.
Label Index is compiling.
3.
tmp
2.
Vertex::Accessor now updates Label index.
1.
Applied changes for code review.
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "data_structures/concurrent/concurrent_map.hpp"
|
||||
#include "mvcc/version_list.hpp"
|
||||
#include "storage/common.hpp"
|
||||
#include "storage/edge_accessor.hpp"
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
class Edges
|
||||
{
|
||||
using prop_familys_t = ConcurrentMap<std::string, PropertyFamily *>;
|
||||
|
||||
public:
|
||||
Option<const Edge::Accessor> find(DbTransaction &t, const Id &id);
|
||||
|
||||
@@ -15,7 +19,15 @@ public:
|
||||
Edge::Accessor insert(DbTransaction &t, VertexRecord *from,
|
||||
VertexRecord *to);
|
||||
|
||||
// auto property_family_access();
|
||||
|
||||
PropertyFamily &property_family_find_or_create(const std::string &name);
|
||||
|
||||
private:
|
||||
ConcurrentMap<uint64_t, EdgeRecord> edges;
|
||||
// TODO: Because familys wont be removed this could be done with more
|
||||
// efficent
|
||||
// data structure.
|
||||
prop_familys_t prop_familys;
|
||||
AtomicCounter<uint64_t> counter;
|
||||
};
|
||||
|
||||
38
include/storage/indexes/impl/nonunique_unordered_index.hpp
Normal file
38
include/storage/indexes/impl/nonunique_unordered_index.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/indexes/index_base.hpp"
|
||||
#include "storage/indexes/index_record.hpp"
|
||||
|
||||
#include "data_structures/concurrent/concurrent_list.hpp"
|
||||
|
||||
template <class T, class K>
|
||||
class NonUniqueUnorderedIndex : public IndexBase<T, K>
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef K key_type;
|
||||
|
||||
NonUniqueUnorderedIndex();
|
||||
|
||||
// Insert's value.
|
||||
// nonunique => always succeds.
|
||||
bool insert(IndexRecord<T, K> &&value) final;
|
||||
|
||||
// Returns iterator which returns valid records in range.
|
||||
// ordered==None => doesn't guarantee any order of submitting records.
|
||||
std::unique_ptr<IteratorBase<const typename T::Accessor>>
|
||||
for_range(DbAccessor &t, Border<K> from = Border<K>(),
|
||||
Border<K> to = Border<K>()) final;
|
||||
|
||||
// Same as for_range just whit known returned iterator.
|
||||
auto for_range_exact(DbAccessor &t, Border<K> from = Border<K>(),
|
||||
Border<K> to = Border<K>());
|
||||
|
||||
// Removes for all transactions obsolete Records.
|
||||
// Cleaner has to call this method when he decideds that it is time for
|
||||
// cleaning.
|
||||
void clean(DbTransaction &) final;
|
||||
|
||||
private:
|
||||
List<IndexRecord<T, K>> list;
|
||||
};
|
||||
@@ -1,44 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "data_structures/concurrent/concurrent_map.hpp"
|
||||
#include "storage/indexes/index_record.hpp"
|
||||
#include "storage/indexes/index_record_collection.hpp"
|
||||
#include "storage/label/label.hpp"
|
||||
|
||||
template <class Key, class Item>
|
||||
class Index
|
||||
{
|
||||
public:
|
||||
using container_t = ConcurrentMap<Key, Item>;
|
||||
|
||||
Index() : index(std::make_unique<container_t>()) {}
|
||||
|
||||
auto update(const Label &label, VertexIndexRecord &&index_record)
|
||||
{
|
||||
auto accessor = index->access();
|
||||
auto label_ref = label_ref_t(label);
|
||||
|
||||
// create Index Record Collection if it doesn't exist
|
||||
if (!accessor.contains(label_ref)) {
|
||||
accessor.insert(label_ref, std::move(VertexIndexRecordCollection()));
|
||||
}
|
||||
|
||||
// add Vertex Index Record to the Record Collection
|
||||
auto &record_collection = (*accessor.find(label_ref)).second;
|
||||
record_collection.add(std::forward<VertexIndexRecord>(index_record));
|
||||
}
|
||||
|
||||
VertexIndexRecordCollection &find(const Label &label)
|
||||
{
|
||||
// TODO: accessor should be outside?
|
||||
// bacause otherwise GC could delete record that has just be returned
|
||||
auto label_ref = label_ref_t(label);
|
||||
auto accessor = index->access();
|
||||
return (*accessor.find(label_ref)).second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<container_t> index;
|
||||
};
|
||||
// #pragma once
|
||||
//
|
||||
// #include <memory>
|
||||
//
|
||||
// #include "data_structures/concurrent/concurrent_map.hpp"
|
||||
// #include "storage/indexes/index_record.hpp"
|
||||
// #include "storage/indexes/index_record_collection.hpp"
|
||||
// #include "storage/label/label.hpp"
|
||||
//
|
||||
// template <class Key, class Item>
|
||||
// class Index
|
||||
// {
|
||||
// public:
|
||||
// using container_t = ConcurrentMap<Key, Item>;
|
||||
//
|
||||
// Index() : index(std::make_unique<container_t>()) {}
|
||||
//
|
||||
// auto update(const Label &label, VertexIndexRecord &&index_record)
|
||||
// {
|
||||
// auto accessor = index->access();
|
||||
// auto label_ref = label_ref_t(label);
|
||||
//
|
||||
// // create Index Record Collection if it doesn't exist
|
||||
// if (!accessor.contains(label_ref)) {
|
||||
// accessor.insert(label_ref, std::move(VertexIndexRecordCollection()));
|
||||
// }
|
||||
//
|
||||
// // add Vertex Index Record to the Record Collection
|
||||
// auto &record_collection = (*accessor.find(label_ref)).second;
|
||||
// record_collection.add(std::forward<VertexIndexRecord>(index_record));
|
||||
// }
|
||||
//
|
||||
// VertexIndexRecordCollection &find(const Label &label)
|
||||
// {
|
||||
// // TODO: accessor should be outside?
|
||||
// // bacause otherwise GC could delete record that has just be returned
|
||||
// auto label_ref = label_ref_t(label);
|
||||
// auto accessor = index->access();
|
||||
// return (*accessor.find(label_ref)).second;
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// std::unique_ptr<container_t> index;
|
||||
// };
|
||||
|
||||
60
include/storage/indexes/index_base.hpp
Normal file
60
include/storage/indexes/index_base.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
// #include "storage/indexes/index_record.hpp"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "utils/border.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
|
||||
class DbTransaction;
|
||||
class DbAccessor;
|
||||
|
||||
template <class T, class K>
|
||||
class IndexRecord;
|
||||
|
||||
// Defines ordering of data
|
||||
enum Order
|
||||
{
|
||||
None = 0,
|
||||
Ascending = 1,
|
||||
Descending = 2,
|
||||
};
|
||||
|
||||
// Interface for all indexes.
|
||||
// T type of record.
|
||||
// K type of key on which records are ordered
|
||||
template <class T, class K>
|
||||
class IndexBase
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef K key_type;
|
||||
|
||||
IndexBase(bool unique, Order order) : unique(unique), order(order) {}
|
||||
|
||||
// Insert's value.
|
||||
// unique => returns false if there is already valid equal value.
|
||||
// nonunique => always succeds.
|
||||
virtual bool insert(IndexRecord<T, K> &&value) = 0;
|
||||
|
||||
// Returns iterator which returns valid records in range.
|
||||
// order==noe => doesn't guarantee any order of returned records.
|
||||
// order==Ascending => guarantees order of returnd records will be from
|
||||
// smallest to largest.
|
||||
// order==Descending => guarantees order of returned records will be from
|
||||
// largest to smallest.
|
||||
// Range must be from<=to
|
||||
virtual std::unique_ptr<IteratorBase<const typename T::Accessor>>
|
||||
for_range(DbAccessor &, Border<K> from = Border<K>(),
|
||||
Border<K> to = Border<K>()) = 0;
|
||||
|
||||
// Removes for all transactions obsolete Records.
|
||||
// Cleaner has to call this method when he decideds that it is time for
|
||||
// cleaning.
|
||||
virtual void clean(DbTransaction &) = 0;
|
||||
|
||||
// Are the records unique
|
||||
const bool unique;
|
||||
// Ordering of the records.
|
||||
const Order order;
|
||||
};
|
||||
@@ -1,46 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include "database/db_transaction.hpp"
|
||||
#include "mvcc/version_list.hpp"
|
||||
#include "utils/total_ordering.hpp"
|
||||
|
||||
template <class T>
|
||||
class IndexRecord : TotalOrdering<IndexRecord<T>>
|
||||
// class DbTransaction;
|
||||
// namespace tx
|
||||
// {
|
||||
// class Transaction;
|
||||
// }
|
||||
|
||||
// T type of record.
|
||||
// K key on which record is ordered.
|
||||
template <class T, class K>
|
||||
class IndexRecord : public TotalOrdering<IndexRecord<T, K>>
|
||||
{
|
||||
public:
|
||||
using vlist_t = mvcc::VersionList<T>;
|
||||
|
||||
IndexRecord() = default;
|
||||
|
||||
IndexRecord(T *record, vlist_t *vlist) : record(record), vlist(vlist)
|
||||
IndexRecord(K key, T *record, vlist_t *vlist)
|
||||
: key(std::move(key)), record(record), vlist(vlist)
|
||||
{
|
||||
assert(record != nullptr);
|
||||
assert(vlist != nullptr);
|
||||
}
|
||||
|
||||
friend bool operator<(const IndexRecord& lhs, const IndexRecord& rhs)
|
||||
friend bool operator<(const IndexRecord &lhs, const IndexRecord &rhs)
|
||||
{
|
||||
return lhs.record < rhs.record;
|
||||
return lhs.key < rhs.key ||
|
||||
(lhs.key == rhs.key && lhs.vlist == rhs.vlist &&
|
||||
lhs.record < rhs.record);
|
||||
}
|
||||
|
||||
friend bool operator==(const IndexRecord& lhs, const IndexRecord& rhs)
|
||||
friend bool operator==(const IndexRecord &lhs, const IndexRecord &rhs)
|
||||
{
|
||||
return lhs.record == rhs.record;
|
||||
return lhs.key == rhs.key &&
|
||||
(lhs.vlist != rhs.vlist || lhs.record == rhs.record);
|
||||
}
|
||||
|
||||
bool empty() const { return record == nullptr; }
|
||||
|
||||
// const typename T::Accessor get()
|
||||
// {
|
||||
// // TODO: if somebody wants to read T content
|
||||
// // const T::Accessor has to be returned from here
|
||||
// // the problem is that here we don't have pointer to store
|
||||
// // TODO: figure it out
|
||||
// }
|
||||
bool is_valid(tx::Transaction &t) const
|
||||
{
|
||||
assert(!empty());
|
||||
return record == vlist->find(t);
|
||||
}
|
||||
|
||||
// private:
|
||||
const auto access(DbTransaction &db) const
|
||||
{
|
||||
return T::Accessor::create(record, vlist, db);
|
||||
}
|
||||
|
||||
const K key;
|
||||
|
||||
private:
|
||||
T *const record{nullptr};
|
||||
vlist_t *const vlist{nullptr};
|
||||
};
|
||||
|
||||
using VertexIndexRecord = IndexRecord<Vertex>;
|
||||
using EdgeIndexRecord = IndexRecord<Edge>;
|
||||
template <class K>
|
||||
using VertexIndexRecord = IndexRecord<Vertex, K>;
|
||||
|
||||
template <class K>
|
||||
using EdgeIndexRecord = IndexRecord<Edge, K>;
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "data_structures/concurrent/concurrent_set.hpp"
|
||||
#include "storage/indexes/index_record.hpp"
|
||||
|
||||
template <class T>
|
||||
class IndexRecordCollection
|
||||
{
|
||||
public:
|
||||
using index_record_t = IndexRecord<T>;
|
||||
using index_record_collection_t = ConcurrentSet<index_record_t>;
|
||||
|
||||
IndexRecordCollection()
|
||||
: records(std::make_unique<index_record_collection_t>())
|
||||
{
|
||||
}
|
||||
|
||||
void add(index_record_t &&record)
|
||||
{
|
||||
auto accessor = records->access();
|
||||
accessor.insert(std::forward<index_record_t>(record));
|
||||
}
|
||||
|
||||
auto access()
|
||||
{
|
||||
return records->access();
|
||||
}
|
||||
|
||||
// TODO: iterator and proxy
|
||||
|
||||
private:
|
||||
std::unique_ptr<index_record_collection_t> records;
|
||||
};
|
||||
|
||||
using VertexIndexRecordCollection = IndexRecordCollection<Vertex>;
|
||||
using EdgeIndexRecordCollection = IndexRecordCollection<Edge>;
|
||||
// #pragma once
|
||||
//
|
||||
// #include <memory>
|
||||
//
|
||||
// #include "data_structures/concurrent/concurrent_set.hpp"
|
||||
// #include "storage/indexes/index_record.hpp"
|
||||
//
|
||||
// template <class T>
|
||||
// class IndexRecordCollection
|
||||
// {
|
||||
// public:
|
||||
// using index_record_t = IndexRecord<T>;
|
||||
// using index_record_collection_t = ConcurrentSet<index_record_t>;
|
||||
//
|
||||
// IndexRecordCollection()
|
||||
// : records(std::make_unique<index_record_collection_t>())
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// void add(index_record_t &&record)
|
||||
// {
|
||||
// auto accessor = records->access();
|
||||
// accessor.insert(std::forward<index_record_t>(record));
|
||||
// }
|
||||
//
|
||||
// auto access()
|
||||
// {
|
||||
// return records->access();
|
||||
// }
|
||||
//
|
||||
// // TODO: iterator and proxy
|
||||
//
|
||||
// private:
|
||||
// std::unique_ptr<index_record_collection_t> records;
|
||||
// };
|
||||
//
|
||||
// using VertexIndexRecordCollection = IndexRecordCollection<Vertex>;
|
||||
// using EdgeIndexRecordCollection = IndexRecordCollection<Edge>;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
template <class T>
|
||||
struct Ascending
|
||||
{
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
constexpr bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
@@ -12,7 +12,7 @@ struct Ascending
|
||||
template <class T>
|
||||
struct Descending
|
||||
{
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
constexpr bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs > rhs;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ostream>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "utils/total_ordering.hpp"
|
||||
#include "storage/indexes/impl/nonunique_unordered_index.hpp"
|
||||
#include "storage/vertex.hpp"
|
||||
#include "storage/vertex_accessor.hpp"
|
||||
#include "utils/reference_wrapper.hpp"
|
||||
#include "utils/total_ordering.hpp"
|
||||
#include "utils/void.hpp"
|
||||
|
||||
using LabelIndexRecord = VertexIndexRecord<std::nullptr_t>;
|
||||
|
||||
class Label : public TotalOrdering<Label>
|
||||
{
|
||||
public:
|
||||
Label(const std::string& name);
|
||||
Label(std::string&& name);
|
||||
using label_index_t = NonUniqueUnorderedIndex<Vertex, std::nullptr_t>;
|
||||
|
||||
Label(const Label&) = default;
|
||||
Label(Label&&) = default;
|
||||
Label() = delete;
|
||||
|
||||
friend bool operator<(const Label& lhs, const Label& rhs);
|
||||
Label(const std::string &name);
|
||||
Label(std::string &&name);
|
||||
|
||||
friend bool operator==(const Label& lhs, const Label& rhs);
|
||||
Label(const Label &) = delete;
|
||||
Label(Label &&other) = default;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream, const Label& label);
|
||||
friend bool operator<(const Label &lhs, const Label &rhs);
|
||||
|
||||
operator const std::string&() const;
|
||||
friend bool operator==(const Label &lhs, const Label &rhs);
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const Label &label);
|
||||
|
||||
operator const std::string &() const;
|
||||
|
||||
std::unique_ptr<label_index_t> index;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "storage/label/label.hpp"
|
||||
// #include "storage/label/label.hpp"
|
||||
#include "utils/reference_wrapper.hpp"
|
||||
|
||||
class Label;
|
||||
using label_ref_t = ReferenceWrapper<const Label>;
|
||||
|
||||
class LabelCollection
|
||||
{
|
||||
@@ -15,12 +19,12 @@ public:
|
||||
auto end() const;
|
||||
auto cend() const;
|
||||
|
||||
bool add(const Label& label);
|
||||
bool has(const Label& label) const;
|
||||
bool add(const Label &label);
|
||||
bool has(const Label &label) const;
|
||||
size_t count() const;
|
||||
bool remove(const Label& label);
|
||||
bool remove(const Label &label);
|
||||
void clear();
|
||||
const std::set<label_ref_t>& operator()() const;
|
||||
const std::set<label_ref_t> &operator()() const;
|
||||
|
||||
private:
|
||||
std::set<label_ref_t> _labels;
|
||||
|
||||
@@ -6,4 +6,3 @@
|
||||
#include "storage/model/properties/int32.hpp"
|
||||
#include "storage/model/properties/int64.hpp"
|
||||
#include "storage/model/properties/string.hpp"
|
||||
|
||||
|
||||
45
include/storage/model/properties/flags.hpp
Normal file
45
include/storage/model/properties/flags.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
enum class Flags : unsigned
|
||||
{
|
||||
// Type | Mask
|
||||
// -----------+----------------------------------------
|
||||
// Null | 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
// -----------+----------------------------------------
|
||||
// Bool | 0000 0000 0000 0000 0000 0000 0000 0001
|
||||
// + True | 0000 0000 0000 0000 0000 0000 0000 0011
|
||||
// + False | 0000 0000 0000 0000 0000 0000 0000 0101
|
||||
// -----------+----------------------------------------
|
||||
// String | 0000 0000 0000 0000 0000 0000 0000 1000
|
||||
// -----------+----------------------------------------
|
||||
// Number | 0000 0000 0000 0000 0000 0000 0001 0000
|
||||
// + Integral | 0000 0000 0000 0000 0000 0000 0011 0000
|
||||
// + Int32 | 0000 0000 0000 0000 0000 0000 0111 0000
|
||||
// + Int64 | 0000 0000 0000 0000 0000 0000 1011 0000
|
||||
// + Floating | 0000 0000 0000 0000 0000 0001 0001 0000
|
||||
// + Float | 0000 0000 0000 0000 0000 0011 0001 0000
|
||||
// + Double | 0000 0000 0000 0000 0000 0101 0001 0000
|
||||
// -----------+----------------------------------------
|
||||
// Array | 0000 0000 0000 0000 0001 0000 0000 0000
|
||||
// -----------+----------------------------------------
|
||||
|
||||
Null = 0x0,
|
||||
Bool = 0x1,
|
||||
True = 0x2 | Bool,
|
||||
False = 0x4 | Bool,
|
||||
|
||||
String = 0x8,
|
||||
|
||||
Number = 0x10,
|
||||
Integral = 0x20 | Number,
|
||||
Int32 = 0x40 | Integral,
|
||||
Int64 = 0x80 | Integral,
|
||||
|
||||
Floating = 0x100 | Number,
|
||||
Float = 0x200 | Floating,
|
||||
Double = 0x400 | Floating,
|
||||
|
||||
Array = 0x1000,
|
||||
|
||||
type_mask = 0xFFF
|
||||
};
|
||||
@@ -1,35 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/property.hpp"
|
||||
#include "storage/model/properties/all.hpp"
|
||||
#include "storage/model/properties/property.hpp"
|
||||
|
||||
template <class Handler>
|
||||
void accept(const Property &property, Handler &h)
|
||||
{
|
||||
switch (property.flags) {
|
||||
|
||||
case Property::Flags::True:
|
||||
return h.handle(static_cast<const Bool &>(property));
|
||||
case Flags::True:
|
||||
return h.handle(static_cast<const Bool &>(property));
|
||||
|
||||
case Property::Flags::False:
|
||||
return h.handle(static_cast<const Bool &>(property));
|
||||
case Flags::False:
|
||||
return h.handle(static_cast<const Bool &>(property));
|
||||
|
||||
case Property::Flags::String:
|
||||
return h.handle(static_cast<const String &>(property));
|
||||
case Flags::String:
|
||||
return h.handle(static_cast<const String &>(property));
|
||||
|
||||
case Property::Flags::Int32:
|
||||
return h.handle(static_cast<const Int32 &>(property));
|
||||
case Flags::Int32:
|
||||
return h.handle(static_cast<const Int32 &>(property));
|
||||
|
||||
case Property::Flags::Int64:
|
||||
return h.handle(static_cast<const Int64 &>(property));
|
||||
case Flags::Int64:
|
||||
return h.handle(static_cast<const Int64 &>(property));
|
||||
|
||||
case Property::Flags::Float:
|
||||
return h.handle(static_cast<const Float &>(property));
|
||||
case Flags::Float:
|
||||
return h.handle(static_cast<const Float &>(property));
|
||||
|
||||
case Property::Flags::Double:
|
||||
return h.handle(static_cast<const Double &>(property));
|
||||
case Flags::Double:
|
||||
return h.handle(static_cast<const Double &>(property));
|
||||
|
||||
default:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,42 +3,49 @@
|
||||
#include <map>
|
||||
|
||||
#include "storage/model/properties/property.hpp"
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
using prop_key_t = PropertyFamily::PropertyType::PropertyFamilyKey;
|
||||
|
||||
template <class T>
|
||||
using type_key_t = PropertyFamily::PropertyType::PropertyTypeKey<T>;
|
||||
|
||||
class Properties
|
||||
{
|
||||
public:
|
||||
using sptr = std::shared_ptr<Properties>;
|
||||
|
||||
auto begin() const { return props.begin(); }
|
||||
auto begin() const { return props.begin(); }
|
||||
auto cbegin() const { return props.cbegin(); }
|
||||
|
||||
auto end() const { return props.end(); }
|
||||
auto end() const { return props.end(); }
|
||||
auto cend() const { return props.cend(); }
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return props.size();
|
||||
}
|
||||
size_t size() const { return props.size(); }
|
||||
|
||||
const Property& at(const std::string& key) const;
|
||||
const Property &at(prop_key_t &key) const;
|
||||
|
||||
template <class T>
|
||||
auto at(type_key_t<T> &key) const;
|
||||
|
||||
template <class T, class... Args>
|
||||
void set(const std::string& key, Args&&... args);
|
||||
void set(type_key_t<T> &key, Args &&... args);
|
||||
|
||||
void set(const std::string& key, Property::sptr value);
|
||||
void set(prop_key_t &key, Property::sptr value);
|
||||
|
||||
void clear(const std::string& key);
|
||||
void clear(prop_key_t &key);
|
||||
|
||||
template <class Handler>
|
||||
void accept(Handler& handler) const
|
||||
void accept(Handler &handler) const
|
||||
{
|
||||
for(auto& kv : props)
|
||||
for (auto &kv : props)
|
||||
handler.handle(kv.first, *kv.second);
|
||||
|
||||
handler.finish();
|
||||
}
|
||||
|
||||
private:
|
||||
using props_t = std::map<std::string, Property::sptr>;
|
||||
using props_t = std::map<prop_key_t, Property::sptr>;
|
||||
props_t props;
|
||||
};
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "utils/underlying_cast.hpp"
|
||||
|
||||
class Null;
|
||||
@@ -15,57 +16,13 @@ class Property
|
||||
public:
|
||||
using sptr = std::shared_ptr<Property>;
|
||||
|
||||
enum class Flags : unsigned
|
||||
{
|
||||
// Type | Mask
|
||||
// -----------+----------------------------------------
|
||||
// Null | 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
// -----------+----------------------------------------
|
||||
// Bool | 0000 0000 0000 0000 0000 0000 0000 0001
|
||||
// + True | 0000 0000 0000 0000 0000 0000 0000 0011
|
||||
// + False | 0000 0000 0000 0000 0000 0000 0000 0101
|
||||
// -----------+----------------------------------------
|
||||
// String | 0000 0000 0000 0000 0000 0000 0000 1000
|
||||
// -----------+----------------------------------------
|
||||
// Number | 0000 0000 0000 0000 0000 0000 0001 0000
|
||||
// + Integral | 0000 0000 0000 0000 0000 0000 0011 0000
|
||||
// + Int32 | 0000 0000 0000 0000 0000 0000 0111 0000
|
||||
// + Int64 | 0000 0000 0000 0000 0000 0000 1011 0000
|
||||
// + Floating | 0000 0000 0000 0000 0000 0001 0001 0000
|
||||
// + Float | 0000 0000 0000 0000 0000 0011 0001 0000
|
||||
// + Double | 0000 0000 0000 0000 0000 0101 0001 0000
|
||||
// -----------+----------------------------------------
|
||||
// Array | 0000 0000 0000 0000 0001 0000 0000 0000
|
||||
// -----------+----------------------------------------
|
||||
|
||||
Null = 0x0,
|
||||
Bool = 0x1,
|
||||
True = 0x2 | Bool,
|
||||
False = 0x4 | Bool,
|
||||
|
||||
String = 0x8,
|
||||
|
||||
Number = 0x10,
|
||||
Integral = 0x20 | Number,
|
||||
Int32 = 0x40 | Integral,
|
||||
Int64 = 0x80 | Integral,
|
||||
|
||||
Floating = 0x100 | Number,
|
||||
Float = 0x200 | Floating,
|
||||
Double = 0x400 | Floating,
|
||||
|
||||
Array = 0x1000,
|
||||
|
||||
type_mask = 0xFFF
|
||||
};
|
||||
|
||||
static const Null Null;
|
||||
|
||||
Property(Flags flags);
|
||||
|
||||
virtual bool operator==(const Property& other) const = 0;
|
||||
virtual bool operator==(const Property &other) const = 0;
|
||||
|
||||
bool operator!=(const Property& other) const;
|
||||
bool operator!=(const Property &other) const;
|
||||
|
||||
template <class T>
|
||||
bool is() const
|
||||
@@ -74,22 +31,22 @@ public:
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T& as()
|
||||
T &as()
|
||||
{
|
||||
assert(this->is<T>());
|
||||
return *static_cast<T*>(this);
|
||||
return *static_cast<T *>(this);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T& as() const
|
||||
const T &as() const
|
||||
{
|
||||
assert(this->is<T>());
|
||||
return *static_cast<const T*>(this);
|
||||
return *static_cast<const T *>(this);
|
||||
}
|
||||
|
||||
virtual std::ostream& print(std::ostream& stream) const = 0;
|
||||
virtual std::ostream &print(std::ostream &stream) const = 0;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream, const Property& prop);
|
||||
friend std::ostream &operator<<(std::ostream &stream, const Property &prop);
|
||||
|
||||
const Flags flags;
|
||||
};
|
||||
|
||||
181
include/storage/model/properties/property_family.hpp
Normal file
181
include/storage/model/properties/property_family.hpp
Normal file
@@ -0,0 +1,181 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "data_structures/concurrent/concurrent_map.hpp"
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "utils/option.hpp"
|
||||
#include "utils/total_ordering.hpp"
|
||||
#include "utils/underlying_cast.hpp"
|
||||
|
||||
typedef Flags Type;
|
||||
|
||||
// Family of properties with the same name but different types.
|
||||
// Ordered on name.
|
||||
class PropertyFamily : public TotalOrdering<PropertyFamily>
|
||||
{
|
||||
friend class PropertyType;
|
||||
friend class PropertyFamilyKey;
|
||||
friend class PropertyTypeKey;
|
||||
|
||||
public:
|
||||
// Type of property defined with his family and his type.
|
||||
// Ordered on PropertyFamily and Type.
|
||||
class PropertyType : public TotalOrdering<PropertyType>
|
||||
{
|
||||
friend class PropertyFamilyKey;
|
||||
friend class PropertyTypeKey;
|
||||
friend class PropertyFamily;
|
||||
|
||||
public:
|
||||
// Ordered on POINTERS to PropertyFamily
|
||||
class PropertyFamilyKey : public TotalOrdering<PropertyFamilyKey>
|
||||
{
|
||||
friend class PropertyType;
|
||||
friend class PropertyTypeKey;
|
||||
|
||||
PropertyFamilyKey(const PropertyType &type) : type(&type) {}
|
||||
|
||||
public:
|
||||
friend bool operator==(const PropertyFamilyKey &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return &(lhs.type->family) == &(rhs.type->family);
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyFamilyKey &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return &(lhs.type->family) < &(rhs.type->family);
|
||||
}
|
||||
|
||||
Type prop_type() const { return type->type; }
|
||||
|
||||
std::string const &family_name() const
|
||||
{
|
||||
return type->family.name();
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyType *type;
|
||||
};
|
||||
|
||||
// Ordered on POINTERS to PropertyType.
|
||||
// When compared with PropertyFamilyKey behaves as PropertyFamilyKey.
|
||||
template <class T>
|
||||
class PropertyTypeKey
|
||||
: public TotalOrdering<PropertyTypeKey<T>>,
|
||||
public TotalOrdering<PropertyFamilyKey, PropertyTypeKey<T>>,
|
||||
public TotalOrdering<PropertyTypeKey<T>, PropertyFamilyKey>
|
||||
{
|
||||
friend class PropertyType;
|
||||
|
||||
PropertyTypeKey(const PropertyType &type) : type(type) {}
|
||||
public:
|
||||
PropertyFamilyKey family_key() { return PropertyFamilyKey(type); }
|
||||
|
||||
Type prop_type() const { return type.type; }
|
||||
|
||||
friend bool operator==(const PropertyTypeKey &lhs,
|
||||
const PropertyTypeKey &rhs)
|
||||
{
|
||||
return &(lhs.type) == &(rhs.type);
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyTypeKey &lhs,
|
||||
const PropertyTypeKey &rhs)
|
||||
{
|
||||
return &(lhs.type) < &(rhs.type);
|
||||
}
|
||||
|
||||
friend bool operator==(const PropertyFamilyKey &lhs,
|
||||
const PropertyTypeKey &rhs)
|
||||
{
|
||||
return &(lhs.type->family) == &(rhs.type.family);
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyFamilyKey &lhs,
|
||||
const PropertyTypeKey &rhs)
|
||||
{
|
||||
return &(lhs.type->family) < &(rhs.type.family);
|
||||
}
|
||||
|
||||
friend bool operator==(const PropertyTypeKey &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return &(lhs.type.family) == &(rhs.type->family);
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyTypeKey &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return &(lhs.type.family) < &(rhs.type->family);
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyType &type;
|
||||
};
|
||||
|
||||
private:
|
||||
PropertyType(PropertyFamily &family, Type type);
|
||||
PropertyType(PropertyFamily &other) = delete;
|
||||
PropertyType(PropertyFamily &&other) = delete;
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
bool is() const
|
||||
{
|
||||
return underlying_cast(type) & underlying_cast(T::type);
|
||||
}
|
||||
|
||||
bool is(Type &t) const;
|
||||
|
||||
// Returns key ordered on POINTERS to PropertyType.
|
||||
// When compared with PropertyFamilyKey behaves as PropertyFamilyKey.
|
||||
template <class T>
|
||||
PropertyTypeKey<T> type_key()
|
||||
{
|
||||
assert(this->is<T>());
|
||||
return PropertyTypeKey<T>(*this);
|
||||
}
|
||||
|
||||
// Returns key ordered on POINTERS to PropertyFamily
|
||||
PropertyFamilyKey family_key();
|
||||
|
||||
friend bool operator<(const PropertyType &lhs, const PropertyType &rhs)
|
||||
{
|
||||
return lhs.family < rhs.family ||
|
||||
(lhs.family == rhs.family && lhs.type < rhs.type);
|
||||
}
|
||||
|
||||
friend bool operator==(const PropertyType &lhs, const PropertyType &rhs)
|
||||
{
|
||||
return lhs.family == rhs.family && lhs.type == rhs.type;
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyFamily &family;
|
||||
const Type type;
|
||||
};
|
||||
|
||||
PropertyFamily(std::string const &name_v);
|
||||
PropertyFamily(std::string &&name_v);
|
||||
PropertyFamily(PropertyFamily &other) = delete;
|
||||
PropertyFamily(PropertyFamily &&other) = delete;
|
||||
|
||||
std::string const &name() const;
|
||||
|
||||
// Returns type if it exists otherwise creates it.
|
||||
PropertyType &get(Type type);
|
||||
|
||||
friend bool operator<(const PropertyFamily &lhs, const PropertyFamily &rhs);
|
||||
|
||||
friend bool operator==(const PropertyFamily &lhs,
|
||||
const PropertyFamily &rhs);
|
||||
|
||||
private:
|
||||
const std::string name_v;
|
||||
|
||||
// TODO: Because types wont be removed this could be done with more efficent
|
||||
// data structure.
|
||||
ConcurrentMap<Type, std::unique_ptr<PropertyType>> types;
|
||||
};
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
#include "storage/model/properties/handler.hpp"
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
@@ -13,12 +13,12 @@ class ConsoleWriter
|
||||
public:
|
||||
ConsoleWriter() {}
|
||||
|
||||
void handle(const std::string &key, const Property &value)
|
||||
void handle(const prop_key_t &key, const Property &value)
|
||||
{
|
||||
cout << "KEY: " << key << "; VALUE: ";
|
||||
cout << "KEY: " << key.family_name() << "; VALUE: ";
|
||||
|
||||
accept(value, *this);
|
||||
|
||||
|
||||
// value.accept(*this);
|
||||
|
||||
cout << endl;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
#include "storage/model/properties/handler.hpp"
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
|
||||
template <class Buffer>
|
||||
struct JsonWriter
|
||||
@@ -9,13 +9,13 @@ struct JsonWriter
|
||||
public:
|
||||
JsonWriter(Buffer &buffer) : buffer(buffer) { buffer << '{'; };
|
||||
|
||||
void handle(const std::string &key, const Property &value)
|
||||
void handle(const prop_key_t &key, const Property &value)
|
||||
{
|
||||
if (!first) buffer << ',';
|
||||
|
||||
if (first) first = false;
|
||||
|
||||
buffer << '"' << key << "\":";
|
||||
buffer << '"' << key.family_name() << "\":";
|
||||
// value.accept(*this);
|
||||
accept(value, *this);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
#include "database/db_transaction.hpp"
|
||||
#include "mvcc/version_list.hpp"
|
||||
#include "storage/indexes/index_record.hpp"
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
#include "storage/model/properties/property.hpp"
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "transactions/transaction.hpp"
|
||||
|
||||
template <class T, class Derived, class vlist_t = mvcc::VersionList<T>>
|
||||
@@ -57,30 +59,32 @@ public:
|
||||
return vlist->remove(record, db.trans);
|
||||
}
|
||||
|
||||
const Property &property(const std::string &key) const
|
||||
{
|
||||
return record->data.props.at(key);
|
||||
}
|
||||
const Property &at(prop_key_t &key) const { return properties().at(key); }
|
||||
|
||||
template <class V>
|
||||
auto at(type_key_t<V> &key) const;
|
||||
|
||||
template <class V, class... Args>
|
||||
void property(const std::string &key, Args &&... args)
|
||||
void set(type_key_t<V> &key, Args &&... args)
|
||||
{
|
||||
record->data.props.template set<V>(key, std::forward<Args>(args)...);
|
||||
properties().template set<V>(key, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void property(const std::string &key, Property::sptr value)
|
||||
void set(prop_key_t &key, Property::sptr value)
|
||||
{
|
||||
record->data.props.set(key, std::move(value));
|
||||
properties().set(key, std::move(value));
|
||||
}
|
||||
|
||||
void clear(prop_key_t &key) { properties().clear(key); }
|
||||
|
||||
template <class Handler>
|
||||
void accept(Handler &handler) const
|
||||
{
|
||||
properties().template accept<Handler>(handler);
|
||||
}
|
||||
|
||||
Properties &properties() const { return record->data.props; }
|
||||
|
||||
template <class V>
|
||||
auto at(const std::string &key) const
|
||||
{
|
||||
return properties().at(key).template as<V>().value_ref();
|
||||
}
|
||||
|
||||
explicit operator bool() const { return record != nullptr; }
|
||||
|
||||
T const *operator->() const { return record; }
|
||||
@@ -99,6 +103,12 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
template <class K>
|
||||
IndexRecord<T, K> create_ir(K &&key)
|
||||
{
|
||||
return IndexRecord<T, K>(std::move(key), record, vlist);
|
||||
}
|
||||
|
||||
T *record{nullptr};
|
||||
vlist_t *const vlist;
|
||||
DbTransaction &db;
|
||||
|
||||
@@ -10,13 +10,23 @@ class Vertex::Accessor : public RecordAccessor<Vertex, Vertex::Accessor>
|
||||
public:
|
||||
using RecordAccessor::RecordAccessor;
|
||||
|
||||
static Vertex::Accessor create(Vertex *t, mvcc::VersionList<Vertex> *vlist,
|
||||
DbTransaction &db)
|
||||
{
|
||||
return Vertex::Accessor(t, vlist, db);
|
||||
}
|
||||
|
||||
size_t out_degree() const;
|
||||
|
||||
size_t in_degree() const;
|
||||
|
||||
size_t degree() const;
|
||||
|
||||
void add_label(const Label &label);
|
||||
// False if it's label with it already.
|
||||
bool add_label(const Label &label);
|
||||
|
||||
// False if it doesn't have label.
|
||||
bool remove_label(const Label &label);
|
||||
|
||||
bool has_label(const Label &label) const;
|
||||
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "data_structures/concurrent/concurrent_map.hpp"
|
||||
#include "database/db_transaction.hpp"
|
||||
// #include "database/db_transaction.hpp"
|
||||
#include "storage/common.hpp"
|
||||
#include "storage/indexes/index.hpp"
|
||||
#include "storage/indexes/index_record_collection.hpp"
|
||||
// #include "storage/indexes/index.hpp"
|
||||
// #include "storage/indexes/index_record_collection.hpp"
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "storage/vertex_accessor.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
class DbTransaction;
|
||||
|
||||
class Vertices
|
||||
{
|
||||
public:
|
||||
using vertices_t = ConcurrentMap<uint64_t, VertexRecord>;
|
||||
using prop_familys_t =
|
||||
ConcurrentMap<std::string, std::unique_ptr<PropertyFamily>>;
|
||||
|
||||
vertices_t::Accessor access();
|
||||
|
||||
@@ -20,13 +27,15 @@ public:
|
||||
// Creates new Vertex and returns filled Vertex::Accessor.
|
||||
Vertex::Accessor insert(DbTransaction &t);
|
||||
|
||||
void update_label_index(const Label &label,
|
||||
VertexIndexRecord &&index_record);
|
||||
PropertyFamily &property_family_find_or_create(const std::string &name);
|
||||
|
||||
VertexIndexRecordCollection &find_label_index(const Label &label);
|
||||
// prop_familys_t::Accessor property_family_access();
|
||||
|
||||
private:
|
||||
vertices_t vertices;
|
||||
Index<label_ref_t, VertexIndexRecordCollection> label_index;
|
||||
// TODO: Because familys wont be removed this could be done with more
|
||||
// efficent
|
||||
// data structure.
|
||||
prop_familys_t prop_familys;
|
||||
AtomicCounter<uint64_t> counter;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user