2024-01-05 07:18:46 +08:00
|
|
|
// Copyright 2024 Memgraph Ltd.
|
2021-10-03 18:07:04 +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-06-26 22:01:51 +08:00
|
|
|
#pragma once
|
|
|
|
|
2023-10-05 22:58:39 +08:00
|
|
|
#include <chrono>
|
2024-01-23 19:06:10 +08:00
|
|
|
#include <functional>
|
|
|
|
#include <optional>
|
2023-10-05 22:58:39 +08:00
|
|
|
#include <semaphore>
|
2023-03-30 21:34:34 +08:00
|
|
|
#include <span>
|
2023-10-05 22:58:39 +08:00
|
|
|
#include <thread>
|
2019-06-26 22:01:51 +08:00
|
|
|
|
2020-12-03 20:28:23 +08:00
|
|
|
#include "io/network/endpoint.hpp"
|
2022-07-07 19:30:28 +08:00
|
|
|
#include "kvstore/kvstore.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "query/exceptions.hpp"
|
2023-10-10 18:44:19 +08:00
|
|
|
#include "replication/config.hpp"
|
2023-11-06 19:50:49 +08:00
|
|
|
#include "replication/replication_server.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "storage/v2/all_vertices_iterable.hpp"
|
[StorageV2] Implement GC
Summary:
Here are some numbers from the benchmark:
```
(TOOLCHAIN) mtomic@poso:~/memgraph/build_release$ tests/benchmark/storage_v2_gc --num-threads 8
Config: NoGc, Time: 25.9836
Config: OnFinishGc, Time: 49.012
Config: 100msPeriodicGc, Time: 45.9856
Config: 1000msPeriodicGc, Time: 40.3094
```
```
(TOOLCHAIN) mtomic@poso:~/memgraph/build_release$ tests/benchmark/storage_v2_gc --num-threads 7
Config: NoGc, Time: 20.4256
Config: OnFinishGc, Time: 39.6669
Config: 100msPeriodicGc, Time: 30.7956
Config: 1000msPeriodicGc, Time: 35.128
```
It is not that bad if there is a core dedicated to doing garbage collection.
Reviewers: mferencevic, teon.banek
Reviewed By: mferencevic, teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2168
2019-07-09 22:34:23 +08:00
|
|
|
#include "storage/v2/commit_log.hpp"
|
2019-09-23 20:08:48 +08:00
|
|
|
#include "storage/v2/config.hpp"
|
2024-01-23 19:06:10 +08:00
|
|
|
#include "storage/v2/database_access.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "storage/v2/durability/paths.hpp"
|
2020-07-25 00:26:36 +08:00
|
|
|
#include "storage/v2/durability/wal.hpp"
|
2019-07-08 21:10:05 +08:00
|
|
|
#include "storage/v2/edge_accessor.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "storage/v2/indices/indices.hpp"
|
2019-07-08 21:10:05 +08:00
|
|
|
#include "storage/v2/mvcc.hpp"
|
2023-08-25 17:52:07 +08:00
|
|
|
#include "storage/v2/replication/enums.hpp"
|
|
|
|
#include "storage/v2/replication/replication_client.hpp"
|
2023-10-10 18:44:19 +08:00
|
|
|
#include "storage/v2/replication/replication_storage_state.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "storage/v2/storage_error.hpp"
|
2023-04-05 00:46:26 +08:00
|
|
|
#include "storage/v2/storage_mode.hpp"
|
2023-09-11 23:30:54 +08:00
|
|
|
#include "storage/v2/transaction.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "storage/v2/vertices_iterable.hpp"
|
|
|
|
#include "utils/event_counter.hpp"
|
|
|
|
#include "utils/event_histogram.hpp"
|
2023-10-05 22:58:39 +08:00
|
|
|
#include "utils/resource_lock.hpp"
|
[StorageV2] Implement GC
Summary:
Here are some numbers from the benchmark:
```
(TOOLCHAIN) mtomic@poso:~/memgraph/build_release$ tests/benchmark/storage_v2_gc --num-threads 8
Config: NoGc, Time: 25.9836
Config: OnFinishGc, Time: 49.012
Config: 100msPeriodicGc, Time: 45.9856
Config: 1000msPeriodicGc, Time: 40.3094
```
```
(TOOLCHAIN) mtomic@poso:~/memgraph/build_release$ tests/benchmark/storage_v2_gc --num-threads 7
Config: NoGc, Time: 20.4256
Config: OnFinishGc, Time: 39.6669
Config: 100msPeriodicGc, Time: 30.7956
Config: 1000msPeriodicGc, Time: 35.128
```
It is not that bad if there is a core dedicated to doing garbage collection.
Reviewers: mferencevic, teon.banek
Reviewed By: mferencevic, teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2168
2019-07-09 22:34:23 +08:00
|
|
|
#include "utils/scheduler.hpp"
|
2023-11-08 21:43:06 +08:00
|
|
|
#include "utils/synchronized_metadata_store.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "utils/timer.hpp"
|
2020-12-01 23:51:25 +08:00
|
|
|
#include "utils/uuid.hpp"
|
2019-06-26 22:01:51 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
namespace memgraph::metrics {
|
|
|
|
extern const Event SnapshotCreationLatency_us;
|
|
|
|
|
|
|
|
extern const Event ActiveLabelIndices;
|
|
|
|
extern const Event ActiveLabelPropertyIndices;
|
2024-02-18 23:07:03 +08:00
|
|
|
extern const Event ActiveTextIndices;
|
2023-06-29 17:44:55 +08:00
|
|
|
} // namespace memgraph::metrics
|
2020-10-27 17:11:43 +08:00
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
namespace memgraph::storage {
|
2023-06-29 17:44:55 +08:00
|
|
|
struct Transaction;
|
|
|
|
class EdgeAccessor;
|
|
|
|
|
|
|
|
struct IndicesInfo {
|
|
|
|
std::vector<LabelId> label;
|
|
|
|
std::vector<std::pair<LabelId, PropertyId>> label_property;
|
2024-02-10 03:55:25 +08:00
|
|
|
std::vector<std::pair<std::string, LabelId>> text_indices;
|
2023-06-29 17:44:55 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ConstraintsInfo {
|
|
|
|
std::vector<std::pair<LabelId, PropertyId>> existence;
|
|
|
|
std::vector<std::pair<LabelId, std::set<PropertyId>>> unique;
|
|
|
|
};
|
2019-07-22 22:05:44 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
struct StorageInfo {
|
|
|
|
uint64_t vertex_count;
|
|
|
|
uint64_t edge_count;
|
|
|
|
double average_degree;
|
2023-11-03 21:40:45 +08:00
|
|
|
uint64_t memory_res;
|
2023-06-29 17:44:55 +08:00
|
|
|
uint64_t disk_usage;
|
2023-10-16 20:16:00 +08:00
|
|
|
uint64_t label_indices;
|
|
|
|
uint64_t label_property_indices;
|
2024-02-03 19:45:11 +08:00
|
|
|
uint64_t text_indices;
|
2023-10-16 20:16:00 +08:00
|
|
|
uint64_t existence_constraints;
|
|
|
|
uint64_t unique_constraints;
|
|
|
|
StorageMode storage_mode;
|
|
|
|
IsolationLevel isolation_level;
|
|
|
|
bool durability_snapshot_enabled;
|
|
|
|
bool durability_wal_enabled;
|
2023-06-29 17:44:55 +08:00
|
|
|
};
|
|
|
|
|
2023-10-16 20:16:00 +08:00
|
|
|
static inline nlohmann::json ToJson(const StorageInfo &info) {
|
|
|
|
nlohmann::json res;
|
|
|
|
|
|
|
|
res["edges"] = info.edge_count;
|
|
|
|
res["vertices"] = info.vertex_count;
|
2023-11-03 21:40:45 +08:00
|
|
|
res["memory"] = info.memory_res;
|
2023-10-16 20:16:00 +08:00
|
|
|
res["disk"] = info.disk_usage;
|
|
|
|
res["label_indices"] = info.label_indices;
|
|
|
|
res["label_prop_indices"] = info.label_property_indices;
|
2024-02-03 19:45:11 +08:00
|
|
|
res["text_indices"] = info.text_indices;
|
2023-10-16 20:16:00 +08:00
|
|
|
res["existence_constraints"] = info.existence_constraints;
|
|
|
|
res["unique_constraints"] = info.unique_constraints;
|
|
|
|
res["storage_mode"] = storage::StorageModeToString(info.storage_mode);
|
|
|
|
res["isolation_level"] = storage::IsolationLevelToString(info.isolation_level);
|
|
|
|
res["durability"] = {{"snapshot_enabled", info.durability_snapshot_enabled},
|
|
|
|
{"WAL_enabled", info.durability_wal_enabled}};
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2023-09-11 00:53:03 +08:00
|
|
|
struct EdgeInfoForDeletion {
|
|
|
|
std::unordered_set<Gid> partial_src_edge_ids{};
|
|
|
|
std::unordered_set<Gid> partial_dest_edge_ids{};
|
|
|
|
std::unordered_set<Vertex *> partial_src_vertices{};
|
|
|
|
std::unordered_set<Vertex *> partial_dest_vertices{};
|
|
|
|
};
|
|
|
|
|
2024-01-23 19:06:10 +08:00
|
|
|
struct CommitReplArgs {
|
|
|
|
// REPLICA on recipt of Deltas will have a desired commit timestamp
|
|
|
|
std::optional<uint64_t> desired_commit_timestamp = std::nullopt;
|
|
|
|
|
|
|
|
bool is_main = true;
|
|
|
|
|
|
|
|
bool IsMain() { return is_main; }
|
|
|
|
};
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
class Storage {
|
2023-08-31 23:06:44 +08:00
|
|
|
friend class ReplicationServer;
|
2023-11-23 18:02:35 +08:00
|
|
|
friend class ReplicationStorageClient;
|
2023-08-31 23:06:44 +08:00
|
|
|
|
2019-07-29 20:26:31 +08:00
|
|
|
public:
|
2023-06-29 17:44:55 +08:00
|
|
|
Storage(Config config, StorageMode storage_mode);
|
2019-07-22 22:05:44 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
Storage(const Storage &) = delete;
|
|
|
|
Storage(Storage &&) = delete;
|
|
|
|
Storage &operator=(const Storage &) = delete;
|
|
|
|
Storage &operator=(Storage &&) = delete;
|
|
|
|
|
2023-08-25 17:52:07 +08:00
|
|
|
virtual ~Storage() = default;
|
2023-06-29 17:44:55 +08:00
|
|
|
|
2024-01-23 19:06:10 +08:00
|
|
|
const std::string &name() const { return config_.salient.name; }
|
|
|
|
|
|
|
|
const utils::UUID &uuid() const { return config_.salient.uuid; }
|
2023-08-02 00:49:11 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
class Accessor {
|
2019-07-22 22:05:44 +08:00
|
|
|
public:
|
2023-10-05 22:58:39 +08:00
|
|
|
static constexpr struct SharedAccess {
|
|
|
|
} shared_access;
|
|
|
|
static constexpr struct UniqueAccess {
|
|
|
|
} unique_access;
|
|
|
|
|
2023-11-06 19:50:49 +08:00
|
|
|
Accessor(SharedAccess /* tag */, Storage *storage, IsolationLevel isolation_level, StorageMode storage_mode,
|
2024-01-29 22:34:00 +08:00
|
|
|
memgraph::replication_coordination_glue::ReplicationRole replication_role);
|
2023-11-06 19:50:49 +08:00
|
|
|
Accessor(UniqueAccess /* tag */, Storage *storage, IsolationLevel isolation_level, StorageMode storage_mode,
|
2024-01-29 22:34:00 +08:00
|
|
|
memgraph::replication_coordination_glue::ReplicationRole replication_role);
|
2023-06-29 17:44:55 +08:00
|
|
|
Accessor(const Accessor &) = delete;
|
|
|
|
Accessor &operator=(const Accessor &) = delete;
|
|
|
|
Accessor &operator=(Accessor &&other) = delete;
|
2019-07-22 22:05:44 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
Accessor(Accessor &&other) noexcept;
|
2019-07-22 22:05:44 +08:00
|
|
|
|
2023-11-22 21:05:02 +08:00
|
|
|
virtual ~Accessor() = default;
|
2019-07-22 22:05:44 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual VertexAccessor CreateVertex() = 0;
|
2019-07-22 22:05:44 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual std::optional<VertexAccessor> FindVertex(Gid gid, View view) = 0;
|
2019-07-22 22:05:44 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual VerticesIterable Vertices(View view) = 0;
|
2019-07-22 22:05:44 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual VerticesIterable Vertices(LabelId label, View view) = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual VerticesIterable Vertices(LabelId label, PropertyId property, View view) = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual VerticesIterable Vertices(LabelId label, PropertyId property, const PropertyValue &value, View view) = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual VerticesIterable Vertices(LabelId label, PropertyId property,
|
|
|
|
const std::optional<utils::Bound<PropertyValue>> &lower_bound,
|
|
|
|
const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view) = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-09-11 00:53:03 +08:00
|
|
|
virtual Result<std::optional<VertexAccessor>> DeleteVertex(VertexAccessor *vertex);
|
|
|
|
|
|
|
|
virtual Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> DetachDeleteVertex(
|
|
|
|
VertexAccessor *vertex);
|
|
|
|
|
|
|
|
virtual Result<std::optional<std::pair<std::vector<VertexAccessor>, std::vector<EdgeAccessor>>>> DetachDelete(
|
|
|
|
std::vector<VertexAccessor *> nodes, std::vector<EdgeAccessor *> edges, bool detach);
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual uint64_t ApproximateVertexCount() const = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual uint64_t ApproximateVertexCount(LabelId label) const = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual uint64_t ApproximateVertexCount(LabelId label, PropertyId property) const = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual uint64_t ApproximateVertexCount(LabelId label, PropertyId property, const PropertyValue &value) const = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual uint64_t ApproximateVertexCount(LabelId label, PropertyId property,
|
|
|
|
const std::optional<utils::Bound<PropertyValue>> &lower,
|
|
|
|
const std::optional<utils::Bound<PropertyValue>> &upper) const = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual std::optional<storage::LabelIndexStats> GetIndexStats(const storage::LabelId &label) const = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual std::optional<storage::LabelPropertyIndexStats> GetIndexStats(
|
|
|
|
const storage::LabelId &label, const storage::PropertyId &property) const = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual void SetIndexStats(const storage::LabelId &label, const LabelIndexStats &stats) = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual void SetIndexStats(const storage::LabelId &label, const storage::PropertyId &property,
|
|
|
|
const LabelPropertyIndexStats &stats) = 0;
|
2019-07-29 20:26:31 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual std::vector<std::pair<LabelId, PropertyId>> DeleteLabelPropertyIndexStats(
|
2023-10-05 22:58:39 +08:00
|
|
|
const storage::LabelId &label) = 0;
|
2019-09-11 19:22:11 +08:00
|
|
|
|
2023-10-05 22:58:39 +08:00
|
|
|
virtual bool DeleteLabelIndexStats(const storage::LabelId &label) = 0;
|
2019-09-11 19:22:11 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual Result<EdgeAccessor> CreateEdge(VertexAccessor *from, VertexAccessor *to, EdgeTypeId edge_type) = 0;
|
2019-06-26 22:01:51 +08:00
|
|
|
|
2023-12-01 20:38:48 +08:00
|
|
|
virtual std::optional<EdgeAccessor> FindEdge(Gid gid, View view, EdgeTypeId edge_type, VertexAccessor *from_vertex,
|
|
|
|
VertexAccessor *to_vertex) = 0;
|
|
|
|
|
2023-09-08 18:52:40 +08:00
|
|
|
virtual Result<EdgeAccessor> EdgeSetFrom(EdgeAccessor *edge, VertexAccessor *new_from) = 0;
|
|
|
|
|
|
|
|
virtual Result<EdgeAccessor> EdgeSetTo(EdgeAccessor *edge, VertexAccessor *new_to) = 0;
|
|
|
|
|
2023-10-24 23:12:09 +08:00
|
|
|
virtual Result<EdgeAccessor> EdgeChangeType(EdgeAccessor *edge, EdgeTypeId new_edge_type) = 0;
|
|
|
|
|
2023-09-11 00:53:03 +08:00
|
|
|
virtual Result<std::optional<EdgeAccessor>> DeleteEdge(EdgeAccessor *edge);
|
2019-06-26 22:01:51 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual bool LabelIndexExists(LabelId label) const = 0;
|
2019-06-26 22:01:51 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual bool LabelPropertyIndexExists(LabelId label, PropertyId property) const = 0;
|
2019-11-12 17:31:57 +08:00
|
|
|
|
2024-02-10 01:03:20 +08:00
|
|
|
bool TextIndexExists(const std::string &index_name) const {
|
2024-02-10 03:55:25 +08:00
|
|
|
return storage_->indices_.text_index_.IndexExists(index_name);
|
2024-01-10 03:46:30 +08:00
|
|
|
}
|
2024-01-08 07:36:13 +08:00
|
|
|
|
2024-02-19 18:52:30 +08:00
|
|
|
void TextIndexAddVertex(const VertexAccessor &vertex) {
|
|
|
|
storage_->indices_.text_index_.AddNode(vertex.vertex_, storage_->name_id_mapper_.get());
|
2024-02-04 08:09:16 +08:00
|
|
|
}
|
|
|
|
|
2024-02-22 05:44:30 +08:00
|
|
|
void TextIndexUpdateVertex(const VertexAccessor &vertex, const std::vector<LabelId> &removed_labels = {}) {
|
2024-02-19 18:52:30 +08:00
|
|
|
storage_->indices_.text_index_.UpdateNode(vertex.vertex_, storage_->name_id_mapper_.get(), removed_labels);
|
2024-02-08 07:14:06 +08:00
|
|
|
}
|
|
|
|
|
2024-02-10 01:03:20 +08:00
|
|
|
std::vector<Gid> TextIndexSearch(const std::string &index_name, const std::string &search_query) const {
|
2024-02-10 03:55:25 +08:00
|
|
|
return storage_->indices_.text_index_.Search(index_name, search_query);
|
2024-01-10 05:20:35 +08:00
|
|
|
}
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual IndicesInfo ListAllIndices() const = 0;
|
|
|
|
|
|
|
|
virtual ConstraintsInfo ListAllConstraints() const = 0;
|
2019-07-03 21:32:03 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
// NOLINTNEXTLINE(google-default-arguments)
|
2024-01-23 19:06:10 +08:00
|
|
|
virtual utils::BasicResult<StorageManipulationError, void> Commit(CommitReplArgs reparg = {},
|
|
|
|
DatabaseAccessProtector db_acc = {}) = 0;
|
2019-07-03 21:32:03 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual void Abort() = 0;
|
2019-06-26 22:01:51 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
virtual void FinalizeTransaction() = 0;
|
2021-04-23 20:19:42 +08:00
|
|
|
|
2023-03-27 21:46:00 +08:00
|
|
|
std::optional<uint64_t> GetTransactionId() const;
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
void AdvanceCommand();
|
|
|
|
|
|
|
|
const std::string &LabelToName(LabelId label) const { return storage_->LabelToName(label); }
|
2020-10-27 17:11:43 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
const std::string &PropertyToName(PropertyId property) const { return storage_->PropertyToName(property); }
|
2020-10-27 17:11:43 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
const std::string &EdgeTypeToName(EdgeTypeId edge_type) const { return storage_->EdgeTypeToName(edge_type); }
|
|
|
|
|
|
|
|
LabelId NameToLabel(std::string_view name) { return storage_->NameToLabel(name); }
|
|
|
|
|
|
|
|
PropertyId NameToProperty(std::string_view name) { return storage_->NameToProperty(name); }
|
|
|
|
|
2024-02-19 20:56:01 +08:00
|
|
|
std::optional<PropertyId> NameToPropertyIfExists(std::string_view name) const {
|
|
|
|
return storage_->NameToPropertyIfExists(name);
|
|
|
|
}
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
EdgeTypeId NameToEdgeType(std::string_view name) { return storage_->NameToEdgeType(name); }
|
|
|
|
|
2023-12-04 15:32:59 +08:00
|
|
|
StorageMode GetCreationStorageMode() const noexcept;
|
2023-06-29 17:44:55 +08:00
|
|
|
|
2024-01-23 19:06:10 +08:00
|
|
|
const std::string &id() const { return storage_->name(); }
|
2023-08-02 00:49:11 +08:00
|
|
|
|
2023-11-07 19:07:52 +08:00
|
|
|
std::vector<LabelId> ListAllPossiblyPresentVertexLabels() const;
|
2023-11-06 19:37:48 +08:00
|
|
|
|
2023-11-07 19:07:52 +08:00
|
|
|
std::vector<EdgeTypeId> ListAllPossiblyPresentEdgeTypes() const;
|
2023-11-06 19:37:48 +08:00
|
|
|
|
2023-10-05 22:58:39 +08:00
|
|
|
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label) = 0;
|
|
|
|
|
|
|
|
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label, PropertyId property) = 0;
|
|
|
|
|
|
|
|
virtual utils::BasicResult<StorageIndexDefinitionError, void> DropIndex(LabelId label) = 0;
|
|
|
|
|
|
|
|
virtual utils::BasicResult<StorageIndexDefinitionError, void> DropIndex(LabelId label, PropertyId property) = 0;
|
|
|
|
|
2024-02-19 18:52:30 +08:00
|
|
|
void CreateTextIndex(const std::string &index_name, LabelId label, query::DbAccessor *db);
|
2024-01-05 07:18:46 +08:00
|
|
|
|
2024-02-19 18:52:30 +08:00
|
|
|
void DropTextIndex(const std::string &index_name);
|
2024-01-05 07:18:46 +08:00
|
|
|
|
2023-10-05 22:58:39 +08:00
|
|
|
virtual utils::BasicResult<StorageExistenceConstraintDefinitionError, void> CreateExistenceConstraint(
|
|
|
|
LabelId label, PropertyId property) = 0;
|
|
|
|
|
|
|
|
virtual utils::BasicResult<StorageExistenceConstraintDroppingError, void> DropExistenceConstraint(
|
|
|
|
LabelId label, PropertyId property) = 0;
|
|
|
|
|
|
|
|
virtual utils::BasicResult<StorageUniqueConstraintDefinitionError, UniqueConstraints::CreationStatus>
|
|
|
|
CreateUniqueConstraint(LabelId label, const std::set<PropertyId> &properties) = 0;
|
|
|
|
|
|
|
|
virtual UniqueConstraints::DeletionStatus DropUniqueConstraint(LabelId label,
|
|
|
|
const std::set<PropertyId> &properties) = 0;
|
|
|
|
|
2024-02-27 22:45:08 +08:00
|
|
|
auto GetTransaction() -> Transaction * { return std::addressof(transaction_); }
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
protected:
|
2019-06-26 22:01:51 +08:00
|
|
|
Storage *storage_;
|
2023-10-05 22:58:39 +08:00
|
|
|
std::shared_lock<utils::ResourceLock> storage_guard_;
|
|
|
|
std::unique_lock<utils::ResourceLock> unique_guard_; // TODO: Split the accessor into Shared/Unique
|
2019-07-11 19:27:50 +08:00
|
|
|
Transaction transaction_;
|
2021-04-23 20:19:42 +08:00
|
|
|
std::optional<uint64_t> commit_timestamp_;
|
2019-07-11 19:27:50 +08:00
|
|
|
bool is_transaction_active_;
|
2019-06-26 22:01:51 +08:00
|
|
|
|
2023-09-11 00:53:03 +08:00
|
|
|
// Detach delete private methods
|
|
|
|
Result<std::optional<std::unordered_set<Vertex *>>> PrepareDeletableNodes(
|
|
|
|
const std::vector<VertexAccessor *> &vertices);
|
|
|
|
EdgeInfoForDeletion PrepareDeletableEdges(const std::unordered_set<Vertex *> &vertices,
|
|
|
|
const std::vector<EdgeAccessor *> &edges, bool detach) noexcept;
|
|
|
|
Result<std::optional<std::vector<EdgeAccessor>>> ClearEdgesOnVertices(const std::unordered_set<Vertex *> &vertices,
|
|
|
|
std::unordered_set<Gid> &deleted_edge_ids);
|
|
|
|
Result<std::optional<std::vector<EdgeAccessor>>> DetachRemainingEdges(
|
|
|
|
EdgeInfoForDeletion info, std::unordered_set<Gid> &partially_detached_edge_ids);
|
|
|
|
Result<std::vector<VertexAccessor>> TryDeleteVertices(const std::unordered_set<Vertex *> &vertices);
|
|
|
|
void MarkEdgeAsDeleted(Edge *edge);
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
private:
|
|
|
|
StorageMode creation_storage_mode_;
|
|
|
|
};
|
2019-09-11 19:22:11 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
const std::string &LabelToName(LabelId label) const { return name_id_mapper_->IdToName(label.AsUint()); }
|
2019-08-20 20:59:13 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
const std::string &PropertyToName(PropertyId property) const { return name_id_mapper_->IdToName(property.AsUint()); }
|
2019-09-11 19:22:11 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
const std::string &EdgeTypeToName(EdgeTypeId edge_type) const {
|
|
|
|
return name_id_mapper_->IdToName(edge_type.AsUint());
|
|
|
|
}
|
2019-12-09 22:49:28 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
LabelId NameToLabel(const std::string_view name) const { return LabelId::FromUint(name_id_mapper_->NameToId(name)); }
|
2020-11-01 22:15:06 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
PropertyId NameToProperty(const std::string_view name) const {
|
|
|
|
return PropertyId::FromUint(name_id_mapper_->NameToId(name));
|
|
|
|
}
|
2020-12-03 20:28:23 +08:00
|
|
|
|
2024-02-19 20:56:01 +08:00
|
|
|
std::optional<PropertyId> NameToPropertyIfExists(std::string_view name) const {
|
|
|
|
const auto id = name_id_mapper_->NameToIdIfExists(name);
|
|
|
|
if (!id) {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
return PropertyId::FromUint(*id);
|
|
|
|
}
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
EdgeTypeId NameToEdgeType(const std::string_view name) const {
|
|
|
|
return EdgeTypeId::FromUint(name_id_mapper_->NameToId(name));
|
|
|
|
}
|
2020-11-01 22:15:06 +08:00
|
|
|
|
2023-12-04 15:32:59 +08:00
|
|
|
StorageMode GetStorageMode() const noexcept;
|
2020-11-19 21:26:03 +08:00
|
|
|
|
2024-02-27 22:45:08 +08:00
|
|
|
virtual void FreeMemory(std::unique_lock<utils::ResourceLock> main_guard, bool periodic) = 0;
|
2023-08-26 20:16:12 +08:00
|
|
|
|
2024-02-27 22:45:08 +08:00
|
|
|
void FreeMemory() {
|
|
|
|
if (storage_mode_ == StorageMode::IN_MEMORY_ANALYTICAL) {
|
|
|
|
FreeMemory(std::unique_lock{main_lock_}, false);
|
|
|
|
} else {
|
|
|
|
FreeMemory({}, false);
|
|
|
|
}
|
|
|
|
}
|
2020-12-03 20:28:23 +08:00
|
|
|
|
2024-01-29 22:34:00 +08:00
|
|
|
virtual std::unique_ptr<Accessor> Access(memgraph::replication_coordination_glue::ReplicationRole replication_role,
|
2024-01-06 00:42:54 +08:00
|
|
|
std::optional<IsolationLevel> override_isolation_level) = 0;
|
2020-12-03 20:28:23 +08:00
|
|
|
|
2024-01-29 22:34:00 +08:00
|
|
|
std::unique_ptr<Accessor> Access(memgraph::replication_coordination_glue::ReplicationRole replication_role) {
|
2024-01-06 00:42:54 +08:00
|
|
|
return Access(replication_role, {});
|
2023-11-06 19:50:49 +08:00
|
|
|
}
|
2024-01-06 00:42:54 +08:00
|
|
|
|
2024-01-29 22:34:00 +08:00
|
|
|
virtual std::unique_ptr<Accessor> UniqueAccess(
|
|
|
|
memgraph::replication_coordination_glue::ReplicationRole replication_role,
|
|
|
|
std::optional<IsolationLevel> override_isolation_level) = 0;
|
|
|
|
std::unique_ptr<Accessor> UniqueAccess(memgraph::replication_coordination_glue::ReplicationRole replication_role) {
|
2024-01-06 00:42:54 +08:00
|
|
|
return UniqueAccess(replication_role, {});
|
2023-11-06 19:50:49 +08:00
|
|
|
}
|
2020-07-25 00:26:36 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
enum class SetIsolationLevelError : uint8_t { DisabledForAnalyticalMode };
|
2020-11-25 19:08:26 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
utils::BasicResult<SetIsolationLevelError> SetIsolationLevel(IsolationLevel isolation_level);
|
|
|
|
IsolationLevel GetIsolationLevel() const noexcept;
|
2023-06-22 01:08:58 +08:00
|
|
|
|
2024-02-26 22:55:45 +08:00
|
|
|
virtual StorageInfo GetBaseInfo() = 0;
|
2023-10-16 20:16:00 +08:00
|
|
|
|
2024-02-26 22:55:45 +08:00
|
|
|
virtual StorageInfo GetInfo(memgraph::replication_coordination_glue::ReplicationRole replication_role) = 0;
|
2022-07-07 19:30:28 +08:00
|
|
|
|
2024-01-06 00:42:54 +08:00
|
|
|
virtual Transaction CreateTransaction(IsolationLevel isolation_level, StorageMode storage_mode,
|
2024-01-29 22:34:00 +08:00
|
|
|
memgraph::replication_coordination_glue::ReplicationRole replication_role) = 0;
|
2023-08-22 19:29:25 +08:00
|
|
|
|
2023-11-06 19:50:49 +08:00
|
|
|
virtual void PrepareForNewEpoch() = 0;
|
2023-08-25 17:52:07 +08:00
|
|
|
|
2023-11-23 18:02:35 +08:00
|
|
|
auto ReplicasInfo() const { return repl_storage_state_.ReplicasInfo(this); }
|
2023-10-16 15:11:07 +08:00
|
|
|
auto GetReplicaState(std::string_view name) const -> std::optional<replication::ReplicaState> {
|
2023-10-10 18:44:19 +08:00
|
|
|
return repl_storage_state_.GetReplicaState(name);
|
2023-08-31 23:06:44 +08:00
|
|
|
}
|
|
|
|
|
2023-10-10 18:44:19 +08:00
|
|
|
// TODO: make non-public
|
|
|
|
ReplicationStorageState repl_storage_state_;
|
2023-08-31 23:06:44 +08:00
|
|
|
|
2019-07-22 20:01:24 +08:00
|
|
|
// Main storage lock.
|
|
|
|
// Accessors take a shared lock when starting, so it is possible to block
|
2019-08-20 20:59:13 +08:00
|
|
|
// creation of new accessors by taking a unique lock. This is used when doing
|
|
|
|
// operations on storage that affect the global state, for example index
|
|
|
|
// creation.
|
2023-10-05 22:58:39 +08:00
|
|
|
mutable utils::ResourceLock main_lock_;
|
2019-07-22 20:01:24 +08:00
|
|
|
|
2019-12-09 22:49:28 +08:00
|
|
|
// Even though the edge count is already kept in the `edges_` SkipList, the
|
|
|
|
// list is used only when properties are enabled for edges. Because of that we
|
2023-08-29 19:07:23 +08:00
|
|
|
// keep a separate count of edges that is always updated. This counter is also used
|
|
|
|
// for disk storage.
|
2019-12-09 22:49:28 +08:00
|
|
|
std::atomic<uint64_t> edge_count_{0};
|
2019-06-26 22:01:51 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
std::unique_ptr<NameIdMapper> name_id_mapper_;
|
|
|
|
Config config_;
|
2019-07-25 23:11:45 +08:00
|
|
|
|
2019-06-26 22:01:51 +08:00
|
|
|
// Transaction engine
|
2023-11-23 18:02:35 +08:00
|
|
|
mutable utils::SpinLock engine_lock_;
|
2019-06-26 22:01:51 +08:00
|
|
|
uint64_t timestamp_{kTimestampInitialId};
|
|
|
|
uint64_t transaction_id_{kTransactionInitialId};
|
[StorageV2] Implement GC
Summary:
Here are some numbers from the benchmark:
```
(TOOLCHAIN) mtomic@poso:~/memgraph/build_release$ tests/benchmark/storage_v2_gc --num-threads 8
Config: NoGc, Time: 25.9836
Config: OnFinishGc, Time: 49.012
Config: 100msPeriodicGc, Time: 45.9856
Config: 1000msPeriodicGc, Time: 40.3094
```
```
(TOOLCHAIN) mtomic@poso:~/memgraph/build_release$ tests/benchmark/storage_v2_gc --num-threads 7
Config: NoGc, Time: 20.4256
Config: OnFinishGc, Time: 39.6669
Config: 100msPeriodicGc, Time: 30.7956
Config: 1000msPeriodicGc, Time: 35.128
```
It is not that bad if there is a core dedicated to doing garbage collection.
Reviewers: mferencevic, teon.banek
Reviewed By: mferencevic, teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2168
2019-07-09 22:34:23 +08:00
|
|
|
|
2021-06-14 21:47:57 +08:00
|
|
|
IsolationLevel isolation_level_;
|
2023-04-05 00:46:26 +08:00
|
|
|
StorageMode storage_mode_;
|
[StorageV2] Implement GC
Summary:
Here are some numbers from the benchmark:
```
(TOOLCHAIN) mtomic@poso:~/memgraph/build_release$ tests/benchmark/storage_v2_gc --num-threads 8
Config: NoGc, Time: 25.9836
Config: OnFinishGc, Time: 49.012
Config: 100msPeriodicGc, Time: 45.9856
Config: 1000msPeriodicGc, Time: 40.3094
```
```
(TOOLCHAIN) mtomic@poso:~/memgraph/build_release$ tests/benchmark/storage_v2_gc --num-threads 7
Config: NoGc, Time: 20.4256
Config: OnFinishGc, Time: 39.6669
Config: 100msPeriodicGc, Time: 30.7956
Config: 1000msPeriodicGc, Time: 35.128
```
It is not that bad if there is a core dedicated to doing garbage collection.
Reviewers: mferencevic, teon.banek
Reviewed By: mferencevic, teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2168
2019-07-09 22:34:23 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
Indices indices_;
|
|
|
|
Constraints constraints_;
|
|
|
|
|
2023-11-06 19:37:48 +08:00
|
|
|
// Datastructures to provide fast retrieval of node-label and
|
|
|
|
// edge-type related metadata.
|
|
|
|
// Currently we should not remove any node-labels or edge-types even
|
|
|
|
// if the set of given types are currently not present in the
|
|
|
|
// database. This metadata is usually used by client side
|
|
|
|
// applications that want to be aware of the kind of data that *may*
|
|
|
|
// be present in the database.
|
|
|
|
|
|
|
|
// TODO(gvolfing): check if this would be faster with flat_maps.
|
2023-11-08 21:43:06 +08:00
|
|
|
utils::SynchronizedMetaDataStore<LabelId> stored_node_labels_;
|
|
|
|
utils::SynchronizedMetaDataStore<EdgeTypeId> stored_edge_types_;
|
2023-11-06 19:37:48 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
std::atomic<uint64_t> vertex_id_{0};
|
|
|
|
std::atomic<uint64_t> edge_id_{0};
|
2019-06-26 22:01:51 +08:00
|
|
|
};
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
} // namespace memgraph::storage
|