Add a common VerticesIterable wrapper

Summary:
This ought to simplify the code which needs to work with any kind of
vertex iteration, be it through an index store or regular.

Reviewers: mtomic, mferencevic

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2258
This commit is contained in:
Teon Banek 2019-07-29 14:26:31 +02:00
parent bad1f8b525
commit ed9f82bcf4
2 changed files with 340 additions and 33 deletions

View File

@ -22,21 +22,21 @@ auto AdvanceToVisibleVertex(utils::SkipList<Vertex>::Iterator it,
return it;
}
VerticesIterable::Iterator::Iterator(VerticesIterable *self,
utils::SkipList<Vertex>::Iterator it)
AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self,
utils::SkipList<Vertex>::Iterator it)
: self_(self),
it_(AdvanceToVisibleVertex(it, self->vertices_accessor_.end(),
self->transaction_, self->view_,
self->indices_)) {}
VertexAccessor VerticesIterable::Iterator::operator*() const {
VertexAccessor AllVerticesIterable::Iterator::operator*() const {
// TODO: current vertex accessor could be cached to avoid reconstructing every
// time
return *VertexAccessor::Create(&*it_, self_->transaction_, self_->indices_,
self_->view_);
}
VerticesIterable::Iterator &VerticesIterable::Iterator::operator++() {
AllVerticesIterable::Iterator &AllVerticesIterable::Iterator::operator++() {
++it_;
it_ = AdvanceToVisibleVertex(it_, self_->vertices_accessor_.end(),
self_->transaction_, self_->view_,
@ -44,6 +44,247 @@ VerticesIterable::Iterator &VerticesIterable::Iterator::operator++() {
return *this;
}
VerticesIterable::VerticesIterable(AllVerticesIterable vertices)
: type_(Type::ALL) {
new (&all_vertices_) AllVerticesIterable(std::move(vertices));
}
VerticesIterable::VerticesIterable(LabelIndex::Iterable vertices)
: type_(Type::BY_LABEL) {
new (&vertices_by_label_) LabelIndex::Iterable(std::move(vertices));
}
VerticesIterable::VerticesIterable(LabelPropertyIndex::Iterable vertices)
: type_(Type::BY_LABEL_PROPERTY) {
new (&vertices_by_label_property_)
LabelPropertyIndex::Iterable(std::move(vertices));
}
VerticesIterable::VerticesIterable(VerticesIterable &&other) noexcept
: type_(other.type_) {
switch (other.type_) {
case Type::ALL:
new (&all_vertices_) AllVerticesIterable(std::move(other.all_vertices_));
break;
case Type::BY_LABEL:
new (&vertices_by_label_)
LabelIndex::Iterable(std::move(other.vertices_by_label_));
break;
case Type::BY_LABEL_PROPERTY:
new (&vertices_by_label_property_) LabelPropertyIndex::Iterable(
std::move(other.vertices_by_label_property_));
break;
}
}
VerticesIterable &VerticesIterable::operator=(
VerticesIterable &&other) noexcept {
switch (type_) {
case Type::ALL:
all_vertices_.AllVerticesIterable::~AllVerticesIterable();
break;
case Type::BY_LABEL:
vertices_by_label_.LabelIndex::Iterable::~Iterable();
break;
case Type::BY_LABEL_PROPERTY:
vertices_by_label_property_.LabelPropertyIndex::Iterable::~Iterable();
break;
}
type_ = other.type_;
switch (other.type_) {
case Type::ALL:
new (&all_vertices_) AllVerticesIterable(std::move(other.all_vertices_));
break;
case Type::BY_LABEL:
new (&vertices_by_label_)
LabelIndex::Iterable(std::move(other.vertices_by_label_));
break;
case Type::BY_LABEL_PROPERTY:
new (&vertices_by_label_property_) LabelPropertyIndex::Iterable(
std::move(other.vertices_by_label_property_));
break;
}
return *this;
}
VerticesIterable::~VerticesIterable() {
switch (type_) {
case Type::ALL:
all_vertices_.AllVerticesIterable::~AllVerticesIterable();
break;
case Type::BY_LABEL:
vertices_by_label_.LabelIndex::Iterable::~Iterable();
break;
case Type::BY_LABEL_PROPERTY:
vertices_by_label_property_.LabelPropertyIndex::Iterable::~Iterable();
break;
}
}
VerticesIterable::Iterator VerticesIterable::begin() {
switch (type_) {
case Type::ALL:
return Iterator(all_vertices_.begin());
case Type::BY_LABEL:
return Iterator(vertices_by_label_.begin());
case Type::BY_LABEL_PROPERTY:
return Iterator(vertices_by_label_property_.begin());
}
}
VerticesIterable::Iterator VerticesIterable::end() {
switch (type_) {
case Type::ALL:
return Iterator(all_vertices_.end());
case Type::BY_LABEL:
return Iterator(vertices_by_label_.end());
case Type::BY_LABEL_PROPERTY:
return Iterator(vertices_by_label_property_.end());
}
}
VerticesIterable::Iterator::Iterator(AllVerticesIterable::Iterator it)
: type_(Type::ALL) {
new (&all_it_) AllVerticesIterable::Iterator(std::move(it));
}
VerticesIterable::Iterator::Iterator(LabelIndex::Iterable::Iterator it)
: type_(Type::BY_LABEL) {
new (&by_label_it_) LabelIndex::Iterable::Iterator(std::move(it));
}
VerticesIterable::Iterator::Iterator(LabelPropertyIndex::Iterable::Iterator it)
: type_(Type::BY_LABEL_PROPERTY) {
new (&by_label_property_it_)
LabelPropertyIndex::Iterable::Iterator(std::move(it));
}
VerticesIterable::Iterator::Iterator(const VerticesIterable::Iterator &other)
: type_(other.type_) {
switch (other.type_) {
case Type::ALL:
new (&all_it_) AllVerticesIterable::Iterator(other.all_it_);
break;
case Type::BY_LABEL:
new (&by_label_it_) LabelIndex::Iterable::Iterator(other.by_label_it_);
break;
case Type::BY_LABEL_PROPERTY:
new (&by_label_property_it_)
LabelPropertyIndex::Iterable::Iterator(other.by_label_property_it_);
break;
}
}
VerticesIterable::Iterator &VerticesIterable::Iterator::operator=(
const VerticesIterable::Iterator &other) {
Destroy();
type_ = other.type_;
switch (other.type_) {
case Type::ALL:
new (&all_it_) AllVerticesIterable::Iterator(other.all_it_);
break;
case Type::BY_LABEL:
new (&by_label_it_) LabelIndex::Iterable::Iterator(other.by_label_it_);
break;
case Type::BY_LABEL_PROPERTY:
new (&by_label_property_it_)
LabelPropertyIndex::Iterable::Iterator(other.by_label_property_it_);
break;
}
return *this;
}
VerticesIterable::Iterator::Iterator(
VerticesIterable::Iterator &&other) noexcept
: type_(other.type_) {
switch (other.type_) {
case Type::ALL:
new (&all_it_) AllVerticesIterable::Iterator(std::move(other.all_it_));
break;
case Type::BY_LABEL:
new (&by_label_it_)
LabelIndex::Iterable::Iterator(std::move(other.by_label_it_));
break;
case Type::BY_LABEL_PROPERTY:
new (&by_label_property_it_) LabelPropertyIndex::Iterable::Iterator(
std::move(other.by_label_property_it_));
break;
}
}
VerticesIterable::Iterator &VerticesIterable::Iterator::operator=(
VerticesIterable::Iterator &&other) noexcept {
Destroy();
type_ = other.type_;
switch (other.type_) {
case Type::ALL:
new (&all_it_) AllVerticesIterable::Iterator(std::move(other.all_it_));
break;
case Type::BY_LABEL:
new (&by_label_it_)
LabelIndex::Iterable::Iterator(std::move(other.by_label_it_));
break;
case Type::BY_LABEL_PROPERTY:
new (&by_label_property_it_) LabelPropertyIndex::Iterable::Iterator(
std::move(other.by_label_property_it_));
break;
}
return *this;
}
VerticesIterable::Iterator::~Iterator() { Destroy(); }
void VerticesIterable::Iterator::Destroy() noexcept {
switch (type_) {
case Type::ALL:
all_it_.AllVerticesIterable::Iterator::~Iterator();
break;
case Type::BY_LABEL:
by_label_it_.LabelIndex::Iterable::Iterator::~Iterator();
break;
case Type::BY_LABEL_PROPERTY:
by_label_property_it_.LabelPropertyIndex::Iterable::Iterator::~Iterator();
break;
}
}
VertexAccessor VerticesIterable::Iterator::operator*() const {
switch (type_) {
case Type::ALL:
return *all_it_;
case Type::BY_LABEL:
return *by_label_it_;
case Type::BY_LABEL_PROPERTY:
return *by_label_property_it_;
}
}
VerticesIterable::Iterator &VerticesIterable::Iterator::operator++() {
switch (type_) {
case Type::ALL:
++all_it_;
break;
case Type::BY_LABEL:
++by_label_it_;
break;
case Type::BY_LABEL_PROPERTY:
++by_label_property_it_;
break;
}
return *this;
}
bool VerticesIterable::Iterator::operator==(const Iterator &other) const {
switch (type_) {
case Type::ALL:
return all_it_ == other.all_it_;
case Type::BY_LABEL:
return by_label_it_ == other.by_label_it_;
case Type::BY_LABEL_PROPERTY:
return by_label_property_it_ == other.by_label_property_it_;
}
}
Storage::Storage(StorageGcConfig gc_config) : gc_config_(gc_config) {
if (gc_config.type == StorageGcConfig::Type::PERIODIC) {
gc_runner_.Run("Storage GC", gc_config.interval,
@ -591,30 +832,31 @@ Storage::Accessor Storage::Access() {
return Accessor{this, transaction_id, start_timestamp};
}
LabelIndex::Iterable Storage::Accessor::Vertices(LabelId label, View view) {
return storage_->indices_.label_index.Vertices(label, view, &transaction_);
VerticesIterable Storage::Accessor::Vertices(LabelId label, View view) {
return VerticesIterable(
storage_->indices_.label_index.Vertices(label, view, &transaction_));
}
LabelPropertyIndex::Iterable Storage::Accessor::Vertices(LabelId label,
PropertyId property,
View view) {
return storage_->indices_.label_property_index.Vertices(
label, property, std::nullopt, std::nullopt, view, &transaction_);
VerticesIterable Storage::Accessor::Vertices(LabelId label, PropertyId property,
View view) {
return VerticesIterable(storage_->indices_.label_property_index.Vertices(
label, property, std::nullopt, std::nullopt, view, &transaction_));
}
LabelPropertyIndex::Iterable Storage::Accessor::Vertices(
LabelId label, PropertyId property, const PropertyValue &value, View view) {
return storage_->indices_.label_property_index.Vertices(
VerticesIterable Storage::Accessor::Vertices(LabelId label, PropertyId property,
const PropertyValue &value,
View view) {
return VerticesIterable(storage_->indices_.label_property_index.Vertices(
label, property, utils::MakeBoundInclusive(value),
utils::MakeBoundInclusive(value), view, &transaction_);
utils::MakeBoundInclusive(value), view, &transaction_));
}
LabelPropertyIndex::Iterable Storage::Accessor::Vertices(
VerticesIterable Storage::Accessor::Vertices(
LabelId label, PropertyId property,
const std::optional<utils::Bound<PropertyValue>> &lower_bound,
const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view) {
return storage_->indices_.label_property_index.Vertices(
label, property, lower_bound, upper_bound, view, &transaction_);
return VerticesIterable(storage_->indices_.label_property_index.Vertices(
label, property, lower_bound, upper_bound, view, &transaction_));
}
void Storage::CollectGarbage() {

View File

@ -47,18 +47,23 @@ inline static constexpr StorageGcConfig DefaultGcConfig = {
.type = StorageGcConfig::Type::PERIODIC,
.interval = std::chrono::milliseconds(1000)};
class VerticesIterable final {
/// Iterable for iterating through all vertices of a Storage.
///
/// An instance of this will be usually be wrapped inside VerticesIterable for
/// generic, public use.
class AllVerticesIterable final {
utils::SkipList<Vertex>::Accessor vertices_accessor_;
Transaction *transaction_;
View view_;
Indices *indices_;
public:
class Iterator final {
VerticesIterable *self_;
AllVerticesIterable *self_;
utils::SkipList<Vertex>::Iterator it_;
public:
Iterator(VerticesIterable *self, utils::SkipList<Vertex>::Iterator it);
Iterator(AllVerticesIterable *self, utils::SkipList<Vertex>::Iterator it);
VertexAccessor operator*() const;
@ -71,9 +76,8 @@ class VerticesIterable final {
bool operator!=(const Iterator &other) const { return !(*this == other); }
};
public:
VerticesIterable(utils::SkipList<Vertex>::Accessor vertices_accessor,
Transaction *transaction, View view, Indices *indices)
AllVerticesIterable(utils::SkipList<Vertex>::Accessor vertices_accessor,
Transaction *transaction, View view, Indices *indices)
: vertices_accessor_(std::move(vertices_accessor)),
transaction_(transaction),
view_(view),
@ -83,6 +87,68 @@ class VerticesIterable final {
Iterator end() { return Iterator(this, vertices_accessor_.end()); }
};
/// Generic access to different kinds of vertex iterations.
///
/// This class should be the primary type used by the client code to iterate
/// over vertices inside a Storage instance.
class VerticesIterable final {
enum class Type { ALL, BY_LABEL, BY_LABEL_PROPERTY };
Type type_;
union {
AllVerticesIterable all_vertices_;
LabelIndex::Iterable vertices_by_label_;
LabelPropertyIndex::Iterable vertices_by_label_property_;
};
public:
explicit VerticesIterable(AllVerticesIterable);
explicit VerticesIterable(LabelIndex::Iterable);
explicit VerticesIterable(LabelPropertyIndex::Iterable);
VerticesIterable(const VerticesIterable &) = delete;
VerticesIterable &operator=(const VerticesIterable &) = delete;
VerticesIterable(VerticesIterable &&) noexcept;
VerticesIterable &operator=(VerticesIterable &&) noexcept;
~VerticesIterable();
class Iterator final {
Type type_;
union {
AllVerticesIterable::Iterator all_it_;
LabelIndex::Iterable::Iterator by_label_it_;
LabelPropertyIndex::Iterable::Iterator by_label_property_it_;
};
void Destroy() noexcept;
public:
explicit Iterator(AllVerticesIterable::Iterator);
explicit Iterator(LabelIndex::Iterable::Iterator);
explicit Iterator(LabelPropertyIndex::Iterable::Iterator);
Iterator(const Iterator &);
Iterator &operator=(const Iterator &);
Iterator(Iterator &&) noexcept;
Iterator &operator=(Iterator &&) noexcept;
~Iterator();
VertexAccessor operator*() const;
Iterator &operator++();
bool operator==(const Iterator &other) const;
bool operator!=(const Iterator &other) const { return !(*this == other); }
};
Iterator begin();
Iterator end();
};
class Storage final {
public:
explicit Storage(StorageGcConfig gc_config = DefaultGcConfig);
@ -112,20 +178,19 @@ class Storage final {
std::optional<VertexAccessor> FindVertex(Gid gid, View view);
VerticesIterable Vertices(View view) {
return VerticesIterable(storage_->vertices_.access(), &transaction_, view,
&storage_->indices_);
return VerticesIterable(AllVerticesIterable(storage_->vertices_.access(),
&transaction_, view,
&storage_->indices_));
}
LabelIndex::Iterable Vertices(LabelId label, View view);
VerticesIterable Vertices(LabelId label, View view);
LabelPropertyIndex::Iterable Vertices(LabelId label, PropertyId property,
View view);
VerticesIterable Vertices(LabelId label, PropertyId property, View view);
LabelPropertyIndex::Iterable Vertices(LabelId label, PropertyId property,
const PropertyValue &value,
View view);
VerticesIterable Vertices(LabelId label, PropertyId property,
const PropertyValue &value, View view);
LabelPropertyIndex::Iterable Vertices(
VerticesIterable Vertices(
LabelId label, PropertyId property,
const std::optional<utils::Bound<PropertyValue>> &lower_bound,
const std::optional<utils::Bound<PropertyValue>> &upper_bound,