283 lines
9.7 KiB
C++
283 lines
9.7 KiB
C++
// Copyright 2023 Memgraph Ltd.
|
|
//
|
|
// Use of this software is governed by the Business Source License
|
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
|
// License, and you may not use this file except in compliance with the Business Source License.
|
|
//
|
|
// As of the Change Date specified in that file, in accordance with
|
|
// the Business Source License, use of this software will be governed
|
|
// by the Apache License, Version 2.0, included in the file
|
|
// licenses/APL.txt.
|
|
|
|
#include "storage/v2/storage.hpp"
|
|
|
|
namespace memgraph::storage {
|
|
|
|
using OOMExceptionEnabler = utils::MemoryTracker::OutOfMemoryExceptionEnabler;
|
|
|
|
auto AdvanceToVisibleVertex(utils::SkipList<Vertex>::Iterator it, utils::SkipList<Vertex>::Iterator end,
|
|
std::optional<VertexAccessor> *vertex, Transaction *tx, View view, Indices *indices,
|
|
Constraints *constraints, Config::Items config) {
|
|
while (it != end) {
|
|
*vertex = VertexAccessor::Create(&*it, tx, indices, constraints, config, view);
|
|
if (!*vertex) {
|
|
++it;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
return it;
|
|
}
|
|
|
|
AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self, utils::SkipList<Vertex>::Iterator it)
|
|
: self_(self),
|
|
it_(AdvanceToVisibleVertex(it, self->vertices_accessor_.end(), &self->vertex_, self->transaction_, self->view_,
|
|
self->indices_, self_->constraints_, self->config_)) {}
|
|
|
|
VertexAccessor AllVerticesIterable::Iterator::operator*() const { return *self_->vertex_; }
|
|
|
|
AllVerticesIterable::Iterator &AllVerticesIterable::Iterator::operator++() {
|
|
++it_;
|
|
it_ = AdvanceToVisibleVertex(it_, self_->vertices_accessor_.end(), &self_->vertex_, self_->transaction_, self_->view_,
|
|
self_->indices_, self_->constraints_, self_->config_);
|
|
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::Accessor::Accessor(Storage *storage, IsolationLevel isolation_level, StorageMode storage_mode)
|
|
: storage_(storage),
|
|
// The lock must be acquired before creating the transaction object to
|
|
// prevent freshly created transactions from dangling in an active state
|
|
// during exclusive operations.
|
|
storage_guard_(storage_->main_lock_),
|
|
transaction_(storage->CreateTransaction(isolation_level, storage_mode)),
|
|
is_transaction_active_(true) {}
|
|
|
|
Storage::Accessor::Accessor(Accessor &&other) noexcept
|
|
: storage_(other.storage_),
|
|
storage_guard_(std::move(other.storage_guard_)),
|
|
transaction_(std::move(other.transaction_)),
|
|
commit_timestamp_(other.commit_timestamp_),
|
|
is_transaction_active_(other.is_transaction_active_) {
|
|
// Don't allow the other accessor to abort our transaction in destructor.
|
|
other.is_transaction_active_ = false;
|
|
other.commit_timestamp_.reset();
|
|
}
|
|
|
|
} // namespace memgraph::storage
|