2023-04-25 22:25:25 +08:00
|
|
|
// Copyright 2023 Memgraph Ltd.
|
2021-10-26 14:53:56 +08:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
#include <gmock/gmock.h>
|
|
|
|
#include <gtest/gtest.h>
|
2019-10-29 22:35:57 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <chrono>
|
2020-11-13 03:18:11 +08:00
|
|
|
#include <csignal>
|
2019-10-01 19:42:27 +08:00
|
|
|
#include <filesystem>
|
2019-10-29 22:35:57 +08:00
|
|
|
#include <iostream>
|
2019-10-01 19:42:27 +08:00
|
|
|
#include <thread>
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "storage/v2/durability/marker.hpp"
|
2020-04-17 16:20:47 +08:00
|
|
|
#include "storage/v2/durability/paths.hpp"
|
2020-07-25 00:26:36 +08:00
|
|
|
#include "storage/v2/durability/snapshot.hpp"
|
2020-04-17 16:20:47 +08:00
|
|
|
#include "storage/v2/durability/version.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "storage/v2/durability/wal.hpp"
|
|
|
|
#include "storage/v2/edge_accessor.hpp"
|
|
|
|
#include "storage/v2/inmemory/storage.hpp"
|
|
|
|
#include "storage/v2/vertex_accessor.hpp"
|
2019-10-01 19:42:27 +08:00
|
|
|
#include "utils/file.hpp"
|
2021-01-21 22:47:56 +08:00
|
|
|
#include "utils/logging.hpp"
|
2019-10-29 22:35:57 +08:00
|
|
|
#include "utils/timer.hpp"
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
using testing::Contains;
|
|
|
|
using testing::UnorderedElementsAre;
|
|
|
|
|
|
|
|
class DurabilityTest : public ::testing::TestWithParam<bool> {
|
2019-10-29 22:35:57 +08:00
|
|
|
protected:
|
2019-10-01 19:42:27 +08:00
|
|
|
const uint64_t kNumBaseVertices = 1000;
|
|
|
|
const uint64_t kNumBaseEdges = 10000;
|
|
|
|
const uint64_t kNumExtendedVertices = 100;
|
|
|
|
const uint64_t kNumExtendedEdges = 1000;
|
|
|
|
|
2019-10-29 22:35:57 +08:00
|
|
|
// We don't want to flush the WAL while we are doing operations because the
|
|
|
|
// flushing adds a large overhead that slows down execution.
|
2021-02-18 22:32:43 +08:00
|
|
|
const uint64_t kFlushWalEvery = (kNumBaseVertices + kNumBaseEdges + kNumExtendedVertices + kNumExtendedEdges) * 2;
|
2019-10-29 22:35:57 +08:00
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
enum class DatasetType {
|
|
|
|
ONLY_BASE,
|
|
|
|
ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS,
|
|
|
|
ONLY_EXTENDED,
|
|
|
|
ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS,
|
|
|
|
BASE_WITH_EXTENDED,
|
|
|
|
};
|
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
public:
|
|
|
|
DurabilityTest()
|
2022-02-22 20:33:45 +08:00
|
|
|
: base_vertex_gids_(kNumBaseVertices, memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max())),
|
|
|
|
base_edge_gids_(kNumBaseEdges, memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max())),
|
|
|
|
extended_vertex_gids_(kNumExtendedVertices,
|
|
|
|
memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max())),
|
|
|
|
extended_edge_gids_(kNumExtendedEdges, memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max())) {
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
void SetUp() override { Clear(); }
|
|
|
|
|
|
|
|
void TearDown() override { Clear(); }
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
void CreateBaseDataset(memgraph::storage::Storage *store, bool properties_on_edges) {
|
2019-10-01 19:42:27 +08:00
|
|
|
auto label_indexed = store->NameToLabel("base_indexed");
|
|
|
|
auto label_unindexed = store->NameToLabel("base_unindexed");
|
|
|
|
auto property_id = store->NameToProperty("id");
|
2020-03-06 20:19:08 +08:00
|
|
|
auto property_extra = store->NameToProperty("extra");
|
2019-10-01 19:42:27 +08:00
|
|
|
auto et1 = store->NameToEdgeType("base_et1");
|
|
|
|
auto et2 = store->NameToEdgeType("base_et2");
|
|
|
|
|
|
|
|
// Create label index.
|
2022-08-09 17:29:55 +08:00
|
|
|
ASSERT_FALSE(store->CreateIndex(label_unindexed).HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Create label+property index.
|
2022-08-09 17:29:55 +08:00
|
|
|
ASSERT_FALSE(store->CreateIndex(label_indexed, property_id).HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Create existence constraint.
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(store->CreateExistenceConstraint(label_unindexed, property_id, {}).HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
2020-03-06 20:19:08 +08:00
|
|
|
// Create unique constraint.
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(store->CreateUniqueConstraint(label_unindexed, {property_id, property_extra}, {}).HasError());
|
2020-03-06 20:19:08 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Create vertices.
|
|
|
|
for (uint64_t i = 0; i < kNumBaseVertices; ++i) {
|
|
|
|
auto acc = store->Access();
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex = acc->CreateVertex();
|
2019-10-01 19:42:27 +08:00
|
|
|
base_vertex_gids_[i] = vertex.Gid();
|
|
|
|
if (i < kNumBaseVertices / 2) {
|
|
|
|
ASSERT_TRUE(vertex.AddLabel(label_indexed).HasValue());
|
|
|
|
} else {
|
|
|
|
ASSERT_TRUE(vertex.AddLabel(label_unindexed).HasValue());
|
|
|
|
}
|
|
|
|
if (i < kNumBaseVertices / 3 || i >= kNumBaseVertices / 2) {
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_TRUE(
|
|
|
|
vertex.SetProperty(property_id, memgraph::storage::PropertyValue(static_cast<int64_t>(i))).HasValue());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create edges.
|
|
|
|
for (uint64_t i = 0; i < kNumBaseEdges; ++i) {
|
|
|
|
auto acc = store->Access();
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex1 = acc->FindVertex(base_vertex_gids_[(i / 2) % kNumBaseVertices], memgraph::storage::View::OLD);
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(vertex1);
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex2 = acc->FindVertex(base_vertex_gids_[(i / 3) % kNumBaseVertices], memgraph::storage::View::OLD);
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(vertex2);
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::EdgeTypeId et;
|
2019-10-01 19:42:27 +08:00
|
|
|
if (i < kNumBaseEdges / 2) {
|
|
|
|
et = et1;
|
|
|
|
} else {
|
|
|
|
et = et2;
|
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
auto edgeRes = acc->CreateEdge(&*vertex1, &*vertex2, et);
|
|
|
|
ASSERT_TRUE(edgeRes.HasValue());
|
|
|
|
auto edge = std::move(edgeRes.GetValue());
|
|
|
|
base_edge_gids_[i] = edge.Gid();
|
2019-10-01 19:42:27 +08:00
|
|
|
if (properties_on_edges) {
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_TRUE(
|
2023-06-29 17:44:55 +08:00
|
|
|
edge.SetProperty(property_id, memgraph::storage::PropertyValue(static_cast<int64_t>(i))).HasValue());
|
2019-10-01 19:42:27 +08:00
|
|
|
} else {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto ret = edge.SetProperty(property_id, memgraph::storage::PropertyValue(static_cast<int64_t>(i)));
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(ret.HasError());
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(ret.GetError(), memgraph::storage::Error::PROPERTIES_DISABLED);
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
void CreateExtendedDataset(memgraph::storage::Storage *store, bool single_transaction = false) {
|
2019-10-01 19:42:27 +08:00
|
|
|
auto label_indexed = store->NameToLabel("extended_indexed");
|
|
|
|
auto label_unused = store->NameToLabel("extended_unused");
|
|
|
|
auto property_count = store->NameToProperty("count");
|
|
|
|
auto et3 = store->NameToEdgeType("extended_et3");
|
|
|
|
auto et4 = store->NameToEdgeType("extended_et4");
|
|
|
|
|
|
|
|
// Create label index.
|
2022-08-09 17:29:55 +08:00
|
|
|
ASSERT_FALSE(store->CreateIndex(label_unused).HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Create label+property index.
|
2022-08-09 17:29:55 +08:00
|
|
|
ASSERT_FALSE(store->CreateIndex(label_indexed, property_count).HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Create existence constraint.
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(store->CreateExistenceConstraint(label_unused, property_count, {}).HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
2020-03-06 20:19:08 +08:00
|
|
|
// Create unique constraint.
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(store->CreateUniqueConstraint(label_unused, {property_count}, {}).HasError());
|
2020-03-06 20:19:08 +08:00
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// Storage accessor.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage::Accessor> acc;
|
|
|
|
if (single_transaction) acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Create vertices.
|
|
|
|
for (uint64_t i = 0; i < kNumExtendedVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
if (!single_transaction) acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
auto vertex = acc->CreateVertex();
|
2019-10-01 19:42:27 +08:00
|
|
|
extended_vertex_gids_[i] = vertex.Gid();
|
|
|
|
if (i < kNumExtendedVertices / 2) {
|
|
|
|
ASSERT_TRUE(vertex.AddLabel(label_indexed).HasValue());
|
|
|
|
}
|
|
|
|
if (i < kNumExtendedVertices / 3 || i >= kNumExtendedVertices / 2) {
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_TRUE(vertex.SetProperty(property_count, memgraph::storage::PropertyValue("nandare")).HasValue());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
2019-10-31 23:19:18 +08:00
|
|
|
if (!single_transaction) ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create edges.
|
|
|
|
for (uint64_t i = 0; i < kNumExtendedEdges; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
if (!single_transaction) acc = store->Access();
|
2022-02-22 20:33:45 +08:00
|
|
|
auto vertex1 =
|
|
|
|
acc->FindVertex(extended_vertex_gids_[(i / 5) % kNumExtendedVertices], memgraph::storage::View::NEW);
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(vertex1);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto vertex2 =
|
|
|
|
acc->FindVertex(extended_vertex_gids_[(i / 6) % kNumExtendedVertices], memgraph::storage::View::NEW);
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(vertex2);
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::EdgeTypeId et;
|
2019-10-01 19:42:27 +08:00
|
|
|
if (i < kNumExtendedEdges / 4) {
|
|
|
|
et = et3;
|
|
|
|
} else {
|
|
|
|
et = et4;
|
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
auto edgeRes = acc->CreateEdge(&*vertex1, &*vertex2, et);
|
|
|
|
ASSERT_TRUE(edgeRes.HasValue());
|
|
|
|
auto edge = std::move(edgeRes.GetValue());
|
|
|
|
extended_edge_gids_[i] = edge.Gid();
|
2019-10-31 23:19:18 +08:00
|
|
|
if (!single_transaction) ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
if (single_transaction) ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
void VerifyDataset(memgraph::storage::Storage *store, DatasetType type, bool properties_on_edges,
|
|
|
|
bool verify_info = true) {
|
2019-10-31 23:19:18 +08:00
|
|
|
auto base_label_indexed = store->NameToLabel("base_indexed");
|
|
|
|
auto base_label_unindexed = store->NameToLabel("base_unindexed");
|
|
|
|
auto property_id = store->NameToProperty("id");
|
2020-03-06 20:19:08 +08:00
|
|
|
auto property_extra = store->NameToProperty("extra");
|
2019-10-31 23:19:18 +08:00
|
|
|
auto et1 = store->NameToEdgeType("base_et1");
|
|
|
|
auto et2 = store->NameToEdgeType("base_et2");
|
|
|
|
|
|
|
|
auto extended_label_indexed = store->NameToLabel("extended_indexed");
|
|
|
|
auto extended_label_unused = store->NameToLabel("extended_unused");
|
2019-10-01 19:42:27 +08:00
|
|
|
auto property_count = store->NameToProperty("count");
|
|
|
|
auto et3 = store->NameToEdgeType("extended_et3");
|
|
|
|
auto et4 = store->NameToEdgeType("extended_et4");
|
|
|
|
|
|
|
|
// Verify indices info.
|
|
|
|
{
|
|
|
|
auto info = store->ListAllIndices();
|
2019-10-31 23:19:18 +08:00
|
|
|
switch (type) {
|
|
|
|
case DatasetType::ONLY_BASE:
|
|
|
|
ASSERT_THAT(info.label, UnorderedElementsAre(base_label_unindexed));
|
2021-02-18 22:32:43 +08:00
|
|
|
ASSERT_THAT(info.label_property, UnorderedElementsAre(std::make_pair(base_label_indexed, property_id)));
|
2019-10-31 23:19:18 +08:00
|
|
|
break;
|
|
|
|
case DatasetType::ONLY_EXTENDED:
|
|
|
|
ASSERT_THAT(info.label, UnorderedElementsAre(extended_label_unused));
|
2021-02-18 22:32:43 +08:00
|
|
|
ASSERT_THAT(info.label_property,
|
|
|
|
UnorderedElementsAre(std::make_pair(base_label_indexed, property_id),
|
|
|
|
std::make_pair(extended_label_indexed, property_count)));
|
2019-10-31 23:19:18 +08:00
|
|
|
break;
|
|
|
|
case DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS:
|
|
|
|
case DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS:
|
|
|
|
case DatasetType::BASE_WITH_EXTENDED:
|
2021-02-18 22:32:43 +08:00
|
|
|
ASSERT_THAT(info.label, UnorderedElementsAre(base_label_unindexed, extended_label_unused));
|
|
|
|
ASSERT_THAT(info.label_property,
|
|
|
|
UnorderedElementsAre(std::make_pair(base_label_indexed, property_id),
|
|
|
|
std::make_pair(extended_label_indexed, property_count)));
|
2019-10-31 23:19:18 +08:00
|
|
|
break;
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Verify constraints info.
|
|
|
|
{
|
|
|
|
auto info = store->ListAllConstraints();
|
2019-10-31 23:19:18 +08:00
|
|
|
switch (type) {
|
|
|
|
case DatasetType::ONLY_BASE:
|
2021-02-18 22:32:43 +08:00
|
|
|
ASSERT_THAT(info.existence, UnorderedElementsAre(std::make_pair(base_label_unindexed, property_id)));
|
|
|
|
ASSERT_THAT(info.unique, UnorderedElementsAre(
|
|
|
|
std::make_pair(base_label_unindexed, std::set{property_id, property_extra})));
|
2019-10-31 23:19:18 +08:00
|
|
|
break;
|
|
|
|
case DatasetType::ONLY_EXTENDED:
|
2021-02-18 22:32:43 +08:00
|
|
|
ASSERT_THAT(info.existence, UnorderedElementsAre(std::make_pair(extended_label_unused, property_count)));
|
2020-03-06 20:19:08 +08:00
|
|
|
ASSERT_THAT(info.unique,
|
2021-02-18 22:32:43 +08:00
|
|
|
UnorderedElementsAre(std::make_pair(extended_label_unused, std::set{property_count})));
|
2019-10-31 23:19:18 +08:00
|
|
|
break;
|
|
|
|
case DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS:
|
|
|
|
case DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS:
|
|
|
|
case DatasetType::BASE_WITH_EXTENDED:
|
2021-02-18 22:32:43 +08:00
|
|
|
ASSERT_THAT(info.existence, UnorderedElementsAre(std::make_pair(base_label_unindexed, property_id),
|
|
|
|
std::make_pair(extended_label_unused, property_count)));
|
2020-03-06 20:19:08 +08:00
|
|
|
ASSERT_THAT(info.unique,
|
2021-02-18 22:32:43 +08:00
|
|
|
UnorderedElementsAre(std::make_pair(base_label_unindexed, std::set{property_id, property_extra}),
|
|
|
|
std::make_pair(extended_label_unused, std::set{property_count})));
|
2019-10-31 23:19:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool have_base_dataset = false;
|
|
|
|
bool have_extended_dataset = false;
|
|
|
|
switch (type) {
|
|
|
|
case DatasetType::ONLY_BASE:
|
|
|
|
case DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS:
|
|
|
|
have_base_dataset = true;
|
|
|
|
break;
|
|
|
|
case DatasetType::ONLY_EXTENDED:
|
|
|
|
case DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS:
|
|
|
|
have_extended_dataset = true;
|
|
|
|
break;
|
|
|
|
case DatasetType::BASE_WITH_EXTENDED:
|
|
|
|
have_base_dataset = true;
|
|
|
|
have_extended_dataset = true;
|
|
|
|
break;
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create storage accessor.
|
|
|
|
auto acc = store->Access();
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// Verify base dataset.
|
|
|
|
if (have_base_dataset) {
|
|
|
|
// Verify vertices.
|
|
|
|
for (uint64_t i = 0; i < kNumBaseVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex = acc->FindVertex(base_vertex_gids_[i], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto labels = vertex->Labels(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(labels.HasValue());
|
|
|
|
if (i < kNumBaseVertices / 2) {
|
|
|
|
ASSERT_THAT(*labels, UnorderedElementsAre(base_label_indexed));
|
|
|
|
} else {
|
|
|
|
ASSERT_THAT(*labels, UnorderedElementsAre(base_label_unindexed));
|
|
|
|
}
|
2022-02-22 20:33:45 +08:00
|
|
|
auto properties = vertex->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(properties.HasValue());
|
|
|
|
if (i < kNumBaseVertices / 3 || i >= kNumBaseVertices / 2) {
|
|
|
|
ASSERT_EQ(properties->size(), 1);
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ((*properties)[property_id], memgraph::storage::PropertyValue(static_cast<int64_t>(i)));
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
ASSERT_EQ(properties->size(), 0);
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// Verify edges.
|
|
|
|
for (uint64_t i = 0; i < kNumBaseEdges; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto find_edge = [&](auto &edges) -> std::optional<memgraph::storage::EdgeAccessor> {
|
|
|
|
for (auto &edge : edges) {
|
2019-10-31 23:19:18 +08:00
|
|
|
if (edge.Gid() == base_edge_gids_[i]) {
|
|
|
|
return edge;
|
|
|
|
}
|
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
return {};
|
2019-10-31 23:19:18 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex1 = acc->FindVertex(base_vertex_gids_[(i / 2) % kNumBaseVertices], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex1);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto out_edges = vertex1->OutEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(out_edges.HasValue());
|
|
|
|
auto edge1 = find_edge(*out_edges);
|
|
|
|
ASSERT_TRUE(edge1);
|
|
|
|
if (i < kNumBaseEdges / 2) {
|
|
|
|
ASSERT_EQ(edge1->EdgeType(), et1);
|
|
|
|
} else {
|
|
|
|
ASSERT_EQ(edge1->EdgeType(), et2);
|
|
|
|
}
|
2022-02-22 20:33:45 +08:00
|
|
|
auto properties = edge1->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(properties.HasValue());
|
|
|
|
if (properties_on_edges) {
|
|
|
|
ASSERT_EQ(properties->size(), 1);
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ((*properties)[property_id], memgraph::storage::PropertyValue(static_cast<int64_t>(i)));
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
ASSERT_EQ(properties->size(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex2 = acc->FindVertex(base_vertex_gids_[(i / 3) % kNumBaseVertices], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex2);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto in_edges = vertex2->InEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(in_edges.HasValue());
|
|
|
|
auto edge2 = find_edge(*in_edges);
|
|
|
|
ASSERT_TRUE(edge2);
|
|
|
|
if (i < kNumBaseEdges / 2) {
|
|
|
|
ASSERT_EQ(edge2->EdgeType(), et1);
|
|
|
|
} else {
|
|
|
|
ASSERT_EQ(edge2->EdgeType(), et2);
|
|
|
|
}
|
2022-02-22 20:33:45 +08:00
|
|
|
auto properties = edge2->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(properties.HasValue());
|
|
|
|
if (properties_on_edges) {
|
|
|
|
ASSERT_EQ(properties->size(), 1);
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ((*properties)[property_id], memgraph::storage::PropertyValue(static_cast<int64_t>(i)));
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
ASSERT_EQ(properties->size(), 0);
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// Verify label indices.
|
2019-10-01 19:42:27 +08:00
|
|
|
{
|
2022-02-22 20:33:45 +08:00
|
|
|
std::vector<memgraph::storage::VertexAccessor> vertices;
|
2019-10-31 23:19:18 +08:00
|
|
|
vertices.reserve(kNumBaseVertices / 2);
|
2023-06-29 17:44:55 +08:00
|
|
|
for (auto vertex : acc->Vertices(base_label_unindexed, memgraph::storage::View::OLD)) {
|
2019-10-31 23:19:18 +08:00
|
|
|
vertices.push_back(vertex);
|
|
|
|
}
|
|
|
|
ASSERT_EQ(vertices.size(), kNumBaseVertices / 2);
|
2021-02-18 22:32:43 +08:00
|
|
|
std::sort(vertices.begin(), vertices.end(), [](const auto &a, const auto &b) { return a.Gid() < b.Gid(); });
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t i = 0; i < kNumBaseVertices / 2; ++i) {
|
2021-02-18 22:32:43 +08:00
|
|
|
ASSERT_EQ(vertices[i].Gid(), base_vertex_gids_[kNumBaseVertices / 2 + i]);
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// Verify label+property index.
|
2019-10-01 19:42:27 +08:00
|
|
|
{
|
2022-02-22 20:33:45 +08:00
|
|
|
std::vector<memgraph::storage::VertexAccessor> vertices;
|
2019-10-31 23:19:18 +08:00
|
|
|
vertices.reserve(kNumBaseVertices / 3);
|
2023-06-29 17:44:55 +08:00
|
|
|
for (auto vertex : acc->Vertices(base_label_indexed, property_id, memgraph::storage::View::OLD)) {
|
2019-10-31 23:19:18 +08:00
|
|
|
vertices.push_back(vertex);
|
|
|
|
}
|
|
|
|
ASSERT_EQ(vertices.size(), kNumBaseVertices / 3);
|
2021-02-18 22:32:43 +08:00
|
|
|
std::sort(vertices.begin(), vertices.end(), [](const auto &a, const auto &b) { return a.Gid() < b.Gid(); });
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t i = 0; i < kNumBaseVertices / 3; ++i) {
|
|
|
|
ASSERT_EQ(vertices[i].Gid(), base_vertex_gids_[i]);
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
// Verify vertices.
|
|
|
|
for (uint64_t i = 0; i < kNumBaseVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex = acc->FindVertex(base_vertex_gids_[i], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_FALSE(vertex);
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
|
2021-02-18 22:32:43 +08:00
|
|
|
if (type == DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS) {
|
2019-10-31 23:19:18 +08:00
|
|
|
// Verify label indices.
|
|
|
|
{
|
|
|
|
uint64_t count = 0;
|
2023-06-29 17:44:55 +08:00
|
|
|
auto iterable = acc->Vertices(base_label_unindexed, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
ASSERT_EQ(count, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify label+property index.
|
|
|
|
{
|
|
|
|
uint64_t count = 0;
|
2023-06-29 17:44:55 +08:00
|
|
|
auto iterable = acc->Vertices(base_label_indexed, property_id, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
ASSERT_EQ(count, 0);
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// Verify extended dataset.
|
|
|
|
if (have_extended_dataset) {
|
|
|
|
// Verify vertices.
|
|
|
|
for (uint64_t i = 0; i < kNumExtendedVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex = acc->FindVertex(extended_vertex_gids_[i], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto labels = vertex->Labels(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(labels.HasValue());
|
|
|
|
if (i < kNumExtendedVertices / 2) {
|
|
|
|
ASSERT_THAT(*labels, UnorderedElementsAre(extended_label_indexed));
|
|
|
|
}
|
2022-02-22 20:33:45 +08:00
|
|
|
auto properties = vertex->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(properties.HasValue());
|
|
|
|
if (i < kNumExtendedVertices / 3 || i >= kNumExtendedVertices / 2) {
|
|
|
|
ASSERT_EQ(properties->size(), 1);
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ((*properties)[property_count], memgraph::storage::PropertyValue("nandare"));
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
ASSERT_EQ(properties->size(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify edges.
|
|
|
|
for (uint64_t i = 0; i < kNumExtendedEdges; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto find_edge = [&](auto &edges) -> std::optional<memgraph::storage::EdgeAccessor> {
|
|
|
|
for (auto &edge : edges) {
|
2019-10-31 23:19:18 +08:00
|
|
|
if (edge.Gid() == extended_edge_gids_[i]) {
|
|
|
|
return edge;
|
|
|
|
}
|
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
return {};
|
2019-10-31 23:19:18 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
{
|
2022-02-22 20:33:45 +08:00
|
|
|
auto vertex1 =
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->FindVertex(extended_vertex_gids_[(i / 5) % kNumExtendedVertices], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex1);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto out_edges = vertex1->OutEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(out_edges.HasValue());
|
|
|
|
auto edge1 = find_edge(*out_edges);
|
|
|
|
ASSERT_TRUE(edge1);
|
|
|
|
if (i < kNumExtendedEdges / 4) {
|
|
|
|
ASSERT_EQ(edge1->EdgeType(), et3);
|
|
|
|
} else {
|
|
|
|
ASSERT_EQ(edge1->EdgeType(), et4);
|
|
|
|
}
|
2022-02-22 20:33:45 +08:00
|
|
|
auto properties = edge1->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(properties.HasValue());
|
|
|
|
ASSERT_EQ(properties->size(), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2022-02-22 20:33:45 +08:00
|
|
|
auto vertex2 =
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->FindVertex(extended_vertex_gids_[(i / 6) % kNumExtendedVertices], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex2);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto in_edges = vertex2->InEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(in_edges.HasValue());
|
|
|
|
auto edge2 = find_edge(*in_edges);
|
|
|
|
ASSERT_TRUE(edge2);
|
|
|
|
if (i < kNumExtendedEdges / 4) {
|
|
|
|
ASSERT_EQ(edge2->EdgeType(), et3);
|
|
|
|
} else {
|
|
|
|
ASSERT_EQ(edge2->EdgeType(), et4);
|
|
|
|
}
|
2022-02-22 20:33:45 +08:00
|
|
|
auto properties = edge2->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(properties.HasValue());
|
|
|
|
ASSERT_EQ(properties->size(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify label indices.
|
|
|
|
{
|
2022-02-22 20:33:45 +08:00
|
|
|
std::vector<memgraph::storage::VertexAccessor> vertices;
|
2019-10-31 23:19:18 +08:00
|
|
|
vertices.reserve(kNumExtendedVertices / 2);
|
2023-06-29 17:44:55 +08:00
|
|
|
for (auto vertex : acc->Vertices(extended_label_unused, memgraph::storage::View::OLD)) {
|
|
|
|
vertices.emplace_back(vertex);
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
ASSERT_EQ(vertices.size(), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify label+property index.
|
|
|
|
{
|
2022-02-22 20:33:45 +08:00
|
|
|
std::vector<memgraph::storage::VertexAccessor> vertices;
|
2019-10-31 23:19:18 +08:00
|
|
|
vertices.reserve(kNumExtendedVertices / 3);
|
2023-06-29 17:44:55 +08:00
|
|
|
for (auto vertex : acc->Vertices(extended_label_indexed, property_count, memgraph::storage::View::OLD)) {
|
|
|
|
vertices.emplace_back(vertex);
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
ASSERT_EQ(vertices.size(), kNumExtendedVertices / 3);
|
2021-02-18 22:32:43 +08:00
|
|
|
std::sort(vertices.begin(), vertices.end(), [](const auto &a, const auto &b) { return a.Gid() < b.Gid(); });
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t i = 0; i < kNumExtendedVertices / 3; ++i) {
|
|
|
|
ASSERT_EQ(vertices[i].Gid(), extended_vertex_gids_[i]);
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
// Verify vertices.
|
|
|
|
for (uint64_t i = 0; i < kNumExtendedVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex = acc->FindVertex(extended_vertex_gids_[i], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_FALSE(vertex);
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:32:43 +08:00
|
|
|
if (type == DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS) {
|
2019-10-31 23:19:18 +08:00
|
|
|
// Verify label indices.
|
|
|
|
{
|
|
|
|
uint64_t count = 0;
|
2023-06-29 17:44:55 +08:00
|
|
|
auto iterable = acc->Vertices(extended_label_unused, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
ASSERT_EQ(count, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify label+property index.
|
|
|
|
{
|
|
|
|
uint64_t count = 0;
|
2023-06-29 17:44:55 +08:00
|
|
|
auto iterable = acc->Vertices(extended_label_indexed, property_count, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
ASSERT_EQ(count, 0);
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
2019-12-09 22:49:28 +08:00
|
|
|
|
|
|
|
if (verify_info) {
|
|
|
|
auto info = store->GetInfo();
|
|
|
|
if (have_base_dataset) {
|
|
|
|
if (have_extended_dataset) {
|
|
|
|
ASSERT_EQ(info.vertex_count, kNumBaseVertices + kNumExtendedVertices);
|
|
|
|
ASSERT_EQ(info.edge_count, kNumBaseEdges + kNumExtendedEdges);
|
|
|
|
} else {
|
|
|
|
ASSERT_EQ(info.vertex_count, kNumBaseVertices);
|
|
|
|
ASSERT_EQ(info.edge_count, kNumBaseEdges);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (have_extended_dataset) {
|
|
|
|
ASSERT_EQ(info.vertex_count, kNumExtendedVertices);
|
|
|
|
ASSERT_EQ(info.edge_count, kNumExtendedEdges);
|
|
|
|
} else {
|
|
|
|
ASSERT_EQ(info.vertex_count, 0);
|
|
|
|
ASSERT_EQ(info.edge_count, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::filesystem::path> GetSnapshotsList() {
|
2022-02-22 20:33:45 +08:00
|
|
|
return GetFilesList(storage_directory / memgraph::storage::durability::kSnapshotDirectory);
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
2019-10-29 19:50:44 +08:00
|
|
|
std::vector<std::filesystem::path> GetBackupSnapshotsList() {
|
2022-02-22 20:33:45 +08:00
|
|
|
return GetFilesList(storage_directory / memgraph::storage::durability::kBackupDirectory /
|
|
|
|
memgraph::storage::durability::kSnapshotDirectory);
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
|
|
|
|
2019-10-29 22:35:57 +08:00
|
|
|
std::vector<std::filesystem::path> GetWalsList() {
|
2022-02-22 20:33:45 +08:00
|
|
|
return GetFilesList(storage_directory / memgraph::storage::durability::kWalDirectory);
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
2019-10-29 19:50:44 +08:00
|
|
|
std::vector<std::filesystem::path> GetBackupWalsList() {
|
2022-02-22 20:33:45 +08:00
|
|
|
return GetFilesList(storage_directory / memgraph::storage::durability::kBackupDirectory /
|
|
|
|
memgraph::storage::durability::kWalDirectory);
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RestoreBackups() {
|
|
|
|
{
|
|
|
|
auto backup_snapshots = GetBackupSnapshotsList();
|
|
|
|
for (const auto &item : backup_snapshots) {
|
2022-02-22 20:33:45 +08:00
|
|
|
std::filesystem::rename(
|
|
|
|
item, storage_directory / memgraph::storage::durability::kSnapshotDirectory / item.filename());
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto backup_wals = GetBackupWalsList();
|
|
|
|
for (const auto &item : backup_wals) {
|
2022-02-22 20:33:45 +08:00
|
|
|
std::filesystem::rename(item,
|
|
|
|
storage_directory / memgraph::storage::durability::kWalDirectory / item.filename());
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:32:43 +08:00
|
|
|
std::filesystem::path storage_directory{std::filesystem::temp_directory_path() /
|
|
|
|
"MG_test_unit_storage_v2_durability"};
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
private:
|
2021-02-18 22:32:43 +08:00
|
|
|
std::vector<std::filesystem::path> GetFilesList(const std::filesystem::path &path) {
|
2019-10-01 19:42:27 +08:00
|
|
|
std::vector<std::filesystem::path> ret;
|
2019-10-29 22:35:57 +08:00
|
|
|
std::error_code ec; // For exception suppression.
|
|
|
|
for (auto &item : std::filesystem::directory_iterator(path, ec)) {
|
2019-10-01 19:42:27 +08:00
|
|
|
ret.push_back(item.path());
|
|
|
|
}
|
|
|
|
std::sort(ret.begin(), ret.end());
|
|
|
|
std::reverse(ret.begin(), ret.end());
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Clear() {
|
|
|
|
if (!std::filesystem::exists(storage_directory)) return;
|
|
|
|
std::filesystem::remove_all(storage_directory);
|
|
|
|
}
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
std::vector<memgraph::storage::Gid> base_vertex_gids_;
|
|
|
|
std::vector<memgraph::storage::Gid> base_edge_gids_;
|
|
|
|
std::vector<memgraph::storage::Gid> extended_vertex_gids_;
|
|
|
|
std::vector<memgraph::storage::Gid> extended_edge_gids_;
|
2019-10-01 19:42:27 +08:00
|
|
|
};
|
|
|
|
|
2023-04-25 22:25:25 +08:00
|
|
|
void CorruptSnapshot(const std::filesystem::path &path) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto info = memgraph::storage::durability::ReadSnapshotInfo(path);
|
2021-01-21 22:47:56 +08:00
|
|
|
spdlog::info("Destroying snapshot {}", path);
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::utils::OutputFile file;
|
|
|
|
file.Open(path, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING);
|
|
|
|
file.SetPosition(memgraph::utils::OutputFile::Position::SET, info.offset_vertices);
|
|
|
|
auto value = static_cast<uint8_t>(memgraph::storage::durability::Marker::TYPE_MAP);
|
2019-10-31 23:19:18 +08:00
|
|
|
file.Write(&value, sizeof(value));
|
|
|
|
file.Sync();
|
|
|
|
file.Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DestroyWalFirstDelta(const std::filesystem::path &path) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto info = memgraph::storage::durability::ReadWalInfo(path);
|
2021-01-21 22:47:56 +08:00
|
|
|
spdlog::info("Destroying WAL {}", path);
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::utils::OutputFile file;
|
|
|
|
file.Open(path, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING);
|
|
|
|
file.SetPosition(memgraph::utils::OutputFile::Position::SET, info.offset_deltas);
|
|
|
|
auto value = static_cast<uint8_t>(memgraph::storage::durability::Marker::TYPE_MAP);
|
2019-10-31 23:19:18 +08:00
|
|
|
file.Write(&value, sizeof(value));
|
|
|
|
file.Sync();
|
|
|
|
file.Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DestroyWalSuffix(const std::filesystem::path &path) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto info = memgraph::storage::durability::ReadWalInfo(path);
|
2021-01-21 22:47:56 +08:00
|
|
|
spdlog::info("Destroying WAL {}", path);
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::utils::OutputFile file;
|
|
|
|
file.Open(path, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING);
|
|
|
|
ASSERT_LT(info.offset_deltas, file.SetPosition(memgraph::utils::OutputFile::Position::RELATIVE_TO_END, -100));
|
2019-10-31 23:19:18 +08:00
|
|
|
uint8_t value = 0;
|
|
|
|
for (size_t i = 0; i < 100; ++i) {
|
|
|
|
file.Write(&value, sizeof(value));
|
|
|
|
}
|
|
|
|
file.Sync();
|
|
|
|
file.Close();
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:32:43 +08:00
|
|
|
INSTANTIATE_TEST_CASE_P(EdgesWithProperties, DurabilityTest, ::testing::Values(true));
|
|
|
|
INSTANTIATE_TEST_CASE_P(EdgesWithoutProperties, DurabilityTest, ::testing::Values(false));
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, SnapshotOnExit) {
|
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
|
|
|
CreateExtendedDataset(store.get());
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Recover snapshot.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, SnapshotPeriodic) {
|
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-01 19:42:27 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
|
|
|
.durability = {.storage_directory = storage_directory,
|
2022-02-22 20:33:45 +08:00
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT,
|
2023-06-29 17:44:55 +08:00
|
|
|
.snapshot_interval = std::chrono::milliseconds(2000)}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
|
|
|
|
}
|
|
|
|
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Recover snapshot.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, SnapshotFallback) {
|
|
|
|
// Create snapshot.
|
2023-09-08 21:21:35 +08:00
|
|
|
std::size_t number_to_save;
|
2019-10-01 19:42:27 +08:00
|
|
|
{
|
2023-09-08 21:21:35 +08:00
|
|
|
// DEVNOTE_1: assumes that snapshot disk write takes less than this
|
|
|
|
auto const expected_write_time = std::chrono::milliseconds(750);
|
|
|
|
auto const snapshot_interval = std::chrono::milliseconds(3000);
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-01 19:42:27 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-09-08 21:21:35 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT,
|
|
|
|
.snapshot_interval = snapshot_interval,
|
|
|
|
.snapshot_retention_count = 10, // We don't anticipate that we make this many
|
|
|
|
}}));
|
|
|
|
|
|
|
|
auto const ensure_snapshot_is_written = [&](auto &&func) {
|
|
|
|
auto const pre_count = GetSnapshotsList().size();
|
|
|
|
func();
|
|
|
|
// wait long enough to ensure at least one CreateSnapshot has been invoked
|
|
|
|
// DEVNOTE_2: no guarantee that it completed, see DEVNOTE_1
|
|
|
|
std::this_thread::sleep_for(snapshot_interval + expected_write_time);
|
|
|
|
auto const post_count = GetSnapshotsList().size();
|
|
|
|
// validate at least one snapshot has happened...hence must have written the writes from func
|
|
|
|
ASSERT_GT(post_count, pre_count) << "No snapshot exists to capture the last transaction";
|
|
|
|
// TODO: maybe double check by looking at InMemoryStorage's commit log,
|
|
|
|
// its oldest active should be newer than the transaction used when running `func`
|
|
|
|
};
|
|
|
|
|
|
|
|
ensure_snapshot_is_written([&]() { CreateBaseDataset(store.get(), GetParam()); });
|
|
|
|
number_to_save = GetSnapshotsList().size();
|
|
|
|
ensure_snapshot_is_written([&]() { CreateExtendedDataset(store.get()); });
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
2023-08-11 16:18:28 +08:00
|
|
|
// Destroy snapshots.
|
2019-10-01 19:42:27 +08:00
|
|
|
{
|
2023-09-08 21:21:35 +08:00
|
|
|
auto snapshots = GetSnapshotsList();
|
|
|
|
// snapshots order newest first, destroy the newest, preserve number_to_save so that we ONLY_BASE
|
2023-08-11 16:18:28 +08:00
|
|
|
auto it = snapshots.begin();
|
2023-09-08 21:21:35 +08:00
|
|
|
auto const e = snapshots.end() - number_to_save;
|
2023-08-11 16:18:28 +08:00
|
|
|
for (; it != e; ++it) {
|
|
|
|
CorruptSnapshot(*it);
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Recover snapshot.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, SnapshotEverythingCorrupt) {
|
|
|
|
// Create unrelated snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t i = 0; i < 1000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Get unrelated UUID.
|
|
|
|
std::string unrelated_uuid;
|
|
|
|
{
|
|
|
|
auto snapshots = GetSnapshotsList();
|
|
|
|
ASSERT_EQ(snapshots.size(), 1);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto info = memgraph::storage::durability::ReadSnapshotInfo(*snapshots.begin());
|
2019-10-31 23:19:18 +08:00
|
|
|
unrelated_uuid = info.uuid;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
|
|
|
.durability = {.storage_directory = storage_directory,
|
2022-02-22 20:33:45 +08:00
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT,
|
2023-06-29 17:44:55 +08:00
|
|
|
.snapshot_interval = std::chrono::milliseconds(2000)}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
|
2023-06-29 17:44:55 +08:00
|
|
|
CreateExtendedDataset(store.get());
|
2019-10-31 23:19:18 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
|
|
|
|
}
|
|
|
|
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_GE(GetSnapshotsList().size(), 1);
|
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 1);
|
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
|
|
|
|
|
|
|
// Restore unrelated snapshots.
|
|
|
|
RestoreBackups();
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetSnapshotsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Destroy all current snapshots.
|
|
|
|
{
|
|
|
|
auto snapshots = GetSnapshotsList();
|
|
|
|
ASSERT_GE(snapshots.size(), 2);
|
|
|
|
for (const auto &snapshot : snapshots) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto info = memgraph::storage::durability::ReadSnapshotInfo(snapshot);
|
2019-10-31 23:19:18 +08:00
|
|
|
if (info.uuid == unrelated_uuid) {
|
2021-01-21 22:47:56 +08:00
|
|
|
spdlog::info("Skipping snapshot {}", snapshot);
|
2019-10-31 23:19:18 +08:00
|
|
|
continue;
|
|
|
|
}
|
2023-04-25 22:25:25 +08:00
|
|
|
CorruptSnapshot(snapshot);
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recover snapshot.
|
|
|
|
ASSERT_DEATH(
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
},
|
|
|
|
"");
|
|
|
|
}
|
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, SnapshotRetention) {
|
2019-10-29 22:35:57 +08:00
|
|
|
// Create unrelated snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-29 22:35:57 +08:00
|
|
|
for (uint64_t i = 0; i < 1000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_GE(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-01 19:42:27 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
|
|
|
.durability = {.storage_directory = storage_directory,
|
2022-02-22 20:33:45 +08:00
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT,
|
2019-10-01 19:42:27 +08:00
|
|
|
.snapshot_interval = std::chrono::milliseconds(2000),
|
2023-06-29 17:44:55 +08:00
|
|
|
.snapshot_retention_count = 3}}));
|
2019-10-29 19:50:44 +08:00
|
|
|
// Restore unrelated snapshots after the database has been started.
|
|
|
|
RestoreBackups();
|
2023-06-29 17:44:55 +08:00
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
// Allow approximately 5 snapshots to be created.
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
|
|
|
|
}
|
|
|
|
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1 + 3);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
// Verify that exactly 3 snapshots and 1 unrelated snapshot exist.
|
2019-10-01 19:42:27 +08:00
|
|
|
{
|
|
|
|
auto snapshots = GetSnapshotsList();
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(snapshots.size(), 1 + 3);
|
|
|
|
std::string uuid;
|
|
|
|
for (size_t i = 0; i < snapshots.size(); ++i) {
|
|
|
|
const auto &path = snapshots[i];
|
2019-10-01 19:42:27 +08:00
|
|
|
// This shouldn't throw.
|
2022-02-22 20:33:45 +08:00
|
|
|
auto info = memgraph::storage::durability::ReadSnapshotInfo(path);
|
2019-10-29 22:35:57 +08:00
|
|
|
if (i == 0) uuid = info.uuid;
|
|
|
|
if (i < snapshots.size() - 1) {
|
|
|
|
ASSERT_EQ(info.uuid, uuid);
|
|
|
|
} else {
|
|
|
|
ASSERT_NE(info.uuid, uuid);
|
|
|
|
}
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recover snapshot.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
2019-10-31 23:19:18 +08:00
|
|
|
TEST_P(DurabilityTest, SnapshotMixedUUID) {
|
2019-10-01 19:42:27 +08:00
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
|
|
|
CreateExtendedDataset(store.get());
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Recover snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// Create another snapshot.
|
2019-10-01 19:42:27 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 1);
|
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
|
|
|
|
|
|
|
// Restore unrelated snapshot.
|
|
|
|
RestoreBackups();
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Recover snapshot.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
2019-10-01 19:42:27 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-29 19:50:44 +08:00
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, SnapshotBackup) {
|
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-29 19:50:44 +08:00
|
|
|
for (uint64_t i = 0; i < 1000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
|
|
|
|
|
|
|
// Start storage without recovery.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 19:50:44 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
|
|
|
.durability = {.storage_directory = storage_directory,
|
2022-02-22 20:33:45 +08:00
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT,
|
2023-06-29 17:44:55 +08:00
|
|
|
.snapshot_interval = std::chrono::minutes(20)}}));
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 1);
|
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
2021-02-18 22:32:43 +08:00
|
|
|
TEST_F(DurabilityTest, SnapshotWithoutPropertiesOnEdgesRecoveryWithPropertiesOnEdges) {
|
2019-10-31 23:19:18 +08:00
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = false},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
CreateBaseDataset(store.get(), false);
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, false);
|
|
|
|
CreateExtendedDataset(store.get());
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, false);
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover snapshot.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = true},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, false);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
2021-02-18 22:32:43 +08:00
|
|
|
TEST_F(DurabilityTest, SnapshotWithPropertiesOnEdgesRecoveryWithoutPropertiesOnEdges) {
|
2019-10-31 23:19:18 +08:00
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = true},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
CreateBaseDataset(store.get(), true);
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, true);
|
|
|
|
CreateExtendedDataset(store.get());
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, true);
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover snapshot.
|
|
|
|
ASSERT_DEATH(
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = false},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
},
|
|
|
|
"");
|
|
|
|
}
|
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
2021-02-18 22:32:43 +08:00
|
|
|
TEST_F(DurabilityTest, SnapshotWithPropertiesOnEdgesButUnusedRecoveryWithoutPropertiesOnEdges) {
|
2019-10-01 19:42:27 +08:00
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = true},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
CreateBaseDataset(store.get(), true);
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, true);
|
|
|
|
CreateExtendedDataset(store.get());
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, true);
|
2019-10-01 19:42:27 +08:00
|
|
|
// Remove properties from edges.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
for (auto vertex : acc->Vertices(memgraph::storage::View::OLD)) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto in_edges = vertex.InEdges(memgraph::storage::View::OLD);
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(in_edges.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
for (auto &edge : *in_edges) {
|
2019-10-01 19:42:27 +08:00
|
|
|
// TODO (mferencevic): Replace with `ClearProperties()`
|
2022-02-22 20:33:45 +08:00
|
|
|
auto props = edge.Properties(memgraph::storage::View::NEW);
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(props.HasValue());
|
|
|
|
for (const auto &prop : *props) {
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_TRUE(edge.SetProperty(prop.first, memgraph::storage::PropertyValue()).HasValue());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
2022-02-22 20:33:45 +08:00
|
|
|
auto out_edges = vertex.InEdges(memgraph::storage::View::OLD);
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(out_edges.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
for (auto &edge : *out_edges) {
|
2019-10-01 19:42:27 +08:00
|
|
|
// TODO (mferencevic): Replace with `ClearProperties()`
|
2022-02-22 20:33:45 +08:00
|
|
|
auto props = edge.Properties(memgraph::storage::View::NEW);
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(props.HasValue());
|
|
|
|
for (const auto &prop : *props) {
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_TRUE(edge.SetProperty(prop.first, memgraph::storage::PropertyValue()).HasValue());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
2019-10-01 19:42:27 +08:00
|
|
|
// Recover snapshot.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = false},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, false);
|
2019-10-01 19:42:27 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-01 19:42:27 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-01 19:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalBasic) {
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
|
|
|
CreateExtendedDataset(store.get());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-29 19:50:44 +08:00
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalBackup) {
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 19:50:44 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-29 19:50:44 +08:00
|
|
|
for (uint64_t i = 0; i < 1000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
|
|
|
auto num_wals = GetWalsList().size();
|
|
|
|
ASSERT_GE(num_wals, 1);
|
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
|
|
|
|
|
|
|
// Start storage without recovery.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 19:50:44 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
2023-06-29 17:44:55 +08:00
|
|
|
.snapshot_interval = std::chrono::minutes(20)}}));
|
2019-10-29 19:50:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), num_wals);
|
|
|
|
}
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalAppendToExisting) {
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Recover WALs and create more WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.recover_on_startup = true,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateExtendedDataset(store.get());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalCreateInSingleTransaction) {
|
|
|
|
// NOLINTNEXTLINE(readability-isolate-declaration)
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::Gid gid_v1, gid_v2, gid_e1, gid_v3;
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
auto acc = store->Access();
|
|
|
|
auto v1 = acc->CreateVertex();
|
2019-10-29 22:35:57 +08:00
|
|
|
gid_v1 = v1.Gid();
|
2023-06-29 17:44:55 +08:00
|
|
|
auto v2 = acc->CreateVertex();
|
2019-10-29 22:35:57 +08:00
|
|
|
gid_v2 = v2.Gid();
|
2023-06-29 17:44:55 +08:00
|
|
|
auto e1Res = acc->CreateEdge(&v1, &v2, store->NameToEdgeType("e1"));
|
|
|
|
ASSERT_TRUE(e1Res.HasValue());
|
|
|
|
auto e1 = std::move(e1Res.GetValue());
|
|
|
|
gid_e1 = e1.Gid();
|
|
|
|
ASSERT_TRUE(v1.AddLabel(store->NameToLabel("l11")).HasValue());
|
|
|
|
ASSERT_TRUE(v1.AddLabel(store->NameToLabel("l12")).HasValue());
|
|
|
|
ASSERT_TRUE(v1.AddLabel(store->NameToLabel("l13")).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
if (GetParam()) {
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_TRUE(
|
2023-06-29 17:44:55 +08:00
|
|
|
e1.SetProperty(store->NameToProperty("test"), memgraph::storage::PropertyValue("nandare")).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(v2.AddLabel(store->NameToLabel("l21")).HasValue());
|
|
|
|
ASSERT_TRUE(v2.SetProperty(store->NameToProperty("hello"), memgraph::storage::PropertyValue("world")).HasValue());
|
|
|
|
auto v3 = acc->CreateVertex();
|
2019-10-29 22:35:57 +08:00
|
|
|
gid_v3 = v3.Gid();
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(v3.SetProperty(store->NameToProperty("v3"), memgraph::storage::PropertyValue(42)).HasValue());
|
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto indices = store->ListAllIndices();
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(indices.label.size(), 0);
|
|
|
|
ASSERT_EQ(indices.label_property.size(), 0);
|
2023-06-29 17:44:55 +08:00
|
|
|
auto constraints = store->ListAllConstraints();
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(constraints.existence.size(), 0);
|
2020-03-06 20:19:08 +08:00
|
|
|
ASSERT_EQ(constraints.unique.size(), 0);
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto v1 = acc->FindVertex(gid_v1, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(v1);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto labels = v1->Labels(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(labels.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_THAT(*labels, UnorderedElementsAre(store->NameToLabel("l11"), store->NameToLabel("l12"),
|
|
|
|
store->NameToLabel("l13")));
|
2022-02-22 20:33:45 +08:00
|
|
|
auto props = v1->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(props.HasValue());
|
|
|
|
ASSERT_EQ(props->size(), 0);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto in_edges = v1->InEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(in_edges.HasValue());
|
|
|
|
ASSERT_EQ(in_edges->size(), 0);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto out_edges = v1->OutEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(out_edges.HasValue());
|
|
|
|
ASSERT_EQ(out_edges->size(), 1);
|
|
|
|
const auto &edge = (*out_edges)[0];
|
|
|
|
ASSERT_EQ(edge.Gid(), gid_e1);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto edge_props = edge.Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge_props.HasValue());
|
|
|
|
if (GetParam()) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_THAT(*edge_props, UnorderedElementsAre(std::make_pair(store->NameToProperty("test"),
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::PropertyValue("nandare"))));
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
ASSERT_EQ(edge_props->size(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto v2 = acc->FindVertex(gid_v2, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(v2);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto labels = v2->Labels(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(labels.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_THAT(*labels, UnorderedElementsAre(store->NameToLabel("l21")));
|
2022-02-22 20:33:45 +08:00
|
|
|
auto props = v2->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(props.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_THAT(*props, UnorderedElementsAre(std::make_pair(store->NameToProperty("hello"),
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::PropertyValue("world"))));
|
|
|
|
auto in_edges = v2->InEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(in_edges.HasValue());
|
|
|
|
ASSERT_EQ(in_edges->size(), 1);
|
|
|
|
const auto &edge = (*in_edges)[0];
|
|
|
|
ASSERT_EQ(edge.Gid(), gid_e1);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto edge_props = edge.Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge_props.HasValue());
|
|
|
|
if (GetParam()) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_THAT(*edge_props, UnorderedElementsAre(std::make_pair(store->NameToProperty("test"),
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::PropertyValue("nandare"))));
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
ASSERT_EQ(edge_props->size(), 0);
|
|
|
|
}
|
2022-02-22 20:33:45 +08:00
|
|
|
auto out_edges = v2->OutEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(out_edges.HasValue());
|
|
|
|
ASSERT_EQ(out_edges->size(), 0);
|
|
|
|
}
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto v3 = acc->FindVertex(gid_v3, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(v3);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto labels = v3->Labels(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(labels.HasValue());
|
|
|
|
ASSERT_EQ(labels->size(), 0);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto props = v3->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(props.HasValue());
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_THAT(*props, UnorderedElementsAre(
|
2023-06-29 17:44:55 +08:00
|
|
|
std::make_pair(store->NameToProperty("v3"), memgraph::storage::PropertyValue(42))));
|
2022-02-22 20:33:45 +08:00
|
|
|
auto in_edges = v3->InEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(in_edges.HasValue());
|
|
|
|
ASSERT_EQ(in_edges->size(), 0);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto out_edges = v3->OutEdges(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(out_edges.HasValue());
|
|
|
|
ASSERT_EQ(out_edges->size(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalCreateAndRemoveEverything) {
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
|
|
|
CreateExtendedDataset(store.get());
|
|
|
|
auto indices = store->ListAllIndices();
|
2020-03-06 20:19:08 +08:00
|
|
|
for (const auto &index : indices.label) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(store->DropIndex(index).HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2020-03-06 20:19:08 +08:00
|
|
|
for (const auto &index : indices.label_property) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(store->DropIndex(index.first, index.second).HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
auto constraints = store->ListAllConstraints();
|
2020-03-06 20:19:08 +08:00
|
|
|
for (const auto &constraint : constraints.existence) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(store->DropExistenceConstraint(constraint.first, constraint.second, {}).HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2020-03-06 20:19:08 +08:00
|
|
|
for (const auto &constraint : constraints.unique) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_EQ(store->DropUniqueConstraint(constraint.first, constraint.second, {}).GetValue(),
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::UniqueConstraints::DeletionStatus::SUCCESS);
|
2020-03-06 20:19:08 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
for (auto vertex : acc->Vertices(memgraph::storage::View::OLD)) {
|
|
|
|
ASSERT_TRUE(acc->DetachDeleteVertex(&vertex).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto indices = store->ListAllIndices();
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(indices.label.size(), 0);
|
|
|
|
ASSERT_EQ(indices.label_property.size(), 0);
|
2023-06-29 17:44:55 +08:00
|
|
|
auto constraints = store->ListAllConstraints();
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(constraints.existence.size(), 0);
|
2020-03-06 20:19:08 +08:00
|
|
|
ASSERT_EQ(constraints.unique.size(), 0);
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
uint64_t count = 0;
|
2023-06-29 17:44:55 +08:00
|
|
|
auto iterable = acc->Vertices(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
ASSERT_EQ(count, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalTransactionOrdering) {
|
|
|
|
// NOLINTNEXTLINE(readability-isolate-declaration)
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::Gid gid1, gid2, gid3;
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
// Create WAL.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2020-11-13 03:18:11 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
2022-02-22 20:33:45 +08:00
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
2020-11-13 03:18:11 +08:00
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 100000,
|
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery,
|
2023-06-29 17:44:55 +08:00
|
|
|
}}));
|
|
|
|
auto acc1 = store->Access();
|
|
|
|
auto acc2 = store->Access();
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
// Create vertex in transaction 2.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex2 = acc2->CreateVertex();
|
2019-10-29 22:35:57 +08:00
|
|
|
gid2 = vertex2.Gid();
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(vertex2.SetProperty(store->NameToProperty("id"), memgraph::storage::PropertyValue(2)).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc3 = store->Access();
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
// Create vertex in transaction 3.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex3 = acc3->CreateVertex();
|
2019-10-29 22:35:57 +08:00
|
|
|
gid3 = vertex3.Gid();
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(vertex3.SetProperty(store->NameToProperty("id"), memgraph::storage::PropertyValue(3)).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create vertex in transaction 1.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex1 = acc1->CreateVertex();
|
2019-10-29 22:35:57 +08:00
|
|
|
gid1 = vertex1.Gid();
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(vertex1.SetProperty(store->NameToProperty("id"), memgraph::storage::PropertyValue(1)).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Commit transaction 3, then 1, then 2.
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc3->Commit().HasError());
|
|
|
|
ASSERT_FALSE(acc1->Commit().HasError());
|
|
|
|
ASSERT_FALSE(acc2->Commit().HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
// Verify WAL data.
|
|
|
|
{
|
|
|
|
auto path = GetWalsList().front();
|
2022-02-22 20:33:45 +08:00
|
|
|
auto info = memgraph::storage::durability::ReadWalInfo(path);
|
|
|
|
memgraph::storage::durability::Decoder wal;
|
|
|
|
wal.Initialize(path, memgraph::storage::durability::kWalMagic);
|
2019-10-29 22:35:57 +08:00
|
|
|
wal.SetPosition(info.offset_deltas);
|
|
|
|
ASSERT_EQ(info.num_deltas, 9);
|
2022-02-22 20:33:45 +08:00
|
|
|
std::vector<std::pair<uint64_t, memgraph::storage::durability::WalDeltaData>> data;
|
2019-10-29 22:35:57 +08:00
|
|
|
for (uint64_t i = 0; i < info.num_deltas; ++i) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto timestamp = memgraph::storage::durability::ReadWalDeltaHeader(&wal);
|
|
|
|
data.emplace_back(timestamp, memgraph::storage::durability::ReadWalDeltaData(&wal));
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
// Verify timestamps.
|
|
|
|
ASSERT_EQ(data[1].first, data[0].first);
|
|
|
|
ASSERT_EQ(data[2].first, data[1].first);
|
|
|
|
ASSERT_GT(data[3].first, data[2].first);
|
|
|
|
ASSERT_EQ(data[4].first, data[3].first);
|
|
|
|
ASSERT_EQ(data[5].first, data[4].first);
|
|
|
|
ASSERT_GT(data[6].first, data[5].first);
|
|
|
|
ASSERT_EQ(data[7].first, data[6].first);
|
|
|
|
ASSERT_EQ(data[8].first, data[7].first);
|
|
|
|
// Verify transaction 3.
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[0].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_CREATE);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(data[0].second.vertex_create_delete.gid, gid3);
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[1].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_SET_PROPERTY);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(data[1].second.vertex_edge_set_property.gid, gid3);
|
|
|
|
ASSERT_EQ(data[1].second.vertex_edge_set_property.property, "id");
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[1].second.vertex_edge_set_property.value, memgraph::storage::PropertyValue(3));
|
|
|
|
ASSERT_EQ(data[2].second.type, memgraph::storage::durability::WalDeltaData::Type::TRANSACTION_END);
|
2019-10-29 22:35:57 +08:00
|
|
|
// Verify transaction 1.
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[3].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_CREATE);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(data[3].second.vertex_create_delete.gid, gid1);
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[4].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_SET_PROPERTY);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(data[4].second.vertex_edge_set_property.gid, gid1);
|
|
|
|
ASSERT_EQ(data[4].second.vertex_edge_set_property.property, "id");
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[4].second.vertex_edge_set_property.value, memgraph::storage::PropertyValue(1));
|
|
|
|
ASSERT_EQ(data[5].second.type, memgraph::storage::durability::WalDeltaData::Type::TRANSACTION_END);
|
2019-10-29 22:35:57 +08:00
|
|
|
// Verify transaction 2.
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[6].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_CREATE);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(data[6].second.vertex_create_delete.gid, gid2);
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[7].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_SET_PROPERTY);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(data[7].second.vertex_edge_set_property.gid, gid2);
|
|
|
|
ASSERT_EQ(data[7].second.vertex_edge_set_property.property, "id");
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(data[7].second.vertex_edge_set_property.value, memgraph::storage::PropertyValue(2));
|
|
|
|
ASSERT_EQ(data[8].second.type, memgraph::storage::durability::WalDeltaData::Type::TRANSACTION_END);
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
2022-02-22 20:33:45 +08:00
|
|
|
for (auto [gid, id] : std::vector<std::pair<memgraph::storage::Gid, int64_t>>{{gid1, 1}, {gid2, 2}, {gid3, 3}}) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex = acc->FindVertex(gid, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto labels = vertex->Labels(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(labels.HasValue());
|
|
|
|
ASSERT_EQ(labels->size(), 0);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto props = vertex->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(props.HasValue());
|
|
|
|
ASSERT_EQ(props->size(), 1);
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_EQ(props->at(store->NameToProperty("id")), memgraph::storage::PropertyValue(id));
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalCreateAndRemoveOnlyBaseDataset) {
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
|
|
|
CreateExtendedDataset(store.get());
|
|
|
|
auto label_indexed = store->NameToLabel("base_indexed");
|
|
|
|
auto label_unindexed = store->NameToLabel("base_unindexed");
|
|
|
|
auto acc = store->Access();
|
|
|
|
for (auto vertex : acc->Vertices(memgraph::storage::View::OLD)) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto has_indexed = vertex.HasLabel(label_indexed, memgraph::storage::View::OLD);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_TRUE(has_indexed.HasValue());
|
2022-02-22 20:33:45 +08:00
|
|
|
auto has_unindexed = vertex.HasLabel(label_unindexed, memgraph::storage::View::OLD);
|
2019-10-29 22:35:57 +08:00
|
|
|
if (!*has_indexed && !*has_unindexed) continue;
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(acc->DetachDeleteVertex(&vertex).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalDeathResilience) {
|
|
|
|
pid_t pid = fork();
|
|
|
|
if (pid == 0) {
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
2019-10-29 22:35:57 +08:00
|
|
|
// Create one million vertices.
|
|
|
|
for (uint64_t i = 0; i < 1000000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
acc->CreateVertex();
|
|
|
|
MG_ASSERT(!acc->Commit().HasError(), "Couldn't commit transaction!");
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (pid > 0) {
|
|
|
|
// Wait for WALs to be created.
|
|
|
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
|
|
|
int status;
|
|
|
|
EXPECT_EQ(waitpid(pid, &status, WNOHANG), 0);
|
|
|
|
EXPECT_EQ(kill(pid, SIGKILL), 0);
|
|
|
|
EXPECT_EQ(waitpid(pid, &status, 0), pid);
|
|
|
|
EXPECT_NE(status, 0);
|
|
|
|
} else {
|
2021-01-21 22:47:56 +08:00
|
|
|
LOG_FATAL("Couldn't create process to execute test!");
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs and create more WALs.
|
|
|
|
const uint64_t kExtraItems = 1000;
|
|
|
|
uint64_t count = 0;
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2020-11-13 03:18:11 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.recover_on_startup = true,
|
2022-02-22 20:33:45 +08:00
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
2020-11-13 03:18:11 +08:00
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery,
|
2023-06-29 17:44:55 +08:00
|
|
|
}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto iterable = acc->Vertices(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
ASSERT_GT(count, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t i = 0; i < kExtraItems; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
|
|
|
uint64_t current = 0;
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto iterable = acc->Vertices(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
|
|
|
++current;
|
|
|
|
}
|
|
|
|
ASSERT_EQ(count + kExtraItems, current);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
2019-10-31 23:19:18 +08:00
|
|
|
TEST_P(DurabilityTest, WalMissingSecond) {
|
|
|
|
// Create unrelated WALs.
|
2019-10-29 22:35:57 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t i = 0; i < 1000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
uint64_t unrelated_wals = GetWalsList().size();
|
|
|
|
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
const uint64_t kNumVertices = 1000;
|
2022-02-22 20:33:45 +08:00
|
|
|
std::vector<memgraph::storage::Gid> gids;
|
2019-10-31 23:19:18 +08:00
|
|
|
gids.reserve(kNumVertices);
|
|
|
|
for (uint64_t i = 0; i < kNumVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
2019-10-31 23:19:18 +08:00
|
|
|
gids.push_back(vertex.Gid());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
for (uint64_t i = 0; i < kNumVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->FindVertex(gids[i], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex);
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(vertex->SetProperty(store->NameToProperty("nandare"), memgraph::storage::PropertyValue("haihaihai!"))
|
2022-02-22 20:33:45 +08:00
|
|
|
.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
|
|
|
ASSERT_GE(GetBackupWalsList().size(), 1);
|
|
|
|
|
|
|
|
// Restore unrelated WALs.
|
|
|
|
RestoreBackups();
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Remove second WAL.
|
|
|
|
{
|
|
|
|
auto wals = GetWalsList();
|
|
|
|
ASSERT_GT(wals.size(), unrelated_wals + 2);
|
|
|
|
const auto &wal_file = wals[wals.size() - unrelated_wals - 2];
|
2021-01-21 22:47:56 +08:00
|
|
|
spdlog::info("Deleting WAL file {}", wal_file);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(std::filesystem::remove(wal_file));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recover WALs.
|
|
|
|
ASSERT_DEATH(
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
},
|
|
|
|
"");
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalCorruptSecond) {
|
|
|
|
// Create unrelated WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t i = 0; i < 1000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
uint64_t unrelated_wals = GetWalsList().size();
|
|
|
|
|
|
|
|
// Create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
const uint64_t kNumVertices = 1000;
|
2022-02-22 20:33:45 +08:00
|
|
|
std::vector<memgraph::storage::Gid> gids;
|
2019-10-31 23:19:18 +08:00
|
|
|
gids.reserve(kNumVertices);
|
|
|
|
for (uint64_t i = 0; i < kNumVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
2019-10-31 23:19:18 +08:00
|
|
|
gids.push_back(vertex.Gid());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
for (uint64_t i = 0; i < kNumVertices; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->FindVertex(gids[i], memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex);
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(vertex->SetProperty(store->NameToProperty("nandare"), memgraph::storage::PropertyValue("haihaihai!"))
|
2022-02-22 20:33:45 +08:00
|
|
|
.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
|
|
|
ASSERT_GE(GetBackupWalsList().size(), 1);
|
|
|
|
|
|
|
|
// Restore unrelated WALs.
|
|
|
|
RestoreBackups();
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Destroy second WAL.
|
|
|
|
{
|
|
|
|
auto wals = GetWalsList();
|
|
|
|
ASSERT_GT(wals.size(), unrelated_wals + 2);
|
|
|
|
const auto &wal_file = wals[wals.size() - unrelated_wals - 2];
|
|
|
|
DestroyWalFirstDelta(wal_file);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recover WALs.
|
|
|
|
ASSERT_DEATH(
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
},
|
|
|
|
"");
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalCorruptLastTransaction) {
|
|
|
|
// Create WALs
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
|
|
|
CreateExtendedDataset(store.get(), /* single_transaction = */ true);
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Destroy last transaction in the latest WAL.
|
|
|
|
{
|
|
|
|
auto wals = GetWalsList();
|
|
|
|
ASSERT_GE(wals.size(), 2);
|
|
|
|
const auto &wal_file = wals.front();
|
|
|
|
DestroyWalSuffix(wal_file);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
// The extended dataset shouldn't be recovered because its WAL transaction was
|
|
|
|
// corrupt.
|
2023-06-29 17:44:55 +08:00
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalAllOperationsInSingleTransaction) {
|
|
|
|
// Create WALs
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex1 = acc->CreateVertex();
|
|
|
|
auto vertex2 = acc->CreateVertex();
|
|
|
|
ASSERT_TRUE(vertex1.AddLabel(acc->NameToLabel("nandare")).HasValue());
|
|
|
|
ASSERT_TRUE(vertex2.SetProperty(acc->NameToProperty("haihai"), memgraph::storage::PropertyValue(42)).HasValue());
|
|
|
|
ASSERT_TRUE(vertex1.RemoveLabel(acc->NameToLabel("nandare")).HasValue());
|
|
|
|
auto edge1Res = acc->CreateEdge(&vertex1, &vertex2, acc->NameToEdgeType("et1"));
|
|
|
|
ASSERT_TRUE(edge1Res.HasValue());
|
|
|
|
auto edge1 = std::move(edge1Res.GetValue());
|
|
|
|
|
|
|
|
ASSERT_TRUE(vertex2.SetProperty(acc->NameToProperty("haihai"), memgraph::storage::PropertyValue()).HasValue());
|
|
|
|
auto vertex3 = acc->CreateVertex();
|
|
|
|
auto edge2Res = acc->CreateEdge(&vertex3, &vertex3, acc->NameToEdgeType("et2"));
|
|
|
|
ASSERT_TRUE(edge2Res.HasValue());
|
|
|
|
auto edge2 = std::move(edge2Res.GetValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
if (GetParam()) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(edge2.SetProperty(acc->NameToProperty("meaning"), memgraph::storage::PropertyValue(true)).HasValue());
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_TRUE(
|
2023-06-29 17:44:55 +08:00
|
|
|
edge1.SetProperty(acc->NameToProperty("hello"), memgraph::storage::PropertyValue("world")).HasValue());
|
|
|
|
ASSERT_TRUE(edge2.SetProperty(acc->NameToProperty("meaning"), memgraph::storage::PropertyValue()).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(vertex3.AddLabel(acc->NameToLabel("test")).HasValue());
|
|
|
|
ASSERT_TRUE(vertex3.SetProperty(acc->NameToProperty("nonono"), memgraph::storage::PropertyValue(-1)).HasValue());
|
|
|
|
ASSERT_TRUE(vertex3.SetProperty(acc->NameToProperty("nonono"), memgraph::storage::PropertyValue()).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
if (GetParam()) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(edge1.SetProperty(acc->NameToProperty("hello"), memgraph::storage::PropertyValue()).HasValue());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(vertex3.RemoveLabel(acc->NameToLabel("test")).HasValue());
|
|
|
|
ASSERT_TRUE(acc->DetachDeleteVertex(&vertex1).HasValue());
|
|
|
|
ASSERT_TRUE(acc->DeleteEdge(&edge2).HasValue());
|
|
|
|
ASSERT_TRUE(acc->DeleteVertex(&vertex2).HasValue());
|
|
|
|
ASSERT_TRUE(acc->DeleteVertex(&vertex3).HasValue());
|
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
uint64_t count = 0;
|
2023-06-29 17:44:55 +08:00
|
|
|
auto iterable = acc->Vertices(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
ASSERT_EQ(count, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalAndSnapshot) {
|
|
|
|
// Create snapshot and WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::milliseconds(2000),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
2019-10-29 22:35:57 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
|
2023-06-29 17:44:55 +08:00
|
|
|
CreateExtendedDataset(store.get());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_GE(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover snapshot and WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalAndSnapshotAppendToExistingSnapshot) {
|
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
// Recover snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Recover snapshot and create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.recover_on_startup = true,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateExtendedDataset(store.get());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover snapshot and WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalAndSnapshotAppendToExistingSnapshotAndWal) {
|
|
|
|
// Create snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_EQ(GetWalsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover snapshot.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::ONLY_BASE, GetParam());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Recover snapshot and create WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.recover_on_startup = true,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
CreateExtendedDataset(store.get());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover snapshot and WALs and create more WALs.
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::Gid vertex_gid;
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.recover_on_startup = true,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
2019-10-31 23:19:18 +08:00
|
|
|
vertex_gid = vertex.Gid();
|
|
|
|
if (GetParam()) {
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_TRUE(
|
|
|
|
vertex.SetProperty(store->NameToProperty("meaning"), memgraph::storage::PropertyValue(42)).HasValue());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover snapshot and WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam(),
|
2019-12-09 22:49:28 +08:00
|
|
|
/* verify_info = */ false);
|
2019-10-31 23:19:18 +08:00
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->FindVertex(vertex_gid, memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto labels = vertex->Labels(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(labels.HasValue());
|
|
|
|
ASSERT_EQ(labels->size(), 0);
|
2022-02-22 20:33:45 +08:00
|
|
|
auto props = vertex->Properties(memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(props.HasValue());
|
|
|
|
if (GetParam()) {
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_THAT(*props, UnorderedElementsAre(
|
2023-06-29 17:44:55 +08:00
|
|
|
std::make_pair(store->NameToProperty("meaning"), memgraph::storage::PropertyValue(42))));
|
2019-10-31 23:19:18 +08:00
|
|
|
} else {
|
|
|
|
ASSERT_EQ(props->size(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, WalAndSnapshotWalRetention) {
|
|
|
|
// Create unrelated WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::minutes(20),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = kFlushWalEvery}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-29 22:35:57 +08:00
|
|
|
for (uint64_t i = 0; i < 1000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 0);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
|
|
|
|
uint64_t unrelated_wals = GetWalsList().size();
|
|
|
|
|
|
|
|
uint64_t items_created = 0;
|
|
|
|
|
|
|
|
// Create snapshot and WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-29 22:35:57 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
|
|
|
.snapshot_interval = std::chrono::seconds(2),
|
|
|
|
.wal_file_size_kibibytes = 1,
|
2023-06-29 17:44:55 +08:00
|
|
|
.wal_file_flush_every_n_tx = 1}}));
|
2019-10-29 19:50:44 +08:00
|
|
|
// Restore unrelated snapshots after the database has been started.
|
|
|
|
RestoreBackups();
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::utils::Timer timer;
|
2019-10-29 22:35:57 +08:00
|
|
|
// Allow at least 6 snapshots to be created.
|
|
|
|
while (timer.Elapsed().count() < 13.0) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
acc->CreateVertex();
|
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-29 22:35:57 +08:00
|
|
|
++items_created;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQ(GetSnapshotsList().size(), 3);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-29 22:35:57 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), unrelated_wals + 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
auto snapshots = GetSnapshotsList();
|
|
|
|
ASSERT_EQ(snapshots.size(), 3);
|
|
|
|
|
|
|
|
for (uint64_t i = 0; i < snapshots.size(); ++i) {
|
2021-01-21 22:47:56 +08:00
|
|
|
spdlog::info("Recovery attempt {}", i);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover and verify data.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t j = 0; j < items_created; ++j) {
|
2023-06-29 17:44:55 +08:00
|
|
|
auto vertex = acc->FindVertex(memgraph::storage::Gid::FromUint(j), memgraph::storage::View::OLD);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(vertex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Destroy current snapshot.
|
2023-04-25 22:25:25 +08:00
|
|
|
CorruptSnapshot(snapshots[i]);
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Recover data after all of the snapshots have been destroyed. The recovery
|
|
|
|
// shouldn't be possible because the initial WALs are already deleted.
|
|
|
|
ASSERT_DEATH(
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
2019-10-31 23:19:18 +08:00
|
|
|
},
|
|
|
|
"");
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
|
|
|
TEST_P(DurabilityTest, SnapshotAndWalMixedUUID) {
|
|
|
|
// Create unrelated snapshot and WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
2023-06-29 17:44:55 +08:00
|
|
|
.snapshot_interval = std::chrono::seconds(2)}}));
|
|
|
|
auto acc = store->Access();
|
2019-10-31 23:19:18 +08:00
|
|
|
for (uint64_t i = 0; i < 1000; ++i) {
|
2023-06-29 17:44:55 +08:00
|
|
|
acc->CreateVertex();
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_GE(GetSnapshotsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Create snapshot and WALs.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2019-10-31 23:19:18 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2022-02-22 20:33:45 +08:00
|
|
|
.durability = {
|
|
|
|
.storage_directory = storage_directory,
|
|
|
|
.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
|
2023-06-29 17:44:55 +08:00
|
|
|
.snapshot_interval = std::chrono::seconds(2)}}));
|
|
|
|
CreateBaseDataset(store.get(), GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
|
2023-06-29 17:44:55 +08:00
|
|
|
CreateExtendedDataset(store.get());
|
2019-10-31 23:19:18 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
|
|
|
|
}
|
|
|
|
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_GE(GetSnapshotsList().size(), 1);
|
|
|
|
ASSERT_GE(GetBackupSnapshotsList().size(), 1);
|
|
|
|
ASSERT_GE(GetWalsList().size(), 1);
|
|
|
|
ASSERT_GE(GetBackupWalsList().size(), 1);
|
|
|
|
|
|
|
|
// Restore unrelated snapshots and WALs.
|
|
|
|
RestoreBackups();
|
|
|
|
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetSnapshotsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupSnapshotsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_GE(GetWalsList().size(), 2);
|
2019-10-29 19:50:44 +08:00
|
|
|
ASSERT_EQ(GetBackupWalsList().size(), 0);
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Recover snapshot and WALs.
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::InMemoryStorage(
|
2022-02-22 20:33:45 +08:00
|
|
|
{.items = {.properties_on_edges = GetParam()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.durability = {.storage_directory = storage_directory, .recover_on_startup = true}}));
|
|
|
|
VerifyDataset(store.get(), DatasetType::BASE_WITH_EXTENDED, GetParam());
|
2019-10-31 23:19:18 +08:00
|
|
|
|
|
|
|
// Try to use the storage.
|
|
|
|
{
|
2023-06-29 17:44:55 +08:00
|
|
|
auto acc = store->Access();
|
|
|
|
auto vertex = acc->CreateVertex();
|
|
|
|
auto edge = acc->CreateEdge(&vertex, &vertex, store->NameToEdgeType("et"));
|
2019-10-31 23:19:18 +08:00
|
|
|
ASSERT_TRUE(edge.HasValue());
|
2023-06-29 17:44:55 +08:00
|
|
|
ASSERT_FALSE(acc->Commit().HasError());
|
2019-10-31 23:19:18 +08:00
|
|
|
}
|
2019-10-29 22:35:57 +08:00
|
|
|
}
|