2023-03-27 21:46:00 +08:00
|
|
|
// Copyright 2023 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.
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "spdlog/spdlog.h"
|
2019-07-03 21:32:03 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "storage/v2/disk/name_id_mapper.hpp"
|
|
|
|
#include "storage/v2/storage.hpp"
|
2021-02-19 18:00:10 +08:00
|
|
|
#include "storage/v2/transaction.hpp"
|
2021-05-10 16:10:01 +08:00
|
|
|
#include "storage/v2/vertex_accessor.hpp"
|
2023-05-18 01:20:56 +08:00
|
|
|
#include "utils/event_counter.hpp"
|
|
|
|
#include "utils/event_histogram.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "utils/exceptions.hpp"
|
2020-11-12 16:55:56 +08:00
|
|
|
#include "utils/file.hpp"
|
2021-01-21 22:47:56 +08:00
|
|
|
#include "utils/logging.hpp"
|
2019-12-09 22:49:28 +08:00
|
|
|
#include "utils/stat.hpp"
|
2023-05-18 01:20:56 +08:00
|
|
|
#include "utils/timer.hpp"
|
2023-06-29 17:44:55 +08:00
|
|
|
#include "utils/typeinfo.hpp"
|
2020-07-25 00:26:36 +08:00
|
|
|
#include "utils/uuid.hpp"
|
2019-07-03 21:32:03 +08:00
|
|
|
|
2023-05-18 01:20:56 +08:00
|
|
|
namespace memgraph::metrics {
|
|
|
|
extern const Event SnapshotCreationLatency_us;
|
|
|
|
|
|
|
|
extern const Event ActiveLabelIndices;
|
|
|
|
extern const Event ActiveLabelPropertyIndices;
|
|
|
|
} // namespace memgraph::metrics
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
namespace memgraph::storage {
|
2019-07-03 21:32:03 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
class InMemoryStorage;
|
2020-07-25 00:26:36 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
using OOMExceptionEnabler = utils::MemoryTracker::OutOfMemoryExceptionEnabler;
|
2020-07-25 00:26:36 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
Storage::Storage(Config config, StorageMode storage_mode)
|
|
|
|
: name_id_mapper_(std::invoke([config, storage_mode]() -> std::unique_ptr<NameIdMapper> {
|
|
|
|
if (storage_mode == StorageMode::ON_DISK_TRANSACTIONAL) {
|
|
|
|
return std::make_unique<DiskNameIdMapper>(config.disk.name_id_mapper_directory,
|
|
|
|
config.disk.id_name_mapper_directory);
|
2021-06-30 18:31:30 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
return std::make_unique<NameIdMapper>();
|
|
|
|
})),
|
|
|
|
config_(config),
|
|
|
|
isolation_level_(config.transaction.isolation_level),
|
|
|
|
storage_mode_(storage_mode),
|
2023-09-06 01:00:53 +08:00
|
|
|
indices_(config, storage_mode),
|
2023-08-02 00:49:11 +08:00
|
|
|
constraints_(config, storage_mode),
|
2023-08-31 23:06:44 +08:00
|
|
|
id_(config.name),
|
|
|
|
replication_state_(config_.durability.restore_replication_state_on_startup,
|
|
|
|
config_.durability.storage_directory) {}
|
[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-04-05 00:46:26 +08:00
|
|
|
Storage::Accessor::Accessor(Storage *storage, IsolationLevel isolation_level, StorageMode storage_mode)
|
2019-07-11 19:27:50 +08:00
|
|
|
: storage_(storage),
|
2019-09-12 18:15:07 +08:00
|
|
|
// The lock must be acquired before creating the transaction object to
|
|
|
|
// prevent freshly created transactions from dangling in an active state
|
|
|
|
// during exclusive operations.
|
|
|
|
storage_guard_(storage_->main_lock_),
|
2023-04-05 00:46:26 +08:00
|
|
|
transaction_(storage->CreateTransaction(isolation_level, storage_mode)),
|
2019-09-24 22:48:36 +08:00
|
|
|
is_transaction_active_(true),
|
2023-06-29 17:44:55 +08:00
|
|
|
creation_storage_mode_(storage_mode) {}
|
2019-07-03 21:32:03 +08:00
|
|
|
|
|
|
|
Storage::Accessor::Accessor(Accessor &&other) noexcept
|
|
|
|
: storage_(other.storage_),
|
2021-04-23 20:19:42 +08:00
|
|
|
storage_guard_(std::move(other.storage_guard_)),
|
[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
|
|
|
transaction_(std::move(other.transaction_)),
|
2021-04-23 20:19:42 +08:00
|
|
|
commit_timestamp_(other.commit_timestamp_),
|
2019-09-24 22:48:36 +08:00
|
|
|
is_transaction_active_(other.is_transaction_active_),
|
2023-06-29 17:44:55 +08:00
|
|
|
creation_storage_mode_(other.creation_storage_mode_) {
|
2019-08-20 16:14:03 +08:00
|
|
|
// Don't allow the other accessor to abort our transaction in destructor.
|
|
|
|
other.is_transaction_active_ = false;
|
2021-04-23 20:19:42 +08:00
|
|
|
other.commit_timestamp_.reset();
|
2019-07-03 21:32:03 +08:00
|
|
|
}
|
|
|
|
|
2019-11-12 17:31:57 +08:00
|
|
|
IndicesInfo Storage::ListAllIndices() const {
|
|
|
|
std::shared_lock<utils::RWLock> storage_guard_(main_lock_);
|
2023-06-29 17:44:55 +08:00
|
|
|
return {indices_.label_index_->ListIndices(), indices_.label_property_index_->ListIndices()};
|
2020-01-30 22:56:11 +08:00
|
|
|
}
|
|
|
|
|
2019-11-12 17:31:57 +08:00
|
|
|
ConstraintsInfo Storage::ListAllConstraints() const {
|
|
|
|
std::shared_lock<utils::RWLock> storage_guard_(main_lock_);
|
2023-06-29 17:44:55 +08:00
|
|
|
return {constraints_.existence_constraints_->ListConstraints(), constraints_.unique_constraints_->ListConstraints()};
|
2020-07-25 00:26:36 +08:00
|
|
|
}
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
/// Main lock is taken by the caller.
|
|
|
|
void Storage::SetStorageMode(StorageMode storage_mode) {
|
|
|
|
std::unique_lock main_guard{main_lock_};
|
|
|
|
MG_ASSERT(
|
|
|
|
(storage_mode_ == StorageMode::IN_MEMORY_ANALYTICAL || storage_mode_ == StorageMode::IN_MEMORY_TRANSACTIONAL) &&
|
|
|
|
(storage_mode == StorageMode::IN_MEMORY_ANALYTICAL || storage_mode == StorageMode::IN_MEMORY_TRANSACTIONAL));
|
|
|
|
if (storage_mode_ != storage_mode) {
|
|
|
|
storage_mode_ = storage_mode;
|
|
|
|
FreeMemory(std::move(main_guard));
|
2022-07-07 19:30:28 +08:00
|
|
|
}
|
2020-10-27 17:11:43 +08:00
|
|
|
}
|
2020-11-19 21:26:03 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
StorageMode Storage::GetStorageMode() const { return storage_mode_; }
|
2020-10-27 17:11:43 +08:00
|
|
|
|
2023-09-06 01:00:53 +08:00
|
|
|
IsolationLevel Storage::GetIsolationLevel() const noexcept { return isolation_level_; }
|
|
|
|
|
2023-04-05 00:46:26 +08:00
|
|
|
utils::BasicResult<Storage::SetIsolationLevelError> Storage::SetIsolationLevel(IsolationLevel isolation_level) {
|
2021-06-14 21:47:57 +08:00
|
|
|
std::unique_lock main_guard{main_lock_};
|
2023-04-05 00:46:26 +08:00
|
|
|
if (storage_mode_ == storage::StorageMode::IN_MEMORY_ANALYTICAL) {
|
|
|
|
return Storage::SetIsolationLevelError::DisabledForAnalyticalMode;
|
|
|
|
}
|
|
|
|
|
2021-06-14 21:47:57 +08:00
|
|
|
isolation_level_ = isolation_level;
|
2023-04-05 00:46:26 +08:00
|
|
|
return {};
|
2021-06-14 21:47:57 +08:00
|
|
|
}
|
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
StorageMode Storage::Accessor::GetCreationStorageMode() const { return creation_storage_mode_; }
|
2023-06-22 01:08:58 +08:00
|
|
|
|
2023-06-29 17:44:55 +08:00
|
|
|
std::optional<uint64_t> Storage::Accessor::GetTransactionId() const {
|
|
|
|
if (is_transaction_active_) {
|
|
|
|
return transaction_.transaction_id.load(std::memory_order_acquire);
|
2022-07-07 19:30:28 +08:00
|
|
|
}
|
2023-06-29 17:44:55 +08:00
|
|
|
return {};
|
2022-07-07 19:30:28 +08:00
|
|
|
}
|
|
|
|
|
2023-08-11 16:18:28 +08:00
|
|
|
void Storage::Accessor::AdvanceCommand() {
|
|
|
|
transaction_.manyDeltasCache.Clear(); // TODO: Just invalidate the View::OLD cache, NEW should still be fine
|
|
|
|
++transaction_.command_id;
|
|
|
|
}
|
2022-07-07 19:30:28 +08:00
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
} // namespace memgraph::storage
|