Implement vertex deletion in storage v2

Reviewers: mtomic, teon.banek

Reviewed By: mtomic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2157
This commit is contained in:
Matej Ferencevic 2019-07-01 16:11:12 +02:00
parent 9e649794fc
commit 83a99aaf7d
6 changed files with 580 additions and 111 deletions

View File

@ -7,6 +7,7 @@ namespace storage {
struct Delta {
enum class Action {
DELETE_OBJECT,
RECREATE_OBJECT,
ADD_LABEL,
REMOVE_LABEL,
};

View File

@ -8,6 +8,7 @@ namespace storage {
enum class Error : uint8_t {
SERIALIZATION_ERROR,
DELETED_OBJECT,
};
template <typename TReturn>
@ -20,14 +21,14 @@ class Result final {
bool IsReturn() const { return return_.has_value(); }
bool IsError() const { return error_.has_value(); }
TReturn *GetReturn() {
TReturn &GetReturn() {
CHECK(return_) << "The storage result is an error!";
return &*return_;
return return_.value();
}
const TReturn *GetReturn() const {
const TReturn &GetReturn() const {
CHECK(return_) << "The storage result is an error!";
return &*return_;
return return_.value();
}
Error GetError() const {

View File

@ -146,6 +146,10 @@ class Storage final {
CHECK(acc.remove(vertex->gid)) << "Invalid database state!";
break;
}
case Delta::Action::RECREATE_OBJECT: {
vertex->deleted = false;
break;
}
}
current = current->next.load(std::memory_order_acquire);
}

View File

@ -12,7 +12,7 @@
namespace storage {
struct Vertex {
Vertex(Gid gid, Delta *delta) : gid(gid), delta(delta) {
Vertex(Gid gid, Delta *delta) : gid(gid), deleted(false), delta(delta) {
CHECK(delta->action == Delta::Action::DELETE_OBJECT)
<< "Vertex must be created with an initial DELETE_OBJECT delta!";
}
@ -24,7 +24,9 @@ struct Vertex {
// std::unordered_map<uint64_t, storage::PropertyValue> properties;
utils::SpinLock lock;
// uint32_t PAD;
bool deleted;
// uint8_t PAD;
// uint16_t PAD;
Delta *delta;
};

View File

@ -21,18 +21,23 @@ class VertexAccessor final {
static std::optional<VertexAccessor> Create(Vertex *vertex,
Transaction *transaction,
View view) {
bool is_visible = true;
Delta *delta = nullptr;
{
std::lock_guard<utils::SpinLock> guard(vertex->lock);
is_visible = !vertex->deleted;
delta = vertex->delta;
}
bool is_visible = true;
ApplyDeltasForRead(transaction, delta, view,
[&is_visible](const Delta &delta) {
switch (delta.action) {
case Delta::Action::ADD_LABEL:
case Delta::Action::REMOVE_LABEL:
break;
case Delta::Action::RECREATE_OBJECT: {
is_visible = true;
break;
}
case Delta::Action::DELETE_OBJECT: {
is_visible = false;
break;
@ -43,12 +48,30 @@ class VertexAccessor final {
return VertexAccessor{vertex, transaction};
}
Result<bool> Delete() {
std::lock_guard<utils::SpinLock> guard(vertex_->lock);
if (!PrepareForWrite(transaction_, vertex_))
return Result<bool>{Error::SERIALIZATION_ERROR};
if (vertex_->deleted) return Result<bool>{false};
CreateAndLinkDelta(transaction_, vertex_, Delta::Action::RECREATE_OBJECT,
0);
vertex_->deleted = true;
return Result<bool>{true};
}
Result<bool> AddLabel(uint64_t label) {
std::lock_guard<utils::SpinLock> guard(vertex_->lock);
if (!PrepareForWrite(transaction_, vertex_))
return Result<bool>{Error::SERIALIZATION_ERROR};
if (vertex_->deleted) return Result<bool>{Error::DELETED_OBJECT};
if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) !=
vertex_->labels.end())
return Result<bool>{false};
@ -66,6 +89,8 @@ class VertexAccessor final {
if (!PrepareForWrite(transaction_, vertex_))
return Result<bool>{Error::SERIALIZATION_ERROR};
if (vertex_->deleted) return Result<bool>{Error::DELETED_OBJECT};
auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label);
if (it == vertex_->labels.end()) return Result<bool>{false};
@ -76,17 +101,19 @@ class VertexAccessor final {
return Result<bool>{true};
}
bool HasLabel(uint64_t label, View view) {
Result<bool> HasLabel(uint64_t label, View view) {
bool deleted = false;
bool has_label = false;
Delta *delta = nullptr;
{
std::lock_guard<utils::SpinLock> guard(vertex_->lock);
deleted = vertex_->deleted;
has_label = std::find(vertex_->labels.begin(), vertex_->labels.end(),
label) != vertex_->labels.end();
delta = vertex_->delta;
}
ApplyDeltasForRead(transaction_, delta, view,
[&has_label, label](const Delta &delta) {
[&deleted, &has_label, label](const Delta &delta) {
switch (delta.action) {
case Delta::Action::REMOVE_LABEL: {
if (delta.value == label) {
@ -106,21 +133,28 @@ class VertexAccessor final {
LOG(FATAL) << "Invalid accessor!";
break;
}
case Delta::Action::RECREATE_OBJECT: {
deleted = false;
break;
}
}
});
return has_label;
if (deleted) return Result<bool>{Error::DELETED_OBJECT};
return Result<bool>{has_label};
}
std::vector<uint64_t> Labels(View view) {
Result<std::vector<uint64_t>> Labels(View view) {
bool deleted = false;
std::vector<uint64_t> labels;
Delta *delta = nullptr;
{
std::lock_guard<utils::SpinLock> guard(vertex_->lock);
deleted = vertex_->deleted;
labels = vertex_->labels;
delta = vertex_->delta;
}
ApplyDeltasForRead(
transaction_, delta, view, [&labels](const Delta &delta) {
transaction_, delta, view, [&deleted, &labels](const Delta &delta) {
switch (delta.action) {
case Delta::Action::REMOVE_LABEL: {
// Remove the label because we don't see the addition.
@ -141,9 +175,14 @@ class VertexAccessor final {
LOG(FATAL) << "Invalid accessor!";
break;
}
case Delta::Action::RECREATE_OBJECT: {
deleted = false;
break;
}
}
});
return labels;
if (deleted) return Result<std::vector<uint64_t>>{Error::DELETED_OBJECT};
return Result<std::vector<uint64_t>>{std::move(labels)};
}
Gid Gid() const { return vertex_->gid; }

View File

@ -23,6 +23,22 @@ TEST(StorageV2, Commit) {
ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value());
acc.Abort();
}
{
auto acc = store.Access();
auto vertex = acc.FindVertex(gid, storage::View::NEW);
ASSERT_TRUE(vertex);
auto res = vertex->Delete();
ASSERT_FALSE(res.IsError());
acc.Commit();
}
{
auto acc = store.Access();
ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_FALSE(acc.FindVertex(gid, storage::View::NEW).has_value());
acc.Abort();
}
}
// NOLINTNEXTLINE(hicpp-special-member-functions)
@ -174,6 +190,412 @@ TEST(StorageV2, AccessorMove) {
}
}
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageV2, VertexDeleteCommit) {
storage::Storage store;
storage::Gid gid =
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
auto acc1 = store.Access(); // read transaction
auto acc2 = store.Access(); // write transaction
// Create the vertex in transaction 2
{
auto vertex = acc2.CreateVertex();
gid = vertex.Gid();
ASSERT_FALSE(acc2.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc2.FindVertex(gid, storage::View::NEW).has_value());
acc2.Commit();
}
auto acc3 = store.Access(); // read transaction
auto acc4 = store.Access(); // write transaction
// Check whether the vertex exists in transaction 1
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 3
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value());
// Delete the vertex in transaction 4
{
auto vertex = acc4.FindVertex(gid, storage::View::NEW);
ASSERT_TRUE(vertex);
auto res = vertex->Delete();
ASSERT_TRUE(res.IsReturn());
acc4.Commit();
}
auto acc5 = store.Access(); // read transaction
// Check whether the vertex exists in transaction 1
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 3
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 5
ASSERT_FALSE(acc5.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_FALSE(acc5.FindVertex(gid, storage::View::NEW).has_value());
}
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageV2, VertexDeleteAbort) {
storage::Storage store;
storage::Gid gid =
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
auto acc1 = store.Access(); // read transaction
auto acc2 = store.Access(); // write transaction
// Create the vertex in transaction 2
{
auto vertex = acc2.CreateVertex();
gid = vertex.Gid();
ASSERT_FALSE(acc2.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc2.FindVertex(gid, storage::View::NEW).has_value());
acc2.Commit();
}
auto acc3 = store.Access(); // read transaction
auto acc4 = store.Access(); // write transaction (aborted)
// Check whether the vertex exists in transaction 1
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 3
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value());
// Delete the vertex in transaction 4, but abort the transaction
{
auto vertex = acc4.FindVertex(gid, storage::View::NEW);
ASSERT_TRUE(vertex);
auto res = vertex->Delete();
ASSERT_TRUE(res.IsReturn());
acc4.Abort();
}
auto acc5 = store.Access(); // read transaction
auto acc6 = store.Access(); // write transaction
// Check whether the vertex exists in transaction 1
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 3
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 5
ASSERT_TRUE(acc5.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc5.FindVertex(gid, storage::View::NEW).has_value());
// Delete the vertex in transaction 6
{
auto vertex = acc6.FindVertex(gid, storage::View::NEW);
ASSERT_TRUE(vertex);
auto res = vertex->Delete();
ASSERT_TRUE(res.IsReturn());
acc6.Commit();
}
auto acc7 = store.Access(); // read transaction
// Check whether the vertex exists in transaction 1
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 3
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 5
ASSERT_TRUE(acc5.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc5.FindVertex(gid, storage::View::NEW).has_value());
// Check whether the vertex exists in transaction 7
ASSERT_FALSE(acc7.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_FALSE(acc7.FindVertex(gid, storage::View::NEW).has_value());
// Commit all accessors
acc1.Commit();
acc3.Commit();
acc5.Commit();
acc7.Commit();
}
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageV2, VertexDeleteSerializationError) {
storage::Storage store;
storage::Gid gid =
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
// Create vertex
{
auto acc = store.Access();
auto vertex = acc.CreateVertex();
gid = vertex.Gid();
acc.Commit();
}
auto acc1 = store.Access();
auto acc2 = store.Access();
// Delete vertex in accessor 1
{
auto vertex = acc1.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
{
auto res = vertex->Delete();
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(res.GetReturn());
}
{
auto res = vertex->Delete();
ASSERT_TRUE(res.IsReturn());
ASSERT_FALSE(res.GetReturn());
}
}
// Delete vertex in accessor 2
{
auto vertex = acc2.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
auto res = vertex->Delete();
ASSERT_TRUE(res.IsError());
ASSERT_EQ(res.GetError(), storage::Error::SERIALIZATION_ERROR);
}
// Finalize both accessors
acc1.Commit();
acc2.Abort();
// Check whether the vertex exists
{
auto acc = store.Access();
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_FALSE(vertex);
acc.Commit();
}
}
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageV2, VertexDeleteSpecialCases) {
storage::Storage store;
storage::Gid gid1 =
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
storage::Gid gid2 =
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
// Create vertex and delete it in the same transaction, but abort the
// transaction
{
auto acc = store.Access();
auto vertex = acc.CreateVertex();
gid1 = vertex.Gid();
ASSERT_FALSE(acc.FindVertex(gid1, storage::View::OLD).has_value());
ASSERT_TRUE(acc.FindVertex(gid1, storage::View::NEW).has_value());
auto res = vertex.Delete();
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(res.GetReturn());
acc.Abort();
}
// Create vertex and delete it in the same transaction
{
auto acc = store.Access();
auto vertex = acc.CreateVertex();
gid2 = vertex.Gid();
ASSERT_FALSE(acc.FindVertex(gid2, storage::View::OLD).has_value());
ASSERT_TRUE(acc.FindVertex(gid2, storage::View::NEW).has_value());
auto res = vertex.Delete();
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(res.GetReturn());
acc.Commit();
}
// Check whether the vertices exist
{
auto acc = store.Access();
ASSERT_FALSE(acc.FindVertex(gid1, storage::View::OLD).has_value());
ASSERT_FALSE(acc.FindVertex(gid1, storage::View::NEW).has_value());
ASSERT_FALSE(acc.FindVertex(gid2, storage::View::OLD).has_value());
ASSERT_FALSE(acc.FindVertex(gid2, storage::View::NEW).has_value());
acc.Abort();
}
}
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageV2, VertexDeleteLabel) {
storage::Storage store;
storage::Gid gid =
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
// Create the vertex
{
auto acc = store.Access();
auto vertex = acc.CreateVertex();
gid = vertex.Gid();
ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value());
ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value());
acc.Commit();
}
// Add label, delete the vertex and check the label API (same command)
{
auto acc = store.Access();
auto vertex = acc.FindVertex(gid, storage::View::NEW);
ASSERT_TRUE(vertex);
// Check whether label 5 exists
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
// Add label 5
ASSERT_TRUE(vertex->AddLabel(5).GetReturn());
// Check whether label 5 exists
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
{
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
// Delete the vertex
ASSERT_TRUE(vertex->Delete().GetReturn());
// Check whether label 5 exists
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_EQ(vertex->HasLabel(5, storage::View::NEW).GetError(),
storage::Error::DELETED_OBJECT);
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetError(),
storage::Error::DELETED_OBJECT);
// Try to add the label
{
auto ret = vertex->AddLabel(5);
ASSERT_TRUE(ret.IsError());
ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT);
}
// Try to remove the label
{
auto ret = vertex->RemoveLabel(5);
ASSERT_TRUE(ret.IsError());
ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT);
}
acc.Abort();
}
// Add label, delete the vertex and check the label API (different command)
{
auto acc = store.Access();
auto vertex = acc.FindVertex(gid, storage::View::NEW);
ASSERT_TRUE(vertex);
// Check whether label 5 exists
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
// Add label 5
ASSERT_TRUE(vertex->AddLabel(5).GetReturn());
// Check whether label 5 exists
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
{
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
// Advance command
acc.AdvanceCommand();
// Check whether label 5 exists
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
{
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
{
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
// Delete the vertex
ASSERT_TRUE(vertex->Delete().GetReturn());
// Check whether label 5 exists
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_EQ(vertex->HasLabel(5, storage::View::NEW).GetError(),
storage::Error::DELETED_OBJECT);
{
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetError(),
storage::Error::DELETED_OBJECT);
// Advance command
acc.AdvanceCommand();
// Check whether label 5 exists
ASSERT_EQ(vertex->HasLabel(5, storage::View::OLD).GetError(),
storage::Error::DELETED_OBJECT);
ASSERT_EQ(vertex->HasLabel(5, storage::View::NEW).GetError(),
storage::Error::DELETED_OBJECT);
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetError(),
storage::Error::DELETED_OBJECT);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetError(),
storage::Error::DELETED_OBJECT);
// Try to add the label
{
auto ret = vertex->AddLabel(5);
ASSERT_TRUE(ret.IsError());
ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT);
}
// Try to remove the label
{
auto ret = vertex->RemoveLabel(5);
ASSERT_TRUE(ret.IsError());
ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT);
}
acc.Abort();
}
}
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageV2, VertexLabelCommit) {
storage::Storage store;
@ -184,18 +606,18 @@ TEST(StorageV2, VertexLabelCommit) {
auto vertex = acc.CreateVertex();
gid = vertex.Gid();
ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex.Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0);
{
auto res = vertex.AddLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(*res.GetReturn());
ASSERT_TRUE(res.GetReturn());
}
ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW));
ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
{
auto labels = vertex.Labels(storage::View::NEW);
auto labels = vertex.Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
@ -203,7 +625,7 @@ TEST(StorageV2, VertexLabelCommit) {
{
auto res = vertex.AddLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_FALSE(*res.GetReturn());
ASSERT_FALSE(res.GetReturn());
}
acc.Commit();
@ -213,22 +635,22 @@ TEST(StorageV2, VertexLabelCommit) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
{
auto labels = vertex->Labels(storage::View::OLD);
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
{
auto labels = vertex->Labels(storage::View::NEW);
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn());
acc.Abort();
}
@ -240,23 +662,23 @@ TEST(StorageV2, VertexLabelCommit) {
{
auto res = vertex->RemoveLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(*res.GetReturn());
ASSERT_TRUE(res.GetReturn());
}
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
{
auto labels = vertex->Labels(storage::View::OLD);
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
{
auto res = vertex->RemoveLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_FALSE(*res.GetReturn());
ASSERT_FALSE(res.GetReturn());
}
acc.Commit();
@ -266,13 +688,13 @@ TEST(StorageV2, VertexLabelCommit) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::OLD).size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn());
acc.Abort();
}
@ -298,18 +720,18 @@ TEST(StorageV2, VertexLabelAbort) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
{
auto res = vertex->AddLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(*res.GetReturn());
ASSERT_TRUE(res.GetReturn());
}
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
{
auto labels = vertex->Labels(storage::View::NEW);
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
@ -317,7 +739,7 @@ TEST(StorageV2, VertexLabelAbort) {
{
auto res = vertex->AddLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_FALSE(*res.GetReturn());
ASSERT_FALSE(res.GetReturn());
}
acc.Abort();
@ -329,13 +751,13 @@ TEST(StorageV2, VertexLabelAbort) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::OLD).size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn());
acc.Abort();
}
@ -346,18 +768,18 @@ TEST(StorageV2, VertexLabelAbort) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
{
auto res = vertex->AddLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(*res.GetReturn());
ASSERT_TRUE(res.GetReturn());
}
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
{
auto labels = vertex->Labels(storage::View::NEW);
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
@ -365,7 +787,7 @@ TEST(StorageV2, VertexLabelAbort) {
{
auto res = vertex->AddLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_FALSE(*res.GetReturn());
ASSERT_FALSE(res.GetReturn());
}
acc.Commit();
@ -377,22 +799,22 @@ TEST(StorageV2, VertexLabelAbort) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
{
auto labels = vertex->Labels(storage::View::OLD);
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
{
auto labels = vertex->Labels(storage::View::NEW);
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn());
acc.Abort();
}
@ -406,23 +828,23 @@ TEST(StorageV2, VertexLabelAbort) {
{
auto res = vertex->RemoveLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(*res.GetReturn());
ASSERT_TRUE(res.GetReturn());
}
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
{
auto labels = vertex->Labels(storage::View::OLD);
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
{
auto res = vertex->RemoveLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_FALSE(*res.GetReturn());
ASSERT_FALSE(res.GetReturn());
}
acc.Abort();
@ -434,22 +856,22 @@ TEST(StorageV2, VertexLabelAbort) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
{
auto labels = vertex->Labels(storage::View::OLD);
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
{
auto labels = vertex->Labels(storage::View::NEW);
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn());
acc.Abort();
}
@ -463,23 +885,23 @@ TEST(StorageV2, VertexLabelAbort) {
{
auto res = vertex->RemoveLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(*res.GetReturn());
ASSERT_TRUE(res.GetReturn());
}
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
{
auto labels = vertex->Labels(storage::View::OLD);
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 5);
}
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
{
auto res = vertex->RemoveLabel(5);
ASSERT_TRUE(res.IsReturn());
ASSERT_FALSE(*res.GetReturn());
ASSERT_FALSE(res.GetReturn());
}
acc.Commit();
@ -491,13 +913,13 @@ TEST(StorageV2, VertexLabelAbort) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::OLD).size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn());
acc.Abort();
}
@ -523,26 +945,26 @@ TEST(StorageV2, VertexLabelSerializationError) {
auto vertex = acc1.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(1, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::OLD).size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(1, storage::View::NEW).GetReturn());
ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
{
auto res = vertex->AddLabel(1);
ASSERT_TRUE(res.IsReturn());
ASSERT_TRUE(*res.GetReturn());
ASSERT_TRUE(res.GetReturn());
}
ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD));
ASSERT_TRUE(vertex->HasLabel(1, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::OLD).size(), 0);
ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD).GetReturn());
ASSERT_TRUE(vertex->HasLabel(1, storage::View::NEW).GetReturn());
ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
{
auto labels = vertex->Labels(storage::View::NEW);
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 1);
}
@ -550,7 +972,7 @@ TEST(StorageV2, VertexLabelSerializationError) {
{
auto res = vertex->AddLabel(1);
ASSERT_TRUE(res.IsReturn());
ASSERT_FALSE(*res.GetReturn());
ASSERT_FALSE(res.GetReturn());
}
}
@ -559,12 +981,12 @@ TEST(StorageV2, VertexLabelSerializationError) {
auto vertex = acc2.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(1, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW));
ASSERT_EQ(vertex->Labels(storage::View::OLD).size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).size(), 0);
ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(1, storage::View::NEW).GetReturn());
ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW).GetReturn());
ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0);
ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0);
{
auto res = vertex->AddLabel(1);
@ -583,18 +1005,18 @@ TEST(StorageV2, VertexLabelSerializationError) {
auto vertex = acc.FindVertex(gid, storage::View::OLD);
ASSERT_TRUE(vertex);
ASSERT_TRUE(vertex->HasLabel(1, storage::View::OLD));
ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD));
ASSERT_TRUE(vertex->HasLabel(1, storage::View::OLD).GetReturn());
ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD).GetReturn());
{
auto labels = vertex->Labels(storage::View::OLD);
auto labels = vertex->Labels(storage::View::OLD).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 1);
}
ASSERT_TRUE(vertex->HasLabel(1, storage::View::NEW));
ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW));
ASSERT_TRUE(vertex->HasLabel(1, storage::View::NEW).GetReturn());
ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW).GetReturn());
{
auto labels = vertex->Labels(storage::View::NEW);
auto labels = vertex->Labels(storage::View::NEW).GetReturn();
ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], 1);
}