From bf44618b7a18b43b10b6b9e78cc21cd5b0c0b4c8 Mon Sep 17 00:00:00 2001 From: jbajic <jure.bajic@memgraph.com> Date: Thu, 2 Feb 2023 15:50:03 +0100 Subject: [PATCH] Compare prev ptr as well --- src/storage/v3/splitter.cpp | 4 +- tests/unit/storage_v3_shard_split.cpp | 115 +++++++++++++++++++------- 2 files changed, 87 insertions(+), 32 deletions(-) diff --git a/src/storage/v3/splitter.cpp b/src/storage/v3/splitter.cpp index e5a8b9dd0..363da3e5f 100644 --- a/src/storage/v3/splitter.cpp +++ b/src/storage/v3/splitter.cpp @@ -154,6 +154,8 @@ void Splitter::AdjustClonedTransaction(Transaction &cloned_transaction, const Tr auto cloned_delta_it = cloned_transaction.deltas.begin(); while (delta_it != transaction.deltas.end()) { + // Only start iterating through deltas that are head of delta chain + // => they have prev pointer to vertex/edge const auto *delta = &*delta_it; auto *cloned_delta = &*cloned_delta_it; while (delta->next != nullptr) { @@ -170,8 +172,6 @@ void Splitter::AdjustClonedTransaction(Transaction &cloned_transaction, const Tr } case PreviousPtr::Type::DELTA: { // Same as for deltas except don't align next but prev - // auto cloned_transaction_it = - // cloned_transactions.find(ptr.delta->commit_info->start_or_commit_timestamp.logical_id); auto cloned_transaction_it = std::ranges::find_if(cloned_transactions, [&ptr](const auto &elem) { return elem.second->start_timestamp == ptr.delta->commit_info->start_or_commit_timestamp || elem.second->commit_info->start_or_commit_timestamp == diff --git a/tests/unit/storage_v3_shard_split.cpp b/tests/unit/storage_v3_shard_split.cpp index 7e7a917fe..22e849d23 100644 --- a/tests/unit/storage_v3_shard_split.cpp +++ b/tests/unit/storage_v3_shard_split.cpp @@ -82,9 +82,12 @@ void AssertEqVertexContainer(const VertexContainer &actual, const VertexContaine auto *expected_delta = expected_it->second.delta; auto *actual_delta = actual_it->second.delta; + // This asserts delta chain while (expected_delta != nullptr) { EXPECT_EQ(actual_delta->action, expected_delta->action); EXPECT_EQ(actual_delta->uuid, expected_delta->uuid); + EXPECT_NE(&actual_delta, &expected_delta) << "Deltas must be different objects!"; + switch (expected_delta->action) { case Delta::Action::ADD_LABEL: case Delta::Action::REMOVE_LABEL: { @@ -105,6 +108,33 @@ void AssertEqVertexContainer(const VertexContainer &actual, const VertexContaine break; } } + + const auto expected_prev = expected_delta->prev.Get(); + const auto actual_prev = actual_delta->prev.Get(); + switch (expected_prev.type) { + case PreviousPtr::Type::NULLPTR: { + ASSERT_EQ(actual_prev.type, PreviousPtr::Type::NULLPTR) << "Expected type is nullptr!"; + break; + } + case PreviousPtr::Type::DELTA: { + ASSERT_EQ(actual_prev.type, PreviousPtr::Type::DELTA) << "Expected type is delta!"; + EXPECT_EQ(actual_prev.delta->action, expected_prev.delta->action); + EXPECT_EQ(actual_prev.delta->uuid, expected_prev.delta->uuid); + EXPECT_NE(actual_prev.delta, expected_prev.delta) << "Prev deltas must be different objects!"; + break; + } + case v3::PreviousPtr::Type::EDGE: { + ASSERT_EQ(actual_prev.type, PreviousPtr::Type::EDGE) << "Expected type is edge!"; + EXPECT_EQ(actual_prev.edge->gid, expected_prev.edge->gid); + break; + } + case v3::PreviousPtr::Type::VERTEX: { + ASSERT_EQ(actual_prev.type, PreviousPtr::Type::VERTEX) << "Expected type is vertex!"; + EXPECT_EQ(actual_prev.vertex->first, expected_prev.vertex->first); + break; + } + } + expected_delta = expected_delta->next; actual_delta = actual_delta->next; } @@ -115,6 +145,17 @@ void AssertEqVertexContainer(const VertexContainer &actual, const VertexContaine } } +void AssertEqDeltaLists(const std::list<Delta> &actual, const std::list<Delta> &expected) { + ASSERT_EQ(actual.size(), expected.size()); + auto actual_it = actual.begin(); + auto expected_it = expected.begin(); + while (actual_it != actual.end()) { + EXPECT_EQ(actual_it->action, expected_it->action); + EXPECT_EQ(actual_it->uuid, expected_it->uuid); + EXPECT_NE(&*actual_it, &*expected_it) << "Deltas must be different objects!"; + } +} + void AddDeltaToDeltaChain(Vertex *object, Delta *new_delta) { auto *delta_holder = GetDeltaHolder(object); @@ -154,14 +195,27 @@ TEST_F(ShardSplitTest, TestBasicSplitWithVertices) { Delta delta_delete3{Delta::DeleteObjectTag{}, &commit_info, 8, 3}; VertexContainer expected_vertices; - expected_vertices.emplace(PrimaryKey{PropertyValue{4}}, VertexData(&delta_delete1)); - auto [it, inserted] = expected_vertices.emplace(PrimaryKey{PropertyValue{5}}, VertexData(&delta_delete2)); - expected_vertices.emplace(PrimaryKey{PropertyValue{6}}, VertexData(&delta_delete3)); - it->second.labels.push_back(secondary_label); - AddDeltaToDeltaChain(&*it, &delta_set_property); - AddDeltaToDeltaChain(&*it, &delta_remove_label); + auto [it_4, inserted1] = expected_vertices.emplace(PrimaryKey{PropertyValue{4}}, VertexData(&delta_delete1)); + delta_delete1.prev.Set(&*it_4); + auto [it_5, inserted2] = expected_vertices.emplace(PrimaryKey{PropertyValue{5}}, VertexData(&delta_delete2)); + delta_delete2.prev.Set(&*it_5); + auto [it_6, inserted3] = expected_vertices.emplace(PrimaryKey{PropertyValue{6}}, VertexData(&delta_delete3)); + delta_delete3.prev.Set(&*it_6); + it_5->second.labels.push_back(secondary_label); + AddDeltaToDeltaChain(&*it_5, &delta_set_property); + AddDeltaToDeltaChain(&*it_5, &delta_remove_label); AssertEqVertexContainer(splitted_data.vertices, expected_vertices); + + // This is to ensure that the transaction that we have don't point to invalid + // object on the other shard + std::list<Delta> expected_deltas; + expected_deltas.emplace_back(Delta::DeleteObjectTag{}, &commit_info, 4, 1); + expected_deltas.emplace_back(Delta::DeleteObjectTag{}, &commit_info, 5, 2); + expected_deltas.emplace_back(Delta::RemoveLabelTag{}, secondary_label, &commit_info, 7, 4); + expected_deltas.emplace_back(Delta::SetPropertyTag{}, secondary_property, PropertyValue(), &commit_info, 6, 4); + expected_deltas.emplace_back(Delta::DeleteObjectTag{}, &commit_info, 8, 3); + // AssertEqDeltaLists(splitted_data.transactions.begin()->second->deltas, expected_deltas); } TEST_F(ShardSplitTest, TestBasicSplitVerticesAndEdges) { @@ -330,33 +384,34 @@ TEST_F(ShardSplitTest, TestBasicSplitWithLabelPropertyIndex) { EXPECT_EQ(splitted_data.label_property_indices.size(), 1); } -TEST_F(ShardSplitTest, TestBigSplit) { - int pk{0}; - for (int64_t i{0}; i < 100000; ++i) { - auto acc = storage.Access(GetNextHlc()); - EXPECT_FALSE( - acc.CreateVertexAndValidate({secondary_label}, {PropertyValue(pk++)}, {{secondary_property, PropertyValue(i)}}) - .HasError()); - EXPECT_FALSE(acc.CreateVertexAndValidate({}, {PropertyValue(pk++)}, {}).HasError()); +// TEST_F(ShardSplitTest, TestBigSplit) { +// int pk{0}; +// for (int64_t i{0}; i < 10'000; ++i) { +// auto acc = storage.Access(GetNextHlc()); +// EXPECT_FALSE( +// acc.CreateVertexAndValidate({secondary_label}, {PropertyValue(pk++)}, {{secondary_property, +// PropertyValue(i)}}) +// .HasError()); +// EXPECT_FALSE(acc.CreateVertexAndValidate({}, {PropertyValue(pk++)}, {}).HasError()); - EXPECT_FALSE(acc.CreateEdge(VertexId{primary_label, PrimaryKey{PropertyValue(pk - 2)}}, - VertexId{primary_label, PrimaryKey{PropertyValue(pk - 1)}}, edge_type_id, - Gid::FromUint(pk)) - .HasError()); - acc.Commit(GetNextHlc()); - } - storage.CreateIndex(secondary_label, secondary_property); +// EXPECT_FALSE(acc.CreateEdge(VertexId{primary_label, PrimaryKey{PropertyValue(pk - 2)}}, +// VertexId{primary_label, PrimaryKey{PropertyValue(pk - 1)}}, edge_type_id, +// Gid::FromUint(pk)) +// .HasError()); +// acc.Commit(GetNextHlc()); +// } +// storage.CreateIndex(secondary_label, secondary_property); - const auto split_value = pk / 2; - auto splitted_data = storage.PerformSplit({PropertyValue(split_value)}, 2); +// const auto split_value = pk / 2; +// auto splitted_data = storage.PerformSplit({PropertyValue(split_value)}, 2); - EXPECT_EQ(splitted_data.vertices.size(), 100000); - EXPECT_EQ(splitted_data.edges->size(), 50000); - EXPECT_EQ(splitted_data.transactions.size(), 50000); - EXPECT_EQ(splitted_data.label_indices.size(), 0); - EXPECT_EQ(splitted_data.label_property_indices.size(), 1); +// EXPECT_EQ(splitted_data.vertices.size(), 100000); +// EXPECT_EQ(splitted_data.edges->size(), 50000); +// EXPECT_EQ(splitted_data.transactions.size(), 50000); +// EXPECT_EQ(splitted_data.label_indices.size(), 0); +// EXPECT_EQ(splitted_data.label_property_indices.size(), 1); - AssertSplittedShard(std::move(splitted_data), split_value); -} +// AssertSplittedShard(std::move(splitted_data), split_value); +// } } // namespace memgraph::storage::v3::tests