Replication refactor part 7 (#1550)

* Split queries into system and data queries
* System queries are sequentially executed and generate separate transaction deltas
* System transaction try locks for 100ms
* last_commited_system_ts saved to DBMS durability
* Replicating CREATE/DROP DATABASE
* Sending a system snapshot if REPLICA behind
* Passing a copy of the gatekeeper::access as std::any to all functions that could call an async execution
* Removed delete_on_drop flag (we now always delete on drop)
* Using UUID as the directory name for databases
* DBMS durability update (added versioning and salient information)
* Automatic migration from previous version
* Interpreter can run some queries without a target database
* SHOW REPLICA returns the status of the currently active DB
* Returning UUID instead of db name in the RPC responses
* Using UUIDs for database specification in RPC (not name)
* FrequentCheck forces update on reconnect
* TimestampRpc will detect if a replica is behind, and will update client's state
* Safer SLK reads
* Split SHOW DATABASES in two SHOW DATABASES (list of current databases) and SHOW DATABASE a single string naming the current database

---------

Co-authored-by: Gareth Lloyd <gareth.lloyd@memgraph.io>
This commit is contained in:
andrejtonev
2024-01-23 12:06:10 +01:00
committed by GitHub
parent 7f10636470
commit 071df2f439
154 changed files with 4896 additions and 1390 deletions

View File

@@ -77,6 +77,10 @@ add_subdirectory(query_modules_storage_modes)
add_subdirectory(garbage_collection)
add_subdirectory(query_planning)
if (MG_EXPERIMENTAL_REPLICATION_MULTITENANCY)
add_subdirectory(replication_experimental)
endif ()
copy_e2e_python_files(pytest_runner pytest_runner.sh "")
copy_e2e_python_files(x x.sh "")
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/memgraph-selfsigned.crt DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

View File

@@ -4,3 +4,5 @@ endfunction()
copy_analytical_mode_e2e_python_files(common.py)
copy_analytical_mode_e2e_python_files(free_memory.py)
copy_e2e_files(analytical_mode workloads.yaml)

View File

@@ -4,3 +4,5 @@ endfunction()
copy_analyze_graph_e2e_python_files(common.py)
copy_analyze_graph_e2e_python_files(optimize_indexes.py)
copy_e2e_files(analyze_graph workloads.yaml)

View File

@@ -7,3 +7,5 @@ copy_batched_procedures_e2e_python_files(conftest.py)
copy_batched_procedures_e2e_python_files(simple_read.py)
add_subdirectory(procedures)
copy_e2e_files(batched_procedures workloads.yaml)

View File

@@ -6,3 +6,5 @@ copy_concurrent_query_modules_e2e_python_files(client.py)
copy_concurrent_query_modules_e2e_python_files(con_query_modules.py)
add_subdirectory(test_query_modules)
copy_e2e_files(concurrent_query_modules workloads.yaml)

View File

@@ -1,7 +1,9 @@
function(copy_configuration_check_e2e_python_files FILE_NAME)
copy_e2e_python_files(write_procedures ${FILE_NAME})
copy_e2e_python_files(configuration ${FILE_NAME})
endfunction()
copy_configuration_check_e2e_python_files(default_config.py)
copy_configuration_check_e2e_python_files(configuration_check.py)
copy_configuration_check_e2e_python_files(storage_info.py)
copy_e2e_files(configuration workloads.yaml)

View File

@@ -174,11 +174,6 @@ startup_config_dict = {
"Default storage mode Memgraph uses. Allowed values: IN_MEMORY_TRANSACTIONAL, IN_MEMORY_ANALYTICAL, ON_DISK_TRANSACTIONAL",
),
"storage_wal_file_size_kib": ("20480", "20480", "Minimum file size of each WAL file."),
"storage_delete_on_drop": (
"true",
"true",
"If set to true the query 'DROP DATABASE x' will delete the underlying storage as well.",
),
"stream_transaction_conflict_retries": (
"30",
"30",

View File

@@ -4,3 +4,5 @@ endfunction()
copy_constraint_validation_e2e_python_files(common.py)
copy_constraint_validation_e2e_python_files(constraints_validation.py)
copy_e2e_files(constraint_validation workloads.yaml)

View File

@@ -13,3 +13,5 @@ copy_disk_storage_e2e_python_files(snapshot_disabled.py)
copy_disk_storage_e2e_python_files(lock_data_dir_disabled.py)
copy_disk_storage_e2e_python_files(create_edge_from_indices.py)
copy_disk_storage_e2e_python_files(storage_info.py)
copy_e2e_files(disk_storage workloads.yaml)

View File

@@ -7,3 +7,5 @@ copy_fine_grained_access_e2e_python_files(create_delete_filtering_tests.py)
copy_fine_grained_access_e2e_python_files(edge_type_filtering_tests.py)
copy_fine_grained_access_e2e_python_files(path_filtering_tests.py)
copy_fine_grained_access_e2e_python_files(show_db.py)
copy_e2e_files(fine_grained_access workloads.yaml)

View File

@@ -23,13 +23,20 @@ def test_show_databases_w_user():
user3_connection = common.connect(username="user3", password="test")
assert common.execute_and_fetch_all(admin_connection.cursor(), "SHOW DATABASES") == [
("db1", ""),
("db2", ""),
("memgraph", "*"),
("db1",),
("db2",),
("memgraph",),
]
assert common.execute_and_fetch_all(user_connection.cursor(), "SHOW DATABASES") == [("db1", ""), ("memgraph", "*")]
assert common.execute_and_fetch_all(user2_connection.cursor(), "SHOW DATABASES") == [("db2", "*")]
assert common.execute_and_fetch_all(user3_connection.cursor(), "SHOW DATABASES") == [("db1", "*"), ("db2", "")]
assert common.execute_and_fetch_all(admin_connection.cursor(), "SHOW DATABASE") == [("memgraph",)]
assert common.execute_and_fetch_all(user_connection.cursor(), "SHOW DATABASES") == [("db1",), ("memgraph",)]
assert common.execute_and_fetch_all(user_connection.cursor(), "SHOW DATABASE") == [("memgraph",)]
assert common.execute_and_fetch_all(user2_connection.cursor(), "SHOW DATABASES") == [("db2",)]
assert common.execute_and_fetch_all(user2_connection.cursor(), "SHOW DATABASE") == [("db2",)]
assert common.execute_and_fetch_all(user3_connection.cursor(), "SHOW DATABASES") == [("db1",), ("db2",)]
assert common.execute_and_fetch_all(user3_connection.cursor(), "SHOW DATABASE") == [("db1",)]
if __name__ == "__main__":

View File

@@ -5,3 +5,5 @@ endfunction()
garbage_collection_e2e_python_files(common.py)
garbage_collection_e2e_python_files(conftest.py)
garbage_collection_e2e_python_files(gc_periodic.py)
copy_e2e_files(garbage_collection workloads.yaml)

View File

@@ -8,3 +8,5 @@ copy_graphql_e2e_python_files(callable_alias_mapping.json)
add_subdirectory(graphql_library_config)
add_subdirectory(temporary_procedures)
copy_e2e_files(graphql workloads.yaml)

View File

@@ -4,3 +4,5 @@ endfunction()
copy_import_mode_e2e_python_files(common.py)
copy_import_mode_e2e_python_files(test_command.py)
copy_e2e_files(import_mode workloads.yaml)

View File

@@ -4,3 +4,5 @@ endfunction()
copy_index_hints_e2e_python_files(common.py)
copy_index_hints_e2e_python_files(index_hints.py)
copy_e2e_files(index_hints workloads.yaml)

View File

@@ -10,3 +10,5 @@ copy_init_file_flags_e2e_python_files(init_file_setup.py)
copy_init_file_flags_e2e_python_files(init_data_file_setup.py)
copy_init_file_flags_e2e_files(init_file.cypherl)
copy_e2e_files(init_file_flags workloads.yaml)

View File

@@ -4,3 +4,5 @@ endfunction()
copy_inspect_query_e2e_python_files(common.py)
copy_inspect_query_e2e_python_files(inspect_query.py)
copy_e2e_files(inspect_query workloads.yaml)

View File

@@ -2,3 +2,5 @@ find_package(gflags REQUIRED)
add_executable(memgraph__e2e__isolation_levels isolation_levels.cpp)
target_link_libraries(memgraph__e2e__isolation_levels gflags mgclient mg-utils mg-io Threads::Threads)
copy_e2e_files(isolation_levels workloads.yaml)

View File

@@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd.
// Copyright 2024 Memgraph Ltd.
//
// 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
@@ -87,18 +87,13 @@ void SwitchToDB(const std::string &name, std::unique_ptr<mg::Client> &client) {
void SwitchToCleanDB(std::unique_ptr<mg::Client> &client) { SwitchToDB("clean", client); }
void SwitchToSameDB(std::unique_ptr<mg::Client> &main, std::unique_ptr<mg::Client> &client) {
MG_ASSERT(main->Execute("SHOW DATABASES;"));
MG_ASSERT(main->Execute("SHOW DATABASE;"));
auto dbs = main->FetchAll();
MG_ASSERT(dbs, "Failed to show databases");
for (const auto &elem : *dbs) {
MG_ASSERT(!elem.empty(), "Show databases wrong output");
const auto &active = elem[1].ValueString();
if (active == "*") {
const auto &name = elem[0].ValueString();
SwitchToDB(std::string(name), client);
break;
}
}
MG_ASSERT(!dbs->empty(), "Show databases wrong output");
MG_ASSERT(!(*dbs)[0].empty(), "Show databases wrong output");
const auto &name = (*dbs)[0][0].ValueString();
SwitchToDB(std::string(name), client);
}
void TestSnapshotIsolation(std::unique_ptr<mg::Client> &client) {

View File

@@ -11,3 +11,5 @@ copy_lba_procedures_e2e_python_files(read_permission_queries.py)
copy_lba_procedures_e2e_python_files(update_permission_queries.py)
add_subdirectory(procedures)
copy_e2e_files(lba_procedures workloads.yaml)

View File

@@ -11,3 +11,5 @@ copy_load_csv_e2e_files(simple.csv)
copy_load_csv_e2e_python_files(load_csv_nullif.py)
copy_load_csv_e2e_files(nullif.csv)
copy_e2e_files(load_csv workloads.yaml)

View File

@@ -8,3 +8,5 @@ copy_magic_functions_e2e_python_files(conftest.py)
copy_magic_functions_e2e_python_files(function_example.py)
add_subdirectory(functions)
copy_e2e_files(functions workloads.yaml)

View File

@@ -49,3 +49,5 @@ target_link_libraries(memgraph__e2e__procedure_memory_limit gflags mgclient mg-u
add_executable(memgraph__e2e__procedure_memory_limit_multi_proc procedure_memory_limit_multi_proc.cpp)
target_link_libraries(memgraph__e2e__procedure_memory_limit_multi_proc gflags mgclient mg-utils mg-io)
copy_e2e_files(memory workloads.yaml)

View File

@@ -6,3 +6,5 @@ add_subdirectory(procedures)
copy_mock_python_api_e2e_files(common.py)
copy_mock_python_api_e2e_files(test_compare_mock.py)
copy_e2e_files(mock_python_api workloads.yaml)

View File

@@ -2,3 +2,5 @@ find_package(gflags REQUIRED)
add_executable(memgraph__e2e__module_file_manager module_file_manager.cpp)
target_link_libraries(memgraph__e2e__module_file_manager gflags mgclient mg-utils mg-io Threads::Threads)
copy_e2e_files(module_file_manager workloads.yaml)

View File

@@ -6,3 +6,5 @@ target_link_libraries(memgraph__e2e__monitoring_server mgclient mg-utils json gf
add_executable(memgraph__e2e__monitoring_server_ssl monitoring_ssl.cpp)
target_link_libraries(memgraph__e2e__monitoring_server_ssl mgclient mg-utils json gflags Boost::headers)
copy_e2e_files(monitoring_server workloads.yaml)

View File

@@ -6,3 +6,5 @@ copy_query_modules_reloading_procedures_e2e_python_files(common.py)
copy_query_modules_reloading_procedures_e2e_python_files(test_reload_query_module.py)
add_subdirectory(procedures)
copy_e2e_files(python_query_modules_reloading workloads.yaml)

View File

@@ -4,3 +4,5 @@ endfunction()
copy_queries_e2e_python_files(common.py)
copy_queries_e2e_python_files(queries.py)
copy_e2e_files(queries workloads.yaml)

View File

@@ -7,3 +7,5 @@ copy_query_modules_e2e_python_files(conftest.py)
copy_query_modules_e2e_python_files(convert_test.py)
copy_query_modules_e2e_python_files(mgps_test.py)
copy_query_modules_e2e_python_files(schema_test.py)
copy_e2e_files(query_modules workloads.yaml)

View File

@@ -17,3 +17,5 @@ copy_e2e_python_files(replication_show edge_delete.py)
copy_e2e_python_files_from_parent_folder(replication_show ".." memgraph.py)
copy_e2e_python_files_from_parent_folder(replication_show ".." interactive_mg_runner.py)
copy_e2e_python_files_from_parent_folder(replication_show ".." mg_utils.py)
copy_e2e_files(replication workloads.yaml)

View File

@@ -49,7 +49,7 @@ int main(int argc, char **argv) {
const auto label_name = (*data)[0][1].ValueString();
const auto property_name = (*data)[0][2].ValueList()[0].ValueString();
if (label_name != "Node" || property_name != "id") {
LOG_FATAL("{} does NOT hava valid constraint created.", database_endpoint);
LOG_FATAL("{} does NOT have a valid constraint created.", database_endpoint);
}
} else {
LOG_FATAL("Unable to get CONSTRAINT INFO from {}", database_endpoint);

View File

@@ -308,7 +308,7 @@ def test_basic_recovery(connection):
"--bolt-port",
"7687",
"--log-level=TRACE",
"--storage-recover-on-startup=true",
"--data-recovery-on-startup=true",
"--replication-restore-state-on-startup=true",
],
"log_file": "main.log",

View File

@@ -0,0 +1,10 @@
find_package(gflags REQUIRED)
copy_e2e_python_files(replication_experiment common.py)
copy_e2e_python_files(replication_experiment conftest.py)
copy_e2e_python_files(replication_experiment multitenancy.py)
copy_e2e_python_files_from_parent_folder(replication_experiment ".." memgraph.py)
copy_e2e_python_files_from_parent_folder(replication_experiment ".." interactive_mg_runner.py)
copy_e2e_python_files_from_parent_folder(replication_experiment ".." mg_utils.py)
copy_e2e_files(replication_experiment workloads.yaml)

View File

@@ -0,0 +1,25 @@
# Copyright 2022 Memgraph Ltd.
#
# 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.
import typing
import mgclient
def execute_and_fetch_all(cursor: mgclient.Cursor, query: str, params: dict = {}) -> typing.List[tuple]:
cursor.execute(query, params)
return cursor.fetchall()
def connect(**kwargs) -> mgclient.Connection:
connection = mgclient.connect(**kwargs)
connection.autocommit = True
return connection

View File

@@ -0,0 +1,33 @@
# Copyright 2022 Memgraph Ltd.
#
# 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.
import pytest
from common import connect, execute_and_fetch_all
@pytest.fixture(scope="function")
def connection():
connection_holder = None
role_holder = None
def inner_connection(port, role):
nonlocal connection_holder, role_holder
connection_holder = connect(host="localhost", port=port)
role_holder = role
return connection_holder
yield inner_connection
# Only main instance can be cleaned up because replicas do NOT accept
# writes.
if role_holder == "main":
cursor = connection_holder.cursor()
execute_and_fetch_all(cursor, "MATCH (n) DETACH DELETE n;")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
workloads:
- name: "Replicate multitenancy"
binary: "tests/e2e/pytest_runner.sh"
args: ["replication_experimental/multitenancy.py"]

View File

@@ -25,7 +25,7 @@ if [ "$#" -eq 0 ]; then
# NOTE: If you want to run all tests under specific folder/section just
# replace the dot (root directory below) with the folder name, e.g.
# `--workloads-root-directory replication`.
python3 runner.py --workloads-root-directory .
python3 runner.py --workloads-root-directory "$SCRIPT_DIR/../../build"
elif [ "$#" -eq 1 ]; then
if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
print_help
@@ -34,7 +34,7 @@ elif [ "$#" -eq 1 ]; then
# NOTE: --workload-name comes from each individual folder/section
# workloads.yaml file. E.g. `streams/workloads.yaml` has a list of
# `workloads:` and each workload has it's `-name`.
python3 runner.py --workloads-root-directory . --workload-name "$1"
python3 runner.py --workloads-root-directory "$SCRIPT_DIR/../../build" --workload-name "$1"
else
print_help
fi

View File

@@ -1,3 +1,5 @@
#!/usr/bin/env python3
# Copyright 2021 Memgraph Ltd.
#
# Use of this software is governed by the Business Source License

View File

@@ -6,3 +6,5 @@ target_link_libraries(memgraph__e2e__server_connection mgclient mg-utils gflags)
add_executable(memgraph__e2e__server_ssl_connection server_ssl_connection.cpp)
target_link_libraries(memgraph__e2e__server_ssl_connection mgclient mg-utils gflags)
copy_e2e_files(server workloads.yaml)

View File

@@ -6,3 +6,5 @@ copy_set_properties_e2e_python_files(common.py)
copy_set_properties_e2e_python_files(set_properties.py)
add_subdirectory(procedures)
copy_e2e_files(set_properties workloads.yaml)

View File

@@ -4,3 +4,5 @@ endfunction()
copy_show_index_info_e2e_python_files(common.py)
copy_show_index_info_e2e_python_files(test_show_index_info.py)
copy_e2e_files(show_index_info workloads.yaml)

View File

@@ -11,3 +11,5 @@ copy_streams_e2e_python_files(pulsar_streams_tests.py)
add_subdirectory(transformations)
copy_e2e_python_files_from_parent_folder(streams ".." mg_utils.py)
copy_e2e_files(streams workloads.yaml)

View File

@@ -4,3 +4,4 @@ find_package(gflags REQUIRED)
add_executable(memgraph__e2e__temporal_roundtrip roundtrip.cpp)
target_link_libraries(memgraph__e2e__temporal_roundtrip PUBLIC mgclient mg-utils gflags)
copy_e2e_files(temporal_roundtrip workloads.yaml)

View File

@@ -6,3 +6,5 @@ copy_query_modules_reloading_procedures_e2e_python_files(common.py)
copy_query_modules_reloading_procedures_e2e_python_files(test_transaction_queue.py)
add_subdirectory(procedures)
copy_e2e_files(transaction_queue workloads.yaml)

View File

@@ -7,3 +7,5 @@ transaction_rollback_e2e_python_files(conftest.py)
transaction_rollback_e2e_python_files(transaction.py)
add_subdirectory(procedures)
copy_e2e_files(transaction_rollback workloads.yaml)

View File

@@ -27,3 +27,5 @@ endfunction()
copy_triggers_e2e_python_files(common.py)
copy_triggers_e2e_python_files(triggers_properties_false.py)
copy_e2e_files(triggers workloads.yaml)

View File

@@ -8,3 +8,5 @@ copy_write_procedures_e2e_python_files(simple_write.py)
copy_write_procedures_e2e_python_files(read_subgraph.py)
add_subdirectory(procedures)
copy_e2e_files(write_procedures workloads.yaml)

View File

@@ -44,7 +44,7 @@ int main(int argc, char **argv) {
memgraph::dbms::DbmsHandler dbms_handler(db_config
#ifdef MG_ENTERPRISE
,
&auth_, false, false
&auth_, false
#endif
);
memgraph::query::InterpreterContext interpreter_context_({}, &dbms_handler, &repl_state, &auth_handler,

View File

@@ -415,6 +415,9 @@ if(MG_ENTERPRISE)
add_unit_test_with_custom_main(dbms_handler.cpp)
target_link_libraries(${test_prefix}dbms_handler mg-query mg-auth mg-glue mg-dbms)
add_unit_test(multi_tenancy.cpp)
target_link_libraries(${test_prefix}multi_tenancy mg-query mg-auth mg-glue mg-dbms)
else()
add_unit_test_with_custom_main(dbms_handler_community.cpp)
target_link_libraries(${test_prefix}dbms_handler_community mg-query mg-auth mg-glue mg-dbms)

View File

@@ -206,11 +206,11 @@ void TestVertexAndEdgeWithDifferentStorages(std::unique_ptr<memgraph::storage::S
// check everything
std::vector<Value> vals;
vals.push_back(*memgraph::glue::ToBoltValue(memgraph::query::TypedValue(memgraph::query::VertexAccessor(va1)), *db,
memgraph::storage::View::NEW));
vals.push_back(*memgraph::glue::ToBoltValue(memgraph::query::TypedValue(memgraph::query::VertexAccessor(va2)), *db,
memgraph::storage::View::NEW));
vals.push_back(*memgraph::glue::ToBoltValue(memgraph::query::TypedValue(memgraph::query::EdgeAccessor(ea)), *db,
vals.push_back(*memgraph::glue::ToBoltValue(memgraph::query::TypedValue(memgraph::query::VertexAccessor(va1)),
db.get(), memgraph::storage::View::NEW));
vals.push_back(*memgraph::glue::ToBoltValue(memgraph::query::TypedValue(memgraph::query::VertexAccessor(va2)),
db.get(), memgraph::storage::View::NEW));
vals.push_back(*memgraph::glue::ToBoltValue(memgraph::query::TypedValue(memgraph::query::EdgeAccessor(ea)), db.get(),
memgraph::storage::View::NEW));
bolt_encoder.MessageRecord(vals);

View File

@@ -108,7 +108,7 @@ TYPED_TEST(InfoTest, InfoCheck) {
auto v2 = acc->CreateVertex();
auto v3 = acc->CreateVertex();
auto v4 = acc->CreateVertex();
auto v5 = acc->CreateVertex();
[[maybe_unused]] auto v5 = acc->CreateVertex();
ASSERT_FALSE(v2.AddLabel(lbl).HasError());
ASSERT_FALSE(v3.AddLabel(lbl).HasError());

View File

@@ -29,7 +29,8 @@ memgraph::storage::Config default_conf(std::string name = "") {
return {.durability = {.storage_directory = storage_directory / name,
.snapshot_wal_mode =
memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL},
.disk = {.main_storage_directory = storage_directory / name / "disk"}};
.disk = {.main_storage_directory = storage_directory / name / "disk"},
.salient.name = name.empty() ? std::string{"memgraph"} : name};
}
class DBMS_Database : public ::testing::Test {
@@ -55,20 +56,21 @@ TEST_F(DBMS_Database, New) {
.durability = {.storage_directory = storage_directory / "db2",
.snapshot_wal_mode =
memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL},
.disk = {.main_storage_directory = storage_directory / "disk"}};
auto db2 = db_handler.New("db2", db_config, generic_repl_state);
.disk = {.main_storage_directory = storage_directory / "disk"},
.salient.name = "db2"};
auto db2 = db_handler.New(db_config, generic_repl_state);
ASSERT_TRUE(db2.HasValue() && db2.GetValue());
ASSERT_TRUE(std::filesystem::exists(storage_directory / "db2"));
}
{
// With default config
auto db3 = db_handler.New("db3", default_conf("db3"), generic_repl_state);
auto db3 = db_handler.New(default_conf("db3"), generic_repl_state);
ASSERT_TRUE(db3.HasValue() && db3.GetValue());
ASSERT_TRUE(std::filesystem::exists(storage_directory / "db3"));
auto db4 = db_handler.New("db4", default_conf("four"), generic_repl_state);
auto db4 = db_handler.New(default_conf("four"), generic_repl_state);
ASSERT_TRUE(db4.HasValue() && db4.GetValue());
ASSERT_TRUE(std::filesystem::exists(storage_directory / "four"));
auto db5 = db_handler.New("db5", default_conf("db3"), generic_repl_state);
auto db5 = db_handler.New(default_conf("db3"), generic_repl_state);
ASSERT_TRUE(db5.HasError() && db5.GetError() == memgraph::dbms::NewError::EXISTS);
}
@@ -77,15 +79,15 @@ TEST_F(DBMS_Database, New) {
ASSERT_EQ(all.size(), 3);
ASSERT_EQ(all[0], "db2");
ASSERT_EQ(all[1], "db3");
ASSERT_EQ(all[2], "db4");
ASSERT_EQ(all[2], "four");
}
TEST_F(DBMS_Database, Get) {
memgraph::dbms::DatabaseHandler db_handler;
auto db1 = db_handler.New("db1", default_conf("db1"), generic_repl_state);
auto db2 = db_handler.New("db2", default_conf("db2"), generic_repl_state);
auto db3 = db_handler.New("db3", default_conf("db3"), generic_repl_state);
auto db1 = db_handler.New(default_conf("db1"), generic_repl_state);
auto db2 = db_handler.New(default_conf("db2"), generic_repl_state);
auto db3 = db_handler.New(default_conf("db3"), generic_repl_state);
ASSERT_TRUE(db1.HasValue());
ASSERT_TRUE(db2.HasValue());
@@ -107,9 +109,9 @@ TEST_F(DBMS_Database, Get) {
TEST_F(DBMS_Database, Delete) {
memgraph::dbms::DatabaseHandler db_handler;
auto db1 = db_handler.New("db1", default_conf("db1"), generic_repl_state);
auto db2 = db_handler.New("db2", default_conf("db2"), generic_repl_state);
auto db3 = db_handler.New("db3", default_conf("db3"), generic_repl_state);
auto db1 = db_handler.New(default_conf("db1"), generic_repl_state);
auto db2 = db_handler.New(default_conf("db2"), generic_repl_state);
auto db3 = db_handler.New(default_conf("db3"), generic_repl_state);
ASSERT_TRUE(db1.HasValue());
ASSERT_TRUE(db2.HasValue());
@@ -119,7 +121,7 @@ TEST_F(DBMS_Database, Delete) {
// Release accessor to storage
db1.GetValue().reset();
// Delete from handler
ASSERT_TRUE(db_handler.Delete("db1"));
ASSERT_TRUE(db_handler.TryDelete("db1"));
ASSERT_FALSE(db_handler.Get("db1"));
auto all = db_handler.All();
std::sort(all.begin(), all.end());
@@ -129,8 +131,8 @@ TEST_F(DBMS_Database, Delete) {
}
{
ASSERT_THROW(db_handler.Delete("db0"), memgraph::utils::BasicException);
ASSERT_THROW(db_handler.Delete("db1"), memgraph::utils::BasicException);
ASSERT_THROW(db_handler.TryDelete("db0"), memgraph::utils::BasicException);
ASSERT_THROW(db_handler.TryDelete("db1"), memgraph::utils::BasicException);
auto all = db_handler.All();
std::sort(all.begin(), all.end());
ASSERT_EQ(all.size(), 2);
@@ -144,17 +146,18 @@ TEST_F(DBMS_Database, DeleteAndRecover) {
memgraph::dbms::DatabaseHandler db_handler;
{
auto db1 = db_handler.New("db1", default_conf("db1"), generic_repl_state);
auto db2 = db_handler.New("db2", default_conf("db2"), generic_repl_state);
auto db1 = db_handler.New(default_conf("db1"), generic_repl_state);
auto db2 = db_handler.New(default_conf("db2"), generic_repl_state);
memgraph::storage::Config conf_w_snap{
.durability = {.storage_directory = storage_directory / "db3",
.snapshot_wal_mode =
memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
.snapshot_on_exit = true},
.disk = {.main_storage_directory = storage_directory / "db3" / "disk"}};
.disk = {.main_storage_directory = storage_directory / "db3" / "disk"},
.salient.name = "db3"};
auto db3 = db_handler.New("db3", conf_w_snap, generic_repl_state);
auto db3 = db_handler.New(conf_w_snap, generic_repl_state);
ASSERT_TRUE(db1.HasValue());
ASSERT_TRUE(db2.HasValue());
@@ -184,23 +187,24 @@ TEST_F(DBMS_Database, DeleteAndRecover) {
}
// Delete from handler
ASSERT_TRUE(db_handler.Delete("db1"));
ASSERT_TRUE(db_handler.Delete("db2"));
ASSERT_TRUE(db_handler.Delete("db3"));
ASSERT_TRUE(db_handler.TryDelete("db1"));
ASSERT_TRUE(db_handler.TryDelete("db2"));
ASSERT_TRUE(db_handler.TryDelete("db3"));
{
// Recover graphs (only db3)
auto db1 = db_handler.New("db1", default_conf("db1"), generic_repl_state);
auto db2 = db_handler.New("db2", default_conf("db2"), generic_repl_state);
auto db1 = db_handler.New(default_conf("db1"), generic_repl_state);
auto db2 = db_handler.New(default_conf("db2"), generic_repl_state);
memgraph::storage::Config conf_w_rec{
.durability = {.storage_directory = storage_directory / "db3",
.recover_on_startup = true,
.snapshot_wal_mode =
memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL},
.disk = {.main_storage_directory = storage_directory / "db3" / "disk"}};
.disk = {.main_storage_directory = storage_directory / "db3" / "disk"},
.salient.name = "db3"};
auto db3 = db_handler.New("db3", conf_w_rec, generic_repl_state);
auto db3 = db_handler.New(conf_w_rec, generic_repl_state);
// Check content
{

View File

@@ -25,8 +25,23 @@
#include "query/config.hpp"
#include "query/interpreter.hpp"
namespace {
std::set<std::string> GetDirs(auto path) {
std::set<std::string> dirs;
// Clean the unused directories
for (const auto &entry : std::filesystem::directory_iterator(path)) {
const auto &name = entry.path().filename().string();
if (entry.is_directory() && !name.empty() && name.front() != '.') {
dirs.emplace(name);
}
}
return dirs;
}
} // namespace
// Global
std::filesystem::path storage_directory{std::filesystem::temp_directory_path() / "MG_test_unit_dbms_handler"};
std::filesystem::path db_dir{storage_directory / "databases"};
static memgraph::storage::Config storage_conf;
std::unique_ptr<memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock>> auth;
@@ -52,7 +67,7 @@ class TestEnvironment : public ::testing::Environment {
auth =
std::make_unique<memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock>>(
storage_directory / "auth");
ptr_ = std::make_unique<memgraph::dbms::DbmsHandler>(storage_conf, auth.get(), false, true);
ptr_ = std::make_unique<memgraph::dbms::DbmsHandler>(storage_conf, auth.get(), false);
}
void TearDown() override {
@@ -74,7 +89,7 @@ TEST(DBMS_Handler, Init) {
std::vector<std::string> dirs = {"snapshots", "streams", "triggers", "wal"};
for (const auto &dir : dirs)
ASSERT_TRUE(std::filesystem::exists(storage_directory / dir)) << (storage_directory / dir);
const auto db_path = storage_directory / "databases" / memgraph::dbms::kDefaultDB;
const auto db_path = db_dir / memgraph::dbms::kDefaultDB;
ASSERT_TRUE(std::filesystem::exists(db_path));
for (const auto &dir : dirs) {
std::error_code ec;
@@ -92,10 +107,14 @@ TEST(DBMS_Handler, New) {
ASSERT_EQ(all[0], memgraph::dbms::kDefaultDB);
}
{
const auto dirs = GetDirs(db_dir);
auto db1 = dbms.New("db1");
ASSERT_TRUE(db1.HasValue());
ASSERT_TRUE(db1.GetValue());
ASSERT_TRUE(std::filesystem::exists(storage_directory / "databases" / "db1"));
// New flow doesn't make db named directories
ASSERT_FALSE(std::filesystem::exists(db_dir / "db1"));
const auto dirs_w_db1 = GetDirs(db_dir);
ASSERT_EQ(dirs_w_db1.size(), dirs.size() + 1);
ASSERT_TRUE(db1.GetValue()->storage() != nullptr);
ASSERT_TRUE(db1.GetValue()->streams() != nullptr);
ASSERT_TRUE(db1.GetValue()->trigger_store() != nullptr);
@@ -111,9 +130,13 @@ TEST(DBMS_Handler, New) {
ASSERT_TRUE(db2.HasError() && db2.GetError() == memgraph::dbms::NewError::EXISTS);
}
{
const auto dirs = GetDirs(db_dir);
auto db3 = dbms.New("db3");
ASSERT_TRUE(db3.HasValue());
ASSERT_TRUE(std::filesystem::exists(storage_directory / "databases" / "db3"));
// New flow doesn't make db named directories
ASSERT_FALSE(std::filesystem::exists(db_dir / "db3"));
const auto dirs_w_db3 = GetDirs(db_dir);
ASSERT_EQ(dirs_w_db3.size(), dirs.size() + 1);
ASSERT_TRUE(db3.GetValue()->storage() != nullptr);
ASSERT_TRUE(db3.GetValue()->streams() != nullptr);
ASSERT_TRUE(db3.GetValue()->trigger_store() != nullptr);
@@ -156,16 +179,16 @@ TEST(DBMS_Handler, Delete) {
auto db1_acc = dbms.Get("db1"); // Holds access to database
{
auto del = dbms.Delete(memgraph::dbms::kDefaultDB);
auto del = dbms.TryDelete(memgraph::dbms::kDefaultDB);
ASSERT_TRUE(del.HasError() && del.GetError() == memgraph::dbms::DeleteError::DEFAULT_DB);
}
{
auto del = dbms.Delete("non-existent");
auto del = dbms.TryDelete("non-existent");
ASSERT_TRUE(del.HasError() && del.GetError() == memgraph::dbms::DeleteError::NON_EXISTENT);
}
{
// db1_acc is using db1
auto del = dbms.Delete("db1");
auto del = dbms.TryDelete("db1");
ASSERT_TRUE(del.HasError());
ASSERT_TRUE(del.GetError() == memgraph::dbms::DeleteError::USING);
}
@@ -173,15 +196,17 @@ TEST(DBMS_Handler, Delete) {
// Reset db1_acc (releases access) so delete will succeed
db1_acc.reset();
ASSERT_FALSE(db1_acc);
auto del = dbms.Delete("db1");
auto del = dbms.TryDelete("db1");
ASSERT_FALSE(del.HasError()) << (int)del.GetError();
auto del2 = dbms.Delete("db1");
auto del2 = dbms.TryDelete("db1");
ASSERT_TRUE(del2.HasError() && del2.GetError() == memgraph::dbms::DeleteError::NON_EXISTENT);
}
{
auto del = dbms.Delete("db3");
const auto dirs = GetDirs(db_dir);
auto del = dbms.TryDelete("db3");
ASSERT_FALSE(del.HasError());
ASSERT_FALSE(std::filesystem::exists(storage_directory / "databases" / "db3"));
const auto dirs_wo_db3 = GetDirs(db_dir);
ASSERT_EQ(dirs_wo_db3.size(), dirs.size() - 1);
}
}

View File

@@ -90,9 +90,9 @@ TEST(DBMS_Handler, Get) {
ASSERT_TRUE(default_db->streams() != nullptr);
ASSERT_TRUE(default_db->trigger_store() != nullptr);
ASSERT_TRUE(default_db->thread_pool() != nullptr);
ASSERT_EQ(default_db->storage()->id(), memgraph::dbms::kDefaultDB);
ASSERT_EQ(default_db->storage()->name(), memgraph::dbms::kDefaultDB);
auto conf = storage_conf;
conf.name = memgraph::dbms::kDefaultDB;
conf.salient.name = memgraph::dbms::kDefaultDB;
ASSERT_EQ(default_db->storage()->config_, conf);
}

View File

@@ -21,8 +21,9 @@ struct InterpreterFaker {
}
auto Prepare(const std::string &query, const std::map<std::string, memgraph::storage::PropertyValue> &params = {}) {
ResultStreamFaker stream(interpreter.current_db_.db_acc_->get()->storage());
const auto [header, _1, qid, _2] = interpreter.Prepare(query, params, {});
auto &db = interpreter.current_db_.db_acc_;
ResultStreamFaker stream(db ? db->get()->storage() : nullptr);
stream.Header(header);
return std::make_pair(std::move(stream), qid);
}

View File

@@ -0,0 +1,378 @@
// Copyright 2024 Memgraph Ltd.
//
// 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.
#include <algorithm>
#include <cstdlib>
#include <filesystem>
#include <thread>
#include "communication/bolt/v1/value.hpp"
#include "communication/result_stream_faker.hpp"
#include "csv/parsing.hpp"
#include "dbms/dbms_handler.hpp"
#include "disk_test_utils.hpp"
#include "flags/run_time_configurable.hpp"
#include "glue/communication.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "interpreter_faker.hpp"
#include "license/license.hpp"
#include "query/auth_checker.hpp"
#include "query/config.hpp"
#include "query/exceptions.hpp"
#include "query/interpreter.hpp"
#include "query/interpreter_context.hpp"
#include "query/metadata.hpp"
#include "query/stream.hpp"
#include "query/typed_value.hpp"
#include "query_common.hpp"
#include "replication/state.hpp"
#include "storage/v2/inmemory/storage.hpp"
#include "storage/v2/isolation_level.hpp"
#include "storage/v2/property_value.hpp"
#include "storage/v2/storage_mode.hpp"
#include "utils/logging.hpp"
#include "utils/lru_cache.hpp"
#include "utils/synchronized.hpp"
namespace {
std::set<std::string> GetDirs(auto path) {
std::set<std::string> dirs;
// Clean the unused directories
for (const auto &entry : std::filesystem::directory_iterator(path)) {
const auto &name = entry.path().filename().string();
if (entry.is_directory() && !name.empty() && name.front() != '.') {
dirs.emplace(name);
}
}
return dirs;
}
auto RunMtQuery(auto &interpreter, const std::string &query, std::string_view res) {
auto [stream, qid] = interpreter.Prepare(query);
ASSERT_EQ(stream.GetHeader().size(), 1U);
EXPECT_EQ(stream.GetHeader()[0], "STATUS");
interpreter.Pull(&stream, 1);
ASSERT_EQ(stream.GetSummary().count("has_more"), 1);
ASSERT_FALSE(stream.GetSummary().at("has_more").ValueBool());
ASSERT_EQ(stream.GetResults()[0].size(), 1U);
ASSERT_EQ(stream.GetResults()[0][0].ValueString(), res);
}
auto RunQuery(auto &interpreter, const std::string &query) {
auto [stream, qid] = interpreter.Prepare(query);
interpreter.Pull(&stream, 1);
return stream.GetResults();
}
void UseDatabase(auto &interpreter, const std::string &name, std::string_view res) {
RunMtQuery(interpreter, "USE DATABASE " + name, res);
}
void DropDatabase(auto &interpreter, const std::string &name, std::string_view res) {
RunMtQuery(interpreter, "DROP DATABASE " + name, res);
}
} // namespace
class MultiTenantTest : public ::testing::Test {
public:
std::filesystem::path data_directory = std::filesystem::temp_directory_path() / "MG_tests_unit_multi_tenancy";
MultiTenantTest() = default;
memgraph::storage::Config config{
[&]() {
memgraph::storage::Config config{};
UpdatePaths(config, data_directory);
return config;
}() // iile
};
struct MinMemgraph {
explicit MinMemgraph(const memgraph::storage::Config &conf)
: dbms{conf,
reinterpret_cast<
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *>(0),
true},
interpreter_context{{}, &dbms, &dbms.ReplicationState()} {
memgraph::utils::global_settings.Initialize(conf.durability.storage_directory / "settings");
memgraph::license::RegisterLicenseSettings(memgraph::license::global_license_checker,
memgraph::utils::global_settings);
memgraph::flags::run_time::Initialize();
memgraph::license::global_license_checker.CheckEnvLicense();
}
~MinMemgraph() { memgraph::utils::global_settings.Finalize(); }
auto NewInterpreter() { return InterpreterFaker{&interpreter_context, dbms.Get()}; }
memgraph::dbms::DbmsHandler dbms;
memgraph::query::InterpreterContext interpreter_context;
};
void SetUp() override {
TearDown();
min_mg.emplace(config);
}
void TearDown() override {
min_mg.reset();
if (std::filesystem::exists(data_directory)) std::filesystem::remove_all(data_directory);
}
auto NewInterpreter() { return min_mg->NewInterpreter(); }
auto &DBMS() { return min_mg->dbms; }
std::optional<MinMemgraph> min_mg;
};
TEST_F(MultiTenantTest, SimpleCreateDrop) {
// 1) Create multiple interpreters with the default db
// 2) Create multiple databases using both
// 3) Drop databases while the other is using
// 1
auto interpreter1 = this->NewInterpreter();
auto interpreter2 = this->NewInterpreter();
// 2
auto create = [&](auto &interpreter, const std::string &name, bool success) {
RunMtQuery(interpreter, "CREATE DATABASE " + name,
success ? ("Successfully created database " + name) : (name + " already exists."));
};
create(interpreter1, "db1", true);
create(interpreter1, "db1", false);
create(interpreter2, "db1", false);
create(interpreter2, "db2", true);
create(interpreter1, "db2", false);
create(interpreter2, "db3", true);
create(interpreter2, "db4", true);
// 3
UseDatabase(interpreter1, "db2", "Using db2");
UseDatabase(interpreter1, "db2", "Already using db2");
UseDatabase(interpreter2, "db2", "Using db2");
UseDatabase(interpreter1, "db4", "Using db4");
ASSERT_THROW(DropDatabase(interpreter1, memgraph::dbms::kDefaultDB.data(), ""),
memgraph::query::QueryRuntimeException); // default db
DropDatabase(interpreter1, "db1", "Successfully deleted db1");
ASSERT_THROW(DropDatabase(interpreter2, "db1", ""), memgraph::query::QueryRuntimeException); // No db1
ASSERT_THROW(DropDatabase(interpreter1, "db1", ""), memgraph::query::QueryRuntimeException); // No db1
ASSERT_THROW(DropDatabase(interpreter1, "db2", ""), memgraph::query::QueryRuntimeException); // i2 using db2
ASSERT_THROW(DropDatabase(interpreter1, "db4", ""), memgraph::query::QueryRuntimeException); // i1 using db4
}
TEST_F(MultiTenantTest, DbmsNewTryDelete) {
// 1) Create multiple interpreters with the default db
// 2) Create multiple databases using dbms
// 3) Try delete databases while the interpreters are using them
// 1
auto interpreter1 = this->NewInterpreter();
auto interpreter2 = this->NewInterpreter();
// 2
auto &dbms = DBMS();
ASSERT_FALSE(dbms.New("db1").HasError());
ASSERT_FALSE(dbms.New("db2").HasError());
ASSERT_FALSE(dbms.New("db3").HasError());
ASSERT_FALSE(dbms.New("db4").HasError());
// 3
UseDatabase(interpreter2, "db2", "Using db2");
UseDatabase(interpreter1, "db4", "Using db4");
ASSERT_FALSE(dbms.TryDelete("db1").HasError());
ASSERT_TRUE(dbms.TryDelete("db2").HasError());
ASSERT_FALSE(dbms.TryDelete("db3").HasError());
ASSERT_TRUE(dbms.TryDelete("db4").HasError());
}
TEST_F(MultiTenantTest, DbmsUpdate) {
// 1) Create multiple interpreters with the default db
// 2) Create multiple databases using dbms
// 3) Try to update databases
auto &dbms = DBMS();
auto interpreter1 = this->NewInterpreter();
// Update clean default db
auto default_db = dbms.Get();
const auto old_uuid = default_db->config().salient.uuid;
const memgraph::utils::UUID new_uuid{/* random */};
const memgraph::storage::SalientConfig &config{.name = "memgraph", .uuid = new_uuid};
auto new_default = dbms.Update(config);
ASSERT_TRUE(new_default.HasValue());
ASSERT_NE(new_uuid, old_uuid);
ASSERT_EQ(default_db->storage(), new_default.GetValue()->storage());
// Add node to default
RunQuery(interpreter1, "CREATE (:Node)");
// Fail to update dirty default db
const memgraph::storage::SalientConfig &failing_config{.name = "memgraph", .uuid = {}};
auto failed_update = dbms.Update(failing_config);
ASSERT_TRUE(failed_update.HasError());
// Succeed when updating with the same config
auto same_update = dbms.Update(config);
ASSERT_TRUE(same_update.HasValue());
ASSERT_EQ(new_default.GetValue()->storage(), same_update.GetValue()->storage());
// Create new db
auto db1 = dbms.New("db1");
ASSERT_FALSE(db1.HasError());
RunMtQuery(interpreter1, "USE DATABASE db1", "Using db1");
RunQuery(interpreter1, "CREATE (:NewNode)");
RunQuery(interpreter1, "CREATE (:NewNode)");
const auto db1_config_old = db1.GetValue()->config();
// Begin a transaction on db1
auto interpreter2 = this->NewInterpreter();
RunMtQuery(interpreter2, "USE DATABASE db1", "Using db1");
ASSERT_EQ(RunQuery(interpreter2, "SHOW DATABASE")[0][0].ValueString(), "db1");
RunQuery(interpreter2, "BEGIN");
// Update and check the new db in clean
auto interpreter3 = this->NewInterpreter();
const memgraph::storage::SalientConfig &db1_config_new{.name = "db1", .uuid = {}};
auto new_db1 = dbms.Update(db1_config_new);
ASSERT_TRUE(new_db1.HasValue());
ASSERT_NE(db1_config_new.uuid, db1_config_old.salient.uuid);
RunMtQuery(interpreter3, "USE DATABASE db1", "Using db1");
ASSERT_EQ(RunQuery(interpreter3, "MATCH(n) RETURN count(*)")[0][0].ValueInt(), 0);
// Check that the interpreter1 is still valid, but lacking a db
ASSERT_THROW(RunQuery(interpreter1, "CREATE (:Node)"), memgraph::query::DatabaseContextRequiredException);
// Check that the interpreter2 is still valid and pointing to the old db1 (until commit)
RunQuery(interpreter2, "CREATE (:NewNode)");
ASSERT_EQ(RunQuery(interpreter2, "MATCH(n) RETURN count(*)")[0][0].ValueInt(), 3);
RunQuery(interpreter2, "COMMIT");
ASSERT_THROW(RunQuery(interpreter2, "MATCH(n) RETURN n"), memgraph::query::DatabaseContextRequiredException);
}
TEST_F(MultiTenantTest, DbmsNewDelete) {
// 1) Create multiple interpreters with the default db
// 2) Create multiple databases using dbms
// 3) Defer delete databases while the interpreters are using them
// 4) Database should be a zombie until the using interpreter retries to query it
// 5) Check it is deleted from disk
// 1
auto interpreter1 = this->NewInterpreter();
auto interpreter2 = this->NewInterpreter();
// 2
auto &dbms = DBMS();
ASSERT_FALSE(dbms.New("db1").HasError());
ASSERT_FALSE(dbms.New("db2").HasError());
ASSERT_FALSE(dbms.New("db3").HasError());
ASSERT_FALSE(dbms.New("db4").HasError());
// 3
UseDatabase(interpreter2, "db2", "Using db2");
UseDatabase(interpreter1, "db4", "Using db4");
RunQuery(interpreter1, "CREATE (:Node{on:\"db4\"})");
RunQuery(interpreter1, "CREATE (:Node{on:\"db4\"})");
RunQuery(interpreter1, "CREATE (:Node{on:\"db4\"})");
RunQuery(interpreter1, "CREATE (:Node{on:\"db4\"})");
RunQuery(interpreter2, "CREATE (:Node{on:\"db2\"})");
RunQuery(interpreter2, "CREATE (:Node{on:\"db2\"})");
ASSERT_FALSE(dbms.Delete("db1").HasError());
ASSERT_FALSE(dbms.Delete("db2").HasError());
ASSERT_FALSE(dbms.Delete("db3").HasError());
ASSERT_FALSE(dbms.Delete("db4").HasError());
// 4
ASSERT_EQ(dbms.All().size(), 1);
ASSERT_EQ(GetDirs(data_directory / "databases").size(), 3); // All used databases remain on disk, but unusable
ASSERT_THROW(RunQuery(interpreter1, "MATCH(:Node{on:db4}) RETURN count(*)"),
memgraph::query::DatabaseContextRequiredException);
ASSERT_THROW(RunQuery(interpreter2, "MATCH(:Node{on:db2}) RETURN count(*)"),
memgraph::query::DatabaseContextRequiredException);
// 5
using namespace std::chrono_literals;
std::this_thread::sleep_for(100ms); // Wait for the filesystem to be updated
ASSERT_EQ(GetDirs(data_directory / "databases").size(), 1); // Databases deleted from disk
ASSERT_THROW(RunQuery(interpreter1, "MATCH(n) RETURN n"), memgraph::query::DatabaseContextRequiredException);
ASSERT_THROW(RunQuery(interpreter2, "MATCH(n) RETURN n"), memgraph::query::DatabaseContextRequiredException);
}
TEST_F(MultiTenantTest, DbmsNewDeleteWTx) {
// 1) Create multiple interpreters with the default db
// 2) Create multiple databases using dbms
// 3) Defer delete databases while the interpreters are using them
// 4) Interpreters that had an open transaction before should still be working
// 5) New transactions on deleted databases should throw
// 6) Switching databases should still be possible
// 1
auto interpreter1 = this->NewInterpreter();
auto interpreter2 = this->NewInterpreter();
// 2
auto &dbms = DBMS();
ASSERT_FALSE(dbms.New("db1").HasError());
ASSERT_FALSE(dbms.New("db2").HasError());
ASSERT_FALSE(dbms.New("db3").HasError());
ASSERT_FALSE(dbms.New("db4").HasError());
// 3
UseDatabase(interpreter2, "db2", "Using db2");
UseDatabase(interpreter1, "db4", "Using db4");
RunQuery(interpreter1, "CREATE (:Node{on:\"db4\"})");
RunQuery(interpreter1, "CREATE (:Node{on:\"db4\"})");
RunQuery(interpreter1, "CREATE (:Node{on:\"db4\"})");
RunQuery(interpreter1, "CREATE (:Node{on:\"db4\"})");
RunQuery(interpreter2, "CREATE (:Node{on:\"db2\"})");
RunQuery(interpreter2, "CREATE (:Node{on:\"db2\"})");
RunQuery(interpreter1, "BEGIN");
RunQuery(interpreter2, "BEGIN");
ASSERT_FALSE(dbms.Delete("db1").HasError());
ASSERT_FALSE(dbms.Delete("db2").HasError());
ASSERT_FALSE(dbms.Delete("db3").HasError());
ASSERT_FALSE(dbms.Delete("db4").HasError());
// 4
ASSERT_EQ(dbms.All().size(), 1);
ASSERT_EQ(GetDirs(data_directory / "databases").size(), 3); // All used databases remain on disk, and usable
ASSERT_EQ(RunQuery(interpreter1, "MATCH(:Node{on:\"db4\"}) RETURN count(*)")[0][0].ValueInt(), 4);
ASSERT_EQ(RunQuery(interpreter2, "MATCH(:Node{on:\"db2\"}) RETURN count(*)")[0][0].ValueInt(), 2);
RunQuery(interpreter1, "MATCH(n:Node{on:\"db4\"}) DELETE n");
RunQuery(interpreter2, "CREATE(:Node{on:\"db2\"})");
ASSERT_EQ(RunQuery(interpreter1, "MATCH(:Node{on:\"db4\"}) RETURN count(*)")[0][0].ValueInt(), 0);
ASSERT_EQ(RunQuery(interpreter2, "MATCH(:Node{on:\"db2\"}) RETURN count(*)")[0][0].ValueInt(), 3);
RunQuery(interpreter1, "COMMIT");
RunQuery(interpreter2, "COMMIT");
// 5
using namespace std::chrono_literals;
std::this_thread::sleep_for(100ms); // Wait for the filesystem to be updated
ASSERT_EQ(GetDirs(data_directory / "databases").size(), 1); // Only the active databases remain
ASSERT_THROW(RunQuery(interpreter1, "MATCH(n) RETURN n"), memgraph::query::DatabaseContextRequiredException);
ASSERT_THROW(RunQuery(interpreter2, "MATCH(n) RETURN n"), memgraph::query::DatabaseContextRequiredException);
// 6
UseDatabase(interpreter2, memgraph::dbms::kDefaultDB.data(), "Using memgraph");
UseDatabase(interpreter1, memgraph::dbms::kDefaultDB.data(), "Using memgraph");
}

View File

@@ -267,7 +267,7 @@ memgraph::storage::EdgeAccessor CreateEdge(memgraph::storage::Storage::Accessor
}
template <class... TArgs>
void VerifyQueries(const std::vector<std::vector<memgraph::communication::bolt::Value>> &results, TArgs &&...args) {
void VerifyQueries(const std::vector<std::vector<memgraph::communication::bolt::Value>> &results, TArgs &&... args) {
std::vector<std::string> expected{std::forward<TArgs>(args)...};
std::vector<std::string> got;
got.reserve(results.size());
@@ -704,11 +704,13 @@ TYPED_TEST(DumpTest, CheckStateVertexWithMultipleProperties) {
config.disk = disk_test_utils::GenerateOnDiskConfig("query-dump-s1").disk;
config.force_on_disk = true;
}
auto on_exit_s1 = memgraph::utils::OnScopeExit{[&]() {
if constexpr (std::is_same_v<TypeParam, memgraph::storage::DiskStorage>) {
auto clean_up_s1 = memgraph::utils::OnScopeExit{[&] {
if (std::is_same<TypeParam, memgraph::storage::DiskStorage>::value) {
disk_test_utils::RemoveRocksDbDirs("query-dump-s1");
}
std::filesystem::remove_all(config.durability.storage_directory);
}};
memgraph::replication::ReplicationState repl_state(ReplicationStateRootPath(config));
memgraph::utils::Gatekeeper<memgraph::dbms::Database> db_gk(config, repl_state);
@@ -823,11 +825,13 @@ TYPED_TEST(DumpTest, CheckStateSimpleGraph) {
config.disk = disk_test_utils::GenerateOnDiskConfig("query-dump-s2").disk;
config.force_on_disk = true;
}
auto on_exit_s2 = memgraph::utils::OnScopeExit{[&]() {
if constexpr (std::is_same_v<TypeParam, memgraph::storage::DiskStorage>) {
auto clean_up_s2 = memgraph::utils::OnScopeExit{[&] {
if (std::is_same<TypeParam, memgraph::storage::DiskStorage>::value) {
disk_test_utils::RemoveRocksDbDirs("query-dump-s2");
}
std::filesystem::remove_all(config.durability.storage_directory);
}};
memgraph::replication::ReplicationState repl_state{ReplicationStateRootPath(config)};
memgraph::utils::Gatekeeper<memgraph::dbms::Database> db_gk{config, repl_state};
auto db_acc_opt = db_gk.access();

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,7 @@ INSTANTIATE_TEST_CASE_P(EdgesWithoutProperties, StorageEdgeTest, ::testing::Valu
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -219,7 +219,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromLargerCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -392,7 +392,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromSameCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
// Create vertex
@@ -538,7 +538,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSameCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromSmallerAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -808,7 +808,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -1078,7 +1078,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromSameAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
// Create vertex
@@ -1305,7 +1305,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSameAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -1574,7 +1574,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromLargerCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -1843,7 +1843,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromSameCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
// Create vertex
@@ -2069,7 +2069,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSameCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -2492,7 +2492,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -2916,7 +2916,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromSameAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
// Create vertex
@@ -3276,7 +3276,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSameAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -3416,7 +3416,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_vertex1 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_vertex2 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -3746,7 +3746,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, VertexDetachDeleteSingleAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -3991,7 +3991,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = GetParam()}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = GetParam()}}}));
memgraph::storage::Gid gid_vertex1 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_vertex2 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -4637,7 +4637,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageWithProperties, EdgePropertyCommit) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = true}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = true}}}));
memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
{
auto acc = store->Access(ReplicationRole::MAIN);
@@ -4768,7 +4768,7 @@ TEST(StorageWithProperties, EdgePropertyCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageWithProperties, EdgePropertyAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = true}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = true}}}));
memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
// Create the vertex.
@@ -5060,7 +5060,7 @@ TEST(StorageWithProperties, EdgePropertyAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageWithProperties, EdgePropertySerializationError) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = true}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = true}}}));
memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
{
auto acc = store->Access(ReplicationRole::MAIN);
@@ -5170,7 +5170,7 @@ TEST(StorageWithProperties, EdgePropertySerializationError) {
TEST(StorageWithProperties, EdgePropertyClear) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = true}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = true}}}));
memgraph::storage::Gid gid;
auto property1 = store->NameToProperty("property1");
auto property2 = store->NameToProperty("property2");
@@ -5286,7 +5286,7 @@ TEST(StorageWithProperties, EdgePropertyClear) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageWithoutProperties, EdgePropertyAbort) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = false}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = false}}}));
memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
{
auto acc = store->Access(ReplicationRole::MAIN);
@@ -5355,7 +5355,7 @@ TEST(StorageWithoutProperties, EdgePropertyAbort) {
TEST(StorageWithoutProperties, EdgePropertyClear) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = false}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = false}}}));
memgraph::storage::Gid gid;
{
auto acc = store->Access(ReplicationRole::MAIN);
@@ -5382,7 +5382,7 @@ TEST(StorageWithoutProperties, EdgePropertyClear) {
TEST(StorageWithProperties, EdgeNonexistentPropertyAPI) {
std::unique_ptr<memgraph::storage::Storage> store(
new memgraph::storage::InMemoryStorage({.items = {.properties_on_edges = true}}));
new memgraph::storage::InMemoryStorage({.salient = {.items = {.properties_on_edges = true}}}));
auto property = store->NameToProperty("property");

View File

@@ -31,7 +31,7 @@ const std::string testSuite = "storage_v2_edge_ondisk";
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -224,7 +224,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromLargerCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -399,7 +399,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromSameCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -547,7 +547,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSameCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromSmallerAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -819,7 +819,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -1091,7 +1091,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeCreateFromSameAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -1320,7 +1320,7 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSameAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -1591,7 +1591,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromLargerCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -1862,7 +1862,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromSameCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -2090,7 +2090,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSameCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -2515,7 +2515,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -2941,7 +2941,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, EdgeDeleteFromSameAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -3303,7 +3303,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSameAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -3445,7 +3445,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_vertex1 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_vertex2 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -3777,7 +3777,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, VertexDetachDeleteSingleAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -4024,7 +4024,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = GetParam();
config.salient.items.properties_on_edges = GetParam();
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid_vertex1 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
memgraph::storage::Gid gid_vertex2 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -4672,7 +4672,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageWithProperties, EdgePropertyCommit) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = true;
config.salient.items.properties_on_edges = true;
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
{
@@ -4808,7 +4808,7 @@ TEST(StorageWithProperties, EdgePropertyCommit) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageWithProperties, EdgePropertyAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = true;
config.salient.items.properties_on_edges = true;
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
@@ -5109,7 +5109,7 @@ TEST(StorageWithProperties, EdgePropertyAbort) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageWithProperties, EdgePropertySerializationError) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = true;
config.salient.items.properties_on_edges = true;
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
{
@@ -5228,7 +5228,7 @@ TEST(StorageWithProperties, EdgePropertySerializationError) {
TEST(StorageWithProperties, EdgePropertyClear) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = true;
config.salient.items.properties_on_edges = true;
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid;
auto property1 = store->NameToProperty("property1");
@@ -5350,7 +5350,7 @@ TEST(StorageWithProperties, EdgePropertyClear) {
// NOLINTNEXTLINE(hicpp-special-member-functions)
TEST(StorageWithoutProperties, EdgePropertyAbort) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = false;
config.salient.items.properties_on_edges = false;
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
{
@@ -5424,7 +5424,7 @@ TEST(StorageWithoutProperties, EdgePropertyAbort) {
TEST(StorageWithoutProperties, EdgePropertyClear) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = false;
config.salient.items.properties_on_edges = false;
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
memgraph::storage::Gid gid;
{
@@ -5454,7 +5454,7 @@ TEST(StorageWithoutProperties, EdgePropertyClear) {
TEST(StorageWithProperties, EdgeNonexistentPropertyAPI) {
auto config = disk_test_utils::GenerateOnDiskConfig(testSuite);
config.items.properties_on_edges = true;
config.salient.items.properties_on_edges = true;
std::unique_ptr<memgraph::storage::Storage> store(new memgraph::storage::DiskStorage(config));
auto property = store->NameToProperty("property");

View File

@@ -64,26 +64,35 @@ class ReplicationTest : public ::testing::Test {
void TearDown() override { Clear(); }
Config main_conf = [&] {
Config config{.items = {.properties_on_edges = true},
.durability = {
.snapshot_wal_mode = Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
}};
Config config{
.durability =
{
.snapshot_wal_mode = Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
},
.salient.items = {.properties_on_edges = true},
};
UpdatePaths(config, storage_directory);
return config;
}();
Config repl_conf = [&] {
Config config{.items = {.properties_on_edges = true},
.durability = {
.snapshot_wal_mode = Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
}};
Config config{
.durability =
{
.snapshot_wal_mode = Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
},
.salient.items = {.properties_on_edges = true},
};
UpdatePaths(config, repl_storage_directory);
return config;
}();
Config repl2_conf = [&] {
Config config{.items = {.properties_on_edges = true},
.durability = {
.snapshot_wal_mode = Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
}};
Config config{
.durability =
{
.snapshot_wal_mode = Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL,
},
.salient.items = {.properties_on_edges = true},
};
UpdatePaths(config, repl2_storage_directory);
return config;
}();
@@ -107,15 +116,17 @@ struct MinMemgraph {
,
reinterpret_cast<
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *>(0),
true, false
true
#endif
},
repl_state{dbms.ReplicationState()},
db{*dbms.Get().get()},
db_acc{dbms.Get()},
db{*db_acc.get()},
repl_handler(dbms) {
}
memgraph::dbms::DbmsHandler dbms;
memgraph::replication::ReplicationState &repl_state;
memgraph::dbms::DatabaseAccess db_acc;
memgraph::dbms::Database &db;
ReplicationHandler repl_handler;
};
@@ -152,7 +163,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
ASSERT_TRUE(v.AddLabel(main.db.storage()->NameToLabel(vertex_label)).HasValue());
ASSERT_TRUE(v.SetProperty(main.db.storage()->NameToProperty(vertex_property), PropertyValue(vertex_property_value))
.HasValue());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
@@ -178,7 +189,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
auto v = acc->FindVertex(*vertex_gid, View::OLD);
ASSERT_TRUE(v);
ASSERT_TRUE(v->RemoveLabel(main.db.storage()->NameToLabel(vertex_label)).HasValue());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
@@ -197,7 +208,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
auto v = acc->FindVertex(*vertex_gid, View::OLD);
ASSERT_TRUE(v);
ASSERT_TRUE(acc->DeleteVertex(&*v).HasValue());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
@@ -224,7 +235,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
ASSERT_TRUE(edge.SetProperty(main.db.storage()->NameToProperty(edge_property), PropertyValue(edge_property_value))
.HasValue());
edge_gid.emplace(edge.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
const auto find_edge = [&](const auto &edges, const Gid edge_gid) -> std::optional<EdgeAccessor> {
@@ -261,7 +272,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
auto edge = find_edge(out_edges->edges, *edge_gid);
ASSERT_TRUE(edge);
ASSERT_TRUE(acc->DeleteEdge(&*edge).HasValue());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
@@ -287,25 +298,25 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
{
auto unique_acc = main.db.UniqueAccess();
ASSERT_FALSE(unique_acc->CreateIndex(main.db.storage()->NameToLabel(label)).HasError());
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
unique_acc->SetIndexStats(main.db.storage()->NameToLabel(label), l_stats);
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
ASSERT_FALSE(
unique_acc->CreateIndex(main.db.storage()->NameToLabel(label), main.db.storage()->NameToProperty(property))
.HasError());
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
unique_acc->SetIndexStats(main.db.storage()->NameToLabel(label), main.db.storage()->NameToProperty(property),
lp_stats);
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
@@ -313,7 +324,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
->CreateExistenceConstraint(main.db.storage()->NameToLabel(label),
main.db.storage()->NameToProperty(property))
.HasError());
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
@@ -322,7 +333,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
{main.db.storage()->NameToProperty(property),
main.db.storage()->NameToProperty(property_extra)})
.HasError());
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
@@ -360,24 +371,24 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
{
auto unique_acc = main.db.UniqueAccess();
unique_acc->DeleteLabelIndexStats(main.db.storage()->NameToLabel(label));
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
ASSERT_FALSE(unique_acc->DropIndex(main.db.storage()->NameToLabel(label)).HasError());
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
unique_acc->DeleteLabelPropertyIndexStats(main.db.storage()->NameToLabel(label));
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
ASSERT_FALSE(
unique_acc->DropIndex(main.db.storage()->NameToLabel(label), main.db.storage()->NameToProperty(property))
.HasError());
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
@@ -385,7 +396,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
->DropExistenceConstraint(main.db.storage()->NameToLabel(label),
main.db.storage()->NameToProperty(property))
.HasError());
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
auto unique_acc = main.db.UniqueAccess();
@@ -393,7 +404,7 @@ TEST_F(ReplicationTest, BasicSynchronousReplicationTest) {
main.db.storage()->NameToLabel(label),
{main.db.storage()->NameToProperty(property), main.db.storage()->NameToProperty(property_extra)}),
memgraph::storage::UniqueConstraints::DeletionStatus::SUCCESS);
ASSERT_FALSE(unique_acc->Commit().HasError());
ASSERT_FALSE(unique_acc->Commit({}, main.db_acc).HasError());
}
{
@@ -455,7 +466,7 @@ TEST_F(ReplicationTest, MultipleSynchronousReplicationTest) {
ASSERT_TRUE(v.SetProperty(main.db.storage()->NameToProperty(vertex_property), PropertyValue(vertex_property_value))
.HasValue());
vertex_gid.emplace(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
const auto check_replica = [&](memgraph::dbms::Database &replica_database) {
@@ -477,7 +488,7 @@ TEST_F(ReplicationTest, MultipleSynchronousReplicationTest) {
auto acc = main.db.Access();
auto v = acc->CreateVertex();
vertex_gid.emplace(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
// REPLICA1 should contain the new vertex
@@ -515,7 +526,7 @@ TEST_F(ReplicationTest, RecoveryProcess) {
// Create the vertex before registering a replica
auto v = acc->CreateVertex();
vertex_gids.emplace_back(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
}
@@ -531,13 +542,13 @@ TEST_F(ReplicationTest, RecoveryProcess) {
auto acc = main.db.Access();
auto v = acc->CreateVertex();
vertex_gids.emplace_back(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
auto acc = main.db.Access();
auto v = acc->CreateVertex();
vertex_gids.emplace_back(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
}
@@ -560,7 +571,7 @@ TEST_F(ReplicationTest, RecoveryProcess) {
ASSERT_TRUE(
v->SetProperty(main.db.storage()->NameToProperty(property_name), PropertyValue(property_value)).HasValue());
}
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
static constexpr const auto *vertex_label = "vertex_label";
@@ -594,7 +605,7 @@ TEST_F(ReplicationTest, RecoveryProcess) {
ASSERT_TRUE(v);
ASSERT_TRUE(v->AddLabel(main.db.storage()->NameToLabel(vertex_label)).HasValue());
}
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
auto acc = replica.db.Access();
@@ -663,7 +674,7 @@ TEST_F(ReplicationTest, BasicAsynchronousReplicationTest) {
auto acc = main.db.Access();
auto v = acc->CreateVertex();
created_vertices.push_back(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
if (i == 0) {
ASSERT_EQ(main.db.storage()->GetReplicaState("REPLICA_ASYNC"), ReplicaState::REPLICATING);
@@ -723,13 +734,13 @@ TEST_F(ReplicationTest, EpochTest) {
auto acc = main.db.Access();
const auto v = acc->CreateVertex();
vertex_gid.emplace(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
auto acc = replica1.db.Access();
const auto v = acc->FindVertex(*vertex_gid, View::OLD);
ASSERT_TRUE(v);
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
auto acc = replica2.db.Access();
@@ -756,13 +767,13 @@ TEST_F(ReplicationTest, EpochTest) {
{
auto acc = main.db.Access();
acc->CreateVertex();
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
{
auto acc = replica1.db.Access();
auto v = acc->CreateVertex();
vertex_gid.emplace(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, replica1.db_acc).HasError());
}
// Replica1 should forward it's vertex to Replica2
{
@@ -790,7 +801,7 @@ TEST_F(ReplicationTest, EpochTest) {
auto acc = main.db.Access();
const auto v = acc->CreateVertex();
vertex_gid.emplace(v.Gid());
ASSERT_FALSE(acc->Commit().HasError());
ASSERT_FALSE(acc->Commit({}, main.db_acc).HasError());
}
// Replica1 is not compatible with the main so it shouldn't contain
// it's newest vertex