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-20 23:54:50 +08:00
|
|
|
#include "audit/log.hpp"
|
2022-02-17 17:35:48 +08:00
|
|
|
#include "communication/websocket/auth.hpp"
|
2022-01-04 19:13:48 +08:00
|
|
|
#include "communication/websocket/server.hpp"
|
2023-09-20 19:13:54 +08:00
|
|
|
#include "dbms/constants.hpp"
|
2023-08-19 00:23:15 +08:00
|
|
|
#include "flags/all.hpp"
|
2023-09-20 19:13:54 +08:00
|
|
|
#include "flags/run_time_configurable.hpp"
|
2023-08-19 00:23:15 +08:00
|
|
|
#include "glue/MonitoringServerT.hpp"
|
|
|
|
#include "glue/ServerT.hpp"
|
[E129-MG <-T0982-MG] implement edge type filtering (#489)
* GRANT, REVOKE, DENY and access_checker DONE
* Added AccessChecker to ExecutionContext
* grammar expanded; (#462)
* current
* T0954 mg expand user and role to hold permissions on labels (#465)
* added FineGrainedAccessPermissions class to model
* expanded user and role with fine grained access permissions
* fixed grammar
* [E129 < T0953-MG] GRANT, DENY, REVOKE added in interpreter and mainVisitor (#464)
* GRANT, DENY, REVOKE added in interpreter and mainVisitor
* Commented labelPermissons
* remove labelsPermission adding
* Fixed
* Removed extra lambda
* fixed
* [E129<-T0955-MG] Expand ExecutionContext with label related information (#467)
* added
* Added FineGrainedAccessChecker to Context
* fixed
* Added filtering
* testing
* Added edge filtering to storage, need to add filtering in simple Expand in operator.cpp
* Removed storage changes
* MATCH filtering working
* EdgeTypeFiltering working, just need to test everything again
* Removed FineGrainedAccessChecker
* Removed Expand Path
* Fix
* Tested FineGrainedAccessHandler, need to test AuthChecker
* Added integration test for lba
* Fixed merge conflicts
* PR fix
* fixed
* PR fix
* Fix test
* removed .vscode, .cache, .githooks
* githooks
* added tests
* fixed build
* Changed ast.lcp and User pointer to value in context.hpp
* Fixed test
* Remove denies on grant all
* AuthChecker
* Pr fix, auth_checker still not fixed
* Create mg-glue and extract UserBasedAuthChecker from AuthChecker
* Build fixed, need to fix test
* e2e tests
* e2e test working
* Added unit test, e2e and FineGrainedChecker
* Mege E129, auth_checker tests
* Fixed test
* e2e fix
Co-authored-by: Boris Taševski <36607228+BorisTasevski@users.noreply.github.com>
Co-authored-by: josipmrden <josip.mrden@external-basf.com>
Co-authored-by: János Benjamin Antal <benjamin.antal@memgraph.io>
2022-08-16 21:57:23 +08:00
|
|
|
#include "glue/auth_checker.hpp"
|
2022-08-31 18:14:16 +08:00
|
|
|
#include "glue/auth_handler.hpp"
|
2023-09-20 19:13:54 +08:00
|
|
|
#include "glue/run_id.hpp"
|
2020-03-03 17:38:50 +08:00
|
|
|
#include "helpers.hpp"
|
2022-11-04 22:23:43 +08:00
|
|
|
#include "license/license_sender.hpp"
|
2023-09-20 19:13:54 +08:00
|
|
|
#include "query/config.hpp"
|
2021-07-05 17:42:40 +08:00
|
|
|
#include "query/discard_value_stream.hpp"
|
2023-09-20 19:13:54 +08:00
|
|
|
#include "query/interpreter.hpp"
|
2023-07-31 20:48:12 +08:00
|
|
|
#include "query/procedure/callable_alias_mapper.hpp"
|
2020-01-15 20:58:41 +08:00
|
|
|
#include "query/procedure/module.hpp"
|
2020-02-24 21:06:21 +08:00
|
|
|
#include "query/procedure/py_module.hpp"
|
|
|
|
#include "requests/requests.hpp"
|
2018-06-20 19:46:54 +08:00
|
|
|
#include "telemetry/telemetry.hpp"
|
2020-02-24 21:06:21 +08:00
|
|
|
#include "utils/signals.hpp"
|
|
|
|
#include "utils/sysinfo/memory.hpp"
|
2022-11-04 22:23:43 +08:00
|
|
|
#include "utils/system_info.hpp"
|
2020-02-24 21:06:21 +08:00
|
|
|
#include "utils/terminate_handler.hpp"
|
|
|
|
#include "version.hpp"
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
#include "dbms/dbms_handler.hpp"
|
|
|
|
#include "query/auth_query_handler.hpp"
|
|
|
|
#include "query/interpreter_context.hpp"
|
|
|
|
|
2022-12-10 01:50:33 +08:00
|
|
|
constexpr const char *kMgUser = "MEMGRAPH_USER";
|
|
|
|
constexpr const char *kMgPassword = "MEMGRAPH_PASSWORD";
|
|
|
|
constexpr const char *kMgPassfile = "MEMGRAPH_PASSFILE";
|
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
// TODO: move elsewhere so that we can remove need of interpreter.hpp
|
|
|
|
void InitFromCypherlFile(memgraph::query::InterpreterContext &ctx, memgraph::dbms::DatabaseAccess &db_acc,
|
|
|
|
std::string cypherl_file_path, memgraph::audit::Log *audit_log = nullptr) {
|
|
|
|
memgraph::query::Interpreter interpreter(&ctx, db_acc);
|
2022-12-10 01:50:33 +08:00
|
|
|
std::ifstream file(cypherl_file_path);
|
|
|
|
|
2023-06-20 23:54:50 +08:00
|
|
|
if (!file.is_open()) {
|
|
|
|
spdlog::trace("Could not find init file {}", cypherl_file_path);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string line;
|
|
|
|
while (std::getline(file, line)) {
|
|
|
|
if (!line.empty()) {
|
|
|
|
auto results = interpreter.Prepare(line, {}, {});
|
|
|
|
memgraph::query::DiscardValueResultStream stream;
|
|
|
|
interpreter.Pull(&stream, {}, results.qid);
|
|
|
|
|
|
|
|
if (audit_log) {
|
2023-08-02 00:49:11 +08:00
|
|
|
audit_log->Record("", "", line, {}, memgraph::dbms::kDefaultDB);
|
2022-12-10 01:50:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-06-20 23:54:50 +08:00
|
|
|
|
|
|
|
file.close();
|
2022-12-10 01:50:33 +08:00
|
|
|
}
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
using memgraph::communication::ServerContext;
|
2020-01-15 20:58:41 +08:00
|
|
|
|
2020-02-24 21:06:21 +08:00
|
|
|
// Needed to correctly handle memgraph destruction from a signal handler.
|
|
|
|
// Without having some sort of a flag, it is possible that a signal is handled
|
|
|
|
// when we are exiting main, inside destructors of database::GraphDb and
|
|
|
|
// similar. The signal handler may then initiate another shutdown on memgraph
|
|
|
|
// which is in half destructed state, causing invalid memory access and crash.
|
2023-08-19 00:23:15 +08:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
2020-02-24 21:06:21 +08:00
|
|
|
volatile sig_atomic_t is_shutting_down = 0;
|
|
|
|
|
|
|
|
void InitSignalHandlers(const std::function<void()> &shutdown_fun) {
|
|
|
|
// Prevent handling shutdown inside a shutdown. For example, SIGINT handler
|
|
|
|
// being interrupted by SIGTERM before is_shutting_down is set, thus causing
|
|
|
|
// double shutdown.
|
|
|
|
sigset_t block_shutdown_signals;
|
|
|
|
sigemptyset(&block_shutdown_signals);
|
|
|
|
sigaddset(&block_shutdown_signals, SIGTERM);
|
|
|
|
sigaddset(&block_shutdown_signals, SIGINT);
|
|
|
|
|
|
|
|
// Wrap the shutdown function in a safe way to prevent recursive shutdown.
|
|
|
|
auto shutdown = [shutdown_fun]() {
|
|
|
|
if (is_shutting_down) return;
|
|
|
|
is_shutting_down = 1;
|
|
|
|
shutdown_fun();
|
|
|
|
};
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
MG_ASSERT(memgraph::utils::SignalHandler::RegisterHandler(memgraph::utils::Signal::Terminate, shutdown,
|
|
|
|
block_shutdown_signals),
|
2021-01-21 22:47:56 +08:00
|
|
|
"Unable to register SIGTERM handler!");
|
2022-02-22 20:33:45 +08:00
|
|
|
MG_ASSERT(memgraph::utils::SignalHandler::RegisterHandler(memgraph::utils::Signal::Interupt, shutdown,
|
|
|
|
block_shutdown_signals),
|
2021-01-21 22:47:56 +08:00
|
|
|
"Unable to register SIGINT handler!");
|
2020-02-24 21:06:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
google::SetUsageMessage("Memgraph database server");
|
|
|
|
gflags::SetVersionString(version_string);
|
|
|
|
|
|
|
|
// Load config before parsing arguments, so that flags from the command line
|
|
|
|
// overwrite the config.
|
2020-03-03 17:38:50 +08:00
|
|
|
LoadConfig("memgraph");
|
2020-02-24 21:06:21 +08:00
|
|
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
|
|
|
|
2022-12-07 23:51:32 +08:00
|
|
|
if (FLAGS_h) {
|
|
|
|
gflags::ShowUsageWithFlags(argv[0]);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2023-08-19 00:23:15 +08:00
|
|
|
memgraph::flags::InitializeLogger();
|
2020-02-24 21:06:21 +08:00
|
|
|
|
|
|
|
// Unhandled exception handler init.
|
2022-02-22 20:33:45 +08:00
|
|
|
std::set_terminate(&memgraph::utils::TerminateHandler);
|
2020-02-24 21:06:21 +08:00
|
|
|
|
|
|
|
// Initialize Python
|
|
|
|
auto *program_name = Py_DecodeLocale(argv[0], nullptr);
|
2021-01-21 22:47:56 +08:00
|
|
|
MG_ASSERT(program_name);
|
2020-02-24 21:06:21 +08:00
|
|
|
// Set program name, so Python can find its way to runtime libraries relative
|
|
|
|
// to executable.
|
|
|
|
Py_SetProgramName(program_name);
|
2022-02-22 20:33:45 +08:00
|
|
|
PyImport_AppendInittab("_mgp", &memgraph::query::procedure::PyInitMgpModule);
|
2020-02-24 21:06:21 +08:00
|
|
|
Py_InitializeEx(0 /* = initsigs */);
|
|
|
|
PyEval_InitThreads();
|
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
|
|
|
|
2020-03-09 18:06:01 +08:00
|
|
|
// Add our Python modules to sys.path
|
|
|
|
try {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto exe_path = memgraph::utils::GetExecutablePath();
|
2020-03-09 18:06:01 +08:00
|
|
|
auto py_support_dir = exe_path.parent_path() / "python_support";
|
|
|
|
if (std::filesystem::is_directory(py_support_dir)) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto gil = memgraph::py::EnsureGIL();
|
|
|
|
auto maybe_exc = memgraph::py::AppendToSysPath(py_support_dir.c_str());
|
2020-03-09 18:06:01 +08:00
|
|
|
if (maybe_exc) {
|
2022-02-22 20:33:45 +08:00
|
|
|
spdlog::error(memgraph::utils::MessageWithLink("Unable to load support for embedded Python: {}.", *maybe_exc,
|
|
|
|
"https://memgr.ph/python"));
|
2022-05-13 17:43:10 +08:00
|
|
|
} else {
|
|
|
|
// Change how we load dynamic libraries on Python by using RTLD_NOW and
|
|
|
|
// RTLD_DEEPBIND flags. This solves an issue with using the wrong version of
|
|
|
|
// libstd.
|
|
|
|
auto gil = memgraph::py::EnsureGIL();
|
|
|
|
// NOLINTNEXTLINE(hicpp-signed-bitwise)
|
|
|
|
auto *flag = PyLong_FromLong(RTLD_NOW | RTLD_DEEPBIND);
|
|
|
|
auto *setdl = PySys_GetObject("setdlopenflags");
|
|
|
|
MG_ASSERT(setdl);
|
|
|
|
auto *arg = PyTuple_New(1);
|
|
|
|
MG_ASSERT(arg);
|
|
|
|
MG_ASSERT(PyTuple_SetItem(arg, 0, flag) == 0);
|
|
|
|
PyObject_CallObject(setdl, arg);
|
|
|
|
Py_DECREF(flag);
|
|
|
|
Py_DECREF(setdl);
|
|
|
|
Py_DECREF(arg);
|
2020-03-09 18:06:01 +08:00
|
|
|
}
|
|
|
|
} else {
|
2022-02-22 20:33:45 +08:00
|
|
|
spdlog::error(
|
|
|
|
memgraph::utils::MessageWithLink("Unable to load support for embedded Python: missing directory {}.",
|
2021-10-07 20:51:30 +08:00
|
|
|
py_support_dir, "https://memgr.ph/python"));
|
2020-03-09 18:06:01 +08:00
|
|
|
}
|
|
|
|
} catch (const std::filesystem::filesystem_error &e) {
|
2022-02-22 20:33:45 +08:00
|
|
|
spdlog::error(memgraph::utils::MessageWithLink("Unable to load support for embedded Python: {}.", e.what(),
|
|
|
|
"https://memgr.ph/python"));
|
2020-03-09 18:06:01 +08:00
|
|
|
}
|
|
|
|
|
2020-02-24 21:06:21 +08:00
|
|
|
// Initialize the communication library.
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::communication::SSLInit sslInit;
|
2020-02-24 21:06:21 +08:00
|
|
|
|
|
|
|
// Initialize the requests library.
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::requests::Init();
|
2020-02-24 21:06:21 +08:00
|
|
|
|
|
|
|
// Start memory warning logger.
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::utils::Scheduler mem_log_scheduler;
|
2020-02-24 21:06:21 +08:00
|
|
|
if (FLAGS_memory_warning_threshold > 0) {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto free_ram = memgraph::utils::sysinfo::AvailableMemory();
|
2020-02-24 21:06:21 +08:00
|
|
|
if (free_ram) {
|
|
|
|
mem_log_scheduler.Run("Memory warning", std::chrono::seconds(3), [] {
|
2022-02-22 20:33:45 +08:00
|
|
|
auto free_ram = memgraph::utils::sysinfo::AvailableMemory();
|
2020-02-24 21:06:21 +08:00
|
|
|
if (free_ram && *free_ram / 1024 < FLAGS_memory_warning_threshold)
|
2022-02-22 20:33:45 +08:00
|
|
|
spdlog::warn(memgraph::utils::MessageWithLink("Running out of available RAM, only {} MB left.",
|
|
|
|
*free_ram / 1024, "https://memgr.ph/ram"));
|
2020-02-24 21:06:21 +08:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// Kernel version for the `MemAvailable` value is from: man procfs
|
2021-01-21 22:47:56 +08:00
|
|
|
spdlog::warn(
|
|
|
|
"You have an older kernel version (<3.14) or the /proc "
|
|
|
|
"filesystem isn't available so remaining memory warnings "
|
|
|
|
"won't be available.");
|
2020-02-24 21:06:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:32:43 +08:00
|
|
|
std::cout << "You are running Memgraph v" << gflags::VersionString() << std::endl;
|
2021-10-07 21:56:06 +08:00
|
|
|
std::cout << "To get started with Memgraph, visit https://memgr.ph/start" << std::endl;
|
2020-01-17 20:02:50 +08:00
|
|
|
|
2020-02-05 22:05:18 +08:00
|
|
|
auto data_directory = std::filesystem::path(FLAGS_data_directory);
|
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
memgraph::utils::EnsureDirOrDie(data_directory);
|
|
|
|
// Verify that the user that started the process is the same user that is
|
|
|
|
// the owner of the storage directory.
|
|
|
|
memgraph::storage::durability::VerifyStorageDirectoryOwnerAndProcessUserOrDie(data_directory);
|
|
|
|
// Create the lock file and open a handle to it. This will crash the
|
|
|
|
// database if it can't open the file for writing or if any other process is
|
|
|
|
// holding the file opened.
|
|
|
|
memgraph::utils::OutputFile lock_file_handle;
|
|
|
|
lock_file_handle.Open(data_directory / ".lock", memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING);
|
|
|
|
MG_ASSERT(lock_file_handle.AcquireLock(),
|
|
|
|
"Couldn't acquire lock on the storage directory {}"
|
|
|
|
"!\nAnother Memgraph process is currently running with the same "
|
|
|
|
"storage directory, please stop it first before starting this "
|
|
|
|
"process!",
|
|
|
|
data_directory);
|
|
|
|
|
2023-08-19 00:23:15 +08:00
|
|
|
const auto memory_limit = memgraph::flags::GetMemoryLimit();
|
2021-09-30 01:14:39 +08:00
|
|
|
// NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
|
2022-02-22 20:33:45 +08:00
|
|
|
spdlog::info("Memory limit in config is set to {}", memgraph::utils::GetReadableSize(memory_limit));
|
|
|
|
memgraph::utils::total_memory_tracker.SetMaximumHardLimit(memory_limit);
|
|
|
|
memgraph::utils::total_memory_tracker.SetHardLimit(memory_limit);
|
2021-09-30 01:14:39 +08:00
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::utils::global_settings.Initialize(data_directory / "settings");
|
|
|
|
memgraph::utils::OnScopeExit settings_finalizer([&] { memgraph::utils::global_settings.Finalize(); });
|
2021-09-30 01:14:39 +08:00
|
|
|
|
|
|
|
// register all runtime settings
|
2022-11-04 22:23:43 +08:00
|
|
|
memgraph::license::RegisterLicenseSettings(memgraph::license::global_license_checker,
|
|
|
|
memgraph::utils::global_settings);
|
2023-09-11 23:30:54 +08:00
|
|
|
memgraph::flags::run_time::Initialize();
|
2021-09-30 01:14:39 +08:00
|
|
|
|
2022-11-04 22:23:43 +08:00
|
|
|
memgraph::license::global_license_checker.CheckEnvLicense();
|
2021-09-30 01:14:39 +08:00
|
|
|
if (!FLAGS_organization_name.empty() && !FLAGS_license_key.empty()) {
|
2022-11-04 22:23:43 +08:00
|
|
|
memgraph::license::global_license_checker.SetLicenseInfoOverride(FLAGS_license_key, FLAGS_organization_name);
|
2021-09-30 01:14:39 +08:00
|
|
|
}
|
|
|
|
|
2022-11-04 22:23:43 +08:00
|
|
|
memgraph::license::global_license_checker.StartBackgroundLicenseChecker(memgraph::utils::global_settings);
|
2021-09-30 01:14:39 +08:00
|
|
|
|
2019-02-19 20:50:46 +08:00
|
|
|
// All enterprise features should be constructed before the main database
|
|
|
|
// storage. This will cause them to be destructed *after* the main database
|
|
|
|
// storage. That way any errors that happen during enterprise features
|
|
|
|
// destruction won't have an impact on the storage engine.
|
|
|
|
// Example: When the main storage is destructed it makes a snapshot. When
|
|
|
|
// audit logging is destructed it syncs all pending data to disk and that can
|
|
|
|
// fail. That is why it must be destructed *after* the main database storage
|
|
|
|
// to minimise the impact of their failure on the main storage.
|
|
|
|
|
|
|
|
// Begin enterprise features initialization
|
|
|
|
|
2021-09-30 01:14:39 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
2019-02-19 20:50:46 +08:00
|
|
|
// Audit log
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::audit::Log audit_log{data_directory / "audit", FLAGS_audit_buffer_size,
|
|
|
|
FLAGS_audit_buffer_flush_interval_ms};
|
2019-02-19 20:50:46 +08:00
|
|
|
// Start the log if enabled.
|
|
|
|
if (FLAGS_audit_enabled) {
|
|
|
|
audit_log.Start();
|
|
|
|
}
|
|
|
|
// Setup SIGUSR2 to be used for reopening audit log files, when e.g. logrotate
|
|
|
|
// rotates our audit logs.
|
2022-02-22 20:33:45 +08:00
|
|
|
MG_ASSERT(memgraph::utils::SignalHandler::RegisterHandler(memgraph::utils::Signal::User2,
|
|
|
|
[&audit_log]() { audit_log.ReopenLog(); }),
|
2021-02-18 22:32:43 +08:00
|
|
|
"Unable to register SIGUSR2 handler!");
|
2019-02-19 20:50:46 +08:00
|
|
|
|
|
|
|
// End enterprise features initialization
|
2020-02-05 22:05:18 +08:00
|
|
|
#endif
|
2019-02-19 20:50:46 +08:00
|
|
|
|
2021-03-04 19:20:11 +08:00
|
|
|
// Main storage and execution engines initialization
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::storage::Config db_config{
|
|
|
|
.gc = {.type = memgraph::storage::Config::Gc::Type::PERIODIC,
|
|
|
|
.interval = std::chrono::seconds(FLAGS_storage_gc_cycle_sec)},
|
2019-10-09 22:00:02 +08:00
|
|
|
.items = {.properties_on_edges = FLAGS_storage_properties_on_edges},
|
2021-02-18 22:32:43 +08:00
|
|
|
.durability = {.storage_directory = FLAGS_data_directory,
|
2023-08-02 00:49:11 +08:00
|
|
|
.recover_on_startup = FLAGS_storage_recover_on_startup || FLAGS_data_recovery_on_startup,
|
2021-02-18 22:32:43 +08:00
|
|
|
.snapshot_retention_count = FLAGS_storage_snapshot_retention_count,
|
|
|
|
.wal_file_size_kibibytes = FLAGS_storage_wal_file_size_kib,
|
|
|
|
.wal_file_flush_every_n_tx = FLAGS_storage_wal_file_flush_every_n_tx,
|
2022-07-07 19:30:28 +08:00
|
|
|
.snapshot_on_exit = FLAGS_storage_snapshot_on_exit,
|
2023-07-20 03:18:43 +08:00
|
|
|
.restore_replication_state_on_startup = FLAGS_replication_restore_state_on_startup,
|
2023-04-25 22:25:25 +08:00
|
|
|
.items_per_batch = FLAGS_storage_items_per_batch,
|
2023-04-26 22:28:02 +08:00
|
|
|
.recovery_thread_count = FLAGS_storage_recovery_thread_count,
|
|
|
|
.allow_parallel_index_creation = FLAGS_storage_parallel_index_recovery},
|
2023-08-19 00:23:15 +08:00
|
|
|
.transaction = {.isolation_level = memgraph::flags::ParseIsolationLevel()},
|
2023-06-29 17:44:55 +08:00
|
|
|
.disk = {.main_storage_directory = FLAGS_data_directory + "/rocksdb_main_storage",
|
|
|
|
.label_index_directory = FLAGS_data_directory + "/rocksdb_label_index",
|
|
|
|
.label_property_index_directory = FLAGS_data_directory + "/rocksdb_label_property_index",
|
|
|
|
.unique_constraints_directory = FLAGS_data_directory + "/rocksdb_unique_constraints",
|
|
|
|
.name_id_mapper_directory = FLAGS_data_directory + "/rocksdb_name_id_mapper",
|
|
|
|
.id_name_mapper_directory = FLAGS_data_directory + "/rocksdb_id_name_mapper",
|
|
|
|
.durability_directory = FLAGS_data_directory + "/rocksdb_durability",
|
2023-09-26 20:47:30 +08:00
|
|
|
.wal_directory = FLAGS_data_directory + "/rocksdb_wal"},
|
|
|
|
.storage_mode = memgraph::flags::ParseStorageMode()};
|
2019-10-09 22:00:02 +08:00
|
|
|
if (FLAGS_storage_snapshot_interval_sec == 0) {
|
2021-01-21 22:47:56 +08:00
|
|
|
if (FLAGS_storage_wal_enabled) {
|
|
|
|
LOG_FATAL(
|
|
|
|
"In order to use write-ahead-logging you must enable "
|
|
|
|
"periodic snapshots by setting the snapshot interval to a "
|
|
|
|
"value larger than 0!");
|
2022-02-22 20:33:45 +08:00
|
|
|
db_config.durability.snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::DISABLED;
|
2021-01-21 22:47:56 +08:00
|
|
|
}
|
2019-10-09 22:00:02 +08:00
|
|
|
} else {
|
|
|
|
if (FLAGS_storage_wal_enabled) {
|
2022-02-22 20:33:45 +08:00
|
|
|
db_config.durability.snapshot_wal_mode =
|
|
|
|
memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL;
|
2019-10-09 22:00:02 +08:00
|
|
|
} else {
|
2022-02-22 20:33:45 +08:00
|
|
|
db_config.durability.snapshot_wal_mode =
|
|
|
|
memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT;
|
2019-10-09 22:00:02 +08:00
|
|
|
}
|
2021-02-18 22:32:43 +08:00
|
|
|
db_config.durability.snapshot_interval = std::chrono::seconds(FLAGS_storage_snapshot_interval_sec);
|
2019-10-09 22:00:02 +08:00
|
|
|
}
|
2021-09-30 01:14:39 +08:00
|
|
|
|
2023-08-02 00:49:11 +08:00
|
|
|
// Default interpreter configuration
|
|
|
|
memgraph::query::InterpreterConfig interp_config{
|
|
|
|
.query = {.allow_load_csv = FLAGS_allow_load_csv},
|
|
|
|
.replication_replica_check_frequency = std::chrono::seconds(FLAGS_replication_replica_check_frequency_sec),
|
|
|
|
.default_kafka_bootstrap_servers = FLAGS_kafka_bootstrap_servers,
|
|
|
|
.default_pulsar_service_url = FLAGS_pulsar_service_url,
|
|
|
|
.stream_transaction_conflict_retries = FLAGS_stream_transaction_conflict_retries,
|
|
|
|
.stream_transaction_retry_interval = std::chrono::milliseconds(FLAGS_stream_transaction_retry_interval)};
|
|
|
|
|
|
|
|
auto auth_glue =
|
|
|
|
[flag = FLAGS_auth_user_or_role_name_regex](
|
|
|
|
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth,
|
|
|
|
std::unique_ptr<memgraph::query::AuthQueryHandler> &ah, std::unique_ptr<memgraph::query::AuthChecker> &ac) {
|
|
|
|
// Glue high level auth implementations to the query side
|
|
|
|
ah = std::make_unique<memgraph::glue::AuthQueryHandler>(auth, flag);
|
|
|
|
ac = std::make_unique<memgraph::glue::AuthChecker>(auth);
|
|
|
|
// Handle users passed via arguments
|
|
|
|
auto *maybe_username = std::getenv(kMgUser);
|
|
|
|
auto *maybe_password = std::getenv(kMgPassword);
|
|
|
|
auto *maybe_pass_file = std::getenv(kMgPassfile);
|
|
|
|
if (maybe_username && maybe_password) {
|
|
|
|
ah->CreateUser(maybe_username, maybe_password);
|
|
|
|
} else if (maybe_pass_file) {
|
|
|
|
const auto [username, password] = LoadUsernameAndPassword(maybe_pass_file);
|
|
|
|
if (!username.empty() && !password.empty()) {
|
|
|
|
ah->CreateUser(username, password);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
// WIP
|
2023-08-02 00:49:11 +08:00
|
|
|
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth_{data_directory /
|
|
|
|
"auth"};
|
|
|
|
std::unique_ptr<memgraph::query::AuthQueryHandler> auth_handler;
|
|
|
|
std::unique_ptr<memgraph::query::AuthChecker> auth_checker;
|
|
|
|
auth_glue(&auth_, auth_handler, auth_checker);
|
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
|
|
|
memgraph::dbms::DbmsHandler new_handler(db_config, &auth_, FLAGS_data_recovery_on_startup,
|
|
|
|
FLAGS_storage_delete_on_drop);
|
|
|
|
auto db_acc = new_handler.Get(memgraph::dbms::kDefaultDB);
|
|
|
|
memgraph::query::InterpreterContext interpreter_context_(interp_config, &new_handler, auth_handler.get(),
|
|
|
|
auth_checker.get());
|
|
|
|
#else
|
|
|
|
memgraph::utils::Gatekeeper<memgraph::dbms::Database> db_gatekeeper{db_config};
|
|
|
|
auto db_acc_opt = db_gatekeeper.access();
|
|
|
|
MG_ASSERT(db_acc_opt, "Failed to access the main database");
|
|
|
|
auto &db_acc = *db_acc_opt;
|
2023-10-05 22:58:39 +08:00
|
|
|
memgraph::query::InterpreterContext interpreter_context_(interp_config, &db_gatekeeper, auth_handler.get(),
|
2023-09-20 19:13:54 +08:00
|
|
|
auth_checker.get());
|
2020-02-05 22:05:18 +08:00
|
|
|
#endif
|
2023-09-20 19:13:54 +08:00
|
|
|
MG_ASSERT(db_acc, "Failed to access the main database");
|
2023-08-02 00:49:11 +08:00
|
|
|
|
2023-08-19 00:23:15 +08:00
|
|
|
memgraph::query::procedure::gModuleRegistry.SetModulesDirectory(memgraph::flags::ParseQueryModulesDirectory(),
|
|
|
|
FLAGS_data_directory);
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::query::procedure::gModuleRegistry.UnloadAndLoadModulesFromDirectories();
|
2023-07-31 20:48:12 +08:00
|
|
|
memgraph::query::procedure::gCallableAliasMapper.LoadMapping(FLAGS_query_callable_mappings_path);
|
2020-02-24 21:06:21 +08:00
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
// TODO Make multi-tenant
|
2022-12-10 01:50:33 +08:00
|
|
|
if (!FLAGS_init_file.empty()) {
|
2023-06-20 23:54:50 +08:00
|
|
|
spdlog::info("Running init file...");
|
2022-12-10 01:50:33 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
|
|
|
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
2023-09-20 19:13:54 +08:00
|
|
|
InitFromCypherlFile(interpreter_context_, db_acc, FLAGS_init_file, &audit_log);
|
2023-06-20 23:54:50 +08:00
|
|
|
} else {
|
2023-09-20 19:13:54 +08:00
|
|
|
InitFromCypherlFile(interpreter_context_, db_acc, FLAGS_init_file);
|
2022-12-10 01:50:33 +08:00
|
|
|
}
|
|
|
|
#else
|
2023-09-20 19:13:54 +08:00
|
|
|
InitFromCypherlFile(interpreter_context_, db_acc, FLAGS_init_file);
|
2022-12-10 01:50:33 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-08-02 00:49:11 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
2023-09-20 19:13:54 +08:00
|
|
|
new_handler.RestoreTriggers(&interpreter_context_);
|
|
|
|
new_handler.RestoreStreams(&interpreter_context_);
|
2023-08-02 00:49:11 +08:00
|
|
|
#else
|
2021-07-22 22:22:08 +08:00
|
|
|
{
|
|
|
|
// Triggers can execute query procedures, so we need to reload the modules first and then
|
|
|
|
// the triggers
|
2023-09-20 19:13:54 +08:00
|
|
|
auto storage_accessor = db_acc->Access();
|
2023-06-29 17:44:55 +08:00
|
|
|
auto dba = memgraph::query::DbAccessor{storage_accessor.get()};
|
2023-09-20 19:13:54 +08:00
|
|
|
db_acc->trigger_store()->RestoreTriggers(&interpreter_context_.ast_cache, &dba, interpreter_context_.config.query,
|
|
|
|
interpreter_context_.auth_checker);
|
2021-07-22 22:22:08 +08:00
|
|
|
}
|
2018-07-06 15:28:05 +08:00
|
|
|
|
2021-11-11 19:17:05 +08:00
|
|
|
// As the Stream transformations are using modules, they have to be restored after the query modules are loaded.
|
2023-09-20 19:13:54 +08:00
|
|
|
db_acc->streams()->RestoreStreams(db_acc, &interpreter_context_);
|
2023-08-02 00:49:11 +08:00
|
|
|
#endif
|
2021-11-11 19:17:05 +08:00
|
|
|
|
2018-06-20 23:44:47 +08:00
|
|
|
ServerContext context;
|
|
|
|
std::string service_name = "Bolt";
|
2019-12-08 18:42:59 +08:00
|
|
|
if (!FLAGS_bolt_key_file.empty() && !FLAGS_bolt_cert_file.empty()) {
|
|
|
|
context = ServerContext(FLAGS_bolt_key_file, FLAGS_bolt_cert_file);
|
2018-06-20 23:44:47 +08:00
|
|
|
service_name = "BoltS";
|
2021-01-21 22:47:56 +08:00
|
|
|
spdlog::info("Using secure Bolt connection (with SSL)");
|
2020-10-20 21:49:10 +08:00
|
|
|
} else {
|
2022-02-22 20:33:45 +08:00
|
|
|
spdlog::warn(
|
|
|
|
memgraph::utils::MessageWithLink("Using non-secure Bolt connection (without SSL).", "https://memgr.ph/ssl"));
|
2018-06-20 23:44:47 +08:00
|
|
|
}
|
2022-04-27 16:13:16 +08:00
|
|
|
auto server_endpoint = memgraph::communication::v2::ServerEndpoint{
|
|
|
|
boost::asio::ip::address::from_string(FLAGS_bolt_address), static_cast<uint16_t>(FLAGS_bolt_port)};
|
2023-08-02 00:49:11 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
2023-09-20 19:13:54 +08:00
|
|
|
Context session_context{&interpreter_context_, &auth_, &audit_log};
|
2023-08-02 00:49:11 +08:00
|
|
|
#else
|
2023-09-20 19:13:54 +08:00
|
|
|
Context session_context{&interpreter_context_, &auth_};
|
|
|
|
#endif
|
2023-08-19 00:23:15 +08:00
|
|
|
memgraph::glue::ServerT server(server_endpoint, &session_context, &context, FLAGS_bolt_session_inactivity_timeout,
|
|
|
|
service_name, FLAGS_bolt_num_workers);
|
2017-12-19 19:40:30 +08:00
|
|
|
|
2022-11-04 22:23:43 +08:00
|
|
|
const auto machine_id = memgraph::utils::GetMachineId();
|
|
|
|
|
2018-06-20 19:46:54 +08:00
|
|
|
// Setup telemetry
|
2022-11-04 22:23:43 +08:00
|
|
|
static constexpr auto telemetry_server{"https://telemetry.memgraph.com/88b5e7e8-746a-11e8-9f85-538a9e9690cc/"};
|
2022-02-22 20:33:45 +08:00
|
|
|
std::optional<memgraph::telemetry::Telemetry> telemetry;
|
2018-06-20 19:46:54 +08:00
|
|
|
if (FLAGS_telemetry_enabled) {
|
2023-09-20 19:13:54 +08:00
|
|
|
telemetry.emplace(telemetry_server, data_directory / "telemetry", memgraph::glue::run_id_, machine_id,
|
|
|
|
std::chrono::minutes(10));
|
2023-08-02 00:49:11 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
2023-09-20 19:13:54 +08:00
|
|
|
telemetry->AddCollector("storage", [&new_handler]() -> nlohmann::json {
|
|
|
|
const auto &info = new_handler.Info();
|
2023-08-02 00:49:11 +08:00
|
|
|
return {{"vertices", info.num_vertex}, {"edges", info.num_edges}, {"databases", info.num_databases}};
|
|
|
|
});
|
|
|
|
#else
|
2023-09-20 19:13:54 +08:00
|
|
|
telemetry->AddCollector("storage", [gk = &db_gatekeeper]() -> nlohmann::json {
|
|
|
|
auto db_acc = gk->access();
|
|
|
|
MG_ASSERT(db_acc, "Failed to get access to the default database");
|
|
|
|
auto info = db_acc->get()->GetInfo();
|
2019-12-11 22:45:34 +08:00
|
|
|
return {{"vertices", info.vertex_count}, {"edges", info.edge_count}};
|
|
|
|
});
|
2023-08-02 00:49:11 +08:00
|
|
|
#endif
|
2021-03-10 02:55:58 +08:00
|
|
|
telemetry->AddCollector("event_counters", []() -> nlohmann::json {
|
|
|
|
nlohmann::json ret;
|
2023-05-18 01:20:56 +08:00
|
|
|
for (size_t i = 0; i < memgraph::metrics::CounterEnd(); ++i) {
|
|
|
|
ret[memgraph::metrics::GetCounterName(i)] =
|
|
|
|
memgraph::metrics::global_counters[i].load(std::memory_order_relaxed);
|
2021-03-10 02:55:58 +08:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
});
|
2022-02-22 20:33:45 +08:00
|
|
|
telemetry->AddCollector("query_module_counters", []() -> nlohmann::json {
|
|
|
|
return memgraph::query::plan::CallProcedure::GetAndResetCounters();
|
|
|
|
});
|
2019-12-11 22:45:34 +08:00
|
|
|
}
|
2023-09-20 19:13:54 +08:00
|
|
|
memgraph::license::LicenseInfoSender license_info_sender(telemetry_server, memgraph::glue::run_id_, machine_id,
|
|
|
|
memory_limit,
|
2022-11-04 22:23:43 +08:00
|
|
|
memgraph::license::global_license_checker.GetLicenseInfo());
|
2018-06-20 19:46:54 +08:00
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
memgraph::communication::websocket::SafeAuth websocket_auth{&auth_};
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::communication::websocket::Server websocket_server{
|
2022-02-17 17:27:24 +08:00
|
|
|
{FLAGS_monitoring_address, static_cast<uint16_t>(FLAGS_monitoring_port)}, &context, websocket_auth};
|
2023-08-19 00:23:15 +08:00
|
|
|
memgraph::flags::AddLoggerSink(websocket_server.GetLoggingSink());
|
2022-01-04 19:13:48 +08:00
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
|
|
|
// TODO: Make multi-tenant
|
2023-08-19 00:23:15 +08:00
|
|
|
memgraph::glue::MonitoringServerT metrics_server{
|
2023-09-20 19:13:54 +08:00
|
|
|
{FLAGS_metrics_address, static_cast<uint16_t>(FLAGS_metrics_port)}, db_acc->storage(), &context};
|
|
|
|
#endif
|
2023-05-18 01:20:56 +08:00
|
|
|
|
2017-12-19 19:40:30 +08:00
|
|
|
// Handler for regular termination signals
|
2023-09-20 19:13:54 +08:00
|
|
|
auto shutdown = [
|
|
|
|
#ifdef MG_ENTERPRISE
|
|
|
|
&metrics_server,
|
|
|
|
#endif
|
|
|
|
&websocket_server, &server, &interpreter_context_] {
|
2021-01-21 22:47:56 +08:00
|
|
|
// Server needs to be shutdown first and then the database. This prevents
|
|
|
|
// a race condition when a transaction is accepted during server shutdown.
|
2017-12-19 19:40:30 +08:00
|
|
|
server.Shutdown();
|
2021-01-21 22:47:56 +08:00
|
|
|
// After the server is notified to stop accepting and processing
|
|
|
|
// connections we tell the execution engine to stop processing all pending
|
|
|
|
// queries.
|
2023-09-20 19:13:54 +08:00
|
|
|
interpreter_context_.Shutdown();
|
2022-01-04 19:13:48 +08:00
|
|
|
websocket_server.Shutdown();
|
2023-09-20 19:13:54 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
|
|
|
metrics_server.Shutdown();
|
|
|
|
#endif
|
2017-12-19 19:40:30 +08:00
|
|
|
};
|
2022-01-04 19:13:48 +08:00
|
|
|
|
2017-12-19 19:40:30 +08:00
|
|
|
InitSignalHandlers(shutdown);
|
2018-04-20 20:58:49 +08:00
|
|
|
|
2023-09-20 19:13:54 +08:00
|
|
|
// Release the temporary database access
|
|
|
|
db_acc.reset();
|
|
|
|
|
|
|
|
// Startup the main server
|
2021-01-21 22:47:56 +08:00
|
|
|
MG_ASSERT(server.Start(), "Couldn't start the Bolt server!");
|
2022-01-04 19:13:48 +08:00
|
|
|
websocket_server.Start();
|
|
|
|
|
2023-05-18 01:20:56 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
|
|
|
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
|
|
|
metrics_server.Start();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-12-10 01:50:33 +08:00
|
|
|
if (!FLAGS_init_data_file.empty()) {
|
|
|
|
spdlog::info("Running init data file.");
|
|
|
|
#ifdef MG_ENTERPRISE
|
2023-09-20 19:13:54 +08:00
|
|
|
auto db_acc = new_handler.Get(memgraph::dbms::kDefaultDB);
|
2022-12-10 01:50:33 +08:00
|
|
|
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
2023-09-20 19:13:54 +08:00
|
|
|
InitFromCypherlFile(interpreter_context_, db_acc, FLAGS_init_data_file, &audit_log);
|
2023-06-20 23:54:50 +08:00
|
|
|
} else {
|
2023-09-20 19:13:54 +08:00
|
|
|
InitFromCypherlFile(interpreter_context_, db_acc, FLAGS_init_data_file);
|
2022-12-10 01:50:33 +08:00
|
|
|
}
|
|
|
|
#else
|
2023-09-20 19:13:54 +08:00
|
|
|
auto db_acc_2 = db_gatekeeper.access();
|
|
|
|
MG_ASSERT(db_acc_2, "Failed to gain access to the main database");
|
|
|
|
InitFromCypherlFile(interpreter_context_, *db_acc_2, FLAGS_init_data_file);
|
2022-12-10 01:50:33 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-01-10 20:56:12 +08:00
|
|
|
server.AwaitShutdown();
|
2022-01-04 19:13:48 +08:00
|
|
|
websocket_server.AwaitShutdown();
|
2023-05-18 01:20:56 +08:00
|
|
|
#ifdef MG_ENTERPRISE
|
|
|
|
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
|
|
|
metrics_server.AwaitShutdown();
|
|
|
|
}
|
|
|
|
#endif
|
2022-01-04 19:13:48 +08:00
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::query::procedure::gModuleRegistry.UnloadAllModules();
|
2017-12-19 19:40:30 +08:00
|
|
|
|
2020-02-24 21:06:21 +08:00
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
// Shutdown Python
|
|
|
|
Py_Finalize();
|
|
|
|
PyMem_RawFree(program_name);
|
2021-02-23 03:51:46 +08:00
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
memgraph::utils::total_memory_tracker.LogPeakMemoryUsage();
|
2020-02-24 21:06:21 +08:00
|
|
|
return 0;
|
2019-12-09 18:31:27 +08:00
|
|
|
}
|