From 45922a987ea4f4e4b08ee418fc098ae41a9e69db Mon Sep 17 00:00:00 2001 From: "matej.gradicek" Date: Wed, 12 Jul 2017 12:35:22 +0200 Subject: [PATCH] Implemented label-property index recovery. Reviewers: buda, florijan, teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D530 --- src/database/graph_db_accessor.hpp | 7 +++ src/database/indexes/label_property_index.hpp | 11 ++++ src/durability/recovery.cpp | 13 +++++ src/durability/snapshooter.cpp | 11 +++- tests/unit/recovery.cpp | 50 ++++++++++++++++++- 5 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/database/graph_db_accessor.hpp b/src/database/graph_db_accessor.hpp index 05bbb26bc..2dafc2eab 100644 --- a/src/database/graph_db_accessor.hpp +++ b/src/database/graph_db_accessor.hpp @@ -308,6 +308,13 @@ class GraphDbAccessor { LabelPropertyIndex::Key(label, property)); } + /** + * @brief - Returns vector of keys of label-property indices. + */ + std::vector GetIndicesKeys() { + return db_.label_property_index_.GetIndicesKeys(); + } + /** * Return approximate number of all vertices in the database. * Note that this is always an over-estimate and never an under-estimate. diff --git a/src/database/indexes/label_property_index.hpp b/src/database/indexes/label_property_index.hpp index 9ab8be190..3ece4d070 100644 --- a/src/database/indexes/label_property_index.hpp +++ b/src/database/indexes/label_property_index.hpp @@ -282,6 +282,17 @@ class LabelPropertyIndex { }); } + /** + * @brief - Returns vector of keys of label-property indice. + */ + std::vector GetIndicesKeys() { + std::vector indices; + for (auto index : indices_.access()) { + indices.push_back(index.first); + } + return indices; + } + private: /** * @brief - Contains value, vlist and vertex record to distinguish between diff --git a/src/durability/recovery.cpp b/src/durability/recovery.cpp index 4b5e8ea0e..aba5d3113 100644 --- a/src/durability/recovery.cpp +++ b/src/durability/recovery.cpp @@ -25,6 +25,19 @@ bool Recovery::Decode(const fs::path &snapshot_file, } std::unordered_map vertices; + query::TypedValue tv; + if (!decoder.ReadTypedValue(&tv, query::TypedValue::Type::List)) { + buffer.Close(); + return false; + } + auto &label_property_vector = tv.Value>(); + for (int i = 0; i < label_property_vector.size(); i += 2) { + auto label = label_property_vector[i].Value(); + auto property = label_property_vector[i + 1].Value(); + db_accessor.BuildIndex(db_accessor.label(label), + db_accessor.property(property)); + } + for (int64_t i = 0; i < summary.vertex_num_; ++i) { communication::bolt::DecodedVertex vertex; if (!decoder.ReadVertex(&vertex)) { diff --git a/src/durability/snapshooter.cpp b/src/durability/snapshooter.cpp index 40f819dd5..fa423563d 100644 --- a/src/durability/snapshooter.cpp +++ b/src/durability/snapshooter.cpp @@ -33,8 +33,17 @@ bool Snapshooter::Encode(const fs::path &snapshot_file, // BaseEncoder encodes graph elements. Flag true is for storing vertex IDs. communication::bolt::BaseEncoder encoder(buffer, true); int64_t vertex_num = 0, edge_num = 0; - buffer.Open(snapshot_file); + + std::vector label_property_vector; + for (const auto &key : db_accessor_.GetIndicesKeys()) { + query::TypedValue label(*key.label_); + query::TypedValue property(*key.property_); + label_property_vector.push_back(label); + label_property_vector.push_back(property); + } + encoder.WriteList(label_property_vector); + for (const auto &vertex : db_accessor_.vertices(false)) { encoder.WriteVertex(vertex); vertex_num++; diff --git a/tests/unit/recovery.cpp b/tests/unit/recovery.cpp index 5ceec8433..ee1eb8705 100644 --- a/tests/unit/recovery.cpp +++ b/tests/unit/recovery.cpp @@ -109,9 +109,11 @@ TEST_F(RecoveryTest, TestEncoding) { snapshot::Summary summary; buffer.Open(snapshot, summary); + query::TypedValue tv; + decoder.ReadTypedValue(&tv); + std::vector ids; std::vector edge_types; - for (int i = 0; i < summary.vertex_num_; ++i) { communication::bolt::DecodedVertex vertex; decoder.ReadVertex(&vertex); @@ -228,6 +230,52 @@ TEST_F(RecoveryTest, TestEncodingAndRecovering) { dba_get->commit(); } +TEST_F(RecoveryTest, TestLabelPropertyIndexRecovery) { + // Creates snapshot of the graph with indices. + Dbms dbms; + auto dba = dbms.active(); + dba->BuildIndex(dba->label("label"), dba->property("prop")); + dba->commit(); + CreateBigGraph(dbms); + TakeSnapshot(dbms, max_retained_snapshots_); + std::string snapshot = GetLatestSnapshot(); + + Dbms dbms_recover; + auto dba_recover = dbms_recover.active(); + + Recovery recovery; + EXPECT_TRUE(recovery.Recover(snapshot, *dba_recover)); + + auto dba_get = dbms_recover.active(); + EXPECT_EQ(dba_get->GetIndicesKeys().size(), 1); + EXPECT_TRUE(dba_get->LabelPropertyIndexExists(dba_get->label("label"), + dba_get->property("prop"))); + + int64_t vertex_count = 0; + for (const auto &vertex : dba_get->vertices(false)) { + EXPECT_EQ(vertex.labels().size(), 1); + EXPECT_TRUE(vertex.has_label(dba_get->label("label"))); + query::TypedValue prop = + query::TypedValue(vertex.PropsAt(dba_get->property("prop"))); + query::TypedValue expected_prop = query::TypedValue(PropertyValue("prop")); + EXPECT_TRUE((prop == expected_prop).Value()); + vertex_count++; + } + EXPECT_EQ(vertex_count, 1000); + + int64_t edge_count = 0; + for (const auto &edge : dba_get->edges(false)) { + EXPECT_EQ(edge.edge_type(), dba_get->edge_type("type")); + query::TypedValue prop = + query::TypedValue(edge.PropsAt(dba_get->property("prop"))); + query::TypedValue expected_prop = query::TypedValue(PropertyValue("prop")); + EXPECT_TRUE((prop == expected_prop).Value()); + edge_count++; + } + EXPECT_EQ(edge_count, 999); + dba_get->commit(); +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();