diff --git a/config/das.json b/config/das.json index 4fb8241f8..a1e096e34 100644 --- a/config/das.json +++ b/config/das.json @@ -19,6 +19,7 @@ "endpoint": "localhost:40021", "username": "admin", "password": "admin", + "seed_protected": false, "cluster": false, "cluster_secret_key": "8UDJSgpUCaVOTQG", "nodes": [ diff --git a/src/agents/atomdb_broker/AtomDBProxy.cc b/src/agents/atomdb_broker/AtomDBProxy.cc index defe8cfe2..98fc22db1 100644 --- a/src/agents/atomdb_broker/AtomDBProxy.cc +++ b/src/agents/atomdb_broker/AtomDBProxy.cc @@ -167,7 +167,7 @@ void AtomDBProxy::add_atoms_callback(const vector& tokens) { for (auto& atom : atoms) { buffer.push_back(atom.get()); } - this->atomdb->add_atoms(buffer, false, true); + this->atomdb->add_atoms(buffer, "", false, true); } catch (const exception& e) { LOG_ERROR("Error processing batch: " << e.what()); } @@ -180,7 +180,7 @@ void AtomDBProxy::delete_atoms_callback(const vector& args) { } vector handles(args.begin(), args.end() - 1); bool delete_link_targets = args.back() == "1"; - uint deleted_count = this->atomdb->delete_atoms(handles, delete_link_targets); + uint deleted_count = this->atomdb->delete_atoms(handles, "", delete_link_targets); LOG_INFO("Deleted " << deleted_count << " atoms"); } catch (const exception& e) { LOG_ERROR("Error processing delete_atoms command: " << e.what()); @@ -215,7 +215,7 @@ void AtomDBProxy::process_atom_batches() { this->pending_atoms_count -= atoms.size(); lock.unlock(); auto job = [this, atoms = std::move(atoms)]() { - this->atomdb->add_atoms(atoms, false, true); + this->atomdb->add_atoms(atoms, "", false, true); for (auto& atom : atoms) { delete atom; } diff --git a/src/agents/evolution/QueryEvolutionProcessor.cc b/src/agents/evolution/QueryEvolutionProcessor.cc index 3f4b79b4e..5d75042a4 100644 --- a/src/agents/evolution/QueryEvolutionProcessor.cc +++ b/src/agents/evolution/QueryEvolutionProcessor.cc @@ -497,12 +497,12 @@ string QueryEvolutionProcessor::answer_to_string_2(shared_ptr answe vector path_link = {" -> ", " -> "}; bool first = true; for (string& handle : answer->get_path_vector(i)) { - auto link = db->get_link(handle); + auto link = db->get_link(handle, ""); if ((link == nullptr) || (link->arity() != 3)) { return "Invalid link: " + handle; } - auto target1 = db->get_link(link->targets[1]); - auto target2 = db->get_link(link->targets[2]); + auto target1 = db->get_link(link->targets[1], ""); + auto target2 = db->get_link(link->targets[2], ""); if ((target1 == nullptr) || (target2 == nullptr)) { return "Invalid link: " + link->to_string(); } @@ -533,9 +533,9 @@ string QueryEvolutionProcessor::answer_to_string_1(shared_ptr answe string path_link = " -> "; bool first = true; for (string& handle : answer->get_path_vector(0)) { - auto link = db->get_link(handle); - auto target1 = db->get_link(link->targets[1]); - auto target2 = db->get_link(link->targets[2]); + auto link = db->get_link(handle, ""); + auto target1 = db->get_link(link->targets[1], ""); + auto target2 = db->get_link(link->targets[2], ""); if (first) { first = false; path = target1->metta_representation(*(this->decoder)) + path_link; diff --git a/src/agents/evolution/fitness_functions/CountLetterFunction.cc b/src/agents/evolution/fitness_functions/CountLetterFunction.cc index f178936db..f4437c55d 100644 --- a/src/agents/evolution/fitness_functions/CountLetterFunction.cc +++ b/src/agents/evolution/fitness_functions/CountLetterFunction.cc @@ -18,9 +18,9 @@ float CountLetterFunction::eval(shared_ptr query_answer) { shared_ptr sentence_link; shared_ptr sentence_name_node; string handle = query_answer->assignment.get(VARIABLE_NAME); - sentence_link = this->db->get_link(handle); + sentence_link = this->db->get_link(handle, ""); handle = sentence_link->targets[1]; - sentence_name_node = this->db->get_node(handle); + sentence_name_node = this->db->get_node(handle, ""); string sentence_name = sentence_name_node->name; unsigned int count = 0; unsigned int sentence_length = 0; diff --git a/src/agents/link_creation_agent/EquivalenceProcessor.cc b/src/agents/link_creation_agent/EquivalenceProcessor.cc index 80fe9f39c..675b6edf0 100644 --- a/src/agents/link_creation_agent/EquivalenceProcessor.cc +++ b/src/agents/link_creation_agent/EquivalenceProcessor.cc @@ -18,8 +18,8 @@ bool EquivalenceProcessor::link_exists(const string& handle1, const string& hand vector targets_c2_c1 = {equivalence_node.handle(), handle2, handle1}; shared_ptr link_c1_c2 = make_shared("Expression", targets_c1_c2); shared_ptr link_c2_c1 = make_shared("Expression", targets_c2_c1); - return AtomDBSingleton::get_instance()->link_exists(link_c1_c2->handle()) && - AtomDBSingleton::get_instance()->link_exists(link_c2_c1->handle()); + return AtomDBSingleton::get_instance()->link_exists(link_c1_c2->handle(), "") && + AtomDBSingleton::get_instance()->link_exists(link_c2_c1->handle(), ""); } static vector build_equivalence_query(const string& handle) { @@ -89,7 +89,7 @@ vector> EquivalenceProcessor::process_query(shared_ptr> result; Node equivalence_node("Symbol", "Equivalence"); try { - AtomDBSingleton::get_instance()->add_node(&equivalence_node); + AtomDBSingleton::get_instance()->add_node(&equivalence_node, ""); } catch (const std::exception& e) { LOG_ERROR("Failed to add node to AtomDB: " << e.what()); } diff --git a/src/agents/link_creation_agent/ImplicationProcessor.cc b/src/agents/link_creation_agent/ImplicationProcessor.cc index fc18bb657..55f4b20e3 100644 --- a/src/agents/link_creation_agent/ImplicationProcessor.cc +++ b/src/agents/link_creation_agent/ImplicationProcessor.cc @@ -57,8 +57,8 @@ bool ImplicationProcessor::link_exists(const string& handle1, const string& hand vector targets_p2_p1 = {implication_node.handle(), handle2, handle1}; shared_ptr p1_link = make_shared("Expression", targets_p1_p2); shared_ptr p2_link = make_shared("Expression", targets_p2_p1); - return AtomDBSingleton::get_instance()->link_exists(p1_link->handle()) && - AtomDBSingleton::get_instance()->link_exists(p2_link->handle()); + return AtomDBSingleton::get_instance()->link_exists(p1_link->handle(), "") && + AtomDBSingleton::get_instance()->link_exists(p2_link->handle(), ""); } vector> ImplicationProcessor::process_query(shared_ptr query_answer, @@ -113,7 +113,7 @@ vector> ImplicationProcessor::process_query(shared_ptr> result; Node implication_node("Symbol", "Implication"); try { - AtomDBSingleton::get_instance()->add_node(&implication_node); + AtomDBSingleton::get_instance()->add_node(&implication_node, ""); } catch (const std::exception& e) { LOG_ERROR("Failed to add node to AtomDB: " << e.what()); } diff --git a/src/agents/link_creation_agent/LinkCreationService.cc b/src/agents/link_creation_agent/LinkCreationService.cc index a483066dd..72e20be3c 100644 --- a/src/agents/link_creation_agent/LinkCreationService.cc +++ b/src/agents/link_creation_agent/LinkCreationService.cc @@ -126,14 +126,14 @@ void LinkCreationService::set_timeout(int timeout) { this->timeout = timeout; } static void add_or_update_link(shared_ptr link) { auto db_instance = AtomDBSingleton::get_instance(); - if (!db_instance->link_exists(link->handle())) { + if (!db_instance->link_exists(link->handle(), "")) { LOG_INFO("Adding link to AtomDB: " << link->to_string()); - db_instance->add_link(link.get()); + db_instance->add_link(link.get(), ""); } else { LOG_INFO("Updating link in AtomDB: " << link->to_string()); auto old_link = db_instance->get_atom(link->handle()); - db_instance->delete_link(link->handle(), false); - db_instance->add_link(link.get()); + db_instance->delete_link(link->handle(), "", false); + db_instance->add_link(link.get(), ""); } } diff --git a/src/agents/link_creation_agent/MettaTemplateProcessor.cc b/src/agents/link_creation_agent/MettaTemplateProcessor.cc index a94f06452..47c860dc3 100644 --- a/src/agents/link_creation_agent/MettaTemplateProcessor.cc +++ b/src/agents/link_creation_agent/MettaTemplateProcessor.cc @@ -40,7 +40,7 @@ static void create_missing_atoms_in_atomdb(shared_ptr parser for (const auto& element : parser_actions->handle_to_atom) { if (dynamic_pointer_cast(element.second) != nullptr) { try { - atomdb->add_node(dynamic_pointer_cast(element.second).get(), false); + atomdb->add_node(dynamic_pointer_cast(element.second).get(), "", false); LOG_DEBUG("Node added to AtomDB: " << element.second->to_string()); } catch (const std::exception& e) { LOG_ERROR("Error adding node to AtomDB: " << e.what()); @@ -68,7 +68,7 @@ static void create_missing_atoms_in_atomdb(shared_ptr parser RAISE_ERROR("Parsed atom is not a Link for metta expression: " + metta_expression_cp); continue; } - atomdb->add_link(dynamic_pointer_cast(link).get(), false); + atomdb->add_link(dynamic_pointer_cast(link).get(), "", false); LOG_DEBUG("Link added to AtomDB: " << metta_expression_cp); } catch (const std::exception& e) { LOG_ERROR("Error adding link to AtomDB: " << e.what()); diff --git a/src/agents/query_engine/query_element/LinkTemplate.cc b/src/agents/query_engine/query_element/LinkTemplate.cc index ba503bfe6..3d02a927c 100644 --- a/src/agents/query_engine/query_element/LinkTemplate.cc +++ b/src/agents/query_engine/query_element/LinkTemplate.cc @@ -182,7 +182,7 @@ void LinkTemplate::processor_method(shared_ptr monitor) { handles = LinkTemplate::fetched_links_cache().get(link_schema_handle); } else { LOG_INFO("Fetching " + link_schema_handle + " from AtomDB"); - handles = db->query_for_pattern(this->link_schema); + handles = db->query_for_pattern(this->link_schema, ""); if (this->use_cache) { LinkTemplate::fetched_links_cache().set(link_schema_handle, handles); } @@ -220,7 +220,7 @@ void LinkTemplate::processor_method(shared_ptr monitor) { pending = 0; } else { if (tagged_handle.second > 0 || !this->positive_importance_flag) { - if (db->allow_nested_indexing()) { + if (db->allow_nested_indexing("")) { if ((this->attention_focus_strictness == 0.0) || (this->attention_focus_strictness == 1.0)) { this->source_element->add_handle( diff --git a/src/atomdb/AtomDB.h b/src/atomdb/AtomDB.h index 25256312b..2bd3dcda6 100644 --- a/src/atomdb/AtomDB.h +++ b/src/atomdb/AtomDB.h @@ -20,56 +20,93 @@ class AtomDB : public HandleDecoder { AtomDB() = default; virtual ~AtomDB() = default; - virtual bool allow_nested_indexing() = 0; + virtual bool allow_nested_indexing(const string& public_key) = 0; virtual bool composite_type_enabled() const = 0; - virtual shared_ptr get_atom(const string& handle) = 0; // HandleDecoder interface - virtual shared_ptr get_node(const string& handle) = 0; - virtual shared_ptr get_link(const string& handle) = 0; - - virtual vector> get_matching_atoms(bool is_toplevel, Atom& key) = 0; - - virtual shared_ptr query_for_pattern(const LinkSchema& link_schema) = 0; - virtual shared_ptr query_for_targets(const string& handle) = 0; - virtual shared_ptr query_for_incoming_set(const string& handle) = 0; - - virtual bool atom_exists(const string& handle) = 0; - virtual bool node_exists(const string& handle) = 0; - virtual bool link_exists(const string& handle) = 0; - - virtual set atoms_exist(const vector& handles) = 0; - virtual set nodes_exist(const vector& handles) = 0; - virtual set links_exist(const vector& handles) = 0; - - virtual string add_atom(const atoms::Atom* atom, bool throw_if_exists = false) = 0; - virtual string add_node(const atoms::Node* node, bool throw_if_exists = false) = 0; - virtual string add_link(const atoms::Link* link, bool throw_if_exists = false) = 0; + /** + * @brief Reports whether this backend points to a protected database. + */ + virtual bool is_protected() const = 0; + + /** + * HandleDecoder requires get_atom(handle) without public_key. Existing callers use that interface, + * so this forwards to get_atom(handle, ""). + */ + shared_ptr get_atom(const string& handle) override { return get_atom(handle, ""); } + + virtual shared_ptr get_atom(const string& handle, const string& public_key) = 0; + virtual shared_ptr get_node(const string& handle, const string& public_key) = 0; + virtual shared_ptr get_link(const string& handle, const string& public_key) = 0; + + virtual vector> get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) = 0; + + virtual shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) = 0; + virtual shared_ptr query_for_targets(const string& handle, + const string& public_key) = 0; + virtual shared_ptr query_for_incoming_set(const string& handle, + const string& public_key) = 0; + + virtual bool atom_exists(const string& handle, const string& public_key) = 0; + virtual bool node_exists(const string& handle, const string& public_key) = 0; + virtual bool link_exists(const string& handle, const string& public_key) = 0; + + virtual set atoms_exist(const vector& handles, const string& public_key) = 0; + virtual set nodes_exist(const vector& handles, const string& public_key) = 0; + virtual set links_exist(const vector& handles, const string& public_key) = 0; + + virtual string add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists = false) = 0; + virtual string add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists = false) = 0; + virtual string add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists = false) = 0; virtual vector add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) = 0; virtual vector add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) = 0; virtual vector add_links(const vector& links, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) = 0; - virtual bool delete_atom(const string& handle, bool delete_link_targets = false) = 0; - virtual bool delete_node(const string& handle, bool delete_link_targets = false) = 0; - virtual bool delete_link(const string& handle, bool delete_link_targets = false) = 0; - - virtual uint delete_atoms(const vector& handles, bool delete_link_targets = false) = 0; - virtual uint delete_nodes(const vector& handles, bool delete_link_targets = false) = 0; - virtual uint delete_links(const vector& handles, bool delete_link_targets = false) = 0; - - virtual void re_index_patterns(bool flush_patterns = true) = 0; - - virtual size_t node_count() const = 0; - virtual size_t link_count() const = 0; - virtual size_t atom_count() const = 0; - - bool empty() const { return atom_count() == 0; } + virtual bool delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets = false) = 0; + virtual bool delete_node(const string& handle, + const string& public_key, + bool delete_link_targets = false) = 0; + virtual bool delete_link(const string& handle, + const string& public_key, + bool delete_link_targets = false) = 0; + + virtual uint delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets = false) = 0; + virtual uint delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets = false) = 0; + virtual uint delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets = false) = 0; + + virtual void re_index_patterns(const string& public_key, bool flush_patterns = true) = 0; + + virtual size_t node_count(const string& public_key) const = 0; + virtual size_t link_count(const string& public_key) const = 0; + virtual size_t atom_count(const string& public_key) const = 0; + + bool empty(const string& public_key) const { return atom_count(public_key) == 0; } }; } // namespace atomdb diff --git a/src/atomdb/AtomDBSingleton.cc b/src/atomdb/AtomDBSingleton.cc index 37c85a08a..288b3bf52 100644 --- a/src/atomdb/AtomDBSingleton.cc +++ b/src/atomdb/AtomDBSingleton.cc @@ -2,6 +2,7 @@ #include "AdapterDB.h" #include "MorkDB.h" +#include "ProtectedAtomDB.h" #include "RedisMongoDB.h" #include "RemoteAtomDB.h" #include "Utils.h" @@ -19,24 +20,32 @@ void AtomDBSingleton::init(const JsonConfig& atomdb_config) { if (AtomDBSingleton::initialized) { RAISE_ERROR( "AtomDBSingleton already initialized. AtomDBSingleton::init() should be called only once."); + } + + shared_ptr atomdb; + auto atomdb_type = atomdb_config.at_path("type").get_or(""); + + if (atomdb_type == "morkdb") { + atomdb = shared_ptr(new MorkDB("", atomdb_config)); + } else if (atomdb_type == "redismongodb") { + atomdb = shared_ptr(new RedisMongoDB("", false, atomdb_config)); + } else if (atomdb_type == "remotedb") { + auto remote_peers_config = + atomdb_config.at_path("remote_peers").get_or(JsonConfig()); + atomdb = shared_ptr(new RemoteAtomDB(remote_peers_config)); + } else if (atomdb_type == "adapterdb") { + atomdb = shared_ptr(new AdapterDB(atomdb_config)); + } else { + RAISE_ERROR("Invalid AtomDB type: " + atomdb_type); + } + + if (atomdb->is_protected()) { + AtomDBSingleton::atom_db = shared_ptr(new ProtectedAtomDB(atomdb, atomdb_config)); } else { - auto atomdb_type = atomdb_config.at_path("type").get_or(""); - if (atomdb_type == "morkdb") { - AtomDBSingleton::atom_db = shared_ptr(new MorkDB("", atomdb_config)); - } else if (atomdb_type == "redismongodb") { - AtomDBSingleton::atom_db = shared_ptr(new RedisMongoDB("", false, atomdb_config)); - } else if (atomdb_type == "remotedb") { - auto remote_peers_config = - atomdb_config.at_path("remote_peers").get_or(JsonConfig()); - AtomDBSingleton::atom_db = shared_ptr(new RemoteAtomDB(remote_peers_config)); - } else if (atomdb_type == "adapterdb") { - AtomDBSingleton::atom_db = shared_ptr(new AdapterDB(atomdb_config)); - } else { - RAISE_ERROR("Invalid AtomDB type: " + atomdb_type); - } - - AtomDBSingleton::initialized = true; + AtomDBSingleton::atom_db = atomdb; } + + AtomDBSingleton::initialized = true; } shared_ptr AtomDBSingleton::get_instance() { diff --git a/src/atomdb/BUILD b/src/atomdb/BUILD index fb0f072b7..1649d889f 100644 --- a/src/atomdb/BUILD +++ b/src/atomdb/BUILD @@ -11,6 +11,7 @@ cc_library( ":atomdb_singleton", ":atomdbutils", "//atomdb/adapterdb:adapterdb_lib", + "//atomdb/auth:protected_atomdb_lib", "//atomdb/inmemorydb:inmemorydb_lib", "//atomdb/morkdb:morkdb_lib", "//atomdb/redis_mongodb:redis_mongodb_lib", @@ -57,6 +58,7 @@ cc_library( deps = [ "//atomdb:atomdb_api_types", "//atomdb/adapterdb", + "//atomdb/auth:protected_atomdb_lib", "//atomdb/morkdb", "//atomdb/redis_mongodb", "//atomdb/remotedb:remotedb_lib", diff --git a/src/atomdb/adapterdb/AdapterDB.cc b/src/atomdb/adapterdb/AdapterDB.cc index 8669381bc..e7f7d08fe 100644 --- a/src/atomdb/adapterdb/AdapterDB.cc +++ b/src/atomdb/adapterdb/AdapterDB.cc @@ -62,9 +62,9 @@ bool AdapterDB::needs_sync() const { return false; } -bool AdapterDB::allow_nested_indexing() { +bool AdapterDB::allow_nested_indexing(const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->allow_nested_indexing(); + return this->atomdb_backend->allow_nested_indexing(public_key); } bool AdapterDB::composite_type_enabled() const { @@ -72,155 +72,174 @@ bool AdapterDB::composite_type_enabled() const { return this->atomdb_backend->composite_type_enabled(); } -shared_ptr AdapterDB::get_atom(const string& handle) { +bool AdapterDB::is_protected() const { this->ensure_backend_ready(); - return this->atomdb_backend->get_atom(handle); + return this->atomdb_backend->is_protected(); } -shared_ptr AdapterDB::get_node(const string& handle) { +shared_ptr AdapterDB::get_atom(const string& handle, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->get_node(handle); + return this->atomdb_backend->get_atom(handle, public_key); } -shared_ptr AdapterDB::get_link(const string& handle) { +shared_ptr AdapterDB::get_node(const string& handle, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->get_link(handle); + return this->atomdb_backend->get_node(handle, public_key); } -vector> AdapterDB::get_matching_atoms(bool is_toplevel, Atom& key) { +shared_ptr AdapterDB::get_link(const string& handle, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->get_matching_atoms(is_toplevel, key); + return this->atomdb_backend->get_link(handle, public_key); } -shared_ptr AdapterDB::query_for_pattern(const LinkSchema& link_schema) { +vector> AdapterDB::get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->query_for_pattern(link_schema); + return this->atomdb_backend->get_matching_atoms(is_toplevel, key, public_key); } -shared_ptr AdapterDB::query_for_targets(const string& handle) { +shared_ptr AdapterDB::query_for_pattern(const LinkSchema& link_schema, + const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->query_for_targets(handle); + return this->atomdb_backend->query_for_pattern(link_schema, public_key); } -shared_ptr AdapterDB::query_for_incoming_set(const string& handle) { +shared_ptr AdapterDB::query_for_targets(const string& handle, + const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->query_for_incoming_set(handle); + return this->atomdb_backend->query_for_targets(handle, public_key); } -bool AdapterDB::atom_exists(const string& handle) { +shared_ptr AdapterDB::query_for_incoming_set(const string& handle, + const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->atom_exists(handle); + return this->atomdb_backend->query_for_incoming_set(handle, public_key); } -bool AdapterDB::node_exists(const string& handle) { +bool AdapterDB::atom_exists(const string& handle, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->node_exists(handle); + return this->atomdb_backend->atom_exists(handle, public_key); } -bool AdapterDB::link_exists(const string& handle) { +bool AdapterDB::node_exists(const string& handle, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->link_exists(handle); + return this->atomdb_backend->node_exists(handle, public_key); } -set AdapterDB::atoms_exist(const vector& handles) { +bool AdapterDB::link_exists(const string& handle, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->atoms_exist(handles); + return this->atomdb_backend->link_exists(handle, public_key); } -set AdapterDB::nodes_exist(const vector& handles) { +set AdapterDB::atoms_exist(const vector& handles, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->nodes_exist(handles); + return this->atomdb_backend->atoms_exist(handles, public_key); } -set AdapterDB::links_exist(const vector& handles) { +set AdapterDB::nodes_exist(const vector& handles, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->links_exist(handles); + return this->atomdb_backend->nodes_exist(handles, public_key); } -string AdapterDB::add_atom(const atoms::Atom* atom, bool throw_if_exists) { +set AdapterDB::links_exist(const vector& handles, const string& public_key) { this->ensure_backend_ready(); - return this->atomdb_backend->add_atom(atom, throw_if_exists); + return this->atomdb_backend->links_exist(handles, public_key); } -string AdapterDB::add_node(const atoms::Node* node, bool throw_if_exists) { +string AdapterDB::add_atom(const atoms::Atom* atom, const string& public_key, bool throw_if_exists) { this->ensure_backend_ready(); - return this->atomdb_backend->add_node(node, throw_if_exists); + return this->atomdb_backend->add_atom(atom, public_key, throw_if_exists); } -string AdapterDB::add_link(const atoms::Link* link, bool throw_if_exists) { +string AdapterDB::add_node(const atoms::Node* node, const string& public_key, bool throw_if_exists) { this->ensure_backend_ready(); - return this->atomdb_backend->add_link(link, throw_if_exists); + return this->atomdb_backend->add_node(node, public_key, throw_if_exists); +} + +string AdapterDB::add_link(const atoms::Link* link, const string& public_key, bool throw_if_exists) { + this->ensure_backend_ready(); + return this->atomdb_backend->add_link(link, public_key, throw_if_exists); } vector AdapterDB::add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists, bool is_transactional) { this->ensure_backend_ready(); - return this->atomdb_backend->add_atoms(atoms, throw_if_exists, is_transactional); + return this->atomdb_backend->add_atoms(atoms, public_key, throw_if_exists, is_transactional); } vector AdapterDB::add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists, bool is_transactional) { this->ensure_backend_ready(); - return this->atomdb_backend->add_nodes(nodes, throw_if_exists, is_transactional); + return this->atomdb_backend->add_nodes(nodes, public_key, throw_if_exists, is_transactional); } vector AdapterDB::add_links(const vector& links, + const string& public_key, bool throw_if_exists, bool is_transactional) { this->ensure_backend_ready(); - return this->atomdb_backend->add_links(links, throw_if_exists, is_transactional); + return this->atomdb_backend->add_links(links, public_key, throw_if_exists, is_transactional); } -bool AdapterDB::delete_atom(const string& handle, bool delete_link_targets) { +bool AdapterDB::delete_atom(const string& handle, const string& public_key, bool delete_link_targets) { this->ensure_backend_ready(); - return this->atomdb_backend->delete_atom(handle, delete_link_targets); + return this->atomdb_backend->delete_atom(handle, public_key, delete_link_targets); } -bool AdapterDB::delete_node(const string& handle, bool delete_link_targets) { +bool AdapterDB::delete_node(const string& handle, const string& public_key, bool delete_link_targets) { this->ensure_backend_ready(); - return this->atomdb_backend->delete_node(handle, delete_link_targets); + return this->atomdb_backend->delete_node(handle, public_key, delete_link_targets); } -bool AdapterDB::delete_link(const string& handle, bool delete_link_targets) { +bool AdapterDB::delete_link(const string& handle, const string& public_key, bool delete_link_targets) { this->ensure_backend_ready(); - return this->atomdb_backend->delete_link(handle, delete_link_targets); + return this->atomdb_backend->delete_link(handle, public_key, delete_link_targets); } -uint AdapterDB::delete_atoms(const vector& handles, bool delete_link_targets) { +uint AdapterDB::delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets) { this->ensure_backend_ready(); - return this->atomdb_backend->delete_atoms(handles, delete_link_targets); + return this->atomdb_backend->delete_atoms(handles, public_key, delete_link_targets); } -uint AdapterDB::delete_nodes(const vector& handles, bool delete_link_targets) { +uint AdapterDB::delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets) { this->ensure_backend_ready(); - return this->atomdb_backend->delete_nodes(handles, delete_link_targets); + return this->atomdb_backend->delete_nodes(handles, public_key, delete_link_targets); } -uint AdapterDB::delete_links(const vector& handles, bool delete_link_targets) { +uint AdapterDB::delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets) { this->ensure_backend_ready(); - return this->atomdb_backend->delete_links(handles, delete_link_targets); + return this->atomdb_backend->delete_links(handles, public_key, delete_link_targets); } -void AdapterDB::re_index_patterns(bool flush_patterns) { +void AdapterDB::re_index_patterns(const string& public_key, bool flush_patterns) { this->ensure_backend_ready(); - this->atomdb_backend->re_index_patterns(flush_patterns); + this->atomdb_backend->re_index_patterns(public_key, flush_patterns); } -size_t AdapterDB::node_count() const { +size_t AdapterDB::node_count(const string& public_key) const { this->ensure_backend_ready(); - return this->atomdb_backend->node_count(); + return this->atomdb_backend->node_count(public_key); } -size_t AdapterDB::link_count() const { +size_t AdapterDB::link_count(const string& public_key) const { this->ensure_backend_ready(); - return this->atomdb_backend->link_count(); + return this->atomdb_backend->link_count(public_key); } -size_t AdapterDB::atom_count() const { +size_t AdapterDB::atom_count(const string& public_key) const { this->ensure_backend_ready(); - return this->atomdb_backend->atom_count(); + return this->atomdb_backend->atom_count(public_key); } // ============================== @@ -237,7 +256,7 @@ void AdapterDB::initialize(bool skip_atomdb_backend_empty) { if (!this->is_context_persisted(context_id)) { LOG_INFO("ContextID <" << context_id << "> NOT found."); - if (!skip_atomdb_backend_empty && !this->atomdb_backend->empty()) { + if (!skip_atomdb_backend_empty && !this->atomdb_backend->empty("")) { RAISE_ERROR("AtomDB backend already populated"); } diff --git a/src/atomdb/adapterdb/AdapterDB.h b/src/atomdb/adapterdb/AdapterDB.h index d7943bc5d..c87db4d40 100644 --- a/src/atomdb/adapterdb/AdapterDB.h +++ b/src/atomdb/adapterdb/AdapterDB.h @@ -55,60 +55,85 @@ class AdapterDB : public AtomDB { // AtomDB API // ------------------------------------------------------------------ - bool allow_nested_indexing() override; + bool allow_nested_indexing(const string& public_key) override; /** * @brief Whether the backend computes and stores composite type fields when adding atoms. */ bool composite_type_enabled() const override; - - shared_ptr get_atom(const string& handle) override; - shared_ptr get_node(const string& handle) override; - shared_ptr get_link(const string& handle) override; - - vector> get_matching_atoms(bool is_toplevel, Atom& key) override; - - shared_ptr query_for_pattern(const LinkSchema& link_schema) override; - - shared_ptr query_for_targets(const string& handle) override; - - shared_ptr query_for_incoming_set(const string& handle) override; - - bool atom_exists(const string& handle) override; - bool node_exists(const string& handle) override; - bool link_exists(const string& handle) override; - - set atoms_exist(const vector& handles) override; - set nodes_exist(const vector& handles) override; - set links_exist(const vector& handles) override; - - string add_atom(const atoms::Atom* atom, bool throw_if_exists = false) override; - string add_node(const atoms::Node* node, bool throw_if_exists = false) override; - string add_link(const atoms::Link* link, bool throw_if_exists = false) override; + bool is_protected() const override; + + shared_ptr get_atom(const string& handle, const string& public_key) override; + shared_ptr get_node(const string& handle, const string& public_key) override; + shared_ptr get_link(const string& handle, const string& public_key) override; + + vector> get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) override; + + shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) override; + shared_ptr query_for_targets(const string& handle, + const string& public_key) override; + shared_ptr query_for_incoming_set(const string& handle, + const string& public_key) override; + + bool atom_exists(const string& handle, const string& public_key) override; + bool node_exists(const string& handle, const string& public_key) override; + bool link_exists(const string& handle, const string& public_key) override; + + set atoms_exist(const vector& handles, const string& public_key) override; + set nodes_exist(const vector& handles, const string& public_key) override; + set links_exist(const vector& handles, const string& public_key) override; + + string add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists = false) override; + string add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists = false) override; + string add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists = false) override; vector add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; vector add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; vector add_links(const vector& links, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; - bool delete_atom(const string& handle, bool delete_link_targets = false) override; - bool delete_node(const string& handle, bool delete_link_targets = false) override; - bool delete_link(const string& handle, bool delete_link_targets = false) override; - - uint delete_atoms(const vector& handles, bool delete_link_targets = false) override; - uint delete_nodes(const vector& handles, bool delete_link_targets = false) override; - uint delete_links(const vector& handles, bool delete_link_targets = false) override; - - void re_index_patterns(bool flush_patterns = true) override; - - size_t node_count() const override; - size_t link_count() const override; - size_t atom_count() const override; + bool delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_node(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_link(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + + uint delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + + void re_index_patterns(const string& public_key, bool flush_patterns = true) override; + + size_t node_count(const string& public_key) const override; + size_t link_count(const string& public_key) const override; + size_t atom_count(const string& public_key) const override; private: AdapterDbType adapter_type; diff --git a/src/atomdb/auth/BUILD b/src/atomdb/auth/BUILD new file mode 100644 index 000000000..38928d78c --- /dev/null +++ b/src/atomdb/auth/BUILD @@ -0,0 +1,24 @@ +load("@rules_cc//cc:cc_library.bzl", "cc_library") + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "protected_atomdb_lib", + includes = ["."], + deps = [ + ":protected_atomdb", + ], +) + +cc_library( + name = "protected_atomdb", + srcs = ["ProtectedAtomDB.cc"], + hdrs = ["ProtectedAtomDB.h"], + includes = ["."], + deps = [ + "//atomdb", + "//atomdb:atomdb_api_types", + "//commons:commons_lib", + "//commons/atoms:atoms_lib", + ], +) diff --git a/src/atomdb/auth/ProtectedAtomDB.cc b/src/atomdb/auth/ProtectedAtomDB.cc new file mode 100644 index 000000000..624bd0c6a --- /dev/null +++ b/src/atomdb/auth/ProtectedAtomDB.cc @@ -0,0 +1,160 @@ +#include "ProtectedAtomDB.h" + +using namespace atomdb; + +ProtectedAtomDB::ProtectedAtomDB(shared_ptr backend, const JsonConfig& config) + : backend(std::move(backend)), config(config) {} + +bool ProtectedAtomDB::allow_nested_indexing(const string& public_key) { return false; } + +bool ProtectedAtomDB::composite_type_enabled() const { return false; } + +bool ProtectedAtomDB::is_protected() const { return true; } + +shared_ptr ProtectedAtomDB::get_atom(const string& handle, const string& public_key) { + return nullptr; +} + +shared_ptr ProtectedAtomDB::get_node(const string& handle, const string& public_key) { + return nullptr; +} + +shared_ptr ProtectedAtomDB::get_link(const string& handle, const string& public_key) { + return nullptr; +} + +vector> ProtectedAtomDB::get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) { + return {}; +} + +shared_ptr ProtectedAtomDB::query_for_pattern(const LinkSchema& link_schema, + const string& public_key) { + return nullptr; +} + +shared_ptr ProtectedAtomDB::query_for_targets(const string& handle, + const string& public_key) { + return nullptr; +} + +shared_ptr ProtectedAtomDB::query_for_incoming_set( + const string& handle, const string& public_key) { + return nullptr; +} + +bool ProtectedAtomDB::atom_exists(const string& handle, const string& public_key) { return false; } + +bool ProtectedAtomDB::node_exists(const string& handle, const string& public_key) { return false; } + +bool ProtectedAtomDB::link_exists(const string& handle, const string& public_key) { return false; } + +set ProtectedAtomDB::atoms_exist(const vector& handles, const string& public_key) { + return {}; +} + +set ProtectedAtomDB::nodes_exist(const vector& handles, const string& public_key) { + return {}; +} + +set ProtectedAtomDB::links_exist(const vector& handles, const string& public_key) { + return {}; +} + +string ProtectedAtomDB::add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists) { + return ""; +} + +string ProtectedAtomDB::add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists) { + return ""; +} + +string ProtectedAtomDB::add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists) { + return ""; +} + +vector ProtectedAtomDB::add_atoms(const vector& atoms, + const string& public_key, + bool throw_if_exists, + bool is_transactional) { + return {}; +} + +vector ProtectedAtomDB::add_nodes(const vector& nodes, + const string& public_key, + bool throw_if_exists, + bool is_transactional) { + return {}; +} + +vector ProtectedAtomDB::add_links(const vector& links, + const string& public_key, + bool throw_if_exists, + bool is_transactional) { + return {}; +} + +bool ProtectedAtomDB::delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets) { + return false; +} + +bool ProtectedAtomDB::delete_node(const string& handle, + const string& public_key, + bool delete_link_targets) { + return false; +} + +bool ProtectedAtomDB::delete_link(const string& handle, + const string& public_key, + bool delete_link_targets) { + return false; +} + +uint ProtectedAtomDB::delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets) { + return 0; +} + +uint ProtectedAtomDB::delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets) { + return 0; +} + +uint ProtectedAtomDB::delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets) { + return 0; +} + +void ProtectedAtomDB::re_index_patterns(const string& public_key, bool flush_patterns) {} + +size_t ProtectedAtomDB::node_count(const string& public_key) const { return 0; } + +size_t ProtectedAtomDB::link_count(const string& public_key) const { return 0; } + +size_t ProtectedAtomDB::atom_count(const string& public_key) const { return 0; } + +bool ProtectedAtomDB::can_read(const string& public_key, const string& handle) { return false; } + +bool ProtectedAtomDB::can_read(const string& public_key, const atoms::Atom& atom) { return false; } + +shared_ptr ProtectedAtomDB::filter_handle_set( + shared_ptr raw, const string& public_key) { + return nullptr; +} + +shared_ptr ProtectedAtomDB::filter_handle_list( + shared_ptr raw, const string& public_key) { + return nullptr; +} diff --git a/src/atomdb/auth/ProtectedAtomDB.h b/src/atomdb/auth/ProtectedAtomDB.h new file mode 100644 index 000000000..2bb782f6b --- /dev/null +++ b/src/atomdb/auth/ProtectedAtomDB.h @@ -0,0 +1,151 @@ +#pragma once + +#include +#include +#include +#include + +#include "AtomDB.h" +#include "JsonConfig.h" + +using namespace std; +using namespace commons; +using namespace atoms; + +namespace atomdb { + +/** + * @brief Authorization wrapper around any AtomDB backend for protected databases. + * + * Delegates storage to backend. When public_key is non-empty, builds AuthorizationManagement for that + * key and filters read results. When public_key is empty, delegates without filtering + * filtering happens in this wrapper after the backend returns data. + */ +class ProtectedAtomDB : public AtomDB { + public: + /** + * @param backend Shared concrete AtomDB. + * @param config Settings used to construct AuthorizationManagement per key. + */ + ProtectedAtomDB(shared_ptr backend, const JsonConfig& config); + + bool allow_nested_indexing(const string& public_key) override; + bool composite_type_enabled() const override; + bool is_protected() const override; + + shared_ptr get_atom(const string& handle, const string& public_key) override; + shared_ptr get_node(const string& handle, const string& public_key) override; + shared_ptr get_link(const string& handle, const string& public_key) override; + + vector> get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) override; + + shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) override; + shared_ptr query_for_targets(const string& handle, + const string& public_key) override; + shared_ptr query_for_incoming_set(const string& handle, + const string& public_key) override; + + bool atom_exists(const string& handle, const string& public_key) override; + bool node_exists(const string& handle, const string& public_key) override; + bool link_exists(const string& handle, const string& public_key) override; + + set atoms_exist(const vector& handles, const string& public_key) override; + set nodes_exist(const vector& handles, const string& public_key) override; + set links_exist(const vector& handles, const string& public_key) override; + + string add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists = false) override; + string add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists = false) override; + string add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists = false) override; + + vector add_atoms(const vector& atoms, + const string& public_key, + bool throw_if_exists = false, + bool is_transactional = false) override; + vector add_nodes(const vector& nodes, + const string& public_key, + bool throw_if_exists = false, + bool is_transactional = false) override; + vector add_links(const vector& links, + const string& public_key, + bool throw_if_exists = false, + bool is_transactional = false) override; + + bool delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_node(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_link(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + + uint delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + + void re_index_patterns(const string& public_key, bool flush_patterns = true) override; + + size_t node_count(const string& public_key) const override; + size_t link_count(const string& public_key) const override; + size_t atom_count(const string& public_key) const override; + + private: + shared_ptr backend; + JsonConfig config; + + /** + * @brief Read check for public_key and handle on this wrapper. + * + * @param public_key key from the AtomDB API. Empty means allow (no filter). + * @param handle Handle to check. + * @return true if key is empty or AccessControl for that key allows read. + */ + bool can_read(const string& public_key, const string& handle); + + /** + * @brief Read check for public_key and atom on this wrapper. + * + * @param public_key key from the AtomDB API. + * @param atom Atom to check. + * @return true if key is empty or AccessControl for that key allows read. + */ + bool can_read(const string& public_key, const atoms::Atom& atom); + + /** + * @brief Builds a filtered HandleSet from a backend result. + * + * @param raw Unfiltered result from backend. + * @param public_key key used for each handle check. + * @return HandleSet containing only authorized handles. + */ + shared_ptr filter_handle_set( + shared_ptr raw, const string& public_key); + + /** + * @brief Builds a filtered HandleList from a backend result. + * + * @param raw Unfiltered result from backend. + * @param public_key key used for each handle check. + * @return HandleList containing only authorized handles. + */ + shared_ptr filter_handle_list( + shared_ptr raw, const string& public_key); +}; + +} // namespace atomdb diff --git a/src/atomdb/inmemorydb/InMemoryDB.cc b/src/atomdb/inmemorydb/InMemoryDB.cc index 9f0c8e843..8d250d2fd 100644 --- a/src/atomdb/inmemorydb/InMemoryDB.cc +++ b/src/atomdb/inmemorydb/InMemoryDB.cc @@ -130,9 +130,11 @@ InMemoryDB::~InMemoryDB() { delete this->incoming_sets_trie_; } -bool InMemoryDB::allow_nested_indexing() { return false; } +bool InMemoryDB::allow_nested_indexing(const string& public_key) { return false; } -shared_ptr InMemoryDB::get_atom(const string& handle) { +bool InMemoryDB::is_protected() const { return false; } + +shared_ptr InMemoryDB::get_atom(const string& handle, const string& public_key) { auto trie_value = this->atoms_trie_->lookup(handle); if (trie_value == NULL) { return nullptr; @@ -152,23 +154,18 @@ shared_ptr InMemoryDB::get_atom(const string& handle) { } } -shared_ptr InMemoryDB::get_node(const string& handle) { - auto atom = get_atom(handle); - if (atom != nullptr) { - return make_shared(*dynamic_cast(atom.get())); - } - return nullptr; +shared_ptr InMemoryDB::get_node(const string& handle, const string& public_key) { + auto atom = get_atom(handle, public_key); + return dynamic_pointer_cast(atom); } -shared_ptr InMemoryDB::get_link(const string& handle) { - auto atom = get_atom(handle); - if (atom != nullptr) { - return make_shared(*dynamic_cast(atom.get())); - } - return nullptr; +shared_ptr InMemoryDB::get_link(const string& handle, const string& public_key) { + auto atom = get_atom(handle, public_key); + return dynamic_pointer_cast(atom); } -shared_ptr InMemoryDB::query_for_pattern(const LinkSchema& link_schema) { +shared_ptr InMemoryDB::query_for_pattern(const LinkSchema& link_schema, + const string& public_key) { auto handle_set = make_shared(); // Check if we have this pattern indexed in the HandleTrie @@ -183,7 +180,7 @@ shared_ptr InMemoryDB::query_for_pattern(const LinkSchema& link_schem return handle_set; } -shared_ptr InMemoryDB::query_for_targets(const string& handle) { +shared_ptr InMemoryDB::query_for_targets(const string& handle, const string& public_key) { auto trie_value = atoms_trie_->lookup(handle); if (trie_value == NULL) { return nullptr; @@ -200,7 +197,8 @@ shared_ptr InMemoryDB::query_for_targets(const string& handle) { return make_shared(link->targets); } -shared_ptr InMemoryDB::query_for_incoming_set(const string& handle) { +shared_ptr InMemoryDB::query_for_incoming_set(const string& handle, + const string& public_key) { auto handle_set = make_shared(); auto incoming_set_trie_value = dynamic_cast(this->incoming_sets_trie_->lookup(handle)); @@ -212,7 +210,9 @@ shared_ptr InMemoryDB::query_for_incoming_set(const string& handle) { return handle_set; } -vector> InMemoryDB::get_matching_atoms(bool is_toplevel, Atom& key) { +vector> InMemoryDB::get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) { vector> matching_atoms; auto trie_value = atoms_trie_->lookup(key.handle()); if (trie_value == NULL) { @@ -231,9 +231,11 @@ vector> InMemoryDB::get_matching_atoms(bool is_toplevel, Atom& return matching_atoms; } -bool InMemoryDB::atom_exists(const string& handle) { return atoms_trie_->lookup(handle) != NULL; } +bool InMemoryDB::atom_exists(const string& handle, const string& public_key) { + return atoms_trie_->lookup(handle) != NULL; +} -bool InMemoryDB::node_exists(const string& handle) { +bool InMemoryDB::node_exists(const string& handle, const string& public_key) { auto trie_value = atoms_trie_->lookup(handle); if (trie_value == NULL) { return false; @@ -246,7 +248,7 @@ bool InMemoryDB::node_exists(const string& handle) { return Atom::is_node(*atom); } -bool InMemoryDB::link_exists(const string& handle) { +bool InMemoryDB::link_exists(const string& handle, const string& public_key) { auto trie_value = atoms_trie_->lookup(handle); if (trie_value == NULL) { return false; @@ -259,7 +261,7 @@ bool InMemoryDB::link_exists(const string& handle) { return Atom::is_link(*atom); } -set InMemoryDB::atoms_exist(const vector& handles) { +set InMemoryDB::atoms_exist(const vector& handles, const string& public_key) { set existing; for (const auto& handle : handles) { if (atoms_trie_->lookup(handle) != NULL) { @@ -269,38 +271,38 @@ set InMemoryDB::atoms_exist(const vector& handles) { return existing; } -set InMemoryDB::nodes_exist(const vector& handles) { +set InMemoryDB::nodes_exist(const vector& handles, const string& public_key) { set existing; for (const auto& handle : handles) { - if (this->node_exists(handle)) { + if (this->node_exists(handle, public_key)) { existing.insert(handle); } } return existing; } -set InMemoryDB::links_exist(const vector& handles) { +set InMemoryDB::links_exist(const vector& handles, const string& public_key) { set existing; for (const auto& handle : handles) { - if (this->link_exists(handle)) { + if (this->link_exists(handle, public_key)) { existing.insert(handle); } } return existing; } -string InMemoryDB::add_atom(const atoms::Atom* atom, bool throw_if_exists) { +string InMemoryDB::add_atom(const atoms::Atom* atom, const string& public_key, bool throw_if_exists) { if (atom->arity() == 0) { - return add_node(dynamic_cast(atom), throw_if_exists); + return add_node(dynamic_cast(atom), public_key, throw_if_exists); } else { - return add_link(dynamic_cast(atom), throw_if_exists); + return add_link(dynamic_cast(atom), public_key, throw_if_exists); } } -string InMemoryDB::add_node(const atoms::Node* node, bool throw_if_exists) { +string InMemoryDB::add_node(const atoms::Node* node, const string& public_key, bool throw_if_exists) { string handle = node->handle(); - if (throw_if_exists && this->node_exists(handle)) { + if (throw_if_exists && this->node_exists(handle, public_key)) { RAISE_ERROR("Node already exists: " + handle); return ""; } @@ -319,13 +321,14 @@ string InMemoryDB::add_node(const atoms::Node* node, bool throw_if_exists) { return handle; } -string InMemoryDB::add_link(const atoms::Link* link, bool throw_if_exists) { +string InMemoryDB::add_link(const atoms::Link* link, const string& public_key, bool throw_if_exists) { vector links = {const_cast(link)}; - auto handles = this->add_links(links, throw_if_exists, false); + auto handles = this->add_links(links, public_key, throw_if_exists, false); return handles.empty() ? "" : handles[0]; } vector InMemoryDB::add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists, bool is_transactional) { if (atoms.empty()) { @@ -342,14 +345,15 @@ vector InMemoryDB::add_atoms(const vector& atoms, links.push_back(dynamic_cast(atom)); } } - auto node_handles = this->add_nodes(nodes, throw_if_exists, is_transactional); - auto link_handles = this->add_links(links, throw_if_exists, is_transactional); + auto node_handles = this->add_nodes(nodes, public_key, throw_if_exists, is_transactional); + auto link_handles = this->add_links(links, public_key, throw_if_exists, is_transactional); node_handles.insert(node_handles.end(), link_handles.begin(), link_handles.end()); return node_handles; } vector InMemoryDB::add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists, bool is_transactional) { if (nodes.empty()) { @@ -362,7 +366,7 @@ vector InMemoryDB::add_nodes(const vector& nodes, } if (throw_if_exists) { - auto existing_handles = this->nodes_exist(handles); + auto existing_handles = this->nodes_exist(handles, public_key); if (!existing_handles.empty()) { vector existing_handles_vector(existing_handles.begin(), existing_handles.end()); RAISE_ERROR("Failed to insert nodes, some nodes already exist: " + @@ -372,13 +376,14 @@ vector InMemoryDB::add_nodes(const vector& nodes, } for (const auto& node : nodes) { - handles.push_back(this->add_node(node, throw_if_exists)); + handles.push_back(this->add_node(node, public_key, throw_if_exists)); } return handles; } vector InMemoryDB::add_links(const vector& links, + const string& public_key, bool throw_if_exists, bool is_transactional) { if (links.empty()) { @@ -390,7 +395,7 @@ vector InMemoryDB::add_links(const vector& links, for (const auto& link : links) { handles.push_back(link->handle()); } - auto existing_handles = this->links_exist(handles); + auto existing_handles = this->links_exist(handles, public_key); if (!existing_handles.empty()) { vector existing_handles_vector(existing_handles.begin(), existing_handles.end()); RAISE_ERROR("Failed to insert links, some links already exist: " + @@ -430,14 +435,14 @@ vector InMemoryDB::add_links(const vector& links, return handles; } -bool InMemoryDB::delete_atom(const string& handle, bool delete_link_targets) { - if (this->delete_node(handle, delete_link_targets)) { +bool InMemoryDB::delete_atom(const string& handle, const string& public_key, bool delete_link_targets) { + if (this->delete_node(handle, public_key, delete_link_targets)) { return true; } - return this->delete_link(handle, delete_link_targets); + return this->delete_link(handle, public_key, delete_link_targets); } -bool InMemoryDB::delete_node(const string& handle, bool delete_link_targets) { +bool InMemoryDB::delete_node(const string& handle, const string& public_key, bool delete_link_targets) { auto trie_value = this->atoms_trie_->lookup(handle); if (trie_value == NULL) { return false; @@ -469,7 +474,7 @@ bool InMemoryDB::delete_node(const string& handle, bool delete_link_targets) { // Delete all links that reference this node for (const auto& link_handle : link_handles_to_delete) { - this->delete_link(link_handle, delete_link_targets); + this->delete_link(link_handle, public_key, delete_link_targets); } // Clear the value in the trie (set to NULL) @@ -479,7 +484,7 @@ bool InMemoryDB::delete_node(const string& handle, bool delete_link_targets) { return true; } -bool InMemoryDB::delete_link(const string& handle, bool delete_link_targets) { +bool InMemoryDB::delete_link(const string& handle, const string& public_key, bool delete_link_targets) { auto trie_value = atoms_trie_->lookup(handle); if (trie_value == NULL) { return false; @@ -525,52 +530,62 @@ bool InMemoryDB::delete_link(const string& handle, bool delete_link_targets) { // Release locks before calling delete_atom to avoid deadlock // Delete targets that have no other incoming links for (const auto& target_handle : targets_to_delete) { - this->delete_atom(target_handle, delete_link_targets); + this->delete_atom(target_handle, public_key, delete_link_targets); } return true; } -uint InMemoryDB::delete_atoms(const vector& handles, bool delete_link_targets) { +uint InMemoryDB::delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets) { uint deleted_count = 0; for (const auto& handle : handles) { - if (this->delete_atom(handle, delete_link_targets)) { + if (this->delete_atom(handle, public_key, delete_link_targets)) { deleted_count++; } } return deleted_count; } -uint InMemoryDB::delete_nodes(const vector& handles, bool delete_link_targets) { +uint InMemoryDB::delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets) { uint deleted_count = 0; for (const auto& handle : handles) { - if (this->delete_node(handle, delete_link_targets)) { + if (this->delete_node(handle, public_key, delete_link_targets)) { deleted_count++; } } return deleted_count; } -uint InMemoryDB::delete_links(const vector& handles, bool delete_link_targets) { +uint InMemoryDB::delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets) { uint deleted_count = 0; for (const auto& handle : handles) { - if (this->delete_link(handle, delete_link_targets)) { + if (this->delete_link(handle, public_key, delete_link_targets)) { deleted_count++; } } return deleted_count; } -size_t InMemoryDB::node_count() const { RAISE_ERROR("node_count() is not implemented yet"); } +size_t InMemoryDB::node_count(const string& public_key) const { + RAISE_ERROR("node_count() is not implemented yet"); +} -size_t InMemoryDB::link_count() const { RAISE_ERROR("link_count() is not implemented yet"); } +size_t InMemoryDB::link_count(const string& public_key) const { + RAISE_ERROR("link_count() is not implemented yet"); +} -size_t InMemoryDB::atom_count() const { +size_t InMemoryDB::atom_count(const string& public_key) const { auto size = this->atoms_trie_->size(); return static_cast(size); } -void InMemoryDB::re_index_patterns(bool flush_patterns) { +void InMemoryDB::re_index_patterns(const string& public_key, bool flush_patterns) { if (flush_patterns) { // Clear all pattern index entries by deleting and recreating the trie this->pattern_index_trie_->traverse( diff --git a/src/atomdb/inmemorydb/InMemoryDB.h b/src/atomdb/inmemorydb/InMemoryDB.h index cc683d1cb..deed2bd0c 100644 --- a/src/atomdb/inmemorydb/InMemoryDB.h +++ b/src/atomdb/inmemorydb/InMemoryDB.h @@ -21,56 +21,81 @@ class InMemoryDB : public AtomDB { InMemoryDB(const string& context = ""); ~InMemoryDB(); - bool allow_nested_indexing() override; + bool allow_nested_indexing(const string& public_key) override; bool composite_type_enabled() const override { return false; } - - shared_ptr get_atom(const string& handle) override; - shared_ptr get_node(const string& handle) override; - shared_ptr get_link(const string& handle) override; - - vector> get_matching_atoms(bool is_toplevel, Atom& key) override; - - shared_ptr query_for_pattern(const LinkSchema& link_schema) override; - - shared_ptr query_for_targets(const string& handle) override; - - shared_ptr query_for_incoming_set(const string& handle) override; - - bool atom_exists(const string& handle) override; - bool node_exists(const string& handle) override; - bool link_exists(const string& handle) override; - - set atoms_exist(const vector& handles) override; - set nodes_exist(const vector& handles) override; - set links_exist(const vector& handles) override; - - string add_atom(const atoms::Atom* atom, bool throw_if_exists = false) override; - string add_node(const atoms::Node* node, bool throw_if_exists = false) override; - string add_link(const atoms::Link* link, bool throw_if_exists = false) override; + bool is_protected() const override; + + shared_ptr get_atom(const string& handle, const string& public_key) override; + shared_ptr get_node(const string& handle, const string& public_key) override; + shared_ptr get_link(const string& handle, const string& public_key) override; + + vector> get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) override; + + shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) override; + shared_ptr query_for_targets(const string& handle, + const string& public_key) override; + shared_ptr query_for_incoming_set(const string& handle, + const string& public_key) override; + + bool atom_exists(const string& handle, const string& public_key) override; + bool node_exists(const string& handle, const string& public_key) override; + bool link_exists(const string& handle, const string& public_key) override; + + set atoms_exist(const vector& handles, const string& public_key) override; + set nodes_exist(const vector& handles, const string& public_key) override; + set links_exist(const vector& handles, const string& public_key) override; + + string add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists = false) override; + string add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists = false) override; + string add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists = false) override; vector add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; vector add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; vector add_links(const vector& links, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; - bool delete_atom(const string& handle, bool delete_link_targets = false) override; - bool delete_node(const string& handle, bool delete_link_targets = false) override; - bool delete_link(const string& handle, bool delete_link_targets = false) override; - - uint delete_atoms(const vector& handles, bool delete_link_targets = false) override; - uint delete_nodes(const vector& handles, bool delete_link_targets = false) override; - uint delete_links(const vector& handles, bool delete_link_targets = false) override; - - size_t node_count() const override; - size_t link_count() const override; - size_t atom_count() const override; - - void re_index_patterns(bool flush_patterns = true) override; + bool delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_node(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_link(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + + uint delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + + void re_index_patterns(const string& public_key, bool flush_patterns = true) override; + + size_t node_count(const string& public_key) const override; + size_t link_count(const string& public_key) const override; + size_t atom_count(const string& public_key) const override; private: string context_; diff --git a/src/atomdb/morkdb/MorkDB.cc b/src/atomdb/morkdb/MorkDB.cc index 9033e05b0..8bbd92a33 100644 --- a/src/atomdb/morkdb/MorkDB.cc +++ b/src/atomdb/morkdb/MorkDB.cc @@ -135,7 +135,7 @@ MorkDB::MorkDB(const string& context, const JsonConfig& config) : RedisMongoDB(c MorkDB::~MorkDB() {} -bool MorkDB::allow_nested_indexing() { return true; } +bool MorkDB::allow_nested_indexing(const string& public_key) { return true; } void MorkDB::mork_setup(const JsonConfig& config) { string address = Utils::trim(config.at_path("morkdb.endpoint").get_or("")); @@ -174,7 +174,8 @@ class MorkDBDecoder : public HandleDecoder { shared_ptr parser_actions; }; -shared_ptr MorkDB::query_for_pattern(const LinkSchema& link_schema) { +shared_ptr MorkDB::query_for_pattern(const LinkSchema& link_schema, + const string& public_key) { string pattern_metta = link_schema.metta_representation(*this); // template should equals to pattern_metta LOG_DEBUG("Fetching data..."); @@ -206,7 +207,8 @@ shared_ptr MorkDB::query_for_pattern(const LinkSche return handle_set; } -shared_ptr MorkDB::query_for_targets(const string& handle) { +shared_ptr MorkDB::query_for_targets(const string& handle, + const string& public_key) { auto document = this->get_atom_document(handle); if (document == nullptr || !document->contains(MONGODB_FIELD_NAME[MONGODB_FIELD::TARGETS])) { return nullptr; @@ -215,6 +217,7 @@ shared_ptr MorkDB::query_for_targets(const string& } vector MorkDB::add_links(const vector& links, + const string& public_key, bool throw_if_exists, bool is_transactional) { if (links.empty()) { @@ -230,7 +233,7 @@ vector MorkDB::add_links(const vector& links, for (const auto& link : links) { handles.push_back(link->handle()); } - auto existing_handles = this->links_exist(handles); + auto existing_handles = this->links_exist(handles, public_key); if (!existing_handles.empty()) { vector existing_handles_vector(existing_handles.begin(), existing_handles.end()); RAISE_ERROR("Failed to insert links, some links already exist: " + @@ -303,14 +306,14 @@ vector MorkDB::add_links(const vector& links, return handles; } -bool MorkDB::delete_link(const string& handle, bool delete_targets) { +bool MorkDB::delete_link(const string& handle, const string& public_key, bool delete_targets) { Utils::error("MORKDB does not support deleting links.", false); return false; } string MorkDB::flush_pattern(const string& pattern) { return this->mork_client->clear(pattern); } -void MorkDB::re_index_patterns(bool flush_patterns) { +void MorkDB::re_index_patterns(const string& public_key, bool flush_patterns) { vector links; uint max_arity = 0; @@ -350,7 +353,7 @@ void MorkDB::re_index_patterns(bool flush_patterns) { } } - this->add_links(links, false, true); + this->add_links(links, "", false, true); } // <-- diff --git a/src/atomdb/morkdb/MorkDB.h b/src/atomdb/morkdb/MorkDB.h index 76be9056b..abd907d5b 100644 --- a/src/atomdb/morkdb/MorkDB.h +++ b/src/atomdb/morkdb/MorkDB.h @@ -43,21 +43,26 @@ class MorkDB : public RedisMongoDB { MorkDB(const string& context, const JsonConfig& config); ~MorkDB(); - bool allow_nested_indexing() override; + bool allow_nested_indexing(const string& public_key) override; - shared_ptr query_for_pattern(const LinkSchema& link_schema) override; - shared_ptr query_for_targets(const string& handle) override; + shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) override; + shared_ptr query_for_targets(const string& handle, + const string& public_key) override; vector add_links(const vector& links, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; // TODO: Implement this once MORK supports deleting links (S-Expressions) - bool delete_link(const string& handle, bool delete_targets) override; + bool delete_link(const string& handle, + const string& public_key, + bool delete_targets = false) override; string flush_pattern(const string& pattern); - void re_index_patterns(bool flush_patterns = true) override; + void re_index_patterns(const string& public_key, bool flush_patterns = true) override; private: shared_ptr mork_client; diff --git a/src/atomdb/redis_mongodb/RedisMongoDB.cc b/src/atomdb/redis_mongodb/RedisMongoDB.cc index 8a9bc47b3..d77ba2f56 100644 --- a/src/atomdb/redis_mongodb/RedisMongoDB.cc +++ b/src/atomdb/redis_mongodb/RedisMongoDB.cc @@ -29,10 +29,13 @@ uint RedisMongoDB::REDIS_CHUNK_SIZE; string RedisMongoDB::MONGODB_DB_NAME; string RedisMongoDB::MONGODB_NODES_COLLECTION_NAME; string RedisMongoDB::MONGODB_LINKS_COLLECTION_NAME; +string RedisMongoDB::MONGODB_CONFIG_COLLECTION_NAME; string RedisMongoDB::MONGODB_PATTERN_INDEX_SCHEMA_COLLECTION_NAME; string RedisMongoDB::MONGODB_FIELD_NAME[MONGODB_FIELD::size]; uint RedisMongoDB::MONGODB_CHUNK_SIZE; +const string RedisMongoDB::MONGODB_CONFIG_DOCUMENT_HANDLE = Hasher::plain_string_hash("config"); + RedisMongoDB::RedisMongoDB(const string& context, bool skip_redis, const JsonConfig& config) : context(context), skip_redis_(skip_redis), @@ -51,7 +54,25 @@ RedisMongoDB::~RedisMongoDB() { if (!skip_redis_) delete this->redis_pool; } -bool RedisMongoDB::allow_nested_indexing() { return false; } +bool RedisMongoDB::allow_nested_indexing(const string& public_key) { return false; } + +bool RedisMongoDB::is_protected() const { + auto conn = this->mongodb_pool->acquire(); + auto config_collection = (*conn)[MONGODB_DB_NAME][MONGODB_CONFIG_COLLECTION_NAME]; + auto filter = bsoncxx::builder::basic::make_document(bsoncxx::builder::basic::kvp( + MONGODB_FIELD_NAME[MONGODB_FIELD::ID], MONGODB_CONFIG_DOCUMENT_HANDLE)); + auto result = config_collection.find_one(filter.view()); + if (!result) { + LOG_DEBUG("MongoDB config document not found; assuming unprotected database"); + return false; + } + auto element = (*result)["protected"]; + if (!element || element.type() != bsoncxx::type::k_bool) { + LOG_ERROR("MongoDB config document has no valid 'protected' field; assuming unprotected"); + return false; + } + return element.get_bool().value; +} void RedisMongoDB::redis_setup(const JsonConfig& config) { if (skip_redis_) return; @@ -81,6 +102,8 @@ void RedisMongoDB::mongodb_setup(const JsonConfig& config) { string user = config.at_path("mongodb.username").get(); string password = config.at_path("mongodb.password").get(); uint chunk_size = config.at_path("mongodb.chunk_size").get_or(0); + bool seed_protected = config.at_path("mongodb.seed_protected").get_or(false); + if (chunk_size > 0) { MONGODB_CHUNK_SIZE = chunk_size; } @@ -103,12 +126,32 @@ void RedisMongoDB::mongodb_setup(const JsonConfig& config) { bsoncxx::builder::basic::make_document(bsoncxx::builder::basic::kvp("ping", 1)); mongodb.run_command(ping_cmd.view()); LOG_INFO("Connected to MongoDB at " << address); + + if (seed_protected) { + auto config_collection = (*conn)[MONGODB_DB_NAME][MONGODB_CONFIG_COLLECTION_NAME]; + auto filter = bsoncxx::builder::basic::make_document(bsoncxx::builder::basic::kvp( + MONGODB_FIELD_NAME[MONGODB_FIELD::ID], MONGODB_CONFIG_DOCUMENT_HANDLE)); + auto result = config_collection.find_one(filter.view()); + + if (!result) { + bsoncxx::builder::stream::document protected_doc; + protected_doc << MONGODB_FIELD_NAME[MONGODB_FIELD::ID] << MONGODB_CONFIG_DOCUMENT_HANDLE + << "protected" << true; + config_collection.insert_one(protected_doc.view()); + LOG_INFO("MongoDB config: set protected=true (handle=" << MONGODB_CONFIG_DOCUMENT_HANDLE + << ")"); + } else { + LOG_INFO("MongoDB config: document already exists; skipping seed (handle=" + << MONGODB_CONFIG_DOCUMENT_HANDLE << ")"); + } + } + } catch (const std::exception& e) { RAISE_ERROR(e.what()); } } -shared_ptr RedisMongoDB::get_atom(const string& handle) { +shared_ptr RedisMongoDB::get_atom(const string& handle, const string& public_key) { auto atom_document = dynamic_pointer_cast(get_atom_document(handle)); if (atom_document != NULL) { @@ -141,15 +184,16 @@ shared_ptr RedisMongoDB::get_atom(const string& handle) { } } -shared_ptr RedisMongoDB::get_node(const string& handle) { - return dynamic_pointer_cast(get_atom(handle)); +shared_ptr RedisMongoDB::get_node(const string& handle, const string& public_key) { + return dynamic_pointer_cast(get_atom(handle, public_key)); } -shared_ptr RedisMongoDB::get_link(const string& handle) { - return dynamic_pointer_cast(get_atom(handle)); +shared_ptr RedisMongoDB::get_link(const string& handle, const string& public_key) { + return dynamic_pointer_cast(get_atom(handle, public_key)); } -shared_ptr RedisMongoDB::query_for_pattern(const LinkSchema& link_schema) { +shared_ptr RedisMongoDB::query_for_pattern(const LinkSchema& link_schema, + const string& public_key) { if (skip_redis_) return nullptr; auto pattern_handle = link_schema.handle(); @@ -190,7 +234,8 @@ shared_ptr RedisMongoDB::query_for_pattern(const Li return handle_set; } -shared_ptr RedisMongoDB::query_for_targets(const string& handle) { +shared_ptr RedisMongoDB::query_for_targets(const string& handle, + const string& public_key) { if (skip_redis_) return nullptr; redisReply* reply; @@ -221,7 +266,8 @@ shared_ptr RedisMongoDB::query_for_targets(const s return handle_list; } -shared_ptr RedisMongoDB::query_for_incoming_set(const string& handle) { +shared_ptr RedisMongoDB::query_for_incoming_set(const string& handle, + const string& public_key) { if (skip_redis_) return nullptr; unsigned int redis_cursor = 0; @@ -603,7 +649,9 @@ vector> RedisMongoDB::get_link_docume return get_documents(handles, fields, MONGODB_LINKS_COLLECTION_NAME); } -vector> RedisMongoDB::get_matching_atoms(bool is_toplevel, Atom& key) { +vector> RedisMongoDB::get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) { vector> matching_atoms; vector collection_names = {MONGODB_NODES_COLLECTION_NAME, MONGODB_LINKS_COLLECTION_NAME}; @@ -632,7 +680,8 @@ vector> RedisMongoDB::get_matching_atoms(bool is_toplevel, Atom for (const auto& document : documents) { Assignment assignment; if (key.match(document->get(MONGODB_FIELD_NAME[MONGODB_FIELD::ID]), assignment, *this)) { - auto atom = this->get_atom(document->get(MONGODB_FIELD_NAME[MONGODB_FIELD::ID])); + auto atom = + this->get_atom(document->get(MONGODB_FIELD_NAME[MONGODB_FIELD::ID]), public_key); if (atom != nullptr) { matching_atoms.push_back(atom); } @@ -651,15 +700,15 @@ bool RedisMongoDB::document_exists(const string& handle, const string& collectio return reply != bsoncxx::v_noabi::stdx::nullopt; } -bool RedisMongoDB::atom_exists(const string& atom_handle) { - return node_exists(atom_handle) || link_exists(atom_handle); +bool RedisMongoDB::atom_exists(const string& atom_handle, const string& public_key) { + return node_exists(atom_handle, "") || link_exists(atom_handle, ""); } -bool RedisMongoDB::node_exists(const string& node_handle) { +bool RedisMongoDB::node_exists(const string& node_handle, const string& public_key) { return document_exists(node_handle, MONGODB_NODES_COLLECTION_NAME); } -bool RedisMongoDB::link_exists(const string& link_handle) { +bool RedisMongoDB::link_exists(const string& link_handle, const string& public_key) { return document_exists(link_handle, MONGODB_LINKS_COLLECTION_NAME); } @@ -699,27 +748,27 @@ set RedisMongoDB::documents_exist(const vector& handles, const s return existing_handles; } -set RedisMongoDB::atoms_exist(const vector& handles) { - auto nodes = nodes_exist(handles); +set RedisMongoDB::atoms_exist(const vector& handles, const string& public_key) { + auto nodes = nodes_exist(handles, public_key); if (nodes.size() == handles.size()) return nodes; - auto links = links_exist(handles); + auto links = links_exist(handles, public_key); nodes.insert(links.begin(), links.end()); return nodes; } -set RedisMongoDB::nodes_exist(const vector& node_handles) { +set RedisMongoDB::nodes_exist(const vector& node_handles, const string& public_key) { return documents_exist(node_handles, MONGODB_NODES_COLLECTION_NAME); } -set RedisMongoDB::links_exist(const vector& link_handles) { +set RedisMongoDB::links_exist(const vector& link_handles, const string& public_key) { return documents_exist(link_handles, MONGODB_LINKS_COLLECTION_NAME); } -string RedisMongoDB::add_atom(const atoms::Atom* atom, bool throw_if_exists) { +string RedisMongoDB::add_atom(const atoms::Atom* atom, const string& public_key, bool throw_if_exists) { if (atom->arity() == 0) { - return add_node(dynamic_cast(atom), throw_if_exists); + return add_node(dynamic_cast(atom), public_key, throw_if_exists); } else { - return add_link(dynamic_cast(atom), throw_if_exists); + return add_link(dynamic_cast(atom), public_key, throw_if_exists); } } @@ -802,8 +851,8 @@ uint RedisMongoDB::upsert_documents(const std::vector& return total_modified; } -string RedisMongoDB::add_node(const atoms::Node* node, bool throw_if_exists) { - if (throw_if_exists && node_exists(node->handle())) { +string RedisMongoDB::add_node(const atoms::Node* node, const string& public_key, bool throw_if_exists) { + if (throw_if_exists && node_exists(node->handle(), public_key)) { RAISE_ERROR("Node already exists: " + node->handle()); return ""; } @@ -816,12 +865,13 @@ string RedisMongoDB::add_node(const atoms::Node* node, bool throw_if_exists) { return node->handle(); } -string RedisMongoDB::add_link(const atoms::Link* link, bool throw_if_exists) { +string RedisMongoDB::add_link(const atoms::Link* link, const string& public_key, bool throw_if_exists) { vector links = {const_cast(link)}; - return add_links(links, throw_if_exists)[0]; + return add_links(links, public_key, throw_if_exists)[0]; } vector RedisMongoDB::add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists, bool is_transactional) { if (atoms.empty()) { @@ -838,14 +888,15 @@ vector RedisMongoDB::add_atoms(const vector& atoms, links.push_back(dynamic_cast(atom)); } } - auto node_handles = add_nodes(nodes, throw_if_exists, is_transactional); - auto link_handles = add_links(links, throw_if_exists, is_transactional); + auto node_handles = add_nodes(nodes, public_key, throw_if_exists, is_transactional); + auto link_handles = add_links(links, public_key, throw_if_exists, is_transactional); node_handles.insert(node_handles.end(), link_handles.begin(), link_handles.end()); return node_handles; } vector RedisMongoDB::add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists, bool is_transactional) { if (nodes.empty()) { @@ -866,7 +917,7 @@ vector RedisMongoDB::add_nodes(const vector& nodes, } if (throw_if_exists) { - auto existing_handles = this->nodes_exist(handles); + auto existing_handles = this->nodes_exist(handles, public_key); if (existing_handles.size() > 0) { RAISE_ERROR("Failed to insert nodes, some nodes already exist."); return {}; @@ -881,6 +932,7 @@ vector RedisMongoDB::add_nodes(const vector& nodes, } vector RedisMongoDB::add_links(const vector& links, + const string& public_key, bool throw_if_exists, bool is_transactional) { if (links.empty()) { @@ -896,7 +948,7 @@ vector RedisMongoDB::add_links(const vector& links, for (const auto& link : links) { handles.push_back(link->handle()); } - auto existing_handles = this->links_exist(handles); + auto existing_handles = this->links_exist(handles, public_key); if (!existing_handles.empty()) { vector existing_handles_vector(existing_handles.begin(), existing_handles.end()); RAISE_ERROR("Failed to insert links, some links already exist: " + @@ -1000,11 +1052,11 @@ bool RedisMongoDB::delete_document(const string& handle, bsoncxx::v_noabi::builder::basic::kvp(MONGODB_FIELD_NAME[MONGODB_FIELD::ID], handle))); if (!skip_redis_) { - auto incoming_set = query_for_incoming_set(handle); + auto incoming_set = query_for_incoming_set(handle, ""); auto it = incoming_set->get_iterator(); char* incoming_handle; while ((incoming_handle = it->next()) != nullptr) { - delete_atom(incoming_handle, delete_targets); + delete_atom(incoming_handle, "", delete_targets); } delete_incoming_set(handle); @@ -1016,18 +1068,18 @@ bool RedisMongoDB::delete_document(const string& handle, return reply->deleted_count() > 0 || !document_exists(handle, collection_name); } -bool RedisMongoDB::delete_atom(const string& handle, bool delete_targets) { - if (delete_node(handle, delete_targets)) return true; - return delete_link(handle, delete_targets); +bool RedisMongoDB::delete_atom(const string& handle, const string& public_key, bool delete_targets) { + if (delete_node(handle, "", delete_targets)) return true; + return delete_link(handle, "", delete_targets); } -bool RedisMongoDB::delete_node(const string& handle, bool delete_targets) { +bool RedisMongoDB::delete_node(const string& handle, const string& public_key, bool delete_targets) { auto node_document = get_node_document(handle); if (node_document == nullptr) return false; return delete_document(handle, MONGODB_NODES_COLLECTION_NAME, delete_targets); } -bool RedisMongoDB::delete_link(const string& handle, bool delete_targets) { +bool RedisMongoDB::delete_link(const string& handle, const string& public_key, bool delete_targets) { auto link_document = get_link_document(handle); if (link_document == nullptr) return false; @@ -1037,10 +1089,10 @@ bool RedisMongoDB::delete_link(const string& handle, bool delete_targets) { auto target_handle = link_document->get(MONGODB_FIELD_NAME[MONGODB_FIELD::TARGETS], i); // If target is referenced more than once, we need to update incoming_set or delete target // otherwise - if (!skip_redis_ && query_for_incoming_set(target_handle)->size() > 1) { + if (!skip_redis_ && query_for_incoming_set(target_handle, "")->size() > 1) { update_incoming_set(target_handle, handle); } else if (delete_targets) { - delete_atom(target_handle, delete_targets); + delete_atom(target_handle, "", delete_targets); } targets.push_back(target_handle); } @@ -1066,40 +1118,48 @@ uint RedisMongoDB::delete_documents(const vector& handles, return deleted_count; } -uint RedisMongoDB::delete_atoms(const vector& handles, bool delete_targets) { +uint RedisMongoDB::delete_atoms(const vector& handles, + const string& public_key, + bool delete_targets) { uint deleted_count = 0; for (const auto& handle : handles) { - if (delete_atom(handle, delete_targets)) { + if (delete_atom(handle, "", delete_targets)) { deleted_count++; } } return deleted_count; } -uint RedisMongoDB::delete_nodes(const vector& handles, bool delete_targets) { +uint RedisMongoDB::delete_nodes(const vector& handles, + const string& public_key, + bool delete_targets) { return delete_documents(handles, MONGODB_NODES_COLLECTION_NAME, delete_targets); } -uint RedisMongoDB::delete_links(const vector& handles, bool delete_targets) { +uint RedisMongoDB::delete_links(const vector& handles, + const string& public_key, + bool delete_targets) { uint deleted_count = 0; for (const auto& handle : handles) { - if (delete_link(handle, delete_targets)) { + if (delete_link(handle, "", delete_targets)) { deleted_count++; } } return deleted_count; } -size_t RedisMongoDB::atom_count() const { return node_count() + link_count(); } +size_t RedisMongoDB::atom_count(const string& public_key) const { + return node_count(public_key) + link_count(public_key); +} -size_t RedisMongoDB::node_count() const { +size_t RedisMongoDB::node_count(const string& public_key) const { auto conn = this->mongodb_pool->acquire(); auto mongodb_collection = (*conn)[MONGODB_DB_NAME][MONGODB_NODES_COLLECTION_NAME]; auto count = mongodb_collection.estimated_document_count(); return static_cast(count); } -size_t RedisMongoDB::link_count() const { +size_t RedisMongoDB::link_count(const string& public_key) const { auto conn = this->mongodb_pool->acquire(); auto mongodb_collection = (*conn)[MONGODB_DB_NAME][MONGODB_LINKS_COLLECTION_NAME]; auto count = mongodb_collection.estimated_document_count(); @@ -1247,7 +1307,7 @@ vector> RedisMongoDB::index_entries_combinations(unsigned int ari return index_entries; } -void RedisMongoDB::re_index_patterns(bool flush_patterns) { +void RedisMongoDB::re_index_patterns(const string& public_key, bool flush_patterns) { vector links; auto conn = this->mongodb_pool->acquire(); auto mongodb_collection = (*conn)[MONGODB_DB_NAME][MONGODB_LINKS_COLLECTION_NAME]; diff --git a/src/atomdb/redis_mongodb/RedisMongoDB.h b/src/atomdb/redis_mongodb/RedisMongoDB.h index 9abd196d4..70ecee290 100644 --- a/src/atomdb/redis_mongodb/RedisMongoDB.h +++ b/src/atomdb/redis_mongodb/RedisMongoDB.h @@ -31,8 +31,10 @@ class RedisMongoDB : public AtomDB { RedisMongoDB(const string& context, bool skip_redis, const JsonConfig& config); ~RedisMongoDB(); - bool allow_nested_indexing() override; + bool allow_nested_indexing(const string& public_key) override; + bool composite_type_enabled() const override { return this->composite_type_enabled_; } + bool is_protected() const override; static string REDIS_PATTERNS_PREFIX; static string REDIS_OUTGOING_PREFIX; @@ -41,10 +43,13 @@ class RedisMongoDB : public AtomDB { static string MONGODB_DB_NAME; static string MONGODB_NODES_COLLECTION_NAME; static string MONGODB_LINKS_COLLECTION_NAME; + static string MONGODB_CONFIG_COLLECTION_NAME; static string MONGODB_PATTERN_INDEX_SCHEMA_COLLECTION_NAME; static string MONGODB_FIELD_NAME[MONGODB_FIELD::size]; static uint MONGODB_CHUNK_SIZE; + static const string MONGODB_CONFIG_DOCUMENT_HANDLE; + static void initialize_statics(const string& context = "") { REDIS_PATTERNS_PREFIX = context + "patterns"; REDIS_OUTGOING_PREFIX = context + "outgoing_set"; @@ -53,6 +58,7 @@ class RedisMongoDB : public AtomDB { MONGODB_DB_NAME = context + "das"; MONGODB_NODES_COLLECTION_NAME = context + "nodes"; MONGODB_LINKS_COLLECTION_NAME = context + "links"; + MONGODB_CONFIG_COLLECTION_NAME = context + "config"; MONGODB_PATTERN_INDEX_SCHEMA_COLLECTION_NAME = context + "pattern_index_schema"; MONGODB_FIELD_NAME[MONGODB_FIELD::ID] = "_id"; MONGODB_FIELD_NAME[MONGODB_FIELD::TARGETS] = "targets"; @@ -61,18 +67,78 @@ class RedisMongoDB : public AtomDB { MONGODB_CHUNK_SIZE = 1000; } - // HandleDecoder interface - shared_ptr get_atom(const string& handle); - shared_ptr get_node(const string& handle); - shared_ptr get_link(const string& handle); - - vector> get_matching_atoms(bool is_toplevel, Atom& key); - - shared_ptr query_for_pattern(const LinkSchema& link_schema); - - shared_ptr query_for_targets(const string& handle); + // AtomDB interface + shared_ptr get_atom(const string& handle, const string& public_key) override; + shared_ptr get_node(const string& handle, const string& public_key) override; + shared_ptr get_link(const string& handle, const string& public_key) override; + + vector> get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) override; + + shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) override; + shared_ptr query_for_targets(const string& handle, + const string& public_key) override; + shared_ptr query_for_incoming_set(const string& handle, + const string& public_key) override; + + bool atom_exists(const string& handle, const string& public_key) override; + bool node_exists(const string& handle, const string& public_key) override; + bool link_exists(const string& handle, const string& public_key) override; + + set atoms_exist(const vector& handles, const string& public_key) override; + set nodes_exist(const vector& handles, const string& public_key) override; + set links_exist(const vector& handles, const string& public_key) override; + + string add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists = false) override; + string add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists = false) override; + string add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists = false) override; - shared_ptr query_for_incoming_set(const string& handle); + vector add_atoms(const vector& atoms, + const string& public_key, + bool throw_if_exists = false, + bool is_transactional = false) override; + vector add_nodes(const vector& nodes, + const string& public_key, + bool throw_if_exists = false, + bool is_transactional = false) override; + vector add_links(const vector& links, + const string& public_key, + bool throw_if_exists = false, + bool is_transactional = false) override; + + bool delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_node(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_link(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + + uint delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + + void re_index_patterns(const string& public_key, bool flush_patterns = true) override; + + size_t node_count(const string& public_key) const override; + size_t link_count(const string& public_key) const override; + size_t atom_count(const string& public_key) const override; shared_ptr get_atom_document(const string& handle); shared_ptr get_node_document(const string& handle); @@ -84,53 +150,11 @@ class RedisMongoDB : public AtomDB { const vector& fields); vector> get_link_documents(const vector& handles, const vector& fields); - - bool atom_exists(const string& handle); - bool node_exists(const string& handle); - bool link_exists(const string& handle); - - set atoms_exist(const vector& handles); - set nodes_exist(const vector& handles); - set links_exist(const vector& handles); - - string add_atom(const atoms::Atom* atom, bool throw_if_exists = false); - string add_node(const atoms::Node* node, bool throw_if_exists = false); - string add_link(const atoms::Link* link, bool throw_if_exists = false); - - vector add_atoms(const vector& atoms, - bool throw_if_exists = false, - bool is_transactional = false); - vector add_nodes(const vector& nodes, - bool throw_if_exists = false, - bool is_transactional = false); - vector add_links(const vector& links, - bool throw_if_exists = false, - bool is_transactional = false); - - bool delete_atom(const string& handle, bool delete_link_targets = false); - bool delete_node(const string& handle, bool delete_link_targets = false); - bool delete_link(const string& handle, bool delete_link_targets = false); - - uint delete_atoms(const vector& handles, bool delete_link_targets = false); - uint delete_nodes(const vector& handles, bool delete_link_targets = false); - uint delete_links(const vector& handles, bool delete_link_targets = false); - - size_t node_count() const; - size_t link_count() const; - size_t atom_count() const override; - - bool upsert_document(const bsoncxx::v_noabi::document::value& document, - const string& collection_name); - uint upsert_documents(const vector& documents, - const string& collection_name); - vector> get_filtered_documents( const string& collection_name, const bsoncxx::builder::stream::document& filter_builder, const vector& fields); - void re_index_patterns(bool flush_patterns = true); - void add_pattern_index_schema(const string& tokens, const vector>& index_entries); void flush_redis_by_prefix(const string& prefix); @@ -140,6 +164,11 @@ class RedisMongoDB : public AtomDB { void check_existing_targets(const vector& links); + bool upsert_document(const bsoncxx::v_noabi::document::value& document, + const string& collection_name); + uint upsert_documents(const vector& documents, + const string& collection_name); + mutex composite_type_hashes_map_mutex; map composite_type_hashes_map; void build_composite_type_entries_map(const vector& links, diff --git a/src/atomdb/remotedb/RemoteAtomDB.cc b/src/atomdb/remotedb/RemoteAtomDB.cc index 82d9569b7..cc1d3c03a 100644 --- a/src/atomdb/remotedb/RemoteAtomDB.cc +++ b/src/atomdb/remotedb/RemoteAtomDB.cc @@ -87,13 +87,22 @@ bool RemoteAtomDB::composite_type_enabled() const { return false; } +bool RemoteAtomDB::is_protected() const { + for (auto& [uid, peer] : remote_db_) { + if (peer->is_protected()) { + return true; + } + } + return false; +} + void RemoteAtomDB::derive_nested_indexing() { // Derive the aggregated nested-indexing capability from the peers. A single global boolean // cannot describe a heterogeneous result set, so mixed configurations are normalized to the // lowest common denominator (false: the query engine re-matches every handle locally). unsigned int nested_peers = 0; for (auto& [uid, peer] : remote_db_) { - if (peer->allow_nested_indexing()) nested_peers++; + if (peer->allow_nested_indexing("")) nested_peers++; } if (!remote_db_.empty() && nested_peers == remote_db_.size()) { nested_indexing_ = true; @@ -110,17 +119,17 @@ void RemoteAtomDB::derive_nested_indexing() { } } -bool RemoteAtomDB::allow_nested_indexing() { return nested_indexing_; } +bool RemoteAtomDB::allow_nested_indexing(const string& public_key) { return nested_indexing_; } -shared_ptr RemoteAtomDB::get_atom(const string& handle) { +shared_ptr RemoteAtomDB::get_atom(const string& handle, const string& public_key) { // Phase 1: probe every peer's in-memory cache first (no network). Silent: this is the hot path. for (auto& [uid, peer] : remote_db_) { - auto atom = peer->get_cached_atom(handle); + auto atom = peer->get_cached_atom(handle, public_key); if (atom) return atom; } // Phase 2: escalate to peers (local_persistence + remote backend) only when no cache has it. for (auto& [uid, peer] : remote_db_) { - auto atom = peer->get_atom(handle); + auto atom = peer->get_atom(handle, public_key); if (atom) { LOG_DEBUG("get_atom(" << handle << ") fetched from [" << uid << "]"); return atom; @@ -130,13 +139,13 @@ shared_ptr RemoteAtomDB::get_atom(const string& handle) { return nullptr; } -shared_ptr RemoteAtomDB::get_node(const string& handle) { +shared_ptr RemoteAtomDB::get_node(const string& handle, const string& public_key) { for (auto& [uid, peer] : remote_db_) { - auto node = peer->get_cached_node(handle); + auto node = peer->get_cached_node(handle, public_key); if (node) return node; } for (auto& [uid, peer] : remote_db_) { - auto node = peer->get_node(handle); + auto node = peer->get_node(handle, public_key); if (node) { LOG_DEBUG("get_node(" << handle << ") fetched from [" << uid << "]"); return node; @@ -146,13 +155,13 @@ shared_ptr RemoteAtomDB::get_node(const string& handle) { return nullptr; } -shared_ptr RemoteAtomDB::get_link(const string& handle) { +shared_ptr RemoteAtomDB::get_link(const string& handle, const string& public_key) { for (auto& [uid, peer] : remote_db_) { - auto link = peer->get_cached_link(handle); + auto link = peer->get_cached_link(handle, public_key); if (link) return link; } for (auto& [uid, peer] : remote_db_) { - auto link = peer->get_link(handle); + auto link = peer->get_link(handle, public_key); if (link) { LOG_DEBUG("get_link(" << handle << ") fetched from [" << uid << "]"); return link; @@ -162,12 +171,14 @@ shared_ptr RemoteAtomDB::get_link(const string& handle) { return nullptr; } -vector> RemoteAtomDB::get_matching_atoms(bool is_toplevel, Atom& key) { +vector> RemoteAtomDB::get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) { vector> result; set seen; for (auto& [uid, peer] : remote_db_) { - auto atoms = peer->get_matching_atoms(is_toplevel, key); + auto atoms = peer->get_matching_atoms(is_toplevel, key, public_key); for (const auto& atom : atoms) { string h = atom->handle(); if (seen.find(h) == seen.end()) { @@ -179,19 +190,20 @@ vector> RemoteAtomDB::get_matching_atoms(bool is_toplevel, Atom return result; } -shared_ptr RemoteAtomDB::query_for_pattern(const LinkSchema& link_schema) { +shared_ptr RemoteAtomDB::query_for_pattern(const LinkSchema& link_schema, + const string& public_key) { auto result = make_shared(); set seen; LOG_DEBUG("query_for_pattern(" << link_schema.handle() << ") fan-out to " << remote_db_.size() << " peers"); for (auto& [uid, peer] : remote_db_) { - auto handle_set = peer->query_for_pattern(link_schema); + auto handle_set = peer->query_for_pattern(link_schema, public_key); if (!handle_set) continue; // Preserve per-handle assignments / metta expressions for nested-indexing peers so the // aggregated result stays faithful instead of silently dropping the backend's match data. - bool copy_metadata = peer->allow_nested_indexing(); + bool copy_metadata = peer->allow_nested_indexing(public_key); LOG_DEBUG(" [" << uid << "] returned " << handle_set->size() << " handles" << (copy_metadata ? " (with metadata)" : "")); @@ -218,9 +230,10 @@ shared_ptr RemoteAtomDB::query_for_pattern(const Li return result; } -shared_ptr RemoteAtomDB::query_for_targets(const string& handle) { +shared_ptr RemoteAtomDB::query_for_targets(const string& handle, + const string& public_key) { for (auto& [uid, peer] : remote_db_) { - auto list = peer->query_for_targets(handle); + auto list = peer->query_for_targets(handle, public_key); if (list) { LOG_DEBUG("query_for_targets(" << handle << ") served by peer [" << uid << "]"); return list; @@ -230,13 +243,14 @@ shared_ptr RemoteAtomDB::query_for_targets(const s return nullptr; } -shared_ptr RemoteAtomDB::query_for_incoming_set(const string& handle) { +shared_ptr RemoteAtomDB::query_for_incoming_set(const string& handle, + const string& public_key) { auto result = make_shared(); set seen; LOG_DEBUG("query_for_incoming_set(" << handle << ") fan-out to " << remote_db_.size() << " peers"); for (auto& [uid, peer] : remote_db_) { - auto handle_set = peer->query_for_incoming_set(handle); + auto handle_set = peer->query_for_incoming_set(handle, public_key); if (!handle_set) continue; auto it = handle_set->get_iterator(); @@ -256,35 +270,35 @@ shared_ptr RemoteAtomDB::query_for_incoming_set(con return result; } -bool RemoteAtomDB::atom_exists(const string& handle) { +bool RemoteAtomDB::atom_exists(const string& handle, const string& public_key) { for (auto& [uid, peer] : remote_db_) { - if (peer->atom_exists(handle)) return true; + if (peer->atom_exists(handle, public_key)) return true; } return false; } -bool RemoteAtomDB::node_exists(const string& handle) { +bool RemoteAtomDB::node_exists(const string& handle, const string& public_key) { for (auto& [uid, peer] : remote_db_) { - if (peer->node_exists(handle)) return true; + if (peer->node_exists(handle, public_key)) return true; } return false; } -bool RemoteAtomDB::link_exists(const string& handle) { +bool RemoteAtomDB::link_exists(const string& handle, const string& public_key) { for (auto& [uid, peer] : remote_db_) { - if (peer->link_exists(handle)) return true; + if (peer->link_exists(handle, public_key)) return true; } return false; } -set RemoteAtomDB::atoms_exist(const vector& handles) { +set RemoteAtomDB::atoms_exist(const vector& handles, const string& public_key) { set result; set remaining(handles.begin(), handles.end()); for (auto& [uid, peer] : remote_db_) { if (remaining.empty()) break; vector to_check(remaining.begin(), remaining.end()); - auto found = peer->atoms_exist(to_check); + auto found = peer->atoms_exist(to_check, public_key); for (const auto& h : found) { result.insert(h); remaining.erase(h); @@ -293,14 +307,14 @@ set RemoteAtomDB::atoms_exist(const vector& handles) { return result; } -set RemoteAtomDB::nodes_exist(const vector& handles) { +set RemoteAtomDB::nodes_exist(const vector& handles, const string& public_key) { set result; set remaining(handles.begin(), handles.end()); for (auto& [uid, peer] : remote_db_) { if (remaining.empty()) break; vector to_check(remaining.begin(), remaining.end()); - auto found = peer->nodes_exist(to_check); + auto found = peer->nodes_exist(to_check, public_key); for (const auto& h : found) { result.insert(h); remaining.erase(h); @@ -309,14 +323,14 @@ set RemoteAtomDB::nodes_exist(const vector& handles) { return result; } -set RemoteAtomDB::links_exist(const vector& handles) { +set RemoteAtomDB::links_exist(const vector& handles, const string& public_key) { set result; set remaining(handles.begin(), handles.end()); for (auto& [uid, peer] : remote_db_) { if (remaining.empty()) break; vector to_check(remaining.begin(), remaining.end()); - auto found = peer->links_exist(to_check); + auto found = peer->links_exist(to_check, public_key); for (const auto& h : found) { result.insert(h); remaining.erase(h); @@ -325,147 +339,162 @@ set RemoteAtomDB::links_exist(const vector& handles) { return result; } -string RemoteAtomDB::add_atom(const atoms::Atom* atom, bool throw_if_exists) { +string RemoteAtomDB::add_atom(const atoms::Atom* atom, const string& public_key, bool throw_if_exists) { string handle; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("add_atom(" << atom->handle() << ") to peer [" << uid << "]"); - handle = peer->add_atom(atom, throw_if_exists); + handle = peer->add_atom(atom, public_key, throw_if_exists); } return handle; } -string RemoteAtomDB::add_node(const atoms::Node* node, bool throw_if_exists) { +string RemoteAtomDB::add_node(const atoms::Node* node, const string& public_key, bool throw_if_exists) { string handle; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("add_node(" << node->handle() << ") to peer [" << uid << "]"); - handle = peer->add_node(node, throw_if_exists); + handle = peer->add_node(node, public_key, throw_if_exists); } return handle; } -string RemoteAtomDB::add_link(const atoms::Link* link, bool throw_if_exists) { +string RemoteAtomDB::add_link(const atoms::Link* link, const string& public_key, bool throw_if_exists) { string handle; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("add_link(" << link->handle() << ") to peer [" << uid << "]"); - handle = peer->add_link(link, throw_if_exists); + handle = peer->add_link(link, public_key, throw_if_exists); } return handle; } vector RemoteAtomDB::add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists, bool is_transactional) { vector handles; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("add_atoms(" << atoms.size() << ") to peer [" << uid << "]"); - handles = peer->add_atoms(atoms, throw_if_exists, is_transactional); + handles = peer->add_atoms(atoms, public_key, throw_if_exists, is_transactional); } return handles; } vector RemoteAtomDB::add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists, bool is_transactional) { vector handles; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("add_nodes(" << nodes.size() << ") to peer [" << uid << "]"); - handles = peer->add_nodes(nodes, throw_if_exists, is_transactional); + handles = peer->add_nodes(nodes, public_key, throw_if_exists, is_transactional); } return handles; } vector RemoteAtomDB::add_links(const vector& links, + const string& public_key, bool throw_if_exists, bool is_transactional) { vector handles; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("add_links(" << links.size() << ") to peer [" << uid << "]"); - handles = peer->add_links(links, throw_if_exists, is_transactional); + handles = peer->add_links(links, public_key, throw_if_exists, is_transactional); } return handles; } -bool RemoteAtomDB::delete_atom(const string& handle, bool delete_link_targets) { +bool RemoteAtomDB::delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets) { bool ok = true; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("delete_atom(" << handle << ") from peer [" << uid << "]"); - ok = peer->delete_atom(handle, delete_link_targets) && ok; + ok = peer->delete_atom(handle, public_key, delete_link_targets) && ok; } return ok; } -bool RemoteAtomDB::delete_node(const string& handle, bool delete_link_targets) { +bool RemoteAtomDB::delete_node(const string& handle, + const string& public_key, + bool delete_link_targets) { bool ok = true; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("delete_node(" << handle << ") from peer [" << uid << "]"); - ok = peer->delete_node(handle, delete_link_targets) && ok; + ok = peer->delete_node(handle, public_key, delete_link_targets) && ok; } return ok; } -bool RemoteAtomDB::delete_link(const string& handle, bool delete_link_targets) { +bool RemoteAtomDB::delete_link(const string& handle, + const string& public_key, + bool delete_link_targets) { bool ok = true; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("delete_link(" << handle << ") from peer [" << uid << "]"); - ok = peer->delete_link(handle, delete_link_targets) && ok; + ok = peer->delete_link(handle, public_key, delete_link_targets) && ok; } return ok; } -uint RemoteAtomDB::delete_atoms(const vector& handles, bool delete_link_targets) { +uint RemoteAtomDB::delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets) { uint count = 0; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("delete_atoms(" << handles.size() << ") from peer [" << uid << "]"); - count = peer->delete_atoms(handles, delete_link_targets); + count = peer->delete_atoms(handles, public_key, delete_link_targets); } return count; } -uint RemoteAtomDB::delete_nodes(const vector& handles, bool delete_link_targets) { +uint RemoteAtomDB::delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets) { uint count = 0; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("delete_nodes(" << handles.size() << ") from peer [" << uid << "]"); - count = peer->delete_nodes(handles, delete_link_targets); + count = peer->delete_nodes(handles, public_key, delete_link_targets); } return count; } -uint RemoteAtomDB::delete_links(const vector& handles, bool delete_link_targets) { +uint RemoteAtomDB::delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets) { uint count = 0; for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("delete_links(" << handles.size() << ") from peer [" << uid << "]"); - count = peer->delete_links(handles, delete_link_targets); + count = peer->delete_links(handles, public_key, delete_link_targets); } return count; } -void RemoteAtomDB::re_index_patterns(bool flush_patterns) { +void RemoteAtomDB::re_index_patterns(const string& public_key, bool flush_patterns) { for (auto& [uid, peer] : remote_db_) { LOG_DEBUG("re_index_patterns(" << flush_patterns << ") from peer [" << uid << "]"); - peer->re_index_patterns(flush_patterns); + peer->re_index_patterns(public_key, flush_patterns); } } -size_t RemoteAtomDB::node_count() const { +size_t RemoteAtomDB::node_count(const string& public_key) const { size_t count = 0; for (auto& [uid, peer] : remote_db_) { - count += peer->node_count(); + count += peer->node_count(public_key); } return count; } -size_t RemoteAtomDB::link_count() const { +size_t RemoteAtomDB::link_count(const string& public_key) const { size_t count = 0; for (auto& [uid, peer] : remote_db_) { - count += peer->link_count(); + count += peer->link_count(public_key); } return count; } -size_t RemoteAtomDB::atom_count() const { +size_t RemoteAtomDB::atom_count(const string& public_key) const { size_t count = 0; for (auto& [uid, peer] : remote_db_) { - count += peer->atom_count(); + count += peer->atom_count(public_key); } return count; } diff --git a/src/atomdb/remotedb/RemoteAtomDB.h b/src/atomdb/remotedb/RemoteAtomDB.h index b63278a94..c69cb7bb7 100644 --- a/src/atomdb/remotedb/RemoteAtomDB.h +++ b/src/atomdb/remotedb/RemoteAtomDB.h @@ -27,54 +27,81 @@ class RemoteAtomDB : public AtomDB { explicit RemoteAtomDB(map> peers); ~RemoteAtomDB(); - bool allow_nested_indexing() override; + bool allow_nested_indexing(const string& public_key) override; bool composite_type_enabled() const override; - - shared_ptr get_atom(const string& handle) override; - shared_ptr get_node(const string& handle) override; - shared_ptr get_link(const string& handle) override; - - vector> get_matching_atoms(bool is_toplevel, Atom& key) override; - - shared_ptr query_for_pattern(const LinkSchema& link_schema) override; - shared_ptr query_for_targets(const string& handle) override; - shared_ptr query_for_incoming_set(const string& handle) override; - - bool atom_exists(const string& handle) override; - bool node_exists(const string& handle) override; - bool link_exists(const string& handle) override; - - set atoms_exist(const vector& handles) override; - set nodes_exist(const vector& handles) override; - set links_exist(const vector& handles) override; - - string add_atom(const atoms::Atom* atom, bool throw_if_exists = false) override; - string add_node(const atoms::Node* node, bool throw_if_exists = false) override; - string add_link(const atoms::Link* link, bool throw_if_exists = false) override; + bool is_protected() const override; + + shared_ptr get_atom(const string& handle, const string& public_key) override; + shared_ptr get_node(const string& handle, const string& public_key) override; + shared_ptr get_link(const string& handle, const string& public_key) override; + + vector> get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) override; + + shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) override; + shared_ptr query_for_targets(const string& handle, + const string& public_key) override; + shared_ptr query_for_incoming_set(const string& handle, + const string& public_key) override; + + bool atom_exists(const string& handle, const string& public_key) override; + bool node_exists(const string& handle, const string& public_key) override; + bool link_exists(const string& handle, const string& public_key) override; + + set atoms_exist(const vector& handles, const string& public_key) override; + set nodes_exist(const vector& handles, const string& public_key) override; + set links_exist(const vector& handles, const string& public_key) override; + + string add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists = false) override; + string add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists = false) override; + string add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists = false) override; vector add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; vector add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; vector add_links(const vector& links, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; - bool delete_atom(const string& handle, bool delete_link_targets = false) override; - bool delete_node(const string& handle, bool delete_link_targets = false) override; - bool delete_link(const string& handle, bool delete_link_targets = false) override; - - uint delete_atoms(const vector& handles, bool delete_link_targets = false) override; - uint delete_nodes(const vector& handles, bool delete_link_targets = false) override; - uint delete_links(const vector& handles, bool delete_link_targets = false) override; - - void re_index_patterns(bool flush_patterns = true) override; - - size_t node_count() const override; - size_t link_count() const override; - size_t atom_count() const override; + bool delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_node(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_link(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + + uint delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + + void re_index_patterns(const string& public_key, bool flush_patterns = true) override; + + size_t node_count(const string& public_key) const override; + size_t link_count(const string& public_key) const override; + size_t atom_count(const string& public_key) const override; const map>& get_remote_dbs() const { return remote_db_; } RemoteAtomDBPeer* get_peer(const string& uid); diff --git a/src/atomdb/remotedb/RemoteAtomDBPeer.cc b/src/atomdb/remotedb/RemoteAtomDBPeer.cc index 4b68df11d..699fc64e7 100644 --- a/src/atomdb/remotedb/RemoteAtomDBPeer.cc +++ b/src/atomdb/remotedb/RemoteAtomDBPeer.cc @@ -32,32 +32,34 @@ RemoteAtomDBPeer::RemoteAtomDBPeer(shared_ptr remote_atomdb, RemoteAtomDBPeer::~RemoteAtomDBPeer() { stop_cleanup_thread(); } -bool RemoteAtomDBPeer::allow_nested_indexing() { - return atomdb_ ? atomdb_->allow_nested_indexing() : false; +bool RemoteAtomDBPeer::allow_nested_indexing(const string& public_key) { + return atomdb_ ? atomdb_->allow_nested_indexing(public_key) : false; } bool RemoteAtomDBPeer::composite_type_enabled() const { return local_persistence_ && local_persistence_->composite_type_enabled(); } -shared_ptr RemoteAtomDBPeer::get_atom(const string& handle) { - auto atom = cache_.get_atom(handle); +bool RemoteAtomDBPeer::is_protected() const { return atomdb_ ? atomdb_->is_protected() : false; } + +shared_ptr RemoteAtomDBPeer::get_atom(const string& handle, const string& public_key) { + auto atom = cache_.get_atom(handle, public_key); if (atom) return atom; if (local_persistence_) { - atom = local_persistence_->get_atom(handle); + atom = local_persistence_->get_atom(handle, public_key); if (atom) { LOG_DEBUG("[" << uid_ << "] get_atom(" << handle << ") <- local_persistence (cached)"); - cache_.add_atom(atom.get()); + cache_.add_atom(atom.get(), public_key); return atom; } } if (atomdb_) { - atom = atomdb_->get_atom(handle); + atom = atomdb_->get_atom(handle, public_key); if (atom) { LOG_DEBUG("[" << uid_ << "] get_atom(" << handle << ") <- remote atomdb (cached)"); - cache_.add_atom(atom.get()); + cache_.add_atom(atom.get(), public_key); return atom; } } @@ -66,24 +68,24 @@ shared_ptr RemoteAtomDBPeer::get_atom(const string& handle) { return nullptr; } -shared_ptr RemoteAtomDBPeer::get_node(const string& handle) { - auto node = cache_.get_node(handle); +shared_ptr RemoteAtomDBPeer::get_node(const string& handle, const string& public_key) { + auto node = cache_.get_node(handle, public_key); if (node) return node; if (local_persistence_) { - node = local_persistence_->get_node(handle); + node = local_persistence_->get_node(handle, public_key); if (node) { LOG_DEBUG("[" << uid_ << "] get_node(" << handle << ") <- local_persistence (cached)"); - cache_.add_node(node.get()); + cache_.add_node(node.get(), public_key); return node; } } if (atomdb_) { - node = atomdb_->get_node(handle); + node = atomdb_->get_node(handle, public_key); if (node) { LOG_DEBUG("[" << uid_ << "] get_node(" << handle << ") <- remote atomdb (cached)"); - cache_.add_node(node.get()); + cache_.add_node(node.get(), public_key); return node; } } @@ -92,24 +94,24 @@ shared_ptr RemoteAtomDBPeer::get_node(const string& handle) { return nullptr; } -shared_ptr RemoteAtomDBPeer::get_link(const string& handle) { - auto link = cache_.get_link(handle); +shared_ptr RemoteAtomDBPeer::get_link(const string& handle, const string& public_key) { + auto link = cache_.get_link(handle, public_key); if (link) return link; if (local_persistence_) { - link = local_persistence_->get_link(handle); + link = local_persistence_->get_link(handle, public_key); if (link) { LOG_DEBUG("[" << uid_ << "] get_link(" << handle << ") <- local_persistence (cached)"); - cache_.add_link(link.get()); + cache_.add_link(link.get(), public_key); return link; } } if (atomdb_) { - link = atomdb_->get_link(handle); + link = atomdb_->get_link(handle, public_key); if (link) { LOG_DEBUG("[" << uid_ << "] get_link(" << handle << ") <- remote atomdb (cached)"); - cache_.add_link(link.get()); + cache_.add_link(link.get(), public_key); return link; } } @@ -118,24 +120,27 @@ shared_ptr RemoteAtomDBPeer::get_link(const string& handle) { return nullptr; } -shared_ptr RemoteAtomDBPeer::get_cached_atom(const string& handle) { - return cache_.get_atom(handle); +shared_ptr RemoteAtomDBPeer::get_cached_atom(const string& handle, const string& public_key) { + return cache_.get_atom(handle, public_key); } -shared_ptr RemoteAtomDBPeer::get_cached_node(const string& handle) { - return cache_.get_node(handle); +shared_ptr RemoteAtomDBPeer::get_cached_node(const string& handle, const string& public_key) { + return cache_.get_node(handle, public_key); } -shared_ptr RemoteAtomDBPeer::get_cached_link(const string& handle) { - return cache_.get_link(handle); +shared_ptr RemoteAtomDBPeer::get_cached_link(const string& handle, const string& public_key) { + return cache_.get_link(handle, public_key); } -vector> RemoteAtomDBPeer::get_matching_atoms(bool is_toplevel, Atom& key) { - return get_matching_atoms(is_toplevel, key, false); +vector> RemoteAtomDBPeer::get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) { + return get_matching_atoms(is_toplevel, key, public_key, false); } vector> RemoteAtomDBPeer::get_matching_atoms(bool is_toplevel, Atom& key, + const string& public_key, bool local_only) { vector> result; set seen_handles; @@ -150,13 +155,13 @@ vector> RemoteAtomDBPeer::get_matching_atoms(bool is_toplevel, } }; - merge_results(cache_.get_matching_atoms(is_toplevel, key)); + merge_results(cache_.get_matching_atoms(is_toplevel, key, public_key)); if (local_persistence_) { - merge_results(local_persistence_->get_matching_atoms(is_toplevel, key)); + merge_results(local_persistence_->get_matching_atoms(is_toplevel, key, public_key)); } if (!local_only && atomdb_) { - merge_results(atomdb_->get_matching_atoms(is_toplevel, key)); + merge_results(atomdb_->get_matching_atoms(is_toplevel, key, public_key)); } return result; @@ -166,7 +171,8 @@ bool RemoteAtomDBPeer::schema_already_fetched(const LinkSchema& link_schema) { return fetched_link_templates_.lookup(link_schema.handle()) != NULL; } -void RemoteAtomDBPeer::feed_cache_from_handle_set(shared_ptr handle_set) { +void RemoteAtomDBPeer::feed_cache_from_handle_set(shared_ptr handle_set, + const string& public_key) { if (!handle_set) return; auto it = handle_set->get_iterator(); @@ -179,9 +185,9 @@ void RemoteAtomDBPeer::feed_cache_from_handle_set(shared_ptr handle_s if (!handle_cstr) break; string handle(handle_cstr); - auto atom = get_atom(handle); + auto atom = get_atom(handle, public_key); if (atom) { - cache_.add_atom(atom.get()); + cache_.add_atom(atom.get(), public_key); } } } @@ -208,31 +214,34 @@ void RemoteAtomDBPeer::merge_handle_set(shared_ptr source, } } -shared_ptr RemoteAtomDBPeer::query_for_pattern(const LinkSchema& link_schema) { +shared_ptr RemoteAtomDBPeer::query_for_pattern(const LinkSchema& link_schema, + const string& public_key) { auto result = make_shared(); set seen; if (schema_already_fetched(link_schema)) { LOG_DEBUG("[" << uid_ << "] query_for_pattern(" << link_schema.handle() << ") cache-hit" << (local_persistence_ ? ", merging cache + local_persistence" : ".")); - merge_handle_set( - cache_.query_for_pattern(link_schema), result, seen, cache_.allow_nested_indexing()); + merge_handle_set(cache_.query_for_pattern(link_schema, public_key), + result, + seen, + cache_.allow_nested_indexing(public_key)); if (local_persistence_) { - merge_handle_set(local_persistence_->query_for_pattern(link_schema), + merge_handle_set(local_persistence_->query_for_pattern(link_schema, public_key), result, seen, - local_persistence_->allow_nested_indexing()); + local_persistence_->allow_nested_indexing(public_key)); } } else { LOG_DEBUG("[" << uid_ << "] query_for_pattern(" << link_schema.handle() << ") cache-miss, fetching from remote atomdb"); if (atomdb_) { - auto handle_set = atomdb_->query_for_pattern(link_schema); + auto handle_set = atomdb_->query_for_pattern(link_schema, public_key); if (handle_set) { - merge_handle_set(handle_set, result, seen, atomdb_->allow_nested_indexing()); + merge_handle_set(handle_set, result, seen, atomdb_->allow_nested_indexing(public_key)); } } - feed_cache_from_handle_set(result); + feed_cache_from_handle_set(result, public_key); fetched_link_templates_.insert(link_schema.handle(), empty_trie_value_); } @@ -241,12 +250,13 @@ shared_ptr RemoteAtomDBPeer::query_for_pattern(const LinkSchema& link return result; } -shared_ptr RemoteAtomDBPeer::query_for_targets(const string& handle) { - auto result = cache_.query_for_targets(handle); +shared_ptr RemoteAtomDBPeer::query_for_targets(const string& handle, + const string& public_key) { + auto result = cache_.query_for_targets(handle, public_key); if (result) return result; if (local_persistence_) { - result = local_persistence_->query_for_targets(handle); + result = local_persistence_->query_for_targets(handle, public_key); if (result) { LOG_DEBUG("[" << uid_ << "] query_for_targets(" << handle << ") <- local_persistence"); return result; @@ -255,22 +265,23 @@ shared_ptr RemoteAtomDBPeer::query_for_targets(const string& handle) if (atomdb_) { LOG_DEBUG("[" << uid_ << "] query_for_targets(" << handle << ") <- remote atomdb"); - return atomdb_->query_for_targets(handle); + return atomdb_->query_for_targets(handle, public_key); } return nullptr; } -shared_ptr RemoteAtomDBPeer::query_for_incoming_set(const string& handle) { +shared_ptr RemoteAtomDBPeer::query_for_incoming_set(const string& handle, + const string& public_key) { auto result = make_shared(); set seen; - merge_handle_set(cache_.query_for_incoming_set(handle), result, seen); + merge_handle_set(cache_.query_for_incoming_set(handle, public_key), result, seen); if (local_persistence_) { - merge_handle_set(local_persistence_->query_for_incoming_set(handle), result, seen); + merge_handle_set(local_persistence_->query_for_incoming_set(handle, public_key), result, seen); } if (atomdb_) { - merge_handle_set(atomdb_->query_for_incoming_set(handle), result, seen); + merge_handle_set(atomdb_->query_for_incoming_set(handle, public_key), result, seen); } LOG_DEBUG("[" << uid_ << "] query_for_incoming_set(" << handle << ") -> " << result->size() @@ -278,35 +289,35 @@ shared_ptr RemoteAtomDBPeer::query_for_incoming_set(const string& han return result; } -bool RemoteAtomDBPeer::atom_exists(const string& handle) { - if (cache_.atom_exists(handle)) return true; - if (local_persistence_ && local_persistence_->atom_exists(handle)) return true; - if (atomdb_ && atomdb_->atom_exists(handle)) return true; +bool RemoteAtomDBPeer::atom_exists(const string& handle, const string& public_key) { + if (cache_.atom_exists(handle, public_key)) return true; + if (local_persistence_ && local_persistence_->atom_exists(handle, public_key)) return true; + if (atomdb_ && atomdb_->atom_exists(handle, public_key)) return true; return false; } -bool RemoteAtomDBPeer::node_exists(const string& handle) { - if (cache_.node_exists(handle)) return true; - if (local_persistence_ && local_persistence_->node_exists(handle)) return true; - if (atomdb_ && atomdb_->node_exists(handle)) return true; +bool RemoteAtomDBPeer::node_exists(const string& handle, const string& public_key) { + if (cache_.node_exists(handle, public_key)) return true; + if (local_persistence_ && local_persistence_->node_exists(handle, public_key)) return true; + if (atomdb_ && atomdb_->node_exists(handle, public_key)) return true; return false; } -bool RemoteAtomDBPeer::link_exists(const string& handle) { - if (cache_.link_exists(handle)) return true; - if (local_persistence_ && local_persistence_->link_exists(handle)) return true; - if (atomdb_ && atomdb_->link_exists(handle)) return true; +bool RemoteAtomDBPeer::link_exists(const string& handle, const string& public_key) { + if (cache_.link_exists(handle, public_key)) return true; + if (local_persistence_ && local_persistence_->link_exists(handle, public_key)) return true; + if (atomdb_ && atomdb_->link_exists(handle, public_key)) return true; return false; } -set RemoteAtomDBPeer::atoms_exist(const vector& handles) { +set RemoteAtomDBPeer::atoms_exist(const vector& handles, const string& public_key) { set result; set remaining(handles.begin(), handles.end()); auto from_source = [&](AtomDB& db) { vector to_check(remaining.begin(), remaining.end()); if (to_check.empty()) return; - auto found = db.atoms_exist(to_check); + auto found = db.atoms_exist(to_check, public_key); for (const auto& h : found) { result.insert(h); remaining.erase(h); @@ -324,14 +335,14 @@ set RemoteAtomDBPeer::atoms_exist(const vector& handles) { return result; } -set RemoteAtomDBPeer::nodes_exist(const vector& handles) { +set RemoteAtomDBPeer::nodes_exist(const vector& handles, const string& public_key) { set result; set remaining(handles.begin(), handles.end()); auto from_source = [&](AtomDB& db) { vector to_check(remaining.begin(), remaining.end()); if (to_check.empty()) return; - auto found = db.nodes_exist(to_check); + auto found = db.nodes_exist(to_check, public_key); for (const auto& h : found) { result.insert(h); remaining.erase(h); @@ -345,14 +356,14 @@ set RemoteAtomDBPeer::nodes_exist(const vector& handles) { return result; } -set RemoteAtomDBPeer::links_exist(const vector& handles) { +set RemoteAtomDBPeer::links_exist(const vector& handles, const string& public_key) { set result; set remaining(handles.begin(), handles.end()); auto from_source = [&](AtomDB& db) { vector to_check(remaining.begin(), remaining.end()); if (to_check.empty()) return; - auto found = db.links_exist(to_check); + auto found = db.links_exist(to_check, public_key); for (const auto& h : found) { result.insert(h); remaining.erase(h); @@ -366,120 +377,144 @@ set RemoteAtomDBPeer::links_exist(const vector& handles) { return result; } -string RemoteAtomDBPeer::add_atom(const atoms::Atom* atom, bool throw_if_exists) { - return cache_.add_atom(atom, throw_if_exists); +string RemoteAtomDBPeer::add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists) { + return cache_.add_atom(atom, public_key, throw_if_exists); } -string RemoteAtomDBPeer::add_node(const atoms::Node* node, bool throw_if_exists) { - return cache_.add_node(node, throw_if_exists); +string RemoteAtomDBPeer::add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists) { + return cache_.add_node(node, public_key, throw_if_exists); } -string RemoteAtomDBPeer::add_link(const atoms::Link* link, bool throw_if_exists) { - return cache_.add_link(link, throw_if_exists); +string RemoteAtomDBPeer::add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists) { + return cache_.add_link(link, public_key, throw_if_exists); } vector RemoteAtomDBPeer::add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists, bool is_transactional) { - return cache_.add_atoms(atoms, throw_if_exists, is_transactional); + return cache_.add_atoms(atoms, public_key, throw_if_exists, is_transactional); } vector RemoteAtomDBPeer::add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists, bool is_transactional) { - return cache_.add_nodes(nodes, throw_if_exists, is_transactional); + return cache_.add_nodes(nodes, public_key, throw_if_exists, is_transactional); } vector RemoteAtomDBPeer::add_links(const vector& links, + const string& public_key, bool throw_if_exists, bool is_transactional) { - return cache_.add_links(links, throw_if_exists, is_transactional); + return cache_.add_links(links, public_key, throw_if_exists, is_transactional); } -bool RemoteAtomDBPeer::delete_atom(const string& handle, bool delete_link_targets) { - bool cache_ok = cache_.delete_atom(handle, delete_link_targets); - bool local_ok = true; - if (local_persistence_) { - local_ok = local_persistence_->delete_atom(handle, delete_link_targets); +bool RemoteAtomDBPeer::delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets) { + bool cache_ok = cache_.delete_atom(handle, public_key, delete_link_targets); + if (!local_persistence_) { + return cache_ok; } + bool local_ok = local_persistence_->delete_atom(handle, public_key, delete_link_targets); return cache_ok || local_ok; } -bool RemoteAtomDBPeer::delete_node(const string& handle, bool delete_link_targets) { - bool cache_ok = cache_.delete_node(handle, delete_link_targets); - bool local_ok = true; - if (local_persistence_) { - local_ok = local_persistence_->delete_node(handle, delete_link_targets); +bool RemoteAtomDBPeer::delete_node(const string& handle, + const string& public_key, + bool delete_link_targets) { + bool cache_ok = cache_.delete_node(handle, public_key, delete_link_targets); + if (!local_persistence_) { + return cache_ok; } + bool local_ok = local_persistence_->delete_node(handle, public_key, delete_link_targets); return cache_ok || local_ok; } -bool RemoteAtomDBPeer::delete_link(const string& handle, bool delete_link_targets) { - bool cache_ok = cache_.delete_link(handle, delete_link_targets); - bool local_ok = true; - if (local_persistence_) { - local_ok = local_persistence_->delete_link(handle, delete_link_targets); +bool RemoteAtomDBPeer::delete_link(const string& handle, + const string& public_key, + bool delete_link_targets) { + bool cache_ok = cache_.delete_link(handle, public_key, delete_link_targets); + if (!local_persistence_) { + return cache_ok; } + bool local_ok = local_persistence_->delete_link(handle, public_key, delete_link_targets); return cache_ok || local_ok; } -uint RemoteAtomDBPeer::delete_atoms(const vector& handles, bool delete_link_targets) { - uint cache_count = cache_.delete_atoms(handles, delete_link_targets); - uint local_count = 0; - if (local_persistence_) { - local_count = local_persistence_->delete_atoms(handles, delete_link_targets); +uint RemoteAtomDBPeer::delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets) { + uint deleted_count = 0; + for (const auto& handle : handles) { + if (delete_atom(handle, public_key, delete_link_targets)) { + deleted_count++; + } } - return cache_count + local_count; + return deleted_count; } -uint RemoteAtomDBPeer::delete_nodes(const vector& handles, bool delete_link_targets) { - uint cache_count = cache_.delete_nodes(handles, delete_link_targets); - uint local_count = 0; - if (local_persistence_) { - local_count = local_persistence_->delete_nodes(handles, delete_link_targets); +uint RemoteAtomDBPeer::delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets) { + uint deleted_count = 0; + for (const auto& handle : handles) { + if (delete_node(handle, public_key, delete_link_targets)) { + deleted_count++; + } } - return cache_count + local_count; + return deleted_count; } -uint RemoteAtomDBPeer::delete_links(const vector& handles, bool delete_link_targets) { - uint cache_count = cache_.delete_links(handles, delete_link_targets); - uint local_count = 0; - if (local_persistence_) { - local_count = local_persistence_->delete_links(handles, delete_link_targets); +uint RemoteAtomDBPeer::delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets) { + uint deleted_count = 0; + for (const auto& handle : handles) { + if (delete_link(handle, public_key, delete_link_targets)) { + deleted_count++; + } } - return cache_count + local_count; + return deleted_count; } -void RemoteAtomDBPeer::re_index_patterns(bool flush_patterns) { - cache_.re_index_patterns(flush_patterns); +void RemoteAtomDBPeer::re_index_patterns(const string& public_key, bool flush_patterns) { + cache_.re_index_patterns(public_key, flush_patterns); if (local_persistence_) { - local_persistence_->re_index_patterns(flush_patterns); + local_persistence_->re_index_patterns(public_key, flush_patterns); } } -size_t RemoteAtomDBPeer::node_count() const { +size_t RemoteAtomDBPeer::node_count(const string& public_key) const { size_t count = 0; - count += cache_.node_count(); + count += cache_.node_count(public_key); if (local_persistence_) { - count += local_persistence_->node_count(); + count += local_persistence_->node_count(public_key); } return count; } -size_t RemoteAtomDBPeer::link_count() const { +size_t RemoteAtomDBPeer::link_count(const string& public_key) const { size_t count = 0; - count += cache_.link_count(); + count += cache_.link_count(public_key); if (local_persistence_) { - count += local_persistence_->link_count(); + count += local_persistence_->link_count(public_key); } return count; } -size_t RemoteAtomDBPeer::atom_count() const { +size_t RemoteAtomDBPeer::atom_count(const string& public_key) const { size_t count = 0; - count += cache_.atom_count(); + count += cache_.atom_count(public_key); if (local_persistence_) { - count += local_persistence_->atom_count(); + count += local_persistence_->atom_count(public_key); } return count; } @@ -488,9 +523,9 @@ void RemoteAtomDBPeer::fetch(const LinkSchema& link_schema) { if (!schema_already_fetched(link_schema) && atomdb_) { LOG_DEBUG("[" << uid_ << "] fetch(" << link_schema.handle() << ") prefetching from remote atomdb"); - auto result = atomdb_->query_for_pattern(link_schema); + auto result = atomdb_->query_for_pattern(link_schema, ""); if (result) { - feed_cache_from_handle_set(result); + feed_cache_from_handle_set(result, ""); fetched_link_templates_.insert(link_schema.handle(), empty_trie_value_); } } @@ -502,16 +537,16 @@ void RemoteAtomDBPeer::release(const LinkSchema& link_schema) { // properly. LOG_DEBUG("[" << uid_ << "] release(" << link_schema.handle() << ") evicting from cache to local_persistence"); - auto handle_set = cache_.query_for_pattern(link_schema); + auto handle_set = cache_.query_for_pattern(link_schema, ""); if (handle_set && local_persistence_) { auto it = handle_set->get_iterator(); char* handle_cstr; while ((handle_cstr = it->next()) != nullptr) { string handle(handle_cstr); - auto atom = cache_.get_atom(handle); + auto atom = cache_.get_atom(handle, ""); if (atom) { - local_persistence_->add_atom(atom.get(), false); - cache_.delete_atom(handle, false); + local_persistence_->add_atom(atom.get(), "", false); + cache_.delete_atom(handle, "", false); } } } diff --git a/src/atomdb/remotedb/RemoteAtomDBPeer.h b/src/atomdb/remotedb/RemoteAtomDBPeer.h index 0c5916fea..7f201d2e2 100644 --- a/src/atomdb/remotedb/RemoteAtomDBPeer.h +++ b/src/atomdb/remotedb/RemoteAtomDBPeer.h @@ -28,61 +28,91 @@ class RemoteAtomDBPeer : public AtomDB, public processor::ThreadMethod { const string& uid = ""); ~RemoteAtomDBPeer(); - bool allow_nested_indexing() override; + bool allow_nested_indexing(const string& public_key) override; bool composite_type_enabled() const override; + bool is_protected() const override; - shared_ptr get_atom(const string& handle) override; - shared_ptr get_node(const string& handle) override; - shared_ptr get_link(const string& handle) override; + shared_ptr get_atom(const string& handle, const string& public_key) override; + shared_ptr get_node(const string& handle, const string& public_key) override; + shared_ptr get_link(const string& handle, const string& public_key) override; // Cache-only lookups (in-memory, no local_persistence / remote escalation). Used by the // RemoteAtomDB facade to probe every peer's cache before escalating any peer to its backend. - shared_ptr get_cached_atom(const string& handle); - shared_ptr get_cached_node(const string& handle); - shared_ptr get_cached_link(const string& handle); - - vector> get_matching_atoms(bool is_toplevel, Atom& key) override; - vector> get_matching_atoms(bool is_toplevel, Atom& key, bool local_only); - - shared_ptr query_for_pattern(const LinkSchema& link_schema) override; - shared_ptr query_for_targets(const string& handle) override; - shared_ptr query_for_incoming_set(const string& handle) override; - - bool atom_exists(const string& handle) override; - bool node_exists(const string& handle) override; - bool link_exists(const string& handle) override; - - set atoms_exist(const vector& handles) override; - set nodes_exist(const vector& handles) override; - set links_exist(const vector& handles) override; - - string add_atom(const atoms::Atom* atom, bool throw_if_exists = false) override; - string add_node(const atoms::Node* node, bool throw_if_exists = false) override; - string add_link(const atoms::Link* link, bool throw_if_exists = false) override; + shared_ptr get_cached_atom(const string& handle, const string& public_key); + shared_ptr get_cached_node(const string& handle, const string& public_key); + shared_ptr get_cached_link(const string& handle, const string& public_key); + + vector> get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key) override; + vector> get_matching_atoms(bool is_toplevel, + Atom& key, + const string& public_key, + bool local_only); + + shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) override; + shared_ptr query_for_targets(const string& handle, + const string& public_key) override; + shared_ptr query_for_incoming_set(const string& handle, + const string& public_key) override; + + bool atom_exists(const string& handle, const string& public_key) override; + bool node_exists(const string& handle, const string& public_key) override; + bool link_exists(const string& handle, const string& public_key) override; + + set atoms_exist(const vector& handles, const string& public_key) override; + set nodes_exist(const vector& handles, const string& public_key) override; + set links_exist(const vector& handles, const string& public_key) override; + + string add_atom(const atoms::Atom* atom, + const string& public_key, + bool throw_if_exists = false) override; + string add_node(const atoms::Node* node, + const string& public_key, + bool throw_if_exists = false) override; + string add_link(const atoms::Link* link, + const string& public_key, + bool throw_if_exists = false) override; vector add_atoms(const vector& atoms, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; vector add_nodes(const vector& nodes, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; vector add_links(const vector& links, + const string& public_key, bool throw_if_exists = false, bool is_transactional = false) override; - bool delete_atom(const string& handle, bool delete_link_targets = false) override; - bool delete_node(const string& handle, bool delete_link_targets = false) override; - bool delete_link(const string& handle, bool delete_link_targets = false) override; - - uint delete_atoms(const vector& handles, bool delete_link_targets = false) override; - uint delete_nodes(const vector& handles, bool delete_link_targets = false) override; - uint delete_links(const vector& handles, bool delete_link_targets = false) override; - - void re_index_patterns(bool flush_patterns = true) override; - - size_t node_count() const override; - size_t link_count() const override; - size_t atom_count() const override; + bool delete_atom(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_node(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + bool delete_link(const string& handle, + const string& public_key, + bool delete_link_targets = false) override; + + uint delete_atoms(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_nodes(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + uint delete_links(const vector& handles, + const string& public_key, + bool delete_link_targets = false) override; + + void re_index_patterns(const string& public_key, bool flush_patterns = true) override; + + size_t node_count(const string& public_key) const override; + size_t link_count(const string& public_key) const override; + size_t atom_count(const string& public_key) const override; // Cache policy API void fetch(const LinkSchema& link_schema); @@ -100,7 +130,8 @@ class RemoteAtomDBPeer : public AtomDB, public processor::ThreadMethod { bool is_readonly() const { return local_persistence_ == nullptr; } private: - void feed_cache_from_handle_set(shared_ptr handle_set); + void feed_cache_from_handle_set(shared_ptr handle_set, + const string& public_key); void merge_handle_set(shared_ptr source, shared_ptr dest, set& seen, diff --git a/src/db_adapter/AtomPersister.cc b/src/db_adapter/AtomPersister.cc index 18c9331bd..57d659797 100644 --- a/src/db_adapter/AtomPersister.cc +++ b/src/db_adapter/AtomPersister.cc @@ -169,7 +169,7 @@ void AtomPersister::send_batch(vector> atoms, for (const auto& atom : atoms) { atom_ptrs.push_back(atom.get()); } - this->atomdb->add_atoms(atom_ptrs, false, true); + this->atomdb->add_atoms(atom_ptrs, "", false, true); if (this->is_save_metta()) { for (auto& atom : atoms) { diff --git a/src/main/db_loader.cc b/src/main/db_loader.cc index 4473dddd6..9e61b789b 100644 --- a/src/main/db_loader.cc +++ b/src/main/db_loader.cc @@ -175,7 +175,7 @@ int main(int argc, char* argv[]) { thread_atoms_count++; if (batch_atoms.size() >= static_cast(chunk_size)) { - thread_atomdb->add_atoms(batch_atoms, false, true); + thread_atomdb->add_atoms(batch_atoms, "", false, true); batch_atoms.clear(); if (parser_actions_list.size() > 10) { parser_actions_list.erase(parser_actions_list.begin(), @@ -190,7 +190,7 @@ int main(int argc, char* argv[]) { } if (!batch_atoms.empty()) { - thread_atomdb->add_atoms(batch_atoms, false, true); + thread_atomdb->add_atoms(batch_atoms, "", false, true); } total_atoms_processed += thread_atoms_count; @@ -280,8 +280,8 @@ int main(int argc, char* argv[]) { links.push_back(link_with_nested); if (j % chunk_size == 0) { - thread_db->add_nodes(nodes, false, true); - thread_db->add_links(links, false, true); + thread_db->add_nodes(nodes, "", false, true); + thread_db->add_links(links, "", false, true); nodes.clear(); links.clear(); } @@ -290,12 +290,12 @@ int main(int argc, char* argv[]) { if (!nodes.empty()) { LOG_INFO("[" + to_string(thread_id) + "] Final - Adding " + to_string(nodes.size()) + " nodes"); - thread_db->add_nodes(nodes, false, true); + thread_db->add_nodes(nodes, "", false, true); } if (!links.empty()) { LOG_INFO("[" + to_string(thread_id) + "] Final - Adding " + to_string(links.size()) + " links"); - thread_db->add_links(links, false, true); + thread_db->add_links(links, "", false, true); } // clang-format off @@ -307,7 +307,7 @@ int main(int argc, char* argv[]) { }); // clang-format on - auto result = thread_db->query_for_pattern(link_schema); + auto result = thread_db->query_for_pattern(link_schema, ""); if (result->size() != 2) { RAISE_ERROR("[" + to_string(thread_id) + "] Expected 2 results, got " + to_string(result->size())); diff --git a/src/tests/benchmark/atomdb/atomdb_operations.cc b/src/tests/benchmark/atomdb/atomdb_operations.cc index 3232fafa0..8cfc1bcb1 100644 --- a/src/tests/benchmark/atomdb/atomdb_operations.cc +++ b/src/tests/benchmark/atomdb/atomdb_operations.cc @@ -21,7 +21,7 @@ void AddAtom::add_node() { [&](int i) -> Node* { return new Node("Symbol", "\"NODE_t" + to_string(tid_) + "_i" + to_string(i) + "\""); }, - [&](Node* node) { db_->add_node(node); }); + [&](Node* node) { db_->add_node(node, ""); }); } void AddAtom::add_link() { run_benchmark( @@ -29,14 +29,14 @@ void AddAtom::add_link() { [&](int i) -> Link* { string suffix = to_string(tid_) + "_i" + to_string(i); auto node_equivalence = new Node("Symbol", "EQUIVALENCE_t" + suffix); - auto node_equivalence_handle = db_->add_node(node_equivalence); + auto node_equivalence_handle = db_->add_node(node_equivalence, ""); auto node_a = new Node("Symbol", "NODE_A_t" + suffix); - auto node_a_handle = db_->add_node(node_a); + auto node_a_handle = db_->add_node(node_a, ""); auto node_b = new Node("Symbol", "NODE_B_t" + suffix); - auto node_b_handle = db_->add_node(node_b); + auto node_b_handle = db_->add_node(node_b, ""); return new Link("Expression", {node_equivalence_handle, node_a_handle, node_b_handle}); }, - [&](Link* link) { db_->add_link(link); }); + [&](Link* link) { db_->add_link(link, ""); }); } void AddAtom::add_atom_node() { run_benchmark( @@ -44,7 +44,7 @@ void AddAtom::add_atom_node() { [&](int i) -> Atom* { return new Node("Symbol", "\"NODE_t" + to_string(tid_) + "_i" + to_string(i) + "\""); }, - [&](Atom* atom) { db_->add_atom(atom); }); + [&](Atom* atom) { db_->add_atom(atom, ""); }); } void AddAtom::add_atom_link() { run_benchmark( @@ -52,14 +52,14 @@ void AddAtom::add_atom_link() { [&](int i) -> Atom* { string suffix = to_string(tid_) + "_i" + to_string(i); auto node_equivalence = new Node("Symbol", "EQUIVALENCE_t" + suffix); - auto node_equivalence_handle = db_->add_node(node_equivalence); + auto node_equivalence_handle = db_->add_node(node_equivalence, ""); auto node_a = new Node("Symbol", "\"NODE_A_t" + suffix + "\""); - auto node_a_handle = db_->add_node(node_a); + auto node_a_handle = db_->add_node(node_a, ""); auto node_b = new Node("Symbol", "\"NODE_B_t" + suffix + "\""); - auto node_b_handle = db_->add_node(node_b); + auto node_b_handle = db_->add_node(node_b, ""); return new Link("Expression", {node_equivalence_handle, node_a_handle, node_b_handle}); }, - [&](Atom* atom) { db_->add_atom(atom); }); + [&](Atom* atom) { db_->add_atom(atom, ""); }); } void AddAtoms::add_nodes() { @@ -74,7 +74,7 @@ void AddAtoms::add_nodes() { } return nodes; }, - [&](vector nodes) { db_->add_nodes(nodes); }, + [&](vector nodes) { db_->add_nodes(nodes, ""); }, BATCH_SIZE); } void AddAtoms::add_links() { @@ -85,17 +85,17 @@ void AddAtoms::add_links() { for (size_t j = 0; j < BATCH_SIZE; j++) { string suffix = to_string(tid_) + "_i" + to_string(i) + "_j" + to_string(j); auto node_equivalence = new Node("Symbol", "EQUIVALENCE_A_t" + suffix); - auto node_equivalence_handle = db_->add_node(node_equivalence); + auto node_equivalence_handle = db_->add_node(node_equivalence, ""); auto node_b = new Node("Symbol", "\"NODES_B_t" + suffix + "\""); - auto node_b_handle = db_->add_node(node_b); + auto node_b_handle = db_->add_node(node_b, ""); auto node_c = new Node("Symbol", "\"NODES_C_t" + suffix + "\""); - auto node_c_handle = db_->add_node(node_c); + auto node_c_handle = db_->add_node(node_c, ""); links.push_back( new Link("Expression", {node_equivalence_handle, node_b_handle, node_c_handle})); } return links; }, - [&](vector links) { db_->add_links(links); }, + [&](vector links) { db_->add_links(links, ""); }, BATCH_SIZE); } void AddAtoms::add_atoms_node() { @@ -110,7 +110,7 @@ void AddAtoms::add_atoms_node() { } return atoms; }, - [&](vector atoms) { db_->add_atoms(atoms); }, + [&](vector atoms) { db_->add_atoms(atoms, ""); }, BATCH_SIZE); } void AddAtoms::add_atoms_link() { @@ -121,17 +121,17 @@ void AddAtoms::add_atoms_link() { for (size_t j = 0; j < BATCH_SIZE; j++) { string suffix = to_string(tid_) + "_i" + to_string(i) + "_j" + to_string(j); auto node_equivalence = new Node("Symbol", "EQUIVALENCE_A_t" + suffix); - auto node_equivalence_handle = db_->add_node(node_equivalence); + auto node_equivalence_handle = db_->add_node(node_equivalence, ""); auto node_b = new Node("Symbol", "\"NODES_B_t" + suffix + "\""); - auto node_b_handle = db_->add_node(node_b); + auto node_b_handle = db_->add_node(node_b, ""); auto node_c = new Node("Symbol", "\"NODES_C_t" + suffix + "\""); - auto node_c_handle = db_->add_node(node_c); + auto node_c_handle = db_->add_node(node_c, ""); atoms.push_back( new Link("Expression", {node_equivalence_handle, node_b_handle, node_c_handle})); } return atoms; }, - [&](vector atoms) { db_->add_atoms(atoms); }, + [&](vector atoms) { db_->add_atoms(atoms, ""); }, BATCH_SIZE); } @@ -140,7 +140,7 @@ void GetAtom::get_node_document() { "get_node_document", [&](int i) -> string { auto link_schema = LinkSchema(Runner::contains_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); auto link_document = db_->get_link_document(random_link_handles[0]); auto contains_node_handle = string(link_document->get("targets", 0)); @@ -153,7 +153,7 @@ void GetAtom::get_link_document() { "get_link_document", [&](int i) -> string { auto link_schema = LinkSchema(Runner::contains_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); return random_link_handles[0]; }, @@ -164,7 +164,7 @@ void GetAtom::get_atom_document_node() { "get_atom_document[node]", [&](int i) -> string { auto link_schema = LinkSchema(Runner::contains_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); auto link_document = db_->get_link_document(random_link_handles[0]); auto contains_node_handle = string(link_document->get("targets", 0)); @@ -177,7 +177,7 @@ void GetAtom::get_atom_document_link() { "get_atom_document[link]", [&](int i) -> string { auto link_schema = LinkSchema(Runner::contains_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); return random_link_handles[0]; }, @@ -188,24 +188,24 @@ void GetAtom::get_atom_node() { "get_atom[node]", [&](int i) -> string { auto link_schema = LinkSchema(Runner::contains_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); auto link_document = db_->get_link_document(random_link_handles[0]); auto contains_node_handle = string(link_document->get("targets", 0)); return contains_node_handle; }, - [&](string handle) { db_->get_atom(handle); }); + [&](string handle) { db_->get_atom(handle, ""); }); } void GetAtom::get_atom_link() { run_benchmark( "get_atom[link]", [&](int i) -> string { auto link_schema = LinkSchema(Runner::contains_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); return random_link_handles[0]; }, - [&](string handle) { db_->get_atom(handle); }); + [&](string handle) { db_->get_atom(handle, ""); }); } void GetAtoms::get_node_documents() { @@ -213,7 +213,7 @@ void GetAtoms::get_node_documents() { "get_node_documents", [&](int i) -> vector { auto link_schema = LinkSchema(Runner::sentence_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); size_t max_count = max(BATCH_SIZE, MAX_COUNT); vector random_link_handles = get_random_link_handle(handle_set, max_count, BATCH_SIZE); @@ -233,7 +233,7 @@ void GetAtoms::get_link_documents() { "get_link_documents", [&](int i) -> vector { auto link_schema = LinkSchema(Runner::sentence_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); size_t max_count = max(BATCH_SIZE, MAX_COUNT); return get_random_link_handle(handle_set, max_count, BATCH_SIZE); }, @@ -244,7 +244,7 @@ void GetAtoms::get_atom_documents_node() { "get_atom_documents[node]", [&](int i) -> vector { auto link_schema = LinkSchema(Runner::sentence_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); size_t max_count = max(BATCH_SIZE, MAX_COUNT); vector random_link_handles = get_random_link_handle(handle_set, max_count, BATCH_SIZE); @@ -264,7 +264,7 @@ void GetAtoms::get_atom_documents_link() { "get_atom_documents[link]", [&](int i) -> vector { auto link_schema = LinkSchema(Runner::sentence_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); size_t max_count = max(BATCH_SIZE, MAX_COUNT); return get_random_link_handle(handle_set, max_count, BATCH_SIZE); }, @@ -275,7 +275,7 @@ void GetAtoms::query_for_pattern() { "query_for_pattern[first_result]", [&](int i) -> vector { return Runner::contains_links_query; }, [&](vector pattern) { - auto handles_set = db_->query_for_pattern(pattern); + auto handles_set = db_->query_for_pattern(pattern, ""); auto iterator = handles_set->get_iterator(); iterator->next(); }); @@ -285,11 +285,11 @@ void GetAtoms::query_for_targets() { "query_for_targets", [&](int i) -> string { auto link_schema = LinkSchema(Runner::sentence_links_query); - auto handle_set = db_->query_for_pattern(link_schema); + auto handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); return random_link_handles[0]; }, - [&](string handle) { db_->query_for_targets(handle); }); + [&](string handle) { db_->query_for_targets(handle, ""); }); } void DeleteAtom::delete_node(string type) { @@ -297,48 +297,48 @@ void DeleteAtom::delete_node(string type) { "delete_node", [&](int i) -> string { auto link_schema = LinkSchema(Runner::sentence_links_query); - shared_ptr handle_set = db_->query_for_pattern(link_schema); + shared_ptr handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); auto link_document = db_->get_link_document(random_link_handles[0]); auto node_handle = string(link_document->get("targets", 1)); return node_handle; }, - [&](string handle) { db_->delete_node(handle); }); + [&](string handle) { db_->delete_node(handle, ""); }); } void DeleteAtom::delete_link(string type) { run_benchmark( "delete_link", [&](int i) -> string { auto link_schema = LinkSchema(Runner::contains_links_query); - shared_ptr handle_set = db_->query_for_pattern(link_schema); + shared_ptr handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); return random_link_handles[0]; }, - [&](string handle) { db_->delete_link(handle); }); + [&](string handle) { db_->delete_link(handle, ""); }); } void DeleteAtom::delete_atom_node(string type) { run_benchmark( "delete_atom[node]", [&](int i) -> string { auto link_schema = LinkSchema(Runner::sentence_links_query); - shared_ptr handle_set = db_->query_for_pattern(link_schema); + shared_ptr handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); auto link_document = db_->get_link_document(random_link_handles[0]); auto node_handle = string(link_document->get("targets", 1)); return node_handle; }, - [&](string handle) { db_->delete_atom(handle); }); + [&](string handle) { db_->delete_atom(handle, ""); }); } void DeleteAtom::delete_atom_link(string type) { run_benchmark( "delete_atom[link]", [&](int i) -> string { auto link_schema = LinkSchema(Runner::contains_links_query); - shared_ptr handle_set = db_->query_for_pattern(link_schema); + shared_ptr handle_set = db_->query_for_pattern(link_schema, ""); vector random_link_handles = get_random_link_handle(handle_set); return random_link_handles[0]; }, - [&](string handle) { db_->delete_atom(handle); }); + [&](string handle) { db_->delete_atom(handle, ""); }); } void DeleteAtoms::delete_nodes(string type) { @@ -346,7 +346,7 @@ void DeleteAtoms::delete_nodes(string type) { "delete_nodes", [&](int i) -> vector { auto link_schema = LinkSchema(Runner::sentence_links_query); - shared_ptr handle_set = db_->query_for_pattern(link_schema); + shared_ptr handle_set = db_->query_for_pattern(link_schema, ""); size_t max_count = max(BATCH_SIZE, MAX_COUNT); vector random_link_handles = get_random_link_handle(handle_set, max_count, BATCH_SIZE); @@ -359,7 +359,7 @@ void DeleteAtoms::delete_nodes(string type) { } return handles; }, - [&](vector handles) { db_->delete_nodes(handles); }, + [&](vector handles) { db_->delete_nodes(handles, ""); }, BATCH_SIZE); } void DeleteAtoms::delete_links(string type) { @@ -367,11 +367,11 @@ void DeleteAtoms::delete_links(string type) { "delete_links", [&](int i) -> vector { auto link_schema = LinkSchema(Runner::contains_links_query); - shared_ptr handle_set = db_->query_for_pattern(link_schema); + shared_ptr handle_set = db_->query_for_pattern(link_schema, ""); size_t max_count = max(BATCH_SIZE, MAX_COUNT); return get_random_link_handle(handle_set, max_count, BATCH_SIZE); }, - [&](vector handles) { db_->delete_links(handles); }, + [&](vector handles) { db_->delete_links(handles, ""); }, BATCH_SIZE); } void DeleteAtoms::delete_atoms_node(string type) { @@ -379,7 +379,7 @@ void DeleteAtoms::delete_atoms_node(string type) { "delete_atoms[node]", [&](int i) -> vector { auto link_schema = LinkSchema(Runner::sentence_links_query); - shared_ptr handle_set = db_->query_for_pattern(link_schema); + shared_ptr handle_set = db_->query_for_pattern(link_schema, ""); size_t max_count = max(BATCH_SIZE, MAX_COUNT); vector random_link_handles = get_random_link_handle(handle_set, max_count, BATCH_SIZE); @@ -392,7 +392,7 @@ void DeleteAtoms::delete_atoms_node(string type) { } return handles; }, - [&](vector handles) { db_->delete_atoms(handles); }, + [&](vector handles) { db_->delete_atoms(handles, ""); }, BATCH_SIZE); } void DeleteAtoms::delete_atoms_link(string type) { @@ -400,10 +400,10 @@ void DeleteAtoms::delete_atoms_link(string type) { "delete_atoms[link]", [&](int i) -> vector { auto link_schema = LinkSchema(Runner::contains_links_query); - shared_ptr handle_set = db_->query_for_pattern(link_schema); + shared_ptr handle_set = db_->query_for_pattern(link_schema, ""); size_t max_count = max(BATCH_SIZE, MAX_COUNT); return get_random_link_handle(handle_set, max_count, BATCH_SIZE); }, - [&](vector handles) { db_->delete_atoms(handles); }, + [&](vector handles) { db_->delete_atoms(handles, ""); }, BATCH_SIZE); } diff --git a/src/tests/cpp/BUILD b/src/tests/cpp/BUILD index ad1bd6cda..a40978c51 100644 --- a/src/tests/cpp/BUILD +++ b/src/tests/cpp/BUILD @@ -786,6 +786,7 @@ cc_test( linkstatic = 1, deps = [ "//atomdb:atomdb_singleton", + "//atomdb/auth:protected_atomdb_lib", "//tests/cpp/test_commons:mock_animals_data_lib", "//tests/cpp/test_commons:test_atomdb_json_config", "@com_github_google_googletest//:gtest_main", @@ -864,6 +865,33 @@ cc_test( ], ) +cc_test( + name = "atomdb_singleton_test", + size = "small", + srcs = ["atomdb_singleton_test.cc"], + copts = [ + "-Iexternal/gtest/googletest/include", + "-Iexternal/gtest/googletest", + ], + linkopts = [ + "-L/usr/local/lib", + "-lhiredis_cluster", + "-lhiredis", + "-lmongocxx", + "-lbsoncxx", + ], + linkstatic = 1, + deps = [ + "//atomdb:atomdb_singleton", + "//atomdb/auth:protected_atomdb_lib", + "//atomdb/remotedb:remotedb_lib", + "//tests/cpp/test_commons:test_atomdb_json_config", + "//tests/cpp/test_commons/mocks:mock_atom_db_lib", + "@com_github_google_googletest//:gtest_main", + "@mbedtls", + ], +) + cc_test( name = "atomdbutils_test", size = "small", diff --git a/src/tests/cpp/adapterdb_test.cc b/src/tests/cpp/adapterdb_test.cc index 54a0040fa..f92d9f3ed 100644 --- a/src/tests/cpp/adapterdb_test.cc +++ b/src/tests/cpp/adapterdb_test.cc @@ -209,24 +209,24 @@ INSTANTIATE_TEST_SUITE_P(AdapterTypes, TEST_P(AdapterDBTest, ConstructorSucceedsWithValidConfig) { auto db = create_current_adapter(); ASSERT_NE(db, nullptr); - EXPECT_GT(db->atom_count(), 0); + EXPECT_GT(db->atom_count(""), 0); } TEST_P(AdapterDBTest, ConstructorLoadsDataIntoBackendOnFirstRun) { auto db = create_current_adapter(); ASSERT_NE(db, nullptr); - EXPECT_GT(db->atom_count(), 0); + EXPECT_GT(db->atom_count(""), 0); } TEST_P(AdapterDBTest, CanBeConstructedTwiceWithSameContext) { auto db1 = create_current_adapter(); ASSERT_NE(db1, nullptr); - EXPECT_GT(db1->atom_count(), 0); + EXPECT_GT(db1->atom_count(""), 0); EXPECT_NO_THROW({ auto db2 = create_current_adapter(); ASSERT_NE(db2, nullptr); - EXPECT_GT(db2->atom_count(), 0); + EXPECT_GT(db2->atom_count(""), 0); }); } @@ -237,14 +237,16 @@ TEST_P(AdapterDBTest, ReloadDoesNotThrowAndKeepsBackendUsable) { EXPECT_NO_THROW({ db->reload(); }); EXPECT_NO_THROW({ - auto count = db->atom_count(); + auto count = db->atom_count(""); (void) count; }); EXPECT_NO_THROW({ - bool nested = db->allow_nested_indexing(); + bool nested = db->allow_nested_indexing(""); (void) nested; }); + + EXPECT_EQ(db->is_protected(), backend->is_protected()); } TEST_P(AdapterDBTest, NeedsSyncIsNotImplemented) { @@ -258,22 +260,22 @@ TEST_P(AdapterDBTest, AddGetAndDeleteNode) { ASSERT_NE(db, nullptr); auto node = new Node("Symbol", "AdapterDBTestNode"); - string handle = db->add_node(node); + string handle = db->add_node(node, ""); EXPECT_NE(handle, ""); - EXPECT_TRUE(db->node_exists(handle)); - EXPECT_TRUE(db->atom_exists(handle)); + EXPECT_TRUE(db->node_exists(handle, "")); + EXPECT_TRUE(db->atom_exists(handle, "")); - auto fetched_atom = db->get_atom(handle); - auto fetched_node = db->get_node(handle); - auto fetched_link = db->get_link(handle); + auto fetched_atom = db->get_atom(handle, ""); + auto fetched_node = db->get_node(handle, ""); + auto fetched_link = db->get_link(handle, ""); ASSERT_NE(fetched_atom, nullptr); ASSERT_NE(fetched_node, nullptr); EXPECT_EQ(fetched_link, nullptr); - EXPECT_TRUE(db->delete_node(handle)); - EXPECT_FALSE(db->node_exists(handle)); + EXPECT_TRUE(db->delete_node(handle, "")); + EXPECT_FALSE(db->node_exists(handle, "")); delete node; } @@ -287,12 +289,12 @@ TEST_P(AdapterDBTest, AddAndDeleteNodes) { nodes.push_back(new Node("Symbol", "AdapterDBNode2")); nodes.push_back(new Node("Symbol", "AdapterDBNode3")); - auto handles = db->add_nodes(nodes); + auto handles = db->add_nodes(nodes, ""); EXPECT_EQ(handles.size(), 3); - EXPECT_EQ(db->nodes_exist(handles).size(), 3); + EXPECT_EQ(db->nodes_exist(handles, "").size(), 3); - EXPECT_EQ(db->delete_nodes(handles), 3); - EXPECT_EQ(db->nodes_exist(handles).size(), 0); + EXPECT_EQ(db->delete_nodes(handles, ""), 3); + EXPECT_EQ(db->nodes_exist(handles, "").size(), 0); for (auto* n : nodes) delete n; } @@ -305,33 +307,33 @@ TEST_P(AdapterDBTest, AddGetAndQueryTargetsLink) { auto n2 = new Node("Symbol", "AdapterLinkNode2"); auto n3 = new Node("Symbol", "AdapterLinkNode3"); - auto h1 = db->add_node(n1); - auto h2 = db->add_node(n2); - auto h3 = db->add_node(n3); + auto h1 = db->add_node(n1, ""); + auto h2 = db->add_node(n2, ""); + auto h3 = db->add_node(n3, ""); auto link = new Link("Expression", {h1, h2, h3}); - auto link_handle = db->add_link(link); + auto link_handle = db->add_link(link, ""); EXPECT_NE(link_handle, ""); - EXPECT_TRUE(db->link_exists(link_handle)); - EXPECT_TRUE(db->atom_exists(link_handle)); + EXPECT_TRUE(db->link_exists(link_handle, "")); + EXPECT_TRUE(db->atom_exists(link_handle, "")); - auto fetched_atom = db->get_atom(link_handle); - auto fetched_link = db->get_link(link_handle); - auto fetched_node = db->get_node(link_handle); + auto fetched_atom = db->get_atom(link_handle, ""); + auto fetched_link = db->get_link(link_handle, ""); + auto fetched_node = db->get_node(link_handle, ""); ASSERT_NE(fetched_atom, nullptr); ASSERT_NE(fetched_link, nullptr); EXPECT_EQ(fetched_node, nullptr); - auto targets = db->query_for_targets(link_handle); + auto targets = db->query_for_targets(link_handle, ""); ASSERT_NE(targets, nullptr); EXPECT_EQ(targets->size(), 3); - EXPECT_TRUE(db->delete_link(link_handle)); - EXPECT_TRUE(db->delete_node(h1)); - EXPECT_TRUE(db->delete_node(h2)); - EXPECT_TRUE(db->delete_node(h3)); + EXPECT_TRUE(db->delete_link(link_handle, "")); + EXPECT_TRUE(db->delete_node(h1, "")); + EXPECT_TRUE(db->delete_node(h2, "")); + EXPECT_TRUE(db->delete_node(h3, "")); delete n1; delete n2; @@ -349,7 +351,7 @@ TEST_P(AdapterDBTest, AddLinkFailsWhenTargetsDoNotExist) { auto link = new Link("Expression", {fake1->handle(), fake2->handle(), fake3->handle()}); - EXPECT_THROW({ db->add_link(link); }, runtime_error); + EXPECT_THROW({ db->add_link(link, ""); }, runtime_error); delete fake1; delete fake2; @@ -361,18 +363,18 @@ TEST_P(AdapterDBTest, DeleteNonExistingAtomReturnsFalse) { auto db = create_current_adapter(); ASSERT_NE(db, nullptr); - EXPECT_FALSE(db->delete_atom("NonExistingHandle")); - EXPECT_FALSE(db->delete_node("NonExistingHandle")); - EXPECT_FALSE(db->delete_link("NonExistingHandle")); + EXPECT_FALSE(db->delete_atom("NonExistingHandle", "")); + EXPECT_FALSE(db->delete_node("NonExistingHandle", "")); + EXPECT_FALSE(db->delete_link("NonExistingHandle", "")); } TEST_P(AdapterDBTest, DeleteEmptyCollectionsReturnsZero) { auto db = create_current_adapter(); ASSERT_NE(db, nullptr); - EXPECT_EQ(db->delete_atoms({}), 0); - EXPECT_EQ(db->delete_nodes({}), 0); - EXPECT_EQ(db->delete_links({}), 0); + EXPECT_EQ(db->delete_atoms({}, ""), 0); + EXPECT_EQ(db->delete_nodes({}, ""), 0); + EXPECT_EQ(db->delete_links({}, ""), 0); } TEST_P(AdapterDBTest, ExistsQueriesReturnEmptyForUnknownHandles) { @@ -385,15 +387,15 @@ TEST_P(AdapterDBTest, ExistsQueriesReturnEmptyForUnknownHandles) { "NonExistingHandle3", }; - EXPECT_EQ(db->atoms_exist(handles).size(), 0); - EXPECT_EQ(db->nodes_exist(handles).size(), 0); - EXPECT_EQ(db->links_exist(handles).size(), 0); + EXPECT_EQ(db->atoms_exist(handles, "").size(), 0); + EXPECT_EQ(db->nodes_exist(handles, "").size(), 0); + EXPECT_EQ(db->links_exist(handles, "").size(), 0); } TEST_P(AdapterDBTest, ReIndexPatternsDoesNotThrow) { auto db = create_current_adapter(); ASSERT_NE(db, nullptr); - EXPECT_NO_THROW({ db->re_index_patterns(); }); + EXPECT_NO_THROW({ db->re_index_patterns(""); }); } TEST_P(AdapterDBTest, AddNodeWithThrowIfExists) { @@ -402,10 +404,10 @@ TEST_P(AdapterDBTest, AddNodeWithThrowIfExists) { auto node = new Node("Symbol", "AdapterThrowIfExistsNode"); - EXPECT_EQ(db->add_node(node, true), node->handle()); - EXPECT_THROW({ db->add_node(node, true); }, runtime_error); + EXPECT_EQ(db->add_node(node, "", true), node->handle()); + EXPECT_THROW({ db->add_node(node, "", true); }, runtime_error); - EXPECT_TRUE(db->delete_node(node->handle())); + EXPECT_TRUE(db->delete_node(node->handle(), "")); delete node; } @@ -417,19 +419,19 @@ TEST_P(AdapterDBTest, AddLinkWithThrowIfExists) { auto n2 = new Node("Symbol", "AdapterThrowIfExistsLink2"); auto n3 = new Node("Symbol", "AdapterThrowIfExistsLink3"); - auto h1 = db->add_node(n1); - auto h2 = db->add_node(n2); - auto h3 = db->add_node(n3); + auto h1 = db->add_node(n1, ""); + auto h2 = db->add_node(n2, ""); + auto h3 = db->add_node(n3, ""); auto link = new Link("Expression", {h1, h2, h3}); - EXPECT_EQ(db->add_link(link), link->handle()); - EXPECT_THROW({ db->add_link(link, true); }, runtime_error); + EXPECT_EQ(db->add_link(link, ""), link->handle()); + EXPECT_THROW({ db->add_link(link, "", true); }, runtime_error); - EXPECT_TRUE(db->delete_link(link->handle())); - EXPECT_TRUE(db->delete_node(h1)); - EXPECT_TRUE(db->delete_node(h2)); - EXPECT_TRUE(db->delete_node(h3)); + EXPECT_TRUE(db->delete_link(link->handle(), "")); + EXPECT_TRUE(db->delete_node(h1, "")); + EXPECT_TRUE(db->delete_node(h2, "")); + EXPECT_TRUE(db->delete_node(h3, "")); delete n1; delete n2; @@ -443,12 +445,12 @@ TEST_P(AdapterDBTest, AddSameNodeWithoutThrowIfExistsIsAccepted) { auto node = new Node("Symbol", "AdapterSameNode"); - EXPECT_EQ(db->add_node(node), node->handle()); - EXPECT_EQ(db->add_node(node), node->handle()); + EXPECT_EQ(db->add_node(node, ""), node->handle()); + EXPECT_EQ(db->add_node(node, ""), node->handle()); - EXPECT_TRUE(db->node_exists(node->handle())); - EXPECT_TRUE(db->delete_node(node->handle())); - EXPECT_FALSE(db->node_exists(node->handle())); + EXPECT_TRUE(db->node_exists(node->handle(), "")); + EXPECT_TRUE(db->delete_node(node->handle(), "")); + EXPECT_FALSE(db->node_exists(node->handle(), "")); delete node; } @@ -461,19 +463,19 @@ TEST_P(AdapterDBTest, AddSameLinkWithoutThrowIfExistsIsAccepted) { auto n2 = new Node("Symbol", "AdapterSameLink2"); auto n3 = new Node("Symbol", "AdapterSameLink3"); - auto h1 = db->add_node(n1); - auto h2 = db->add_node(n2); - auto h3 = db->add_node(n3); + auto h1 = db->add_node(n1, ""); + auto h2 = db->add_node(n2, ""); + auto h3 = db->add_node(n3, ""); auto link = new Link("Expression", {h1, h2, h3}); - EXPECT_EQ(db->add_link(link), link->handle()); - EXPECT_EQ(db->add_link(link), link->handle()); + EXPECT_EQ(db->add_link(link, ""), link->handle()); + EXPECT_EQ(db->add_link(link, ""), link->handle()); - EXPECT_TRUE(db->delete_link(link->handle())); - EXPECT_TRUE(db->delete_node(h1)); - EXPECT_TRUE(db->delete_node(h2)); - EXPECT_TRUE(db->delete_node(h3)); + EXPECT_TRUE(db->delete_link(link->handle(), "")); + EXPECT_TRUE(db->delete_node(h1, "")); + EXPECT_TRUE(db->delete_node(h2, "")); + EXPECT_TRUE(db->delete_node(h3, "")); delete n1; delete n2; diff --git a/src/tests/cpp/atomdb_broker_test.cc b/src/tests/cpp/atomdb_broker_test.cc index 00eb28a22..ab1cf5d75 100644 --- a/src/tests/cpp/atomdb_broker_test.cc +++ b/src/tests/cpp/atomdb_broker_test.cc @@ -127,10 +127,10 @@ TEST_F(AtomDBTest, AddAtoms) { EXPECT_TRUE(atoms[2]->handle() == node3); EXPECT_TRUE(atoms[3]->handle() == link_handle); - EXPECT_FALSE(db->node_exists(node1)); - EXPECT_FALSE(db->node_exists(node2)); - EXPECT_FALSE(db->node_exists(node3)); - EXPECT_FALSE(db->link_exists(link_handle)); + EXPECT_FALSE(db->node_exists(node1, "")); + EXPECT_FALSE(db->node_exists(node2, "")); + EXPECT_FALSE(db->node_exists(node3, "")); + EXPECT_FALSE(db->link_exists(link_handle, "")); vector handles = proxy->add_atoms(atoms); added_atom_handles.insert(added_atom_handles.end(), handles.begin(), handles.end()); @@ -142,10 +142,10 @@ TEST_F(AtomDBTest, AddAtoms) { Utils::sleep(2000); - EXPECT_TRUE(db->node_exists(node1)); - EXPECT_TRUE(db->node_exists(node2)); - EXPECT_TRUE(db->node_exists(node3)); - EXPECT_TRUE(db->link_exists(link_handle)); + EXPECT_TRUE(db->node_exists(node1, "")); + EXPECT_TRUE(db->node_exists(node2, "")); + EXPECT_TRUE(db->node_exists(node3, "")); + EXPECT_TRUE(db->link_exists(link_handle, "")); } TEST_F(AtomDBTest, AddAtomsStreaming) { @@ -176,10 +176,10 @@ TEST_F(AtomDBTest, AddAtomsStreaming) { EXPECT_TRUE(atoms[2]->handle() == node3); EXPECT_TRUE(atoms[3]->handle() == link_handle); - EXPECT_FALSE(db->node_exists(node1)); - EXPECT_FALSE(db->node_exists(node2)); - EXPECT_FALSE(db->node_exists(node3)); - EXPECT_FALSE(db->link_exists(link_handle)); + EXPECT_FALSE(db->node_exists(node1, "")); + EXPECT_FALSE(db->node_exists(node2, "")); + EXPECT_FALSE(db->node_exists(node3, "")); + EXPECT_FALSE(db->link_exists(link_handle, "")); vector handles = proxy->add_atoms(atoms, true); added_atom_handles.insert(added_atom_handles.end(), handles.begin(), handles.end()); @@ -191,10 +191,10 @@ TEST_F(AtomDBTest, AddAtomsStreaming) { Utils::sleep(2000); - EXPECT_TRUE(db->node_exists(node1)); - EXPECT_TRUE(db->node_exists(node2)); - EXPECT_TRUE(db->node_exists(node3)); - EXPECT_TRUE(db->link_exists(link_handle)); + EXPECT_TRUE(db->node_exists(node1, "")); + EXPECT_TRUE(db->node_exists(node2, "")); + EXPECT_TRUE(db->node_exists(node3, "")); + EXPECT_TRUE(db->link_exists(link_handle, "")); } TEST_F(AtomDBTest, DeleteAtoms) { @@ -207,7 +207,7 @@ TEST_F(AtomDBTest, DeleteAtoms) { Utils::sleep(2000); for (const auto& handle : added_atom_handles) { - EXPECT_FALSE(db->node_exists(handle)); + EXPECT_FALSE(db->node_exists(handle, "")); } } @@ -239,27 +239,27 @@ TEST_F(AtomDBTest, DeleteLinkTargetsTop) { EXPECT_TRUE(atoms[2]->handle() == node3); EXPECT_TRUE(atoms[3]->handle() == link_handle); - EXPECT_FALSE(db->node_exists(node1)); - EXPECT_FALSE(db->node_exists(node2)); - EXPECT_FALSE(db->node_exists(node3)); - EXPECT_FALSE(db->link_exists(link_handle)); + EXPECT_FALSE(db->node_exists(node1, "")); + EXPECT_FALSE(db->node_exists(node2, "")); + EXPECT_FALSE(db->node_exists(node3, "")); + EXPECT_FALSE(db->link_exists(link_handle, "")); vector handles = proxy->add_atoms(atoms); Utils::sleep(2000); - EXPECT_TRUE(db->node_exists(node1)); - EXPECT_TRUE(db->node_exists(node2)); - EXPECT_TRUE(db->node_exists(node3)); - EXPECT_TRUE(db->link_exists(link_handle)); + EXPECT_TRUE(db->node_exists(node1, "")); + EXPECT_TRUE(db->node_exists(node2, "")); + EXPECT_TRUE(db->node_exists(node3, "")); + EXPECT_TRUE(db->link_exists(link_handle, "")); proxy->delete_atoms({link_handle}, true); Utils::sleep(2000); - EXPECT_FALSE(db->link_exists(link_handle)); - EXPECT_FALSE(db->node_exists(node1)); - EXPECT_FALSE(db->node_exists(node2)); - EXPECT_FALSE(db->node_exists(node3)); + EXPECT_FALSE(db->link_exists(link_handle, "")); + EXPECT_FALSE(db->node_exists(node1, "")); + EXPECT_FALSE(db->node_exists(node2, "")); + EXPECT_FALSE(db->node_exists(node3, "")); } TEST_F(AtomDBTest, DeleteLinkTargetsBottom) { @@ -297,30 +297,30 @@ TEST_F(AtomDBTest, DeleteLinkTargetsBottom) { EXPECT_TRUE(atoms[3]->handle() == node4); EXPECT_TRUE(atoms[4]->handle() == link_handle); - EXPECT_FALSE(db->node_exists(node1)); - EXPECT_FALSE(db->node_exists(node2)); - EXPECT_FALSE(db->node_exists(node3)); - EXPECT_FALSE(db->node_exists(node4)); - EXPECT_FALSE(db->link_exists(link_handle)); + EXPECT_FALSE(db->node_exists(node1, "")); + EXPECT_FALSE(db->node_exists(node2, "")); + EXPECT_FALSE(db->node_exists(node3, "")); + EXPECT_FALSE(db->node_exists(node4, "")); + EXPECT_FALSE(db->link_exists(link_handle, "")); vector handles = proxy->add_atoms(atoms); Utils::sleep(2000); - EXPECT_TRUE(db->node_exists(node1)); - EXPECT_TRUE(db->node_exists(node2)); - EXPECT_TRUE(db->node_exists(node3)); - EXPECT_TRUE(db->node_exists(node4)); - EXPECT_TRUE(db->link_exists(link_handle)); + EXPECT_TRUE(db->node_exists(node1, "")); + EXPECT_TRUE(db->node_exists(node2, "")); + EXPECT_TRUE(db->node_exists(node3, "")); + EXPECT_TRUE(db->node_exists(node4, "")); + EXPECT_TRUE(db->link_exists(link_handle, "")); proxy->delete_atoms({node3}, true); Utils::sleep(2000); - EXPECT_FALSE(db->link_exists(link_handle)); - EXPECT_FALSE(db->node_exists(node1)); - EXPECT_FALSE(db->node_exists(node2)); - EXPECT_FALSE(db->node_exists(node3)); - EXPECT_TRUE(db->node_exists(node4)); + EXPECT_FALSE(db->link_exists(link_handle, "")); + EXPECT_FALSE(db->node_exists(node1, "")); + EXPECT_FALSE(db->node_exists(node2, "")); + EXPECT_FALSE(db->node_exists(node3, "")); + EXPECT_TRUE(db->node_exists(node4, "")); } int main(int argc, char** argv) { diff --git a/src/tests/cpp/atomdb_singleton_test.cc b/src/tests/cpp/atomdb_singleton_test.cc new file mode 100644 index 000000000..a5a07e3c0 --- /dev/null +++ b/src/tests/cpp/atomdb_singleton_test.cc @@ -0,0 +1,55 @@ +#include +#include + +#include + +#include "AtomDBSingleton.h" +#include "MockAtomDB.h" +#include "ProtectedAtomDB.h" +#include "RedisMongoDB.h" +#include "RemoteAtomDB.h" +#include "TestAtomDBJsonConfig.h" + +using namespace atomdb; +using namespace commons; +using namespace std; +using namespace testing; + +TEST(AtomDBSingletonTest, InitWrapsProtectedBackend) { + auto config = test_atomdb_json_config(); + config["mongodb"]["seed_protected"] = true; + AtomDBSingleton::init(config); + + auto db = AtomDBSingleton::get_instance(); + ASSERT_NE(db, nullptr); + EXPECT_NE(dynamic_cast(db.get()), nullptr); + EXPECT_TRUE(db->is_protected()); + + { + auto cleanup = make_shared("", false, test_atomdb_json_config()); + cleanup->drop_all(); + } + AtomDBSingleton::provide(nullptr); +} + +TEST(AtomDBSingletonTest, InitAndProvideBehavior) { + nlohmann::json json; + json["remote_peers"] = nlohmann::json::array( + {{{"uid", "peer1"}, {"type", "inmemorydb"}, {"context", "atomdb_singleton_test_"}}}); + AtomDBSingleton::provide(make_shared(JsonConfig(json["remote_peers"]))); + + auto db = AtomDBSingleton::get_instance(); + EXPECT_EQ(dynamic_cast(db.get()), nullptr); + EXPECT_NE(dynamic_cast(db.get()), nullptr); + EXPECT_FALSE(db->is_protected()); + + auto mock = make_shared(); + EXPECT_CALL(*mock, is_protected()).WillRepeatedly(Return(true)); + AtomDBSingleton::provide(mock); + + db = AtomDBSingleton::get_instance(); + EXPECT_EQ(db.get(), mock.get()); + EXPECT_EQ(dynamic_cast(db.get()), nullptr); + + AtomDBSingleton::provide(nullptr); +} diff --git a/src/tests/cpp/atomdbutils_test.cc b/src/tests/cpp/atomdbutils_test.cc index dc30b9626..1f36d26db 100644 --- a/src/tests/cpp/atomdbutils_test.cc +++ b/src/tests/cpp/atomdbutils_test.cc @@ -27,30 +27,30 @@ TEST(AtomDBTest, reachable_terminal_set) { auto K = new Node("Symbol", "K"); auto NOT_ADDED = new Node("Symbol", "NOT_ADDED"); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 1" << endl; - db->add_nodes({A, B, C, D, E, F, G, H, I, J, K}); + db->add_nodes({A, B, C, D, E, F, G, H, I, J, K}, ""); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2" << endl; auto L6 = new Link("Expression", {I->handle(), J->handle(), K->handle()}, true); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 3" << endl; - db->add_link(L6); + db->add_link(L6, ""); auto L5 = new Link("Expression", {C->handle(), D->handle()}, true); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 4" << endl; - db->add_link(L5); + db->add_link(L5, ""); auto L4 = new Link("Expression", {L5->handle(), E->handle()}, true); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 5" << endl; - db->add_link(L4); + db->add_link(L4, ""); auto L3 = new Link("Expression", {L4->handle(), F->handle()}, true); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 6" << endl; - db->add_link(L3); + db->add_link(L3, ""); auto L2 = new Link("Expression", {G->handle(), L6->handle(), H->handle()}, true); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 7" << endl; - db->add_link(L2); + db->add_link(L2, ""); auto L1 = new Link("Expression", {A->handle(), B->handle(), L3->handle()}, true); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 8" << endl; - db->add_link(L1); + db->add_link(L1, ""); auto L0 = new Link("Expression", {L1->handle(), L2->handle()}, true); cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 9" << endl; - db->add_link(L0); + db->add_link(L0, ""); string a = A->handle(); string b = B->handle(); @@ -125,5 +125,6 @@ TEST(AtomDBTest, reachable_terminal_set) { L4->handle(), L5->handle(), L6->handle()}, + "", true); } diff --git a/src/tests/cpp/chain_operator_test.cc b/src/tests/cpp/chain_operator_test.cc index 0d4ec55c4..c8a19c173 100644 --- a/src/tests/cpp/chain_operator_test.cc +++ b/src/tests/cpp/chain_operator_test.cc @@ -57,19 +57,19 @@ class ChainOperatorTestEnvironment : public ::testing::Environment { atoms::Link* link; node1 = new atoms::Node(NODE_TYPE, EVALUATION); LOG_DEBUG("Add node: " + node1->handle() + " " + node1->to_string()); - db->add_node(node1, false); + db->add_node(node1, "", false); for (unsigned int i = 0; i <= (NODE_COUNT + 1); i++) { node1 = new atoms::Node(NODE_TYPE, node_name(i)); - db->add_node(node1, false); + db->add_node(node1, "", false); LOG_DEBUG("Add node: " + node1->handle() + " " + node1->to_string()); for (unsigned int j = 0; j <= (NODE_COUNT + 1); j++) { node2 = new atoms::Node(NODE_TYPE, node_name(j)); LOG_DEBUG("Add node: " + node2->handle() + " " + node2->to_string()); - db->add_node(node2, false); + db->add_node(node2, "", false); link = new atoms::Link( LINK_TYPE, {EVALUATION_HANDLE, node1->handle(), node2->handle()}, true); LOG_DEBUG("Add link: " + link->handle() + " " + link->to_string()); - db->add_link(link, false); + db->add_link(link, "", false); } } } diff --git a/src/tests/cpp/inmemorydb_test.cc b/src/tests/cpp/inmemorydb_test.cc index 234d0651c..8540d6e06 100644 --- a/src/tests/cpp/inmemorydb_test.cc +++ b/src/tests/cpp/inmemorydb_test.cc @@ -37,20 +37,20 @@ TEST_F(InMemoryDBTest, AddNodesAndLinks) { auto similarity = new Node("Symbol", "Similarity"); auto inheritance = new Node("Symbol", "Inheritance"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string chimp_handle = db->add_node(chimp, false); - string mammal_handle = db->add_node(mammal, false); - string similarity_handle = db->add_node(similarity, false); - string inheritance_handle = db->add_node(inheritance, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string chimp_handle = db->add_node(chimp, "", false); + string mammal_handle = db->add_node(mammal, "", false); + string similarity_handle = db->add_node(similarity, "", false); + string inheritance_handle = db->add_node(inheritance, "", false); // Verify nodes were added - EXPECT_TRUE(db->node_exists(human_handle)); - EXPECT_TRUE(db->node_exists(monkey_handle)); - EXPECT_TRUE(db->node_exists(chimp_handle)); - EXPECT_TRUE(db->node_exists(mammal_handle)); - EXPECT_TRUE(db->node_exists(similarity_handle)); - EXPECT_TRUE(db->node_exists(inheritance_handle)); + EXPECT_TRUE(db->node_exists(human_handle, "")); + EXPECT_TRUE(db->node_exists(monkey_handle, "")); + EXPECT_TRUE(db->node_exists(chimp_handle, "")); + EXPECT_TRUE(db->node_exists(mammal_handle, "")); + EXPECT_TRUE(db->node_exists(similarity_handle, "")); + EXPECT_TRUE(db->node_exists(inheritance_handle, "")); auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); auto link2 = new Link("Expression", {similarity_handle, human_handle, chimp_handle}); @@ -58,27 +58,46 @@ TEST_F(InMemoryDBTest, AddNodesAndLinks) { auto link4 = new Link("Expression", {inheritance_handle, monkey_handle, mammal_handle}); auto link5 = new Link("Expression", {inheritance_handle, chimp_handle, mammal_handle}); - string link1_handle = db->add_link(link1, false); - string link2_handle = db->add_link(link2, false); - string link3_handle = db->add_link(link3, false); - string link4_handle = db->add_link(link4, false); - string link5_handle = db->add_link(link5, false); + string link1_handle = db->add_link(link1, "", false); + string link2_handle = db->add_link(link2, "", false); + string link3_handle = db->add_link(link3, "", false); + string link4_handle = db->add_link(link4, "", false); + string link5_handle = db->add_link(link5, "", false); // Verify links were added - EXPECT_TRUE(db->link_exists(link1_handle)); - EXPECT_TRUE(db->link_exists(link2_handle)); - EXPECT_TRUE(db->link_exists(link3_handle)); - EXPECT_TRUE(db->link_exists(link4_handle)); - EXPECT_TRUE(db->link_exists(link5_handle)); + EXPECT_TRUE(db->link_exists(link1_handle, "")); + EXPECT_TRUE(db->link_exists(link2_handle, "")); + EXPECT_TRUE(db->link_exists(link3_handle, "")); + EXPECT_TRUE(db->link_exists(link4_handle, "")); + EXPECT_TRUE(db->link_exists(link5_handle, "")); // Verify we can retrieve atoms - auto retrieved_human = db->get_atom(human_handle); + auto retrieved_human = db->get_atom(human_handle, ""); EXPECT_EQ(retrieved_human->handle(), human_handle); - auto retrieved_link1 = db->get_atom(link1_handle); + auto retrieved_link1 = db->get_atom(link1_handle, ""); EXPECT_EQ(retrieved_link1->handle(), link1_handle); } +TEST_F(InMemoryDBTest, GetNodeAndGetLinkValidateAtomType) { + auto human = new Node("Symbol", "\"human\""); + string human_handle = db->add_node(human, "", false); + + auto link = new Link("Expression", {human_handle, human_handle}); + string link_handle = db->add_link(link, "", false); + + auto node = db->get_node(human_handle, ""); + ASSERT_NE(node, nullptr); + EXPECT_EQ(node->handle(), human_handle); + + auto retrieved_link = db->get_link(link_handle, ""); + ASSERT_NE(retrieved_link, nullptr); + EXPECT_EQ(retrieved_link->handle(), link_handle); + + EXPECT_EQ(db->get_node(link_handle, ""), nullptr); + EXPECT_EQ(db->get_link(human_handle, ""), nullptr); +} + TEST_F(InMemoryDBTest, QueryForPattern) { auto human = new Node("Symbol", "\"human\""); auto monkey = new Node("Symbol", "\"monkey\""); @@ -86,22 +105,22 @@ TEST_F(InMemoryDBTest, QueryForPattern) { auto mammal = new Node("Symbol", "\"mammal\""); auto inheritance = new Node("Symbol", "Inheritance"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string chimp_handle = db->add_node(chimp, false); - string mammal_handle = db->add_node(mammal, false); - string inheritance_handle = db->add_node(inheritance, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string chimp_handle = db->add_node(chimp, "", false); + string mammal_handle = db->add_node(mammal, "", false); + string inheritance_handle = db->add_node(inheritance, "", false); auto link1 = new Link("Expression", {inheritance_handle, human_handle, mammal_handle}); auto link2 = new Link("Expression", {inheritance_handle, monkey_handle, mammal_handle}); auto link3 = new Link("Expression", {inheritance_handle, chimp_handle, mammal_handle}); - string link1_handle = db->add_link(link1, false); - string link2_handle = db->add_link(link2, false); - string link3_handle = db->add_link(link3, false); + string link1_handle = db->add_link(link1, "", false); + string link2_handle = db->add_link(link2, "", false); + string link3_handle = db->add_link(link3, "", false); // Re-index patterns to ensure re_index works - db->re_index_patterns(true); + db->re_index_patterns("", true); LinkSchema link_schema({"LINK_TEMPLATE", "Expression", @@ -115,7 +134,7 @@ TEST_F(InMemoryDBTest, QueryForPattern) { "Symbol", "\"mammal\""}); - auto result = db->query_for_pattern(link_schema); + auto result = db->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 3); // Verify we got the expected handles @@ -137,13 +156,13 @@ TEST_F(InMemoryDBTest, QueryForPatternWithSpecificMatch) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string similarity_handle = db->add_node(similarity, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string similarity_handle = db->add_node(similarity, "", false); auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link1_handle = db->add_link(link1, false); + string link1_handle = db->add_link(link1, "", false); LinkSchema link_schema({"LINK_TEMPLATE", "Expression", @@ -157,7 +176,7 @@ TEST_F(InMemoryDBTest, QueryForPatternWithSpecificMatch) { "VARIABLE", "x"}); - auto result = db->query_for_pattern(link_schema); + auto result = db->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 1); @@ -178,7 +197,7 @@ TEST_F(InMemoryDBTest, QueryForPatternNoMatches) { "VARIABLE", "y"}); - auto result = db->query_for_pattern(link_schema); + auto result = db->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 0); } @@ -188,18 +207,18 @@ TEST_F(InMemoryDBTest, QueryForTargets) { auto node3 = new Node("Symbol", "Node3"); auto similarity = new Node("Symbol", "Similarity"); - string node1_handle = db->add_node(node1, false); - string node2_handle = db->add_node(node2, false); - string node3_handle = db->add_node(node3, false); - string similarity_handle = db->add_node(similarity, false); + string node1_handle = db->add_node(node1, "", false); + string node2_handle = db->add_node(node2, "", false); + string node3_handle = db->add_node(node3, "", false); + string similarity_handle = db->add_node(similarity, "", false); - auto node_targets = db->query_for_targets(node1_handle); + auto node_targets = db->query_for_targets(node1_handle, ""); EXPECT_EQ(node_targets, nullptr); auto link1 = new Link("Expression", {similarity_handle, node1_handle, node2_handle, node3_handle}); - string link1_handle = db->add_link(link1, false); + string link1_handle = db->add_link(link1, "", false); - auto link1_targets = db->query_for_targets(link1_handle); + auto link1_targets = db->query_for_targets(link1_handle, ""); EXPECT_EQ(link1_targets->size(), 4); EXPECT_EQ(string(link1_targets->get_handle(0)), similarity_handle); EXPECT_EQ(string(link1_targets->get_handle(1)), node1_handle); @@ -209,7 +228,7 @@ TEST_F(InMemoryDBTest, QueryForTargets) { TEST_F(InMemoryDBTest, QueryForTargetsNonExistent) { string non_existent_handle = "00000000000000000000000000000000"; - auto targets = db->query_for_targets(non_existent_handle); + auto targets = db->query_for_targets(non_existent_handle, ""); EXPECT_EQ(targets, nullptr); } @@ -219,32 +238,32 @@ TEST_F(InMemoryDBTest, QueryForTargetsMultipleLinks) { auto chimp = new Node("Symbol", "\"chimp\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string chimp_handle = db->add_node(chimp, false); - string similarity_handle = db->add_node(similarity, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string chimp_handle = db->add_node(chimp, "", false); + string similarity_handle = db->add_node(similarity, "", false); auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); auto link2 = new Link("Expression", {similarity_handle, human_handle, chimp_handle}); auto link3 = new Link("Expression", {similarity_handle, monkey_handle, chimp_handle}); - string link1_handle = db->add_link(link1, false); - string link2_handle = db->add_link(link2, false); - string link3_handle = db->add_link(link3, false); + string link1_handle = db->add_link(link1, "", false); + string link2_handle = db->add_link(link2, "", false); + string link3_handle = db->add_link(link3, "", false); - auto link1_targets = db->query_for_targets(link1_handle); + auto link1_targets = db->query_for_targets(link1_handle, ""); EXPECT_EQ(link1_targets->size(), 3); EXPECT_EQ(string(link1_targets->get_handle(0)), similarity_handle); EXPECT_EQ(string(link1_targets->get_handle(1)), human_handle); EXPECT_EQ(string(link1_targets->get_handle(2)), monkey_handle); - auto link2_targets = db->query_for_targets(link2_handle); + auto link2_targets = db->query_for_targets(link2_handle, ""); EXPECT_EQ(link2_targets->size(), 3); EXPECT_EQ(string(link2_targets->get_handle(0)), similarity_handle); EXPECT_EQ(string(link2_targets->get_handle(1)), human_handle); EXPECT_EQ(string(link2_targets->get_handle(2)), chimp_handle); - auto link3_targets = db->query_for_targets(link3_handle); + auto link3_targets = db->query_for_targets(link3_handle, ""); EXPECT_EQ(link3_targets->size(), 3); EXPECT_EQ(string(link3_targets->get_handle(0)), similarity_handle); EXPECT_EQ(string(link3_targets->get_handle(1)), monkey_handle); @@ -256,19 +275,19 @@ TEST_F(InMemoryDBTest, QueryForTargetsAfterDeletion) { auto node2 = new Node("Symbol", "Node2"); auto similarity = new Node("Symbol", "Similarity"); - string node1_handle = db->add_node(node1, false); - string node2_handle = db->add_node(node2, false); - string similarity_handle = db->add_node(similarity, false); + string node1_handle = db->add_node(node1, "", false); + string node2_handle = db->add_node(node2, "", false); + string similarity_handle = db->add_node(similarity, "", false); auto link1 = new Link("Expression", {similarity_handle, node1_handle, node2_handle}); - string link1_handle = db->add_link(link1, false); + string link1_handle = db->add_link(link1, "", false); - auto targets = db->query_for_targets(link1_handle); + auto targets = db->query_for_targets(link1_handle, ""); EXPECT_EQ(targets->size(), 3); - db->delete_link(link1_handle, false); + db->delete_link(link1_handle, "", false); - targets = db->query_for_targets(link1_handle); + targets = db->query_for_targets(link1_handle, ""); EXPECT_EQ(targets, nullptr); } @@ -280,24 +299,24 @@ TEST_F(InMemoryDBTest, QueryForIncomingSet) { auto similarity = new Node("Symbol", "Similarity"); auto inheritance = new Node("Symbol", "Inheritance"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string chimp_handle = db->add_node(chimp, false); - string mammal_handle = db->add_node(mammal, false); - string similarity_handle = db->add_node(similarity, false); - string inheritance_handle = db->add_node(inheritance, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string chimp_handle = db->add_node(chimp, "", false); + string mammal_handle = db->add_node(mammal, "", false); + string similarity_handle = db->add_node(similarity, "", false); + string inheritance_handle = db->add_node(inheritance, "", false); // Create links that reference human auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); auto link2 = new Link("Expression", {similarity_handle, human_handle, chimp_handle}); auto link3 = new Link("Expression", {inheritance_handle, human_handle, mammal_handle}); - string link1_handle = db->add_link(link1, false); - string link2_handle = db->add_link(link2, false); - string link3_handle = db->add_link(link3, false); + string link1_handle = db->add_link(link1, "", false); + string link2_handle = db->add_link(link2, "", false); + string link3_handle = db->add_link(link3, "", false); // Query incoming set for human - auto incoming_set = db->query_for_incoming_set(human_handle); + auto incoming_set = db->query_for_incoming_set(human_handle, ""); EXPECT_EQ(incoming_set->size(), 3); // Verify we got the expected link handles @@ -313,16 +332,16 @@ TEST_F(InMemoryDBTest, QueryForIncomingSet) { EXPECT_TRUE(find(handles.begin(), handles.end(), link3_handle) != handles.end()); // Query incoming set for monkey (should have 1 link) - auto monkey_incoming = db->query_for_incoming_set(monkey_handle); + auto monkey_incoming = db->query_for_incoming_set(monkey_handle, ""); EXPECT_EQ(monkey_incoming->size(), 1); // Query incoming set for mammal (should have 1 link) - auto mammal_incoming = db->query_for_incoming_set(mammal_handle); + auto mammal_incoming = db->query_for_incoming_set(mammal_handle, ""); EXPECT_EQ(mammal_incoming->size(), 1); // Query incoming set for non-existent node (should be empty) string non_existent_handle = "00000000000000000000000000000000"; - auto non_existent_incoming = db->query_for_incoming_set(non_existent_handle); + auto non_existent_incoming = db->query_for_incoming_set(non_existent_handle, ""); EXPECT_EQ(non_existent_incoming->size(), 0); } @@ -331,22 +350,22 @@ TEST_F(InMemoryDBTest, QueryForIncomingSetAfterDeletion) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string similarity_handle = db->add_node(similarity, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string similarity_handle = db->add_node(similarity, "", false); auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link1_handle = db->add_link(link1, false); + string link1_handle = db->add_link(link1, "", false); // Verify incoming set before deletion - auto incoming_set = db->query_for_incoming_set(human_handle); + auto incoming_set = db->query_for_incoming_set(human_handle, ""); EXPECT_EQ(incoming_set->size(), 1); // Delete the link - db->delete_link(link1_handle, false); + db->delete_link(link1_handle, "", false); // Verify incoming set is now empty - incoming_set = db->query_for_incoming_set(human_handle); + incoming_set = db->query_for_incoming_set(human_handle, ""); EXPECT_EQ(incoming_set->size(), 0); } @@ -355,35 +374,35 @@ TEST_F(InMemoryDBTest, DeleteAtom) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string similarity_handle = db->add_node(similarity, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string similarity_handle = db->add_node(similarity, "", false); // Create a link that references human auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link1_handle = db->add_link(link1, false); + string link1_handle = db->add_link(link1, "", false); // Try to delete human atom with delete_link_targets=false (should fail) - bool deleted = db->delete_atom(human_handle, false); + bool deleted = db->delete_atom(human_handle, "", false); EXPECT_FALSE(deleted); // Verify human still exists - EXPECT_TRUE(db->node_exists(human_handle)); - EXPECT_TRUE(db->link_exists(link1_handle)); + EXPECT_TRUE(db->node_exists(human_handle, "")); + EXPECT_TRUE(db->link_exists(link1_handle, "")); // Create a link that references human auto link2 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link2_handle = db->add_link(link2, false); + string link2_handle = db->add_link(link2, "", false); // Delete human atom with delete_link_targets=true (should succeed and delete the link) - deleted = db->delete_atom(human_handle, true); + deleted = db->delete_atom(human_handle, "", true); EXPECT_TRUE(deleted); // Verify human is deleted - EXPECT_FALSE(db->node_exists(human_handle)); + EXPECT_FALSE(db->node_exists(human_handle, "")); // Verify the link is also deleted - EXPECT_FALSE(db->link_exists(link2_handle)); + EXPECT_FALSE(db->link_exists(link2_handle, "")); } TEST_F(InMemoryDBTest, DeleteNode) { @@ -391,42 +410,42 @@ TEST_F(InMemoryDBTest, DeleteNode) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string similarity_handle = db->add_node(similarity, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string similarity_handle = db->add_node(similarity, "", false); // Create a link that references human auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link1_handle = db->add_link(link1, false); + string link1_handle = db->add_link(link1, "", false); // Try to delete human with delete_link_targets=false (should fail) - bool deleted = db->delete_node(human_handle, false); + bool deleted = db->delete_node(human_handle, "", false); EXPECT_FALSE(deleted); // Verify human still exists - EXPECT_TRUE(db->node_exists(human_handle)); - EXPECT_TRUE(db->link_exists(link1_handle)); + EXPECT_TRUE(db->node_exists(human_handle, "")); + EXPECT_TRUE(db->link_exists(link1_handle, "")); // Verify incoming set still has the link - auto incoming_set = db->query_for_incoming_set(human_handle); + auto incoming_set = db->query_for_incoming_set(human_handle, ""); EXPECT_EQ(incoming_set->size(), 1); // Create a link that references human auto link2 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link2_handle = db->add_link(link2, false); + string link2_handle = db->add_link(link2, "", false); // Delete human with delete_link_targets=true (should succeed and delete the link) - deleted = db->delete_node(human_handle, true); + deleted = db->delete_node(human_handle, "", true); EXPECT_TRUE(deleted); // Verify human is deleted - EXPECT_FALSE(db->node_exists(human_handle)); + EXPECT_FALSE(db->node_exists(human_handle, "")); // Verify the link is also deleted - EXPECT_FALSE(db->link_exists(link2_handle)); + EXPECT_FALSE(db->link_exists(link2_handle, "")); // Verify incoming set is empty - incoming_set = db->query_for_incoming_set(human_handle); + incoming_set = db->query_for_incoming_set(human_handle, ""); EXPECT_EQ(incoming_set->size(), 0); } @@ -435,47 +454,47 @@ TEST_F(InMemoryDBTest, DeleteLink) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string similarity_handle = db->add_node(similarity, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string similarity_handle = db->add_node(similarity, "", false); // Create a link that references human and monkey auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link1_handle = db->add_link(link1, false); + string link1_handle = db->add_link(link1, "", false); // Delete link with delete_link_targets=false (should succeed, targets remain) - bool deleted = db->delete_link(link1_handle, false); + bool deleted = db->delete_link(link1_handle, "", false); EXPECT_TRUE(deleted); // Verify link is deleted - EXPECT_FALSE(db->link_exists(link1_handle)); + EXPECT_FALSE(db->link_exists(link1_handle, "")); // Verify targets still exist - EXPECT_TRUE(db->node_exists(human_handle)); - EXPECT_TRUE(db->node_exists(monkey_handle)); - EXPECT_TRUE(db->node_exists(similarity_handle)); + EXPECT_TRUE(db->node_exists(human_handle, "")); + EXPECT_TRUE(db->node_exists(monkey_handle, "")); + EXPECT_TRUE(db->node_exists(similarity_handle, "")); // Verify incoming sets are empty - auto human_incoming = db->query_for_incoming_set(human_handle); + auto human_incoming = db->query_for_incoming_set(human_handle, ""); EXPECT_EQ(human_incoming->size(), 0); - auto monkey_incoming = db->query_for_incoming_set(monkey_handle); + auto monkey_incoming = db->query_for_incoming_set(monkey_handle, ""); EXPECT_EQ(monkey_incoming->size(), 0); // Create a link that references human and monkey auto link2 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link2_handle = db->add_link(link2, false); + string link2_handle = db->add_link(link2, "", false); // Delete link with delete_link_targets=true (should delete targets if no other references) - deleted = db->delete_link(link2_handle, true); + deleted = db->delete_link(link2_handle, "", true); EXPECT_TRUE(deleted); // Verify link is deleted - EXPECT_FALSE(db->link_exists(link2_handle)); + EXPECT_FALSE(db->link_exists(link2_handle, "")); // Verify targets are deleted (they had no other incoming links) - EXPECT_FALSE(db->node_exists(similarity_handle)); - EXPECT_FALSE(db->node_exists(human_handle)); - EXPECT_FALSE(db->node_exists(monkey_handle)); + EXPECT_FALSE(db->node_exists(similarity_handle, "")); + EXPECT_FALSE(db->node_exists(human_handle, "")); + EXPECT_FALSE(db->node_exists(monkey_handle, "")); } TEST_F(InMemoryDBTest, DeleteLinkMultipleReferences) { @@ -484,61 +503,61 @@ TEST_F(InMemoryDBTest, DeleteLinkMultipleReferences) { auto chimp = new Node("Symbol", "\"chimp\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = db->add_node(human, false); - string monkey_handle = db->add_node(monkey, false); - string chimp_handle = db->add_node(chimp, false); - string similarity_handle = db->add_node(similarity, false); + string human_handle = db->add_node(human, "", false); + string monkey_handle = db->add_node(monkey, "", false); + string chimp_handle = db->add_node(chimp, "", false); + string similarity_handle = db->add_node(similarity, "", false); // Create two links that both reference human auto link1 = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); auto link2 = new Link("Expression", {similarity_handle, human_handle, chimp_handle}); - string link1_handle = db->add_link(link1, false); - string link2_handle = db->add_link(link2, false); + string link1_handle = db->add_link(link1, "", false); + string link2_handle = db->add_link(link2, "", false); // Verify human has 2 incoming links - auto human_incoming = db->query_for_incoming_set(human_handle); + auto human_incoming = db->query_for_incoming_set(human_handle, ""); EXPECT_EQ(human_incoming->size(), 2); // Delete link1 with delete_link_targets=true - bool deleted = db->delete_link(link1_handle, true); + bool deleted = db->delete_link(link1_handle, "", true); EXPECT_TRUE(deleted); // Verify link1 is deleted - EXPECT_FALSE(db->link_exists(link1_handle)); + EXPECT_FALSE(db->link_exists(link1_handle, "")); // Verify human still exists (has another incoming link) - EXPECT_TRUE(db->node_exists(human_handle)); + EXPECT_TRUE(db->node_exists(human_handle, "")); // Verify monkey is deleted (no other references) - EXPECT_FALSE(db->node_exists(monkey_handle)); + EXPECT_FALSE(db->node_exists(monkey_handle, "")); // Verify human now has only 1 incoming link - human_incoming = db->query_for_incoming_set(human_handle); + human_incoming = db->query_for_incoming_set(human_handle, ""); EXPECT_EQ(human_incoming->size(), 1); // Verify link2 still exists - EXPECT_TRUE(db->link_exists(link2_handle)); + EXPECT_TRUE(db->link_exists(link2_handle, "")); } TEST_F(InMemoryDBTest, AtomsCount) { - EXPECT_EQ(db->atom_count(), 0); - EXPECT_EQ(db->empty(), true); + EXPECT_EQ(db->atom_count(""), 0); + EXPECT_EQ(db->empty(""), true); auto node1 = new Node("Symbol", "Node1"); auto node2 = new Node("Symbol", "Node2"); auto similarity = new Node("Symbol", "Similarity"); - db->add_node(node1, false); - db->add_node(node2, false); - db->add_node(similarity, false); + db->add_node(node1, "", false); + db->add_node(node2, "", false); + db->add_node(similarity, "", false); - EXPECT_EQ(db->atom_count(), 3); + EXPECT_EQ(db->atom_count(""), 3); auto link1 = new Link("Expression", {similarity->handle(), node1->handle(), node2->handle()}); - db->add_link(link1, false); + db->add_link(link1, "", false); - EXPECT_EQ(db->atom_count(), 4); - EXPECT_EQ(db->empty(), false); + EXPECT_EQ(db->atom_count(""), 4); + EXPECT_EQ(db->empty(""), false); } // ============================================================================= diff --git a/src/tests/cpp/link_creation_agent_test.cc b/src/tests/cpp/link_creation_agent_test.cc index 55413e822..f47bf69ad 100644 --- a/src/tests/cpp/link_creation_agent_test.cc +++ b/src/tests/cpp/link_creation_agent_test.cc @@ -385,13 +385,14 @@ TEST_F(LinkCreationAgentTest, TestLinkTemplateProcessor) { "custom_attributes: {})"); auto mock_atom = dynamic_cast(AtomDBSingleton::get_instance().get()); vector targets_node = {"Value1", "Value2", "A", "Value1", "B", "C", "B"}; - EXPECT_CALL(*mock_atom, get_atom(testing::_)) + EXPECT_CALL(*mock_atom, get_atom(testing::_, testing::_)) .Times(targets_node.size()) - .WillRepeatedly(::testing::Invoke([&targets_node](const string& handle) { - auto node = make_shared("Symbol", targets_node.front()); - targets_node.erase(targets_node.begin()); - return node; - })); + .WillRepeatedly( + ::testing::Invoke([&targets_node](const string& handle, const string& public_key) { + auto node = make_shared("Symbol", targets_node.front()); + targets_node.erase(targets_node.begin()); + return node; + })); EXPECT_EQ(links[0]->metta_representation(*AtomDBSingleton::get_instance().get()), "(Value1 Value2)"); link_template.clear(); links.clear(); @@ -550,16 +551,17 @@ TEST_F(LinkCreationAgentTest, TestImplicationProcessorLinkCreationOr) { auto targets = vector>{{A, B}, {B, A}, {B, C}, {C, B}, {C, A}, {A, C}}; int t_count = 0; auto mock_atomdb = dynamic_cast(AtomDBSingleton::get_instance().get()); - EXPECT_CALL(*mock_atomdb, get_atom(testing::_)) + EXPECT_CALL(*mock_atomdb, get_atom(testing::_, testing::_)) .Times(5) - .WillRepeatedly(::testing::Invoke([&targets, &t_count](const string& handle) { - Properties props; - props["strength"] = 0.33 * (t_count + 1); - vector targets_ = {targets[t_count].first, targets[t_count].second}; - auto link = make_shared("Expression", targets_, props); - t_count++; - return link; - })); + .WillRepeatedly( + ::testing::Invoke([&targets, &t_count](const string& handle, const string& public_key) { + Properties props; + props["strength"] = 0.33 * (t_count + 1); + vector targets_ = {targets[t_count].first, targets[t_count].second}; + auto link = make_shared("Expression", targets_, props); + t_count++; + return link; + })); auto ip = make_shared(); shared_ptr query_answer = make_shared(1.0); query_answer->add_handle(A); @@ -646,16 +648,17 @@ TEST_F(LinkCreationAgentTest, TestEquivalenceProcessorLinkCreationOr) { auto targets = vector>{{A, B}, {B, A}, {B, C}, {C, B}, {C, A}, {A, C}}; int t_count = 0; auto mock_atomdb = dynamic_cast(AtomDBSingleton::get_instance().get()); - EXPECT_CALL(*mock_atomdb, get_atom(testing::_)) + EXPECT_CALL(*mock_atomdb, get_atom(testing::_, testing::_)) .Times(5) - .WillRepeatedly(::testing::Invoke([&targets, &t_count](const string& handle) { - Properties props; - props["strength"] = 0.33 * (t_count + 1); - vector targets_ = {targets[t_count].first, targets[t_count].second}; - auto link = make_shared("Expression", targets_, props); - t_count++; - return link; - })); + .WillRepeatedly( + ::testing::Invoke([&targets, &t_count](const string& handle, const string& public_key) { + Properties props; + props["strength"] = 0.33 * (t_count + 1); + vector targets_ = {targets[t_count].first, targets[t_count].second}; + auto link = make_shared("Expression", targets_, props); + t_count++; + return link; + })); auto ip = make_shared(); shared_ptr query_answer = make_shared(1.0); query_answer->add_handle(A); @@ -681,14 +684,15 @@ TEST_F(LinkCreationAgentTest, TestMettaProcessorLinkCreation) { std::queue target_queue; target_queue.push(C); target_queue.push(D); - EXPECT_CALL(*mock_atomdb, get_atom(testing::_)) + EXPECT_CALL(*mock_atomdb, get_atom(testing::_, testing::_)) .Times(2) - .WillRepeatedly(::testing::Invoke([&target_queue](const string& handle) { - string name = target_queue.front(); - target_queue.pop(); - auto link = make_shared("Symbol", name); - return link; - })); + .WillRepeatedly( + ::testing::Invoke([&target_queue](const string& handle, const string& public_key) { + string name = target_queue.front(); + target_queue.pop(); + auto link = make_shared("Symbol", name); + return link; + })); auto links = mp->process_query(query_answer, vector({"($V1 $V2 (Expression $V1 Test (Tttt $V2)))"})); EXPECT_EQ(links.size(), 1); @@ -710,26 +714,28 @@ TEST_F(LinkCreationAgentTest, TestMettaProcessorLinkCreationInnerCheck) { std::queue target_queue; target_queue.push(C); target_queue.push(D); - EXPECT_CALL(*mock_atomdb, get_atom(testing::_)) + EXPECT_CALL(*mock_atomdb, get_atom(testing::_, testing::_)) .Times(2) - .WillRepeatedly(::testing::Invoke([&target_queue](const string& handle) { - string name = target_queue.front(); - target_queue.pop(); - auto link = make_shared("Symbol", name); - return link; - })); + .WillRepeatedly( + ::testing::Invoke([&target_queue](const string& handle, const string& public_key) { + string name = target_queue.front(); + target_queue.pop(); + auto link = make_shared("Symbol", name); + return link; + })); vector expected_nodes = {"Tttt", "Test", C, Z, D}; int nodes_count = 0; - EXPECT_CALL(*mock_atomdb, add_node(testing::_, testing::_)) + EXPECT_CALL(*mock_atomdb, add_node(testing::_, testing::_, testing::_)) .Times(expected_nodes.size()) - .WillRepeatedly(::testing::Invoke( - [&expected_nodes, &nodes_count](const atoms::Node* node, bool throw_if_exists) { - EXPECT_EQ(node->type, "Symbol"); - EXPECT_EQ(node->name, expected_nodes[nodes_count].c_str()); - nodes_count++; - return ""; - })); + .WillRepeatedly(::testing::Invoke([&expected_nodes, &nodes_count](const atoms::Node* node, + const string& public_key, + bool throw_if_exists) { + EXPECT_EQ(node->type, "Symbol"); + EXPECT_EQ(node->name, expected_nodes[nodes_count].c_str()); + nodes_count++; + return ""; + })); string C_HASH = make_shared("Symbol", C)->handle(); string Z_HASH = make_shared("Symbol", Z)->handle(); string D_HASH = make_shared("Symbol", D)->handle(); @@ -746,18 +752,19 @@ TEST_F(LinkCreationAgentTest, TestMettaProcessorLinkCreationInnerCheck) { {C_HASH, TEST_HASH, INNER_HASH}, }; int links_count = 0; - EXPECT_CALL(*mock_atomdb, add_link(testing::_, testing::_)) + EXPECT_CALL(*mock_atomdb, add_link(testing::_, testing::_, testing::_)) .Times(expected_links.size()) - .WillRepeatedly(::testing::Invoke( - [&links_count, &expected_links](const atoms::Link* link, bool throw_if_exists) { - EXPECT_EQ(link->type, "Expression"); - EXPECT_EQ(link->targets.size(), expected_links[links_count].size()); - for (size_t i = 0; i < expected_links[links_count].size(); i++) { - EXPECT_EQ(link->targets[i], expected_links[links_count][i]); - } - links_count++; - return ""; - })); + .WillRepeatedly(::testing::Invoke([&links_count, &expected_links](const atoms::Link* link, + const string& public_key, + bool throw_if_exists) { + EXPECT_EQ(link->type, "Expression"); + EXPECT_EQ(link->targets.size(), expected_links[links_count].size()); + for (size_t i = 0; i < expected_links[links_count].size(); i++) { + EXPECT_EQ(link->targets[i], expected_links[links_count][i]); + } + links_count++; + return ""; + })); string metta_expression_str = "($V1 $V2 ($V1 Test (Tttt ($V1 Z) $V2)))"; auto links = mp->process_query(query_answer, vector({metta_expression_str})); EXPECT_EQ(links.size(), 1); @@ -779,28 +786,30 @@ TEST_F(LinkCreationAgentTest, TestMettaProcessorLinkCreationSimpleMeta) { std::queue target_queue; target_queue.push(C); target_queue.push(D); - EXPECT_CALL(*mock_atomdb, get_atom(testing::_)) + EXPECT_CALL(*mock_atomdb, get_atom(testing::_, testing::_)) .Times(2) - .WillRepeatedly(::testing::Invoke([&target_queue](const string& handle) { - string name = target_queue.front(); - target_queue.pop(); - auto link = make_shared("Symbol", name); - return link; - })); + .WillRepeatedly( + ::testing::Invoke([&target_queue](const string& handle, const string& public_key) { + string name = target_queue.front(); + target_queue.pop(); + auto link = make_shared("Symbol", name); + return link; + })); vector expected_nodes = {A, C, D}; int nodes_count = 0; - EXPECT_CALL(*mock_atomdb, add_node(testing::_, testing::_)) + EXPECT_CALL(*mock_atomdb, add_node(testing::_, testing::_, testing::_)) .Times(expected_nodes.size()) - .WillRepeatedly(::testing::Invoke( - [&expected_nodes, &nodes_count](const atoms::Node* node, bool throw_if_exists) { - EXPECT_EQ(node->type, "Symbol"); - EXPECT_EQ(node->name, expected_nodes[nodes_count].c_str()); - nodes_count++; - return ""; - })); + .WillRepeatedly(::testing::Invoke([&expected_nodes, &nodes_count](const atoms::Node* node, + const string& public_key, + bool throw_if_exists) { + EXPECT_EQ(node->type, "Symbol"); + EXPECT_EQ(node->name, expected_nodes[nodes_count].c_str()); + nodes_count++; + return ""; + })); // This should never be called - EXPECT_CALL(*mock_atomdb, add_link(testing::_, testing::_)).Times(0); + EXPECT_CALL(*mock_atomdb, add_link(testing::_, testing::_, testing::_)).Times(0); auto links = mp->process_query(query_answer, vector({"(A $V1 $V2)"})); EXPECT_EQ(links.size(), 1); } diff --git a/src/tests/cpp/morkdb_test.cc b/src/tests/cpp/morkdb_test.cc index a5c798d3b..b204d6ef9 100644 --- a/src/tests/cpp/morkdb_test.cc +++ b/src/tests/cpp/morkdb_test.cc @@ -81,7 +81,7 @@ TEST_F(MorkDBTest, QueryForPattern) { node, symbol, mammal}); // clang-format on - auto result = db->query_for_pattern(link_schema); + auto result = db->query_for_pattern(link_schema, ""); ASSERT_EQ(result->size(), 4); @@ -102,21 +102,21 @@ TEST_F(MorkDBTest, QueryForPattern) { TEST_F(MorkDBTest, QueryForTargets) { auto node1 = new Node("Symbol", "QueryForTargetsNode1"); - auto node1_handle = db->add_node(node1); + auto node1_handle = db->add_node(node1, ""); auto node2 = new Node("Symbol", "QueryForTargetsNode2"); - auto node2_handle = db->add_node(node2); + auto node2_handle = db->add_node(node2, ""); auto node3 = new Node("Symbol", "QueryForTargetsNode3"); - auto node3_handle = db->add_node(node3); + auto node3_handle = db->add_node(node3, ""); - auto node1_targets = db->query_for_targets(node1_handle); + auto node1_targets = db->query_for_targets(node1_handle, ""); EXPECT_EQ(node1_targets, nullptr); auto link1 = new Link("Expression", {node1_handle, node2_handle, node3_handle}); - auto link1_handle = db->add_link(link1); + auto link1_handle = db->add_link(link1, ""); - ASSERT_TRUE(db->link_exists(link1_handle)); + ASSERT_TRUE(db->link_exists(link1_handle, "")); - auto link1_targets = db->query_for_targets(link1_handle); + auto link1_targets = db->query_for_targets(link1_handle, ""); EXPECT_NE(link1_targets, nullptr); EXPECT_EQ(link1_targets->size(), 3); EXPECT_EQ(link1_targets->get_handle(0), node1_handle); @@ -138,7 +138,7 @@ TEST_F(MorkDBTest, ConcurrentQueryForPattern) { variable, "x", variable, "y"}); // clang-format on - auto handle_set = db->query_for_pattern(link_schema); + auto handle_set = db->query_for_pattern(link_schema, ""); ASSERT_NE(handle_set, nullptr); ASSERT_EQ(handle_set->size(), 14); success_count++; @@ -165,19 +165,19 @@ TEST_F(MorkDBTest, ConcurrentQueryForPattern) { variable, "x", variable, "y"}); // clang-format on - auto handle_set = db->query_for_pattern(link_schema); + auto handle_set = db->query_for_pattern(link_schema, ""); EXPECT_EQ(handle_set->size(), 0); } TEST_F(MorkDBTest, AddGetAndDeleteNode) { auto node = new Node("Symbol", "TestNode"); - auto node_handle = db->add_node(node); + auto node_handle = db->add_node(node, ""); auto node_document = db->get_atom_document(node_handle); EXPECT_EQ(string(node_document->get("named_type")), string("Symbol")); EXPECT_EQ(string(node_document->get("name")), string("TestNode")); - ASSERT_TRUE(db->delete_node(node_handle)); + ASSERT_TRUE(db->delete_node(node_handle, "")); } TEST_F(MorkDBTest, AddGetAndDeleteNodes) { @@ -186,40 +186,40 @@ TEST_F(MorkDBTest, AddGetAndDeleteNodes) { nodes.push_back(new Node("Symbol", "TestNode" + to_string(i))); } - auto nodes_handles = db->add_nodes(nodes); + auto nodes_handles = db->add_nodes(nodes, ""); EXPECT_EQ(nodes.size(), nodes.size()); auto nodes_documents = db->get_atom_documents(nodes_handles, {"_id"}); EXPECT_EQ(nodes_documents.size(), nodes.size()); - EXPECT_EQ(db->delete_nodes(nodes_handles), nodes.size()); + EXPECT_EQ(db->delete_nodes(nodes_handles, ""), nodes.size()); - ASSERT_EQ(db->nodes_exist(nodes_handles).size(), 0); + ASSERT_EQ(db->nodes_exist(nodes_handles, "").size(), 0); } TEST_F(MorkDBTest, AddGetAndDeleteLink) { auto similarity_node = new Node("Symbol", "Similarity"); - auto similarity_node_handle = db->add_node(similarity_node); + auto similarity_node_handle = db->add_node(similarity_node, ""); auto node1 = new Node("Symbol", "Node1"); - auto node1_handle = db->add_node(node1); + auto node1_handle = db->add_node(node1, ""); auto node2 = new Node("Symbol", "Node2"); - auto node2_handle = db->add_node(node2); + auto node2_handle = db->add_node(node2, ""); auto node3 = new Node("Symbol", "Node3"); - auto node3_handle = db->add_node(node3); + auto node3_handle = db->add_node(node3, ""); auto node4 = new Node("Symbol", "Node4"); - auto node4_handle = db->add_node(node4); + auto node4_handle = db->add_node(node4, ""); - ASSERT_TRUE(db->node_exists(similarity_node_handle)); - ASSERT_TRUE(db->node_exists(node1_handle)); - ASSERT_TRUE(db->node_exists(node2_handle)); - ASSERT_TRUE(db->node_exists(node3_handle)); - ASSERT_TRUE(db->node_exists(node4_handle)); + ASSERT_TRUE(db->node_exists(similarity_node_handle, "")); + ASSERT_TRUE(db->node_exists(node1_handle, "")); + ASSERT_TRUE(db->node_exists(node2_handle, "")); + ASSERT_TRUE(db->node_exists(node3_handle, "")); + ASSERT_TRUE(db->node_exists(node4_handle, "")); auto link = new Link("Expression", {similarity_node_handle, node1_handle, node2_handle}); - auto link_handle = db->add_link(link); + auto link_handle = db->add_link(link, ""); - ASSERT_TRUE(db->link_exists(link_handle)); + ASSERT_TRUE(db->link_exists(link_handle, "")); auto link_document = db->get_atom_document(link_handle); EXPECT_EQ(string(link_document->get("named_type")), string("Expression")); @@ -235,45 +235,45 @@ TEST_F(MorkDBTest, AddGetAndDeleteLink) { variable, "S"}); // clang-format on - auto handle_set = db->query_for_pattern(link_schema); + auto handle_set = db->query_for_pattern(link_schema, ""); EXPECT_EQ(handle_set->size(), 1); auto link_13 = new Link("Expression", {similarity_node_handle, node1_handle, node3_handle}); auto link_14 = new Link("Expression", {similarity_node_handle, node1_handle, node4_handle}); - auto new_link_handles = db->add_links({link_13, link_14}); + auto new_link_handles = db->add_links({link_13, link_14}, ""); EXPECT_EQ(new_link_handles.size(), 2); - handle_set = db->query_for_pattern(link_schema); + handle_set = db->query_for_pattern(link_schema, ""); EXPECT_EQ(handle_set->size(), 3); // MORKDB does not support deleting links, so it must always return false - EXPECT_FALSE(db->delete_link(link_handle, true)); + EXPECT_FALSE(db->delete_link(link_handle, "", true)); } TEST_F(MorkDBTest, AddGetAndDeleteLinks) { auto similarity_node = new Node("Symbol", "Similarity"); - auto similarity_node_handle = db->add_node(similarity_node); + auto similarity_node_handle = db->add_node(similarity_node, ""); auto from_node = new Node("Symbol", "From"); - auto from_node_handle = db->add_node(from_node); + auto from_node_handle = db->add_node(from_node, ""); vector links; for (int i = 0; i < 10; i++) { auto to_node = new Node("Symbol", "To-" + to_string(i)); - auto to_node_handle = db->add_node(to_node); + auto to_node_handle = db->add_node(to_node, ""); links.push_back( new Link("Expression", {similarity_node_handle, from_node_handle, to_node_handle})); } - auto links_handles = db->add_links(links); + auto links_handles = db->add_links(links, ""); EXPECT_EQ(links_handles.size(), links.size()); auto links_documents = db->get_atom_documents(links_handles, {"_id"}); EXPECT_EQ(links_documents.size(), links.size()); // MORKDB does not support deleting links, so it must always return false - EXPECT_FALSE(db->delete_links(links_handles, true)); + EXPECT_FALSE(db->delete_links(links_handles, "", true)); } TEST_F(MorkDBTest, AddLinksWithDuplicateTargets) { @@ -281,7 +281,7 @@ TEST_F(MorkDBTest, AddLinksWithDuplicateTargets) { nodes.push_back(new Node("Symbol", "DuplicateTargets1")); nodes.push_back(new Node("Symbol", "DuplicateTargets2")); nodes.push_back(new Node("Symbol", "DuplicateTargets3")); - EXPECT_EQ(db->add_nodes(nodes, true).size(), 3); + EXPECT_EQ(db->add_nodes(nodes, "", true).size(), 3); auto link = new Link("Expression", {nodes[0]->handle(), @@ -291,9 +291,9 @@ TEST_F(MorkDBTest, AddLinksWithDuplicateTargets) { nodes[2]->handle(), nodes[0]->handle(), nodes[2]->handle()}); - EXPECT_EQ(db->add_link(link), link->handle()); + EXPECT_EQ(db->add_link(link, ""), link->handle()); // MORKDB does not support deleting links, so it must always return false - EXPECT_FALSE(db->delete_link(link->handle(), true)); + EXPECT_FALSE(db->delete_link(link->handle(), "", true)); } TEST_F(MorkDBTest, ConcurrentAddLinks) { @@ -340,15 +340,15 @@ TEST_F(MorkDBTest, ConcurrentAddLinks) { links.push_back(link_with_nested); if (i % chunck_size == 0) { - db->add_nodes(nodes, false, true); - db->add_links(links, false, true); + db->add_nodes(nodes, "", false, true); + db->add_links(links, "", false, true); nodes.clear(); links.clear(); } } - if (!nodes.empty()) db->add_nodes(nodes, false, true); - if (!links.empty()) db->add_links(links, false, true); + if (!nodes.empty()) db->add_nodes(nodes, "", false, true); + if (!links.empty()) db->add_links(links, "", false, true); success_count++; } catch (const exception& e) { @@ -375,7 +375,7 @@ TEST_F(MorkDBTest, ConcurrentAddLinks) { }); // clang-format on - auto result = db->query_for_pattern(link_schema); + auto result = db->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 2); } @@ -384,14 +384,14 @@ TEST_F(MorkDBTest, AddLinkWithoutMettaExpressionMustPopulateIt) { auto human = new Node("Symbol", "\"human\""); auto robot = new Node("Symbol", "\"robot\""); - db->add_node(similarity, false); - db->add_node(human, false); - auto robot_handle = db->add_node(robot); + db->add_node(similarity, "", false); + db->add_node(human, "", false); + auto robot_handle = db->add_node(robot, ""); auto link = new Link("Expression", {similarity->handle(), human->handle(), robot->handle()}); EXPECT_EQ(link->custom_attributes.get_or("metta_expression", ""), ""); - auto link_handle = db->add_link(link); + auto link_handle = db->add_link(link, ""); auto link_document = dynamic_pointer_cast(db->get_link_document(link_handle)); @@ -439,7 +439,7 @@ TEST_F(MorkDBTest, ReIndexPatterns) { "VARIABLE", "C" }); // clang-format on - auto result = db->query_for_pattern(link_schema); + auto result = db->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 0); // Resetting MongoDB database to animals data @@ -451,15 +451,15 @@ TEST_F(MorkDBTest, ReIndexPatterns) { RedisMongoDB::MONGODB_LINKS_COLLECTION_NAME); EXPECT_EQ(inserted_count, 3); - db->re_index_patterns(); + db->re_index_patterns(""); - result = db->query_for_pattern(link_schema); + result = db->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 3); string pattern = "(EvaluationReIndex $P $C)"; db->flush_pattern(pattern); - result = db->query_for_pattern(link_schema); + result = db->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 0); // Confirm that patterns are re-indexed @@ -472,7 +472,7 @@ TEST_F(MorkDBTest, ReIndexPatterns) { node, symbol, mammal}); // clang-format on - result = db->query_for_pattern(link_schema); + result = db->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 4); } diff --git a/src/tests/cpp/pattern_matching_query_test.cc b/src/tests/cpp/pattern_matching_query_test.cc index 55ce3f331..b996c430d 100644 --- a/src/tests/cpp/pattern_matching_query_test.cc +++ b/src/tests/cpp/pattern_matching_query_test.cc @@ -20,7 +20,7 @@ using das_test::init_test_system_parameters_singleton; string handle_to_atom(const string& handle) { shared_ptr db = AtomDBSingleton::get_instance(); - shared_ptr atom = db->get_atom(handle); + shared_ptr atom = db->get_atom(handle, ""); string answer; if (atom->arity() > 0) { @@ -51,7 +51,7 @@ string handle_to_atom(const string& handle) { string get_target(const string& handle, unsigned int index) { shared_ptr db = AtomDBSingleton::get_instance(); - shared_ptr atom = db->get_atom(handle); + shared_ptr atom = db->get_atom(handle, ""); auto link = dynamic_cast(atom.get()); if ((link == nullptr) || (link == NULL)) { LOG_INFO("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX NULL link"); diff --git a/src/tests/cpp/redis_mongodb_test.cc b/src/tests/cpp/redis_mongodb_test.cc index ff0e7c4f6..a5417cadb 100644 --- a/src/tests/cpp/redis_mongodb_test.cc +++ b/src/tests/cpp/redis_mongodb_test.cc @@ -14,6 +14,7 @@ #include "MettaMapping.h" #include "MockAnimalsData.h" #include "Node.h" +#include "ProtectedAtomDB.h" #include "RedisMongoDB.h" #include "TestAtomDBJsonConfig.h" #include "UntypedVariable.h" @@ -89,7 +90,7 @@ TEST_F(RedisMongoDBTest, ConcurrentQueryForPattern) { auto worker = [&](int thread_id) { try { auto link_schema = new LinkSchemaHandle("e8ca47108af6d35664f8813e1f96c5fa"); - auto handle_set = db->query_for_pattern(*link_schema); + auto handle_set = db->query_for_pattern(*link_schema, ""); ASSERT_NE(handle_set, nullptr); ASSERT_EQ(handle_set->size(), 3); success_count++; @@ -111,7 +112,7 @@ TEST_F(RedisMongoDBTest, ConcurrentQueryForPattern) { // Test non-existing pattern auto link_schema = new LinkSchemaHandle("00000000000000000000000000000000"); - auto handle_set = db->query_for_pattern(*link_schema); + auto handle_set = db->query_for_pattern(*link_schema, ""); delete link_schema; EXPECT_EQ(handle_set->size(), 0); } @@ -123,7 +124,7 @@ TEST_F(RedisMongoDBTest, ConcurrentQueryForTargets) { auto worker = [&](int thread_id) { try { - auto targets = db->query_for_targets("68ea071c32d4dbf0a7d8e8e00f2fb823"); + auto targets = db->query_for_targets("68ea071c32d4dbf0a7d8e8e00f2fb823", ""); ASSERT_NE(targets, nullptr); ASSERT_EQ(targets->size(), 3); success_count++; @@ -143,7 +144,7 @@ TEST_F(RedisMongoDBTest, ConcurrentQueryForTargets) { EXPECT_EQ(success_count, num_threads); // Test non-existing link - auto targets = db->query_for_targets("00000000000000000000000000000000"); + auto targets = db->query_for_targets("00000000000000000000000000000000", ""); EXPECT_EQ(targets, nullptr); } @@ -236,7 +237,7 @@ TEST_F(RedisMongoDBTest, ConcurrentLinkExists) { auto worker = [&](int thread_id) { try { - auto link_exists = db->link_exists("68ea071c32d4dbf0a7d8e8e00f2fb823"); + auto link_exists = db->link_exists("68ea071c32d4dbf0a7d8e8e00f2fb823", ""); ASSERT_TRUE(link_exists); success_count++; } catch (const exception& e) { @@ -255,7 +256,7 @@ TEST_F(RedisMongoDBTest, ConcurrentLinkExists) { EXPECT_EQ(success_count, num_threads); // Test non-existing link - auto link_exists = db->link_exists("00000000000000000000000000000000"); + auto link_exists = db->link_exists("00000000000000000000000000000000", ""); EXPECT_FALSE(link_exists); } @@ -268,7 +269,8 @@ TEST_F(RedisMongoDBTest, ConcurrentLinksExist) { try { auto links_exist = db->links_exist({"68ea071c32d4dbf0a7d8e8e00f2fb823", "00000000000000000000000000000000", - "7ec8526b8c8f15a6ac55273fedbf694f"}); + "7ec8526b8c8f15a6ac55273fedbf694f"}, + ""); ASSERT_EQ(links_exist.size(), 2); success_count++; } catch (const exception& e) { @@ -289,7 +291,8 @@ TEST_F(RedisMongoDBTest, ConcurrentLinksExist) { // Test non-existing link auto links_exist = db->links_exist({"00000000000000000000000000000000", "00000000000000000000000000000001", - "00000000000000000000000000000002"}); + "00000000000000000000000000000002"}, + ""); EXPECT_EQ(links_exist.size(), 0); } @@ -305,26 +308,26 @@ TEST_F(RedisMongoDBTest, ConcurrentAddNodesAndLinks) { auto link_node = new Node("Symbol", "link-" + to_string(thread_id)); auto link = new Link("Expression", {link_node->handle(), n1->handle(), n2->handle()}); - db->add_node(n1); - db->add_node(n2); - db->add_node(link_node); + db->add_node(n1, ""); + db->add_node(n2, ""); + db->add_node(link_node, ""); - db->add_link(link); + db->add_link(link, ""); - ASSERT_TRUE(db->node_exists(n1->handle())); - ASSERT_TRUE(db->node_exists(n2->handle())); - ASSERT_TRUE(db->node_exists(link_node->handle())); - ASSERT_TRUE(db->link_exists(link->handle())); + ASSERT_TRUE(db->node_exists(n1->handle(), "")); + ASSERT_TRUE(db->node_exists(n2->handle(), "")); + ASSERT_TRUE(db->node_exists(link_node->handle(), "")); + ASSERT_TRUE(db->link_exists(link->handle(), "")); - EXPECT_TRUE(db->delete_atom(link->handle())); - EXPECT_TRUE(db->delete_atom(link_node->handle())); - EXPECT_TRUE(db->delete_atom(n1->handle())); - EXPECT_TRUE(db->delete_atom(n2->handle())); + EXPECT_TRUE(db->delete_atom(link->handle(), "")); + EXPECT_TRUE(db->delete_atom(link_node->handle(), "")); + EXPECT_TRUE(db->delete_atom(n1->handle(), "")); + EXPECT_TRUE(db->delete_atom(n2->handle(), "")); - ASSERT_FALSE(db->link_exists(link->handle())); - ASSERT_FALSE(db->link_exists(link_node->handle())); - ASSERT_FALSE(db->node_exists(n1->handle())); - ASSERT_FALSE(db->node_exists(n2->handle())); + ASSERT_FALSE(db->link_exists(link->handle(), "")); + ASSERT_FALSE(db->link_exists(link_node->handle(), "")); + ASSERT_FALSE(db->node_exists(n1->handle(), "")); + ASSERT_FALSE(db->node_exists(n2->handle(), "")); success_count++; } catch (const exception& e) { @@ -354,20 +357,20 @@ TEST_F(RedisMongoDBTest, AddGetAndDeleteNode) { // Check if node exists, if so, delete it auto node_document = db->get_atom_document(node_handle); if (node_document != nullptr) { - auto deleted = db->delete_atom(node_handle.c_str()); + auto deleted = db->delete_atom(node_handle.c_str(), ""); EXPECT_TRUE(deleted); } - auto handle = db->add_node(node); + auto handle = db->add_node(node, ""); EXPECT_NE(handle, ""); - auto fetched_atom = db->get_atom(handle); - auto fetched_node = db->get_node(handle); + auto fetched_atom = db->get_atom(handle, ""); + auto fetched_node = db->get_node(handle, ""); ASSERT_NE(fetched_atom, nullptr); ASSERT_NE(fetched_node, nullptr); - auto deleted = db->delete_atom(handle); + auto deleted = db->delete_atom(handle, ""); EXPECT_TRUE(deleted); } @@ -377,13 +380,13 @@ TEST_F(RedisMongoDBTest, AddAndDeleteNodes) { nodes.push_back(new Node("Symbol", "add-nodes-" + to_string(i))); } - auto handles = db->add_nodes(nodes); + auto handles = db->add_nodes(nodes, ""); EXPECT_EQ(handles.size(), 10); auto nodes_documents = db->get_atom_documents(handles, {"_id"}); EXPECT_EQ(nodes_documents.size(), 10); - auto deleted = db->delete_atoms(handles); + auto deleted = db->delete_atoms(handles, ""); EXPECT_EQ(deleted, 10); auto nodes_documents_after_delete = db->get_atom_documents(handles, {"_id"}); @@ -401,8 +404,8 @@ TEST_F(RedisMongoDBTest, AddGetAndDeleteLink) { auto test_1_node = decoder.add_atom(make_shared(symbol, "\"test-1\"")); auto test_2_node = decoder.add_atom(make_shared(symbol, "\"test-2\"")); - auto test_1_node_handle = db->add_node((Node*) test_1_node.get()); - auto test_2_node_handle = db->add_node((Node*) test_2_node.get()); + auto test_1_node_handle = db->add_node((Node*) test_1_node.get(), ""); + auto test_2_node_handle = db->add_node((Node*) test_2_node.get(), ""); bool is_toplevel = true; @@ -413,26 +416,26 @@ TEST_F(RedisMongoDBTest, AddGetAndDeleteLink) { auto link_handle = link->handle(); // Check if link exists, if so, delete it - auto link_exists = db->link_exists(link_handle.c_str()); + auto link_exists = db->link_exists(link_handle.c_str(), ""); if (link_exists) { - auto deleted = db->delete_atom(link_handle.c_str()); + auto deleted = db->delete_atom(link_handle.c_str(), ""); EXPECT_TRUE(deleted); } - auto handle = db->add_link(link); + auto handle = db->add_link(link, ""); EXPECT_NE(handle, ""); - auto fetched_atom = db->get_atom(handle); - auto fetched_link = db->get_link(handle); + auto fetched_atom = db->get_atom(handle, ""); + auto fetched_link = db->get_link(handle, ""); ASSERT_NE(fetched_atom, nullptr); ASSERT_NE(fetched_link, nullptr); auto link_document = db->get_atom_document(handle); - EXPECT_TRUE(db->delete_atom(handle)); - EXPECT_TRUE(db->delete_atom(test_1_node_handle)); - EXPECT_TRUE(db->delete_atom(test_2_node_handle)); + EXPECT_TRUE(db->delete_atom(handle, "")); + EXPECT_TRUE(db->delete_atom(test_1_node_handle, "")); + EXPECT_TRUE(db->delete_atom(test_2_node_handle, "")); } TEST_F(RedisMongoDBTest, AddAndDeleteLinks) { @@ -444,24 +447,24 @@ TEST_F(RedisMongoDBTest, AddAndDeleteLinks) { for (int i = 0; i < 10; i++) { auto test_1_node = decoder.add_atom(make_shared("Symbol", "add-links-1-" + to_string(i))); auto test_2_node = decoder.add_atom(make_shared("Symbol", "add-links-2-" + to_string(i))); - test_node_handles.push_back(db->add_node((Node*) test_1_node.get())); - test_node_handles.push_back(db->add_node((Node*) test_2_node.get())); + test_node_handles.push_back(db->add_node((Node*) test_1_node.get(), "")); + test_node_handles.push_back(db->add_node((Node*) test_2_node.get(), "")); links.push_back(new Link( "Expression", {similarity_node->handle(), test_1_node->handle(), test_2_node->handle()})); } - auto handles = db->add_links(links); + auto handles = db->add_links(links, ""); EXPECT_EQ(handles.size(), 10); - auto links_exist = db->links_exist(handles); + auto links_exist = db->links_exist(handles, ""); EXPECT_EQ(links_exist.size(), 10); - EXPECT_EQ(db->delete_atoms(handles), 10); + EXPECT_EQ(db->delete_atoms(handles, ""), 10); - auto links_exist_after_delete = db->links_exist(handles); + auto links_exist_after_delete = db->links_exist(handles, ""); EXPECT_EQ(links_exist_after_delete.size(), 0); - EXPECT_EQ(db->delete_nodes(test_node_handles), test_node_handles.size()); + EXPECT_EQ(db->delete_nodes(test_node_handles, ""), test_node_handles.size()); } TEST_F(RedisMongoDBTest, DeleteNodesAndLinks) { @@ -479,27 +482,27 @@ TEST_F(RedisMongoDBTest, DeleteNodesAndLinks) { "Expression", {similarity_node->handle(), test_1_node->handle(), test_2_node->handle()})); } - auto nodes_handles = db->add_nodes(nodes); + auto nodes_handles = db->add_nodes(nodes, ""); EXPECT_EQ(nodes_handles.size(), nodes.size()); - auto nodes_exist = db->nodes_exist(nodes_handles); + auto nodes_exist = db->nodes_exist(nodes_handles, ""); EXPECT_EQ(nodes_exist.size(), nodes.size()); - auto links_handles = db->add_links(links); + auto links_handles = db->add_links(links, ""); EXPECT_EQ(links_handles.size(), links.size()); - auto links_exist = db->links_exist(links_handles); + auto links_exist = db->links_exist(links_handles, ""); EXPECT_EQ(links_exist.size(), links.size()); - EXPECT_EQ(db->delete_links(links_handles), links.size()); + EXPECT_EQ(db->delete_links(links_handles, ""), links.size()); // Deleting nodes first will delete the links (via incoming set deletion, as nodes are referenced by // links). - EXPECT_EQ(db->delete_nodes(nodes_handles), nodes.size()); + EXPECT_EQ(db->delete_nodes(nodes_handles, ""), nodes.size()); - auto nodes_exist_after_delete = db->nodes_exist(nodes_handles); + auto nodes_exist_after_delete = db->nodes_exist(nodes_handles, ""); EXPECT_EQ(nodes_exist_after_delete.size(), 0); - auto links_exist_after_delete = db->links_exist(links_handles); + auto links_exist_after_delete = db->links_exist(links_handles, ""); EXPECT_EQ(links_exist_after_delete.size(), 0); } @@ -507,22 +510,22 @@ TEST_F(RedisMongoDBTest, DeleteLinkAndDeleteItsTargets) { vector nodes_handles; auto link_name_node = new Node("Symbol", "TestLinkName"); - nodes_handles.push_back(db->add_node(link_name_node)); + nodes_handles.push_back(db->add_node(link_name_node, "")); auto test_1_node = new Node("Symbol", "del-links-1"); - nodes_handles.push_back(db->add_node(test_1_node)); + nodes_handles.push_back(db->add_node(test_1_node, "")); auto test_2_node = new Node("Symbol", "del-links-2"); - nodes_handles.push_back(db->add_node(test_2_node)); + nodes_handles.push_back(db->add_node(test_2_node, "")); auto link = new Link("Expression", {link_name_node->handle(), test_1_node->handle(), test_2_node->handle()}); - auto link_handle = db->add_link(link); + auto link_handle = db->add_link(link, ""); - EXPECT_TRUE(db->delete_link(link_handle)); - EXPECT_FALSE(db->link_exists(link_handle)); + EXPECT_TRUE(db->delete_link(link_handle, "")); + EXPECT_FALSE(db->link_exists(link_handle, "")); - EXPECT_EQ(db->delete_nodes(nodes_handles), 3); - EXPECT_EQ(db->nodes_exist(nodes_handles).size(), 0); + EXPECT_EQ(db->delete_nodes(nodes_handles, ""), 3); + EXPECT_EQ(db->nodes_exist(nodes_handles, "").size(), 0); } TEST_F(RedisMongoDBTest, DeleteLinkWithNestedLink) { @@ -531,46 +534,46 @@ TEST_F(RedisMongoDBTest, DeleteLinkWithNestedLink) { vector handles; auto link_node = new Node("Symbol", "TestLink"); - handles.push_back(db->add_node(link_node)); + handles.push_back(db->add_node(link_node, "")); auto nested_link_node_1 = new Node("Symbol", "TestNestedLink1"); - handles.push_back(db->add_node(nested_link_node_1)); + handles.push_back(db->add_node(nested_link_node_1, "")); auto nested_link_node_2 = new Node("Symbol", "TestNestedLink2"); - handles.push_back(db->add_node(nested_link_node_2)); + handles.push_back(db->add_node(nested_link_node_2, "")); auto n1_node = new Node("Symbol", "N1"); - handles.push_back(db->add_node(n1_node)); + handles.push_back(db->add_node(n1_node, "")); auto n2_node = new Node("Symbol", "N2"); - handles.push_back(db->add_node(n2_node)); + handles.push_back(db->add_node(n2_node, "")); auto n3_node = new Node("Symbol", "N3"); - handles.push_back(db->add_node(n3_node)); + handles.push_back(db->add_node(n3_node, "")); auto n4_node = new Node("Symbol", "N4"); - handles.push_back(db->add_node(n4_node)); + handles.push_back(db->add_node(n4_node, "")); auto nested_link_2 = new Link("Expression", {nested_link_node_2->handle(), n1_node->handle(), n2_node->handle()}); - handles.push_back(db->add_link(nested_link_2)); + handles.push_back(db->add_link(nested_link_2, "")); auto nested_link_1 = new Link( "Expression", {nested_link_node_1->handle(), nested_link_2->handle(), n3_node->handle()}); - handles.push_back(db->add_link(nested_link_1)); + handles.push_back(db->add_link(nested_link_1, "")); auto link = new Link("Expression", {link_node->handle(), nested_link_1->handle(), n4_node->handle()}); - handles.push_back(db->add_link(link)); + handles.push_back(db->add_link(link, "")); // Delete nested_link_1 means deleting link but not nested_link_2. - EXPECT_TRUE(db->delete_link(nested_link_1->handle())); - EXPECT_FALSE(db->link_exists(link->handle())); - EXPECT_FALSE(db->link_exists(nested_link_1->handle())); - EXPECT_TRUE(db->link_exists(nested_link_2->handle())); + EXPECT_TRUE(db->delete_link(nested_link_1->handle(), "")); + EXPECT_FALSE(db->link_exists(link->handle(), "")); + EXPECT_FALSE(db->link_exists(nested_link_1->handle(), "")); + EXPECT_TRUE(db->link_exists(nested_link_2->handle(), "")); // Before delete: 7 nodes + 3 links // After delete: 7 nodes + 1 link (nested_link_2) - EXPECT_EQ(db->atoms_exist(handles).size(), 8); + EXPECT_EQ(db->atoms_exist(handles, "").size(), 8); - db->delete_atoms(handles); - EXPECT_EQ(db->atoms_exist(handles).size(), 0); + db->delete_atoms(handles, ""); + EXPECT_EQ(db->atoms_exist(handles, "").size(), 0); } TEST_F(RedisMongoDBTest, DeleteLinkWithNestedLinkAndDeleteTargets) { @@ -579,37 +582,37 @@ TEST_F(RedisMongoDBTest, DeleteLinkWithNestedLinkAndDeleteTargets) { vector handles; auto link_node = new Node("Symbol", "TestLink"); - handles.push_back(db->add_node(link_node)); + handles.push_back(db->add_node(link_node, "")); auto nested_link_node_1 = new Node("Symbol", "TestNestedLink1"); - handles.push_back(db->add_node(nested_link_node_1)); + handles.push_back(db->add_node(nested_link_node_1, "")); auto nested_link_node_2 = new Node("Symbol", "TestNestedLink2"); - handles.push_back(db->add_node(nested_link_node_2)); + handles.push_back(db->add_node(nested_link_node_2, "")); auto n1_node = new Node("Symbol", "N1"); - handles.push_back(db->add_node(n1_node)); + handles.push_back(db->add_node(n1_node, "")); auto n2_node = new Node("Symbol", "N2"); - handles.push_back(db->add_node(n2_node)); + handles.push_back(db->add_node(n2_node, "")); auto n3_node = new Node("Symbol", "N3"); - handles.push_back(db->add_node(n3_node)); + handles.push_back(db->add_node(n3_node, "")); auto n4_node = new Node("Symbol", "N4"); - handles.push_back(db->add_node(n4_node)); + handles.push_back(db->add_node(n4_node, "")); auto nested_link_2 = new Link("Expression", {nested_link_node_2->handle(), n1_node->handle(), n2_node->handle()}); - handles.push_back(db->add_link(nested_link_2)); + handles.push_back(db->add_link(nested_link_2, "")); auto nested_link_1 = new Link( "Expression", {nested_link_node_1->handle(), nested_link_2->handle(), n3_node->handle()}); - handles.push_back(db->add_link(nested_link_1)); + handles.push_back(db->add_link(nested_link_1, "")); auto link = new Link("Expression", {link_node->handle(), nested_link_1->handle(), n4_node->handle()}); - handles.push_back(db->add_link(link)); + handles.push_back(db->add_link(link, "")); // Delete nested_link_1 and its targets means deleting link and nested_link_2 (recursively). - EXPECT_TRUE(db->delete_link(nested_link_1->handle(), true)); - EXPECT_EQ(db->atoms_exist(handles).size(), 0); + EXPECT_TRUE(db->delete_link(nested_link_1->handle(), "", true)); + EXPECT_EQ(db->atoms_exist(handles, "").size(), 0); } TEST_F(RedisMongoDBTest, DeleteLinkWithTargetsUsedByOtherLinks) { @@ -617,26 +620,26 @@ TEST_F(RedisMongoDBTest, DeleteLinkWithTargetsUsedByOtherLinks) { // This node is referenced by other links. auto similarity_node = new Node("Symbol", "Similarity"); - auto handle_set = db->query_for_incoming_set(similarity_node->handle()); + auto handle_set = db->query_for_incoming_set(similarity_node->handle(), ""); EXPECT_EQ(handle_set->size(), 15); auto test_1_node = new Node("Symbol", "Test1"); auto test_2_node = new Node("Symbol", "Test2"); - handles.push_back(db->add_node(test_1_node)); - handles.push_back(db->add_node(test_2_node)); + handles.push_back(db->add_node(test_1_node, "")); + handles.push_back(db->add_node(test_2_node, "")); auto link = new Link("Expression", {similarity_node->handle(), test_1_node->handle(), test_2_node->handle()}); - handles.push_back(db->add_link(link)); + handles.push_back(db->add_link(link, "")); - handle_set = db->query_for_incoming_set(similarity_node->handle()); + handle_set = db->query_for_incoming_set(similarity_node->handle(), ""); EXPECT_EQ(handle_set->size(), 16); - EXPECT_TRUE(db->delete_link(link->handle(), true)); - handle_set = db->query_for_incoming_set(similarity_node->handle()); + EXPECT_TRUE(db->delete_link(link->handle(), "", true)); + handle_set = db->query_for_incoming_set(similarity_node->handle(), ""); EXPECT_EQ(handle_set->size(), 15); - EXPECT_EQ(db->atoms_exist(handles).size(), 0); + EXPECT_EQ(db->atoms_exist(handles, "").size(), 0); } TEST_F(RedisMongoDBTest, QueryForIncomingSet) { @@ -646,27 +649,27 @@ TEST_F(RedisMongoDBTest, QueryForIncomingSet) { auto n1 = new Node("Symbol", "N1"); auto n2 = new Node("Symbol", "N2"); - handles.push_back(db->add_node(symbol)); - handles.push_back(db->add_node(n1)); - handles.push_back(db->add_node(n2)); + handles.push_back(db->add_node(symbol, "")); + handles.push_back(db->add_node(n1, "")); + handles.push_back(db->add_node(n2, "")); auto link_1 = new Link("Expression", {symbol->handle(), n1->handle(), n2->handle()}); auto link_2 = new Link("Expression", {symbol->handle(), n2->handle(), n1->handle()}); - handles.push_back(db->add_link(link_1)); - handles.push_back(db->add_link(link_2)); + handles.push_back(db->add_link(link_1, "")); + handles.push_back(db->add_link(link_2, "")); - auto handle_set = db->query_for_incoming_set(symbol->handle()); + auto handle_set = db->query_for_incoming_set(symbol->handle(), ""); EXPECT_EQ(handle_set->size(), 2); - EXPECT_TRUE(db->delete_link(link_1->handle())); - handle_set = db->query_for_incoming_set(symbol->handle()); + EXPECT_TRUE(db->delete_link(link_1->handle(), "")); + handle_set = db->query_for_incoming_set(symbol->handle(), ""); EXPECT_EQ(handle_set->size(), 1); - EXPECT_TRUE(db->delete_link(link_2->handle(), true)); - handle_set = db->query_for_incoming_set(symbol->handle()); + EXPECT_TRUE(db->delete_link(link_2->handle(), "", true)); + handle_set = db->query_for_incoming_set(symbol->handle(), ""); EXPECT_EQ(handle_set->size(), 0); - EXPECT_EQ(db->atoms_exist(handles).size(), 0); + EXPECT_EQ(db->atoms_exist(handles, "").size(), 0); } TEST_F(RedisMongoDBTest, QueryForSimilarityIncomingSet) { @@ -674,25 +677,25 @@ TEST_F(RedisMongoDBTest, QueryForSimilarityIncomingSet) { // This node is referenced by other links. auto similarity = new Node("Symbol", "Similarity"); - auto handle_set = db->query_for_incoming_set(similarity->handle()); + auto handle_set = db->query_for_incoming_set(similarity->handle(), ""); EXPECT_EQ(handle_set->size(), 15); auto n1 = new Node("Symbol", "N1"); auto n2 = new Node("Symbol", "N2"); - handles.push_back(db->add_node(n1)); - handles.push_back(db->add_node(n2)); + handles.push_back(db->add_node(n1, "")); + handles.push_back(db->add_node(n2, "")); auto link = new Link("Expression", {similarity->handle(), n1->handle(), n2->handle()}); - handles.push_back(db->add_link(link)); + handles.push_back(db->add_link(link, "")); - handle_set = db->query_for_incoming_set(similarity->handle()); + handle_set = db->query_for_incoming_set(similarity->handle(), ""); EXPECT_EQ(handle_set->size(), 16); - EXPECT_TRUE(db->delete_link(link->handle(), true)); - handle_set = db->query_for_incoming_set(similarity->handle()); + EXPECT_TRUE(db->delete_link(link->handle(), "", true)); + handle_set = db->query_for_incoming_set(similarity->handle(), ""); EXPECT_EQ(handle_set->size(), 15); - EXPECT_EQ(db->atoms_exist(handles).size(), 0); + EXPECT_EQ(db->atoms_exist(handles, "").size(), 0); } TEST_F(RedisMongoDBTest, AddLinkAndQueryForSimilarityPattern) { @@ -700,49 +703,49 @@ TEST_F(RedisMongoDBTest, AddLinkAndQueryForSimilarityPattern) { // (Similarity * *) auto similarity_link_schema = new LinkSchemaHandle("dabd1f087cf4a9739911c0385fae0819"); - auto handle_set = db->query_for_pattern(*similarity_link_schema); + auto handle_set = db->query_for_pattern(*similarity_link_schema, ""); EXPECT_EQ(handle_set->size(), 14); auto symbol = new Node("Symbol", "Similarity"); auto n1 = new Node("Symbol", "N1"); auto n2 = new Node("Symbol", "N2"); - handles.push_back(db->add_node(n1)); - handles.push_back(db->add_node(n2)); + handles.push_back(db->add_node(n1, "")); + handles.push_back(db->add_node(n2, "")); auto link_1 = new Link("Expression", {symbol->handle(), n1->handle(), n2->handle()}); auto link_2 = new Link("Expression", {symbol->handle(), n2->handle(), n1->handle()}); - handles.push_back(db->add_link(link_1)); - handles.push_back(db->add_link(link_2)); + handles.push_back(db->add_link(link_1, "")); + handles.push_back(db->add_link(link_2, "")); // (Similarity * *) must have 2 more links - handle_set = db->query_for_pattern(*similarity_link_schema); + handle_set = db->query_for_pattern(*similarity_link_schema, ""); EXPECT_EQ(handle_set->size(), 16); - EXPECT_TRUE(db->delete_link(link_1->handle())); - handle_set = db->query_for_pattern(*similarity_link_schema); + EXPECT_TRUE(db->delete_link(link_1->handle(), "")); + handle_set = db->query_for_pattern(*similarity_link_schema, ""); EXPECT_EQ(handle_set->size(), 15); - EXPECT_TRUE(db->delete_link(link_2->handle(), true)); - handle_set = db->query_for_pattern(*similarity_link_schema); + EXPECT_TRUE(db->delete_link(link_2->handle(), "", true)); + handle_set = db->query_for_pattern(*similarity_link_schema, ""); EXPECT_EQ(handle_set->size(), 14); - EXPECT_EQ(db->atoms_exist(handles).size(), 0); + EXPECT_EQ(db->atoms_exist(handles, "").size(), 0); } TEST_F(RedisMongoDBTest, GetAtomWithCustomAttributes) { auto node_with_no_custom_attributes = new Node("Symbol", "NodeWithNoCustomAttributes"); - db->add_node(node_with_no_custom_attributes); - auto atom_with_no_custom_attributes = db->get_atom(node_with_no_custom_attributes->handle()); + db->add_node(node_with_no_custom_attributes, ""); + auto atom_with_no_custom_attributes = db->get_atom(node_with_no_custom_attributes->handle(), ""); EXPECT_EQ(atom_with_no_custom_attributes->custom_attributes.empty(), true); - EXPECT_EQ(db->delete_atom(node_with_no_custom_attributes->handle()), true); + EXPECT_EQ(db->delete_atom(node_with_no_custom_attributes->handle(), ""), true); Properties custom_attributes( {{"key_string", "string"}, {"key_long", 1}, {"key_double", 1.55}, {"key_bool", true}}); auto node_with_custom_attributes = new Node("Symbol", "NodeWithCustomAttributes", custom_attributes); - db->add_node(node_with_custom_attributes); + db->add_node(node_with_custom_attributes, ""); - auto atom_with_custom_attributes = db->get_atom(node_with_custom_attributes->handle()); + auto atom_with_custom_attributes = db->get_atom(node_with_custom_attributes->handle(), ""); const string* string_value = atom_with_custom_attributes->custom_attributes.get_ptr("key_string"); @@ -755,16 +758,16 @@ TEST_F(RedisMongoDBTest, GetAtomWithCustomAttributes) { const bool* bool_value = atom_with_custom_attributes->custom_attributes.get_ptr("key_bool"); EXPECT_EQ(*bool_value, true); - EXPECT_EQ(db->delete_atom(node_with_custom_attributes->handle()), true); + EXPECT_EQ(db->delete_atom(node_with_custom_attributes->handle(), ""), true); // MongoDB does not support unsigned int. Properties custom_attributes_2({{"key_unsigned_int", 1U}}); auto node_with_custom_attributes_2 = new Node("Symbol", "NodeWithCustomAttributes2", custom_attributes_2); try { - db->add_node(node_with_custom_attributes_2); + db->add_node(node_with_custom_attributes_2, ""); } catch (const exception& e) { - EXPECT_EQ(db->node_exists(node_with_custom_attributes_2->handle()), false); + EXPECT_EQ(db->node_exists(node_with_custom_attributes_2->handle(), ""), false); } } @@ -774,7 +777,7 @@ TEST_F(RedisMongoDBTest, ReIndexPatterns) { auto similarity_pattern = new Link( "Expression", {similarity_node->handle(), Atom::WILDCARD_STRING, Atom::WILDCARD_STRING}); auto similarity_link_schema = new LinkSchemaHandle(similarity_pattern->handle().c_str()); - auto handle_set = db->query_for_pattern(*similarity_link_schema); + auto handle_set = db->query_for_pattern(*similarity_link_schema, ""); EXPECT_EQ(handle_set->size(), 14); // (Inheritance * *) @@ -782,38 +785,38 @@ TEST_F(RedisMongoDBTest, ReIndexPatterns) { auto inheritance_pattern = new Link( "Expression", {inheritance_node->handle(), Atom::WILDCARD_STRING, Atom::WILDCARD_STRING}); auto inheritance_link_schema = new LinkSchemaHandle(inheritance_pattern->handle().c_str()); - handle_set = db->query_for_pattern(*inheritance_link_schema); + handle_set = db->query_for_pattern(*inheritance_link_schema, ""); EXPECT_EQ(handle_set->size(), 12); // (OddLink * *) auto odd_link_node = new Node("Symbol", "OddLink"); auto odd_link_pattern = new Link("Expression", {odd_link_node->handle(), Atom::WILDCARD_STRING}); auto odd_link_schema = new LinkSchemaHandle(odd_link_pattern->handle().c_str()); - handle_set = db->query_for_pattern(*odd_link_schema); + handle_set = db->query_for_pattern(*odd_link_schema, ""); EXPECT_EQ(handle_set->size(), 9); // Flush Redis patterns indexes db->flush_redis_by_prefix("test_patterns"); - handle_set = db->query_for_pattern(*similarity_link_schema); + handle_set = db->query_for_pattern(*similarity_link_schema, ""); EXPECT_EQ(handle_set->size(), 0); - handle_set = db->query_for_pattern(*inheritance_link_schema); + handle_set = db->query_for_pattern(*inheritance_link_schema, ""); EXPECT_EQ(handle_set->size(), 0); - handle_set = db->query_for_pattern(*odd_link_schema); + handle_set = db->query_for_pattern(*odd_link_schema, ""); EXPECT_EQ(handle_set->size(), 0); // Clear Redis patterns indexes and re-index them - db->re_index_patterns(); + db->re_index_patterns(""); - handle_set = db->query_for_pattern(*similarity_link_schema); + handle_set = db->query_for_pattern(*similarity_link_schema, ""); EXPECT_EQ(handle_set->size(), 14); - handle_set = db->query_for_pattern(*inheritance_link_schema); + handle_set = db->query_for_pattern(*inheritance_link_schema, ""); EXPECT_EQ(handle_set->size(), 12); - handle_set = db->query_for_pattern(*odd_link_schema); + handle_set = db->query_for_pattern(*odd_link_schema, ""); EXPECT_EQ(handle_set->size(), 9); } @@ -822,19 +825,19 @@ TEST_F(RedisMongoDBTest, GetMatchingAtoms) { auto human_node = new Node("Symbol", "\"human\""); auto monkey_node = new Node("Symbol", "\"monkey\""); - auto matching_atoms = db->get_matching_atoms(false, *similarity_node); + auto matching_atoms = db->get_matching_atoms(false, *similarity_node, ""); EXPECT_EQ(matching_atoms.size(), 1); string named_type = matching_atoms[0]->type; EXPECT_EQ(named_type, string("Symbol")); - matching_atoms = db->get_matching_atoms(true, *similarity_node); + matching_atoms = db->get_matching_atoms(true, *similarity_node, ""); EXPECT_EQ(matching_atoms.size(), 0); auto link = new Link("Expression", {similarity_node->handle(), human_node->handle(), monkey_node->handle()}); - matching_atoms = db->get_matching_atoms(true, *link); + matching_atoms = db->get_matching_atoms(true, *link, ""); EXPECT_EQ(matching_atoms.size(), 1); - matching_atoms = db->get_matching_atoms(false, *link); + matching_atoms = db->get_matching_atoms(false, *link, ""); EXPECT_EQ(matching_atoms.size(), 0); auto link_document = db->get_atom_document(link->handle()); @@ -844,30 +847,30 @@ TEST_F(RedisMongoDBTest, GetMatchingAtoms) { auto all_links = db->get_filtered_documents(RedisMongoDB::MONGODB_LINKS_COLLECTION_NAME, {}, {}); auto untyped_variable = new UntypedVariable("V1", true); - matching_atoms = db->get_matching_atoms(false, *untyped_variable); + matching_atoms = db->get_matching_atoms(false, *untyped_variable, ""); // Nodes are is_toplevel = false EXPECT_EQ(matching_atoms.size(), all_nodes.size()); - matching_atoms = db->get_matching_atoms(true, *untyped_variable); + matching_atoms = db->get_matching_atoms(true, *untyped_variable, ""); // Links are is_toplevel = true EXPECT_EQ(matching_atoms.size(), all_links.size()); auto test_node = new Node("Symbol", "\"test\""); - db->add_node(test_node); + db->add_node(test_node, ""); bool is_toplevel = true; auto top_level_link = new Link("Expression", {similarity_node->handle(), human_node->handle(), test_node->handle()}, is_toplevel); - db->add_link(top_level_link); + db->add_link(top_level_link, ""); - matching_atoms = db->get_matching_atoms(is_toplevel, *top_level_link); + matching_atoms = db->get_matching_atoms(is_toplevel, *top_level_link, ""); EXPECT_EQ(matching_atoms.size(), 1); auto top_level_link_document = db->get_atom_document(top_level_link->handle()); EXPECT_EQ(top_level_link_document->get_bool("is_toplevel"), is_toplevel); - EXPECT_EQ(db->delete_atom(test_node->handle()), true); + EXPECT_EQ(db->delete_atom(test_node->handle(), ""), true); } TEST_F(RedisMongoDBTest, UpdateAtom) { @@ -876,7 +879,7 @@ TEST_F(RedisMongoDBTest, UpdateAtom) { nodes.push_back(new Node("Symbol", "UpdateAtom2")); nodes.push_back(new Node("Symbol", "UpdateAtom3")); - vector node_handles = db->add_nodes(nodes); + vector node_handles = db->add_nodes(nodes, ""); EXPECT_EQ(node_handles.size(), 3); // Node 1 has no custom attributes @@ -888,7 +891,7 @@ TEST_F(RedisMongoDBTest, UpdateAtom) { custom_attributes["field1"] = string("value1"); // Update Node 1 with custom attributes - string updated_node = db->add_node(new Node("Symbol", "UpdateAtom1", custom_attributes)); + string updated_node = db->add_node(new Node("Symbol", "UpdateAtom1", custom_attributes), ""); node1_document = dynamic_pointer_cast(db->get_atom_document(updated_node)); auto extracted_custom_attributes = @@ -896,7 +899,7 @@ TEST_F(RedisMongoDBTest, UpdateAtom) { EXPECT_EQ(extracted_custom_attributes.get("field1"), string("value1")); auto link = new Link("Expression", node_handles, custom_attributes); - string link_handle = db->add_link(link); + string link_handle = db->add_link(link, ""); auto atom_document = dynamic_pointer_cast(db->get_atom_document(link_handle)); @@ -907,7 +910,7 @@ TEST_F(RedisMongoDBTest, UpdateAtom) { // Update Link with modified custom attributes custom_attributes["field1"] = string("value2"); link = new Link("Expression", node_handles, custom_attributes); - link_handle = db->add_link(link); + link_handle = db->add_link(link, ""); atom_document = dynamic_pointer_cast(db->get_atom_document(link_handle)); @@ -915,12 +918,12 @@ TEST_F(RedisMongoDBTest, UpdateAtom) { atom_document->extract_custom_attributes(atom_document->get_object("custom_attributes")); EXPECT_EQ(extracted_custom_attributes.get("field1"), string("value2")); - EXPECT_EQ(db->delete_atom(link_handle, true), true); + EXPECT_EQ(db->delete_atom(link_handle, "", true), true); - EXPECT_EQ(db->link_exists(link_handle), false); - EXPECT_EQ(db->node_exists(node_handles[0]), false); - EXPECT_EQ(db->node_exists(node_handles[1]), false); - EXPECT_EQ(db->node_exists(node_handles[2]), false); + EXPECT_EQ(db->link_exists(link_handle, ""), false); + EXPECT_EQ(db->node_exists(node_handles[0], ""), false); + EXPECT_EQ(db->node_exists(node_handles[1], ""), false); + EXPECT_EQ(db->node_exists(node_handles[2], ""), false); } TEST_F(RedisMongoDBTest, AddSameAtomMustNotThrow) { @@ -928,50 +931,50 @@ TEST_F(RedisMongoDBTest, AddSameAtomMustNotThrow) { nodes.push_back(new Node("Symbol", "AddSameAtomMustNotThrowNode1")); nodes.push_back(new Node("Symbol", "AddSameAtomMustNotThrowNode2")); nodes.push_back(new Node("Symbol", "AddSameAtomMustNotThrowNode3")); - EXPECT_EQ(db->add_nodes(nodes).size(), 3); - EXPECT_EQ(db->add_nodes(nodes).size(), 3); + EXPECT_EQ(db->add_nodes(nodes, "").size(), 3); + EXPECT_EQ(db->add_nodes(nodes, "").size(), 3); - EXPECT_EQ(db->add_node(nodes[0]), nodes[0]->handle()); - EXPECT_EQ(db->add_node(nodes[0]), nodes[0]->handle()); + EXPECT_EQ(db->add_node(nodes[0], ""), nodes[0]->handle()); + EXPECT_EQ(db->add_node(nodes[0], ""), nodes[0]->handle()); auto link = new Link("Expression", {nodes[0]->handle(), nodes[1]->handle(), nodes[2]->handle()}); - EXPECT_EQ(db->add_link(link), link->handle()); - EXPECT_EQ(db->add_link(link), link->handle()); + EXPECT_EQ(db->add_link(link, ""), link->handle()); + EXPECT_EQ(db->add_link(link, ""), link->handle()); - EXPECT_EQ(db->add_links({link, link}).size(), 2); - EXPECT_EQ(db->add_links({link, link}).size(), 2); + EXPECT_EQ(db->add_links({link, link}, "").size(), 2); + EXPECT_EQ(db->add_links({link, link}, "").size(), 2); - EXPECT_EQ(db->delete_link(link->handle(), true), true); + EXPECT_EQ(db->delete_link(link->handle(), "", true), true); - EXPECT_EQ(db->link_exists(link->handle()), false); + EXPECT_EQ(db->link_exists(link->handle(), ""), false); for (auto node : nodes) { - EXPECT_EQ(db->node_exists(node->handle()), false); + EXPECT_EQ(db->node_exists(node->handle(), ""), false); } } TEST_F(RedisMongoDBTest, AddNodesWithThrowIfExists) { auto node1 = new Node("Symbol", "ThrowIfExists1"); - EXPECT_EQ(db->add_node(node1, true), node1->handle()); + EXPECT_EQ(db->add_node(node1, "", true), node1->handle()); vector nodes; nodes.push_back(new Node("Symbol", "ThrowIfExists2")); nodes.push_back(new Node("Symbol", "ThrowIfExists3")); - EXPECT_EQ(db->add_nodes(nodes, true).size(), 2); + EXPECT_EQ(db->add_nodes(nodes, "", true).size(), 2); auto link = new Link("Expression", {node1->handle(), nodes[0]->handle(), nodes[1]->handle()}); - EXPECT_EQ(db->add_link(link, true), link->handle()); + EXPECT_EQ(db->add_link(link, "", true), link->handle()); // Try to add the same node again - EXPECT_THROW(db->add_node(node1, true), runtime_error); - EXPECT_THROW(db->add_nodes(nodes, true), runtime_error); - EXPECT_THROW(db->add_link(link, true), runtime_error); - - EXPECT_EQ(db->delete_link(link->handle(), true), true); - EXPECT_EQ(db->link_exists(link->handle()), false); - EXPECT_EQ(db->node_exists(node1->handle()), false); - EXPECT_EQ(db->node_exists(nodes[0]->handle()), false); - EXPECT_EQ(db->node_exists(nodes[1]->handle()), false); + EXPECT_THROW(db->add_node(node1, "", true), runtime_error); + EXPECT_THROW(db->add_nodes(nodes, "", true), runtime_error); + EXPECT_THROW(db->add_link(link, "", true), runtime_error); + + EXPECT_EQ(db->delete_link(link->handle(), "", true), true); + EXPECT_EQ(db->link_exists(link->handle(), ""), false); + EXPECT_EQ(db->node_exists(node1->handle(), ""), false); + EXPECT_EQ(db->node_exists(nodes[0]->handle(), ""), false); + EXPECT_EQ(db->node_exists(nodes[1]->handle(), ""), false); } TEST_F(RedisMongoDBTest, AddLinksWithDuplicateTargets) { @@ -979,7 +982,7 @@ TEST_F(RedisMongoDBTest, AddLinksWithDuplicateTargets) { nodes.push_back(new Node("Symbol", "DuplicateTargets1")); nodes.push_back(new Node("Symbol", "DuplicateTargets2")); nodes.push_back(new Node("Symbol", "DuplicateTargets3")); - EXPECT_EQ(db->add_nodes(nodes, true).size(), 3); + EXPECT_EQ(db->add_nodes(nodes, "", true).size(), 3); auto link = new Link("Expression", {nodes[0]->handle(), @@ -989,38 +992,75 @@ TEST_F(RedisMongoDBTest, AddLinksWithDuplicateTargets) { nodes[2]->handle(), nodes[0]->handle(), nodes[2]->handle()}); - EXPECT_EQ(db->add_link(link), link->handle()); - EXPECT_EQ(db->delete_link(link->handle(), true), true); + EXPECT_EQ(db->add_link(link, ""), link->handle()); + EXPECT_EQ(db->delete_link(link->handle(), "", true), true); } TEST_F(RedisMongoDBTest, AtomsCount) { db->drop_all(); - EXPECT_EQ(db->node_count(), 0); - EXPECT_EQ(db->link_count(), 0); - EXPECT_EQ(db->atom_count(), 0); - EXPECT_EQ(db->empty(), true); + EXPECT_EQ(db->node_count(""), 0); + EXPECT_EQ(db->link_count(""), 0); + EXPECT_EQ(db->atom_count(""), 0); + EXPECT_EQ(db->empty(""), true); auto node1 = new Node("Symbol", "Node1"); auto node2 = new Node("Symbol", "Node2"); auto similarity = new Node("Symbol", "Similarity"); - db->add_node(node1, false); - db->add_node(node2, false); - db->add_node(similarity, false); + db->add_node(node1, "", false); + db->add_node(node2, "", false); + db->add_node(similarity, "", false); - EXPECT_EQ(db->node_count(), 3); - EXPECT_EQ(db->link_count(), 0); - EXPECT_EQ(db->atom_count(), 3); - EXPECT_EQ(db->empty(), false); + EXPECT_EQ(db->node_count(""), 3); + EXPECT_EQ(db->link_count(""), 0); + EXPECT_EQ(db->atom_count(""), 3); + EXPECT_EQ(db->empty(""), false); auto link1 = new Link("Expression", {similarity->handle(), node1->handle(), node2->handle()}); - db->add_link(link1, false); + db->add_link(link1, "", false); - EXPECT_EQ(db->node_count(), 3); - EXPECT_EQ(db->link_count(), 1); - EXPECT_EQ(db->atom_count(), 4); - EXPECT_EQ(db->empty(), false); + EXPECT_EQ(db->node_count(""), 3); + EXPECT_EQ(db->link_count(""), 1); + EXPECT_EQ(db->atom_count(""), 4); + EXPECT_EQ(db->empty(""), false); +} + +TEST_F(RedisMongoDBTest, ProtectionDetection) { + const string prefix = "prot_detect_"; + auto config = test_atomdb_json_config(); + + auto fresh = make_shared(prefix, false, config); + EXPECT_FALSE(fresh->is_protected()); + + auto seed_config = test_atomdb_json_config(); + seed_config["mongodb"]["seed_protected"] = true; + auto seeder = make_shared(prefix, false, seed_config); + EXPECT_TRUE(seeder->is_protected()); + EXPECT_TRUE(fresh->is_protected()); + + auto reopened = make_shared(prefix, false, config); + EXPECT_TRUE(reopened->is_protected()); + + fresh->drop_all(); +} + +TEST_F(RedisMongoDBTest, ProtectedAtomDBEmptyPublicKeyBehavior) { + // Stub wrapper: empty public_key does not delegate to the backend yet. + auto config = test_atomdb_json_config(); + config["mongodb"]["seed_protected"] = true; + auto backend = make_shared("prot_wrap_", false, config); + auto node = new Node("Symbol", "ProtectedWrapNode"); + string handle = backend->add_node(node, "", false); + ASSERT_FALSE(handle.empty()); + + auto wrapped = make_shared(backend, test_atomdb_json_config()); + EXPECT_TRUE(wrapped->is_protected()); + EXPECT_NE(backend->get_atom(handle, ""), nullptr); + EXPECT_EQ(wrapped->get_atom(handle, ""), nullptr); + EXPECT_FALSE(wrapped->atom_exists(handle, "")); + + backend->drop_all(); } TEST_F(RedisMongoDBTest, CompositeTypeEnabledFlag) { @@ -1034,11 +1074,11 @@ TEST_F(RedisMongoDBTest, CompositeTypeEnabledFlag) { vector enabled_nodes = {new Node("Symbol", "CompositeTypeEnabled-A"), new Node("Symbol", "CompositeTypeEnabled-B"), new Node("Symbol", "CompositeTypeEnabled-C")}; - ASSERT_EQ(db->add_nodes(enabled_nodes).size(), 3); + ASSERT_EQ(db->add_nodes(enabled_nodes, "").size(), 3); auto enabled_link = new Link("Expression", {enabled_nodes[0]->handle(), enabled_nodes[1]->handle(), enabled_nodes[2]->handle()}); - string enabled_link_handle = db->add_link(enabled_link); + string enabled_link_handle = db->add_link(enabled_link, ""); ASSERT_FALSE(enabled_link_handle.empty()); auto enabled_doc = db->get_atom_document(enabled_link_handle); @@ -1056,11 +1096,11 @@ TEST_F(RedisMongoDBTest, CompositeTypeEnabledFlag) { vector disabled_nodes = {new Node("Symbol", "CompositeTypeDisabled-A"), new Node("Symbol", "CompositeTypeDisabled-B"), new Node("Symbol", "CompositeTypeDisabled-C")}; - ASSERT_EQ(db_disabled->add_nodes(disabled_nodes).size(), 3); + ASSERT_EQ(db_disabled->add_nodes(disabled_nodes, "").size(), 3); auto disabled_link = new Link( "Expression", {disabled_nodes[0]->handle(), disabled_nodes[1]->handle(), disabled_nodes[2]->handle()}); - string disabled_link_handle = db_disabled->add_link(disabled_link); + string disabled_link_handle = db_disabled->add_link(disabled_link, ""); ASSERT_FALSE(disabled_link_handle.empty()); auto disabled_doc = db_disabled->get_atom_document(disabled_link_handle); @@ -1075,17 +1115,17 @@ TEST_F(RedisMongoDBTest, CompositeTypeEnabledFlag) { {transactional_nodes[0]->handle(), transactional_nodes[1]->handle(), transactional_nodes[2]->handle()}); - ASSERT_EQ(db_disabled->add_nodes(transactional_nodes, false, true).size(), 3); - ASSERT_EQ(db_disabled->add_links({transactional_link}, false, true).size(), 1); + ASSERT_EQ(db_disabled->add_nodes(transactional_nodes, "", false, true).size(), 3); + ASSERT_EQ(db_disabled->add_links({transactional_link}, "", false, true).size(), 1); auto transactional_doc = db_disabled->get_atom_document(transactional_link->handle()); ASSERT_NE(transactional_doc, nullptr); EXPECT_FALSE(transactional_doc->contains("composite_type_hash")); EXPECT_FALSE(transactional_doc->contains("composite_type")); - EXPECT_TRUE(db->delete_atom(enabled_link_handle, true)); - EXPECT_TRUE(db_disabled->delete_atom(disabled_link_handle, true)); - EXPECT_TRUE(db_disabled->delete_atom(transactional_link->handle(), true)); + EXPECT_TRUE(db->delete_atom(enabled_link_handle, "", true)); + EXPECT_TRUE(db_disabled->delete_atom(disabled_link_handle, "", true)); + EXPECT_TRUE(db_disabled->delete_atom(transactional_link->handle(), "", true)); } int main(int argc, char** argv) { diff --git a/src/tests/cpp/redis_mongodb_test_2.cc b/src/tests/cpp/redis_mongodb_test_2.cc index a2ab5398b..26fa72541 100644 --- a/src/tests/cpp/redis_mongodb_test_2.cc +++ b/src/tests/cpp/redis_mongodb_test_2.cc @@ -62,143 +62,144 @@ TEST_F(RedisMongoDBTest, AddLinksWithNoPatternIndexSchema) { vector handles; auto link_node = new Node("Symbol", "TestLink"); - handles.push_back(db2->add_node(link_node)); + handles.push_back(db2->add_node(link_node, "")); auto nested_link_node_1 = new Node("Symbol", "TestNestedLink1"); - handles.push_back(db2->add_node(nested_link_node_1)); + handles.push_back(db2->add_node(nested_link_node_1, "")); auto nested_link_node_2 = new Node("Symbol", "TestNestedLink2"); - handles.push_back(db2->add_node(nested_link_node_2)); + handles.push_back(db2->add_node(nested_link_node_2, "")); auto n1_node = new Node("Symbol", "N1"); - handles.push_back(db2->add_node(n1_node)); + handles.push_back(db2->add_node(n1_node, "")); auto n2_node = new Node("Symbol", "N2"); - handles.push_back(db2->add_node(n2_node)); + handles.push_back(db2->add_node(n2_node, "")); auto nested_link_2 = new Link("Expression", {nested_link_node_2->handle(), n1_node->handle(), n2_node->handle()}); - handles.push_back(db2->add_link(nested_link_2)); + handles.push_back(db2->add_link(nested_link_2, "")); auto nested_link_1 = new Link( "Expression", {nested_link_node_1->handle(), nested_link_2->handle(), n2_node->handle()}); - handles.push_back(db2->add_link(nested_link_1)); + handles.push_back(db2->add_link(nested_link_1, "")); auto link = new Link("Expression", {link_node->handle(), nested_link_1->handle(), n2_node->handle()}); - handles.push_back(db2->add_link(link)); + handles.push_back(db2->add_link(link, "")); // (TestNestedLink2 * *) string hash = Hasher::link_handle( "Expression", {nested_link_node_2->handle(), Atom::WILDCARD_STRING, Atom::WILDCARD_STRING}); auto link_schema = new LinkSchemaHandle(hash.c_str()); - auto handle_set = db2->query_for_pattern(*link_schema); + auto handle_set = db2->query_for_pattern(*link_schema, ""); EXPECT_EQ(handle_set->size(), 1); // (TestNestedLink1 * *) hash = Hasher::link_handle( "Expression", {nested_link_node_1->handle(), Atom::WILDCARD_STRING, Atom::WILDCARD_STRING}); link_schema = new LinkSchemaHandle(hash.c_str()); - handle_set = db2->query_for_pattern(*link_schema); + handle_set = db2->query_for_pattern(*link_schema, ""); EXPECT_EQ(handle_set->size(), 1); // (TestLinkName * *) hash = Hasher::link_handle("Expression", {link_node->handle(), Atom::WILDCARD_STRING, Atom::WILDCARD_STRING}); link_schema = new LinkSchemaHandle(hash.c_str()); - handle_set = db2->query_for_pattern(*link_schema); + handle_set = db2->query_for_pattern(*link_schema, ""); EXPECT_EQ(handle_set->size(), 1); // (* * *) hash = Hasher::link_handle("Expression", {Atom::WILDCARD_STRING, Atom::WILDCARD_STRING, Atom::WILDCARD_STRING}); link_schema = new LinkSchemaHandle(hash.c_str()); - handle_set = db2->query_for_pattern(*link_schema); + handle_set = db2->query_for_pattern(*link_schema, ""); EXPECT_EQ(handle_set->size(), 3); // (* N1 *) hash = Hasher::link_handle("Expression", {Atom::WILDCARD_STRING, n1_node->handle(), Atom::WILDCARD_STRING}); link_schema = new LinkSchemaHandle(hash.c_str()); - handle_set = db2->query_for_pattern(*link_schema); + handle_set = db2->query_for_pattern(*link_schema, ""); EXPECT_EQ(handle_set->size(), 1); // (* * N2) hash = Hasher::link_handle("Expression", {Atom::WILDCARD_STRING, Atom::WILDCARD_STRING, n2_node->handle()}); link_schema = new LinkSchemaHandle(hash.c_str()); - handle_set = db2->query_for_pattern(*link_schema); + handle_set = db2->query_for_pattern(*link_schema, ""); EXPECT_EQ(handle_set->size(), 3); // Delete nested_link_1 means deleting link but not nested_link_2. - EXPECT_TRUE(db2->delete_link(nested_link_1->handle())); - EXPECT_FALSE(db2->link_exists(link->handle())); - EXPECT_FALSE(db2->link_exists(nested_link_1->handle())); - EXPECT_TRUE(db2->link_exists(nested_link_2->handle())); + EXPECT_TRUE(db2->delete_link(nested_link_1->handle(), "")); + EXPECT_FALSE(db2->link_exists(link->handle(), "")); + EXPECT_FALSE(db2->link_exists(nested_link_1->handle(), "")); + EXPECT_TRUE(db2->link_exists(nested_link_2->handle(), "")); // Before delete: 5 nodes + 3 links // After delete: 5 nodes + 1 link (nested_link_2) - EXPECT_EQ(db2->atoms_exist(handles).size(), 6); + EXPECT_EQ(db2->atoms_exist(handles, "").size(), 6); - db2->delete_atoms(handles); - EXPECT_EQ(db2->atoms_exist(handles).size(), 0); + db2->delete_atoms(handles, ""); + EXPECT_EQ(db2->atoms_exist(handles, "").size(), 0); } TEST_F(RedisMongoDBTest, DeleteNestedLink) { // (outter (intermediate (inner a) b) c) - string node1 = db2->add_node(new Node("Symbol", "outter")); - string node2 = db2->add_node(new Node("Symbol", "intermediate")); - string node3 = db2->add_node(new Node("Symbol", "inner")); - string node4 = db2->add_node(new Node("Symbol", "a")); - string node5 = db2->add_node(new Node("Symbol", "b")); - string node6 = db2->add_node(new Node("Symbol", "c")); - string link1 = db2->add_link(new Link("Expression", {node3, node4})); - string link2 = db2->add_link(new Link("Expression", {node2, link1, node5})); - string link3 = db2->add_link(new Link("Expression", {node1, link2, node6}, true)); + string node1 = db2->add_node(new Node("Symbol", "outter"), ""); + string node2 = db2->add_node(new Node("Symbol", "intermediate"), ""); + string node3 = db2->add_node(new Node("Symbol", "inner"), ""); + string node4 = db2->add_node(new Node("Symbol", "a"), ""); + string node5 = db2->add_node(new Node("Symbol", "b"), ""); + string node6 = db2->add_node(new Node("Symbol", "c"), ""); + string link1 = db2->add_link(new Link("Expression", {node3, node4}), ""); + string link2 = db2->add_link(new Link("Expression", {node2, link1, node5}), ""); + string link3 = db2->add_link(new Link("Expression", {node1, link2, node6}, true), ""); auto link_pattern = new Link("Expression", {node1, Atom::WILDCARD_STRING, Atom::WILDCARD_STRING}); auto link_schema = new LinkSchemaHandle(link_pattern->handle().c_str()); - auto handle_set = db2->query_for_pattern(*link_schema); + auto handle_set = db2->query_for_pattern(*link_schema, ""); EXPECT_EQ(handle_set->size(), 1); - auto link3_targets = db2->query_for_targets(link3); + auto link3_targets = db2->query_for_targets(link3, ""); EXPECT_EQ(link3_targets->size(), 3); - db2->delete_link(link3, true); + db2->delete_link(link3, "", true); - handle_set = db2->query_for_pattern(*link_schema); + handle_set = db2->query_for_pattern(*link_schema, ""); EXPECT_EQ(handle_set->size(), 0); - link3_targets = db2->query_for_targets(link3); + link3_targets = db2->query_for_targets(link3, ""); EXPECT_EQ(link3_targets, nullptr); - EXPECT_FALSE(db2->node_exists(node1)); - EXPECT_FALSE(db2->node_exists(node2)); - EXPECT_FALSE(db2->node_exists(node3)); - EXPECT_FALSE(db2->node_exists(node4)); - EXPECT_FALSE(db2->node_exists(node5)); - EXPECT_FALSE(db2->node_exists(node6)); - EXPECT_FALSE(db2->link_exists(link1)); - EXPECT_FALSE(db2->link_exists(link2)); - EXPECT_FALSE(db2->link_exists(link3)); + EXPECT_FALSE(db2->node_exists(node1, "")); + EXPECT_FALSE(db2->node_exists(node2, "")); + EXPECT_FALSE(db2->node_exists(node3, "")); + EXPECT_FALSE(db2->node_exists(node4, "")); + EXPECT_FALSE(db2->node_exists(node5, "")); + EXPECT_FALSE(db2->node_exists(node6, "")); + EXPECT_FALSE(db2->link_exists(link1, "")); + EXPECT_FALSE(db2->link_exists(link2, "")); + EXPECT_FALSE(db2->link_exists(link3, "")); } TEST_F(RedisMongoDBTest, MongodbDocumentGetSize) { - string node1 = db2->add_node(new Node("Symbol", "1")); - string node2 = db2->add_node(new Node("Symbol", "2")); - string node3 = db2->add_node(new Node("Symbol", "3")); - string node4 = db2->add_node(new Node("Symbol", "4")); - string node5 = db2->add_node(new Node("Symbol", "5")); - string node6 = db2->add_node(new Node("Symbol", "6")); - string node7 = db2->add_node(new Node("Symbol", "7")); - string node8 = db2->add_node(new Node("Symbol", "8")); - string node9 = db2->add_node(new Node("Symbol", "9")); - string node10 = db2->add_node(new Node("Symbol", "10")); - - string link1 = db2->add_link(new Link("Expression", {node1, node2, node3, node4, node5})); - string link2 = db2->add_link(new Link("Expression", {node1, node2, node3, node4, node5, node6})); - string link3 = - db2->add_link(new Link("Expression", {node1, node2, node3, node4, node5, node6, node7, node8})); + string node1 = db2->add_node(new Node("Symbol", "1"), ""); + string node2 = db2->add_node(new Node("Symbol", "2"), ""); + string node3 = db2->add_node(new Node("Symbol", "3"), ""); + string node4 = db2->add_node(new Node("Symbol", "4"), ""); + string node5 = db2->add_node(new Node("Symbol", "5"), ""); + string node6 = db2->add_node(new Node("Symbol", "6"), ""); + string node7 = db2->add_node(new Node("Symbol", "7"), ""); + string node8 = db2->add_node(new Node("Symbol", "8"), ""); + string node9 = db2->add_node(new Node("Symbol", "9"), ""); + string node10 = db2->add_node(new Node("Symbol", "10"), ""); + + string link1 = db2->add_link(new Link("Expression", {node1, node2, node3, node4, node5}), ""); + string link2 = db2->add_link(new Link("Expression", {node1, node2, node3, node4, node5, node6}), ""); + string link3 = db2->add_link( + new Link("Expression", {node1, node2, node3, node4, node5, node6, node7, node8}), ""); string link4 = db2->add_link( - new Link("Expression", {node1, node2, node3, node4, node5, node6, node7, node8, node9, node10})); + new Link("Expression", {node1, node2, node3, node4, node5, node6, node7, node8, node9, node10}), + ""); auto link1_document = db2->get_atom_document(link1); auto link2_document = db2->get_atom_document(link2); @@ -241,15 +242,15 @@ TEST_F(RedisMongoDBTest, ConcurrentAddLinks) { links.push_back(link_with_nested); if (i % chunck_size == 0) { - db2->add_nodes(nodes, false, true); - db2->add_links(links, false, true); + db2->add_nodes(nodes, "", false, true); + db2->add_links(links, "", false, true); nodes.clear(); links.clear(); } } - if (!nodes.empty()) db2->add_nodes(nodes, false, true); - if (!links.empty()) db2->add_links(links, false, true); + if (!nodes.empty()) db2->add_nodes(nodes, "", false, true); + if (!links.empty()) db2->add_links(links, "", false, true); success_count++; } catch (const exception& e) { @@ -276,7 +277,7 @@ TEST_F(RedisMongoDBTest, ConcurrentAddLinks) { }); // clang-format on - auto result = db2->query_for_pattern(link_schema); + auto result = db2->query_for_pattern(link_schema, ""); EXPECT_EQ(result->size(), 2); } diff --git a/src/tests/cpp/remote_atomdb_test.cc b/src/tests/cpp/remote_atomdb_test.cc index 76e3f2ce0..5ffe5c617 100644 --- a/src/tests/cpp/remote_atomdb_test.cc +++ b/src/tests/cpp/remote_atomdb_test.cc @@ -9,6 +9,7 @@ #include #include "Assignment.h" +#include "Hasher.h" #include "InMemoryDB.h" #include "InMemoryDBAPITypes.h" #include "JsonConfig.h" @@ -47,15 +48,15 @@ TEST_F(RemoteAtomDBPeerTest, AddAndGetNodes) { auto human = new Node("Symbol", "\"human\""); auto monkey = new Node("Symbol", "\"monkey\""); - string human_handle = peer_->add_node(human, false); - string monkey_handle = peer_->add_node(monkey, false); + string human_handle = peer_->add_node(human, "", false); + string monkey_handle = peer_->add_node(monkey, "", false); EXPECT_FALSE(human_handle.empty()); EXPECT_FALSE(monkey_handle.empty()); - EXPECT_TRUE(peer_->node_exists(human_handle)); - EXPECT_TRUE(peer_->node_exists(monkey_handle)); + EXPECT_TRUE(peer_->node_exists(human_handle, "")); + EXPECT_TRUE(peer_->node_exists(monkey_handle, "")); - auto retrieved = peer_->get_node(human_handle); + auto retrieved = peer_->get_node(human_handle, ""); ASSERT_NE(retrieved, nullptr); EXPECT_EQ(retrieved->handle(), human_handle); } @@ -65,17 +66,17 @@ TEST_F(RemoteAtomDBPeerTest, AddAndGetLinks) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = peer_->add_node(human, false); - string monkey_handle = peer_->add_node(monkey, false); - string similarity_handle = peer_->add_node(similarity, false); + string human_handle = peer_->add_node(human, "", false); + string monkey_handle = peer_->add_node(monkey, "", false); + string similarity_handle = peer_->add_node(similarity, "", false); auto link = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link_handle = peer_->add_link(link, false); + string link_handle = peer_->add_link(link, "", false); EXPECT_FALSE(link_handle.empty()); - EXPECT_TRUE(peer_->link_exists(link_handle)); + EXPECT_TRUE(peer_->link_exists(link_handle, "")); - auto retrieved = peer_->get_link(link_handle); + auto retrieved = peer_->get_link(link_handle, ""); ASSERT_NE(retrieved, nullptr); EXPECT_EQ(retrieved->handle(), link_handle); } @@ -83,26 +84,26 @@ TEST_F(RemoteAtomDBPeerTest, AddAndGetLinks) { TEST_F(RemoteAtomDBPeerTest, GetFromCacheThenRemote) { // Add to remote only (bypass peer) auto human = new Node("Symbol", "\"human\""); - string human_handle = remote_->add_node(human, false); + string human_handle = remote_->add_node(human, "", false); // Peer should find it via remote - auto retrieved = peer_->get_node(human_handle); + auto retrieved = peer_->get_node(human_handle, ""); ASSERT_NE(retrieved, nullptr); EXPECT_EQ(retrieved->handle(), human_handle); // Second get should come from cache - auto cached = peer_->get_node(human_handle); + auto cached = peer_->get_node(human_handle, ""); ASSERT_NE(cached, nullptr); EXPECT_EQ(cached->handle(), human_handle); } TEST_F(RemoteAtomDBPeerTest, PersistsToLocal) { auto human = new Node("Symbol", "\"human\""); - string human_handle = peer_->add_node(human, false); + string human_handle = peer_->add_node(human, "", false); // cache should have it - EXPECT_TRUE(peer_->node_exists(human_handle)); - auto from_cache = peer_->get_node(human_handle); + EXPECT_TRUE(peer_->node_exists(human_handle, "")); + auto from_cache = peer_->get_node(human_handle, ""); ASSERT_NE(from_cache, nullptr); EXPECT_EQ(from_cache->handle(), human_handle); } @@ -115,17 +116,17 @@ TEST_F(RemoteAtomDBPeerTest, QueryForPattern) { auto mammal = new Node("Symbol", "\"mammal\""); auto inheritance = new Node("Symbol", "Inheritance"); - string human_handle = remote_->add_node(human, false); - string monkey_handle = remote_->add_node(monkey, false); - string mammal_handle = remote_->add_node(mammal, false); - string inheritance_handle = remote_->add_node(inheritance, false); + string human_handle = remote_->add_node(human, "", false); + string monkey_handle = remote_->add_node(monkey, "", false); + string mammal_handle = remote_->add_node(mammal, "", false); + string inheritance_handle = remote_->add_node(inheritance, "", false); auto link1 = new Link("Expression", {inheritance_handle, human_handle, mammal_handle}); auto link2 = new Link("Expression", {inheritance_handle, monkey_handle, mammal_handle}); - string link1_handle = remote_->add_link(link1, false); - string link2_handle = remote_->add_link(link2, false); + string link1_handle = remote_->add_link(link1, "", false); + string link2_handle = remote_->add_link(link2, "", false); - remote_->re_index_patterns(true); + remote_->re_index_patterns("", true); LinkSchema link_schema({"LINK_TEMPLATE", "Expression", @@ -139,7 +140,7 @@ TEST_F(RemoteAtomDBPeerTest, QueryForPattern) { "Symbol", "\"mammal\""}); - auto result = peer_->query_for_pattern(link_schema); + auto result = peer_->query_for_pattern(link_schema, ""); ASSERT_NE(result, nullptr); EXPECT_EQ(result->size(), 2); @@ -158,14 +159,14 @@ TEST_F(RemoteAtomDBPeerTest, QueryForTargets) { auto node2 = new Node("Symbol", "Node2"); auto similarity = new Node("Symbol", "Similarity"); - string node1_handle = peer_->add_node(node1, false); - string node2_handle = peer_->add_node(node2, false); - string similarity_handle = peer_->add_node(similarity, false); + string node1_handle = peer_->add_node(node1, "", false); + string node2_handle = peer_->add_node(node2, "", false); + string similarity_handle = peer_->add_node(similarity, "", false); auto link = new Link("Expression", {similarity_handle, node1_handle, node2_handle}); - string link_handle = peer_->add_link(link, false); + string link_handle = peer_->add_link(link, "", false); - auto targets = peer_->query_for_targets(link_handle); + auto targets = peer_->query_for_targets(link_handle, ""); ASSERT_NE(targets, nullptr); EXPECT_EQ(targets->size(), 3); EXPECT_EQ(string(targets->get_handle(0)), similarity_handle); @@ -178,14 +179,14 @@ TEST_F(RemoteAtomDBPeerTest, QueryForIncomingSet) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = peer_->add_node(human, false); - string monkey_handle = peer_->add_node(monkey, false); - string similarity_handle = peer_->add_node(similarity, false); + string human_handle = peer_->add_node(human, "", false); + string monkey_handle = peer_->add_node(monkey, "", false); + string similarity_handle = peer_->add_node(similarity, "", false); auto link = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link_handle = peer_->add_link(link, false); + string link_handle = peer_->add_link(link, "", false); - auto incoming = peer_->query_for_incoming_set(human_handle); + auto incoming = peer_->query_for_incoming_set(human_handle, ""); ASSERT_NE(incoming, nullptr); EXPECT_EQ(incoming->size(), 1); @@ -200,21 +201,40 @@ TEST_F(RemoteAtomDBPeerTest, DeleteLink) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = peer_->add_node(human, false); - string monkey_handle = peer_->add_node(monkey, false); - string similarity_handle = peer_->add_node(similarity, false); + string human_handle = peer_->add_node(human, "", false); + string monkey_handle = peer_->add_node(monkey, "", false); + string similarity_handle = peer_->add_node(similarity, "", false); auto link = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link_handle = peer_->add_link(link, false); + string link_handle = peer_->add_link(link, "", false); - bool deleted = peer_->delete_link(link_handle, false); + bool deleted = peer_->delete_link(link_handle, "", false); EXPECT_TRUE(deleted); - EXPECT_FALSE(peer_->link_exists(link_handle)); + EXPECT_FALSE(peer_->link_exists(link_handle, "")); +} + +TEST_F(RemoteAtomDBPeerTest, DeleteWithoutLocalPersistenceReportsActualResult) { + auto remote = make_shared("delete_remote_"); + auto peer = make_shared(remote, nullptr, "delete_no_local"); + string missing_handle = Hasher::node_handle("Symbol", "\"not_in_db\""); + + EXPECT_FALSE(peer->delete_atom(missing_handle, "", false)); + EXPECT_EQ(peer->delete_atoms({missing_handle}, "", false), 0u); +} + +TEST_F(RemoteAtomDBPeerTest, BatchDeleteCountsHandleOnceAcrossTiers) { + auto human = new Node("Symbol", "\"human\""); + string human_handle = local_->add_node(human, "", false); + + ASSERT_NE(peer_->get_node(human_handle, ""), nullptr); + + EXPECT_EQ(peer_->delete_nodes({human_handle}, "", false), 1u); + EXPECT_FALSE(peer_->node_exists(human_handle, "")); } TEST_F(RemoteAtomDBPeerTest, GetUid) { EXPECT_EQ(peer_->get_uid(), "test_peer"); } -TEST_F(RemoteAtomDBPeerTest, AllowNestedIndexing) { EXPECT_FALSE(peer_->allow_nested_indexing()); } +TEST_F(RemoteAtomDBPeerTest, AllowNestedIndexing) { EXPECT_FALSE(peer_->allow_nested_indexing("")); } TEST_F(RemoteAtomDBPeerTest, FetchAndRelease) { auto human = new Node("Symbol", "\"human\""); @@ -223,16 +243,16 @@ TEST_F(RemoteAtomDBPeerTest, FetchAndRelease) { auto inheritance = new Node("Symbol", "Inheritance"); // Add nodes and links to the remote DB directly (bypass peer) - string human_handle = remote_->add_node(human, false); - string monkey_handle = remote_->add_node(monkey, false); - string mammal_handle = remote_->add_node(mammal, false); - string inheritance_handle = remote_->add_node(inheritance, false); + string human_handle = remote_->add_node(human, "", false); + string monkey_handle = remote_->add_node(monkey, "", false); + string mammal_handle = remote_->add_node(mammal, "", false); + string inheritance_handle = remote_->add_node(inheritance, "", false); auto link1 = new Link("Expression", {inheritance_handle, human_handle, mammal_handle}); auto link2 = new Link("Expression", {inheritance_handle, monkey_handle, mammal_handle}); - string link1_handle = remote_->add_link(link1, false); - string link2_handle = remote_->add_link(link2, false); - remote_->re_index_patterns(true); + string link1_handle = remote_->add_link(link1, "", false); + string link2_handle = remote_->add_link(link2, "", false); + remote_->re_index_patterns("", true); LinkSchema link_schema({"LINK_TEMPLATE", "Expression", @@ -250,12 +270,12 @@ TEST_F(RemoteAtomDBPeerTest, FetchAndRelease) { peer_->fetch(link_schema); // The peer should now answer the query from its cache - auto result = peer_->query_for_pattern(link_schema); + auto result = peer_->query_for_pattern(link_schema, ""); ASSERT_NE(result, nullptr); EXPECT_EQ(result->size(), 2); // Atoms from the query results should be in the cache (retrievable via peer) - auto atom1 = peer_->get_atom(link1_handle); + auto atom1 = peer_->get_atom(link1_handle, ""); ASSERT_NE(atom1, nullptr); EXPECT_EQ(atom1->handle(), link1_handle); @@ -263,11 +283,11 @@ TEST_F(RemoteAtomDBPeerTest, FetchAndRelease) { peer_->release(link_schema); // After release, atoms should be in local_persistence - EXPECT_TRUE(local_->atom_exists(link1_handle)); - EXPECT_TRUE(local_->atom_exists(link2_handle)); + EXPECT_TRUE(local_->atom_exists(link1_handle, "")); + EXPECT_TRUE(local_->atom_exists(link2_handle, "")); // The peer should still find the atoms (via local_persistence fallback) - auto after_release = peer_->get_atom(link1_handle); + auto after_release = peer_->get_atom(link1_handle, ""); ASSERT_NE(after_release, nullptr); EXPECT_EQ(after_release->handle(), link1_handle); } @@ -281,13 +301,13 @@ TEST_F(RemoteAtomDBPeerTest, ReleaseWithoutLocalPersistence) { auto mammal = new Node("Symbol", "\"mammal\""); auto inheritance = new Node("Symbol", "Inheritance"); - string human_handle = remote->add_node(human, false); - string mammal_handle = remote->add_node(mammal, false); - string inheritance_handle = remote->add_node(inheritance, false); + string human_handle = remote->add_node(human, "", false); + string mammal_handle = remote->add_node(mammal, "", false); + string inheritance_handle = remote->add_node(inheritance, "", false); auto link = new Link("Expression", {inheritance_handle, human_handle, mammal_handle}); - string link_handle = remote->add_link(link, false); - remote->re_index_patterns(true); + string link_handle = remote->add_link(link, "", false); + remote->re_index_patterns("", true); LinkSchema link_schema({"LINK_TEMPLATE", "Expression", @@ -302,7 +322,7 @@ TEST_F(RemoteAtomDBPeerTest, ReleaseWithoutLocalPersistence) { "\"mammal\""}); peer_no_local->fetch(link_schema); - auto result = peer_no_local->query_for_pattern(link_schema); + auto result = peer_no_local->query_for_pattern(link_schema, ""); ASSERT_NE(result, nullptr); EXPECT_EQ(result->size(), 1); @@ -310,29 +330,29 @@ TEST_F(RemoteAtomDBPeerTest, ReleaseWithoutLocalPersistence) { peer_no_local->release(link_schema); // Atom should still be available via the remote fallback - auto atom = peer_no_local->get_atom(link_handle); + auto atom = peer_no_local->get_atom(link_handle, ""); ASSERT_NE(atom, nullptr); } TEST_F(RemoteAtomDBPeerTest, AtomsCount) { - EXPECT_EQ(peer_->atom_count(), 0); - EXPECT_EQ(peer_->empty(), true); + EXPECT_EQ(peer_->atom_count(""), 0); + EXPECT_EQ(peer_->empty(""), true); auto node1 = new Node("Symbol", "Node1"); auto node2 = new Node("Symbol", "Node2"); auto similarity = new Node("Symbol", "Similarity"); - peer_->add_node(node1, false); - peer_->add_node(node2, false); - peer_->add_node(similarity, false); + peer_->add_node(node1, "", false); + peer_->add_node(node2, "", false); + peer_->add_node(similarity, "", false); - EXPECT_EQ(peer_->atom_count(), 3); + EXPECT_EQ(peer_->atom_count(""), 3); auto link1 = new Link("Expression", {similarity->handle(), node1->handle(), node2->handle()}); - peer_->add_link(link1, false); + peer_->add_link(link1, "", false); - EXPECT_EQ(peer_->atom_count(), 4); - EXPECT_EQ(peer_->empty(), false); + EXPECT_EQ(peer_->atom_count(""), 4); + EXPECT_EQ(peer_->empty(""), false); } // Resolves path to config file from Bazel runfiles or workspace. @@ -411,12 +431,12 @@ TEST_F(RemoteAtomDBTest, GetPeer) { TEST_F(RemoteAtomDBTest, AddAndGetAcrossPeers) { auto human = new Node("Symbol", "\"human\""); - string human_handle = db_->add_node(human, false); + string human_handle = db_->add_node(human, "", false); EXPECT_FALSE(human_handle.empty()); - EXPECT_TRUE(db_->node_exists(human_handle)); + EXPECT_TRUE(db_->node_exists(human_handle, "")); - auto retrieved = db_->get_node(human_handle); + auto retrieved = db_->get_node(human_handle, ""); ASSERT_NE(retrieved, nullptr); EXPECT_EQ(retrieved->handle(), human_handle); } @@ -427,24 +447,24 @@ TEST_F(RemoteAtomDBTest, AddLinksAndRetrieve) { auto mammal = new Node("Symbol", "\"mammal\""); auto inheritance = new Node("Symbol", "Inheritance"); - string human_handle = db_->add_node(human, false); - string monkey_handle = db_->add_node(monkey, false); - string mammal_handle = db_->add_node(mammal, false); - string inheritance_handle = db_->add_node(inheritance, false); + string human_handle = db_->add_node(human, "", false); + string monkey_handle = db_->add_node(monkey, "", false); + string mammal_handle = db_->add_node(mammal, "", false); + string inheritance_handle = db_->add_node(inheritance, "", false); auto link1 = new Link("Expression", {inheritance_handle, human_handle, mammal_handle}); auto link2 = new Link("Expression", {inheritance_handle, monkey_handle, mammal_handle}); - string link1_handle = db_->add_link(link1, false); - string link2_handle = db_->add_link(link2, false); + string link1_handle = db_->add_link(link1, "", false); + string link2_handle = db_->add_link(link2, "", false); - EXPECT_TRUE(db_->link_exists(link1_handle)); - EXPECT_TRUE(db_->link_exists(link2_handle)); + EXPECT_TRUE(db_->link_exists(link1_handle, "")); + EXPECT_TRUE(db_->link_exists(link2_handle, "")); - auto retrieved1 = db_->get_link(link1_handle); + auto retrieved1 = db_->get_link(link1_handle, ""); ASSERT_NE(retrieved1, nullptr); EXPECT_EQ(retrieved1->handle(), link1_handle); - auto retrieved2 = db_->get_link(link2_handle); + auto retrieved2 = db_->get_link(link2_handle, ""); ASSERT_NE(retrieved2, nullptr); EXPECT_EQ(retrieved2->handle(), link2_handle); } @@ -454,16 +474,16 @@ TEST_F(RemoteAtomDBTest, DeleteOperations) { auto monkey = new Node("Symbol", "\"monkey\""); auto similarity = new Node("Symbol", "Similarity"); - string human_handle = db_->add_node(human, false); - string monkey_handle = db_->add_node(monkey, false); - string similarity_handle = db_->add_node(similarity, false); + string human_handle = db_->add_node(human, "", false); + string monkey_handle = db_->add_node(monkey, "", false); + string similarity_handle = db_->add_node(similarity, "", false); auto link = new Link("Expression", {similarity_handle, human_handle, monkey_handle}); - string link_handle = db_->add_link(link, false); + string link_handle = db_->add_link(link, "", false); - bool deleted = db_->delete_link(link_handle, false); + bool deleted = db_->delete_link(link_handle, "", false); EXPECT_TRUE(deleted); - EXPECT_FALSE(db_->link_exists(link_handle)); + EXPECT_FALSE(db_->link_exists(link_handle, "")); } // ============================================================================= @@ -493,8 +513,8 @@ TEST_F(RemoteAtomDBConfigTest, SingleConfigWorks) { EXPECT_NE(peers.find("single_peer"), peers.end()); auto human = new Node("Symbol", "\"human\""); - string human_handle = db_->add_node(human, false); - EXPECT_TRUE(db_->node_exists(human_handle)); + string human_handle = db_->add_node(human, "", false); + EXPECT_TRUE(db_->node_exists(human_handle, "")); } // ============================================================================= @@ -511,10 +531,11 @@ class NestedInMemoryDB : public InMemoryDB { public: explicit NestedInMemoryDB(const string& context) : InMemoryDB(context) {} - bool allow_nested_indexing() override { return true; } + bool allow_nested_indexing(const string& public_key) override { return true; } - shared_ptr query_for_pattern(const LinkSchema& link_schema) override { - auto base = InMemoryDB::query_for_pattern(link_schema); + shared_ptr query_for_pattern(const LinkSchema& link_schema, + const string& public_key) override { + auto base = InMemoryDB::query_for_pattern(link_schema, public_key); auto result = make_shared(); if (base) { auto it = base->get_iterator(); @@ -562,16 +583,16 @@ static vector populate_inheritance_links(shared_ptr backend) auto mammal = new Node("Symbol", "\"mammal\""); auto inheritance = new Node("Symbol", "Inheritance"); - string human_handle = backend->add_node(human, false); - string monkey_handle = backend->add_node(monkey, false); - string mammal_handle = backend->add_node(mammal, false); - string inheritance_handle = backend->add_node(inheritance, false); + string human_handle = backend->add_node(human, "", false); + string monkey_handle = backend->add_node(monkey, "", false); + string mammal_handle = backend->add_node(mammal, "", false); + string inheritance_handle = backend->add_node(inheritance, "", false); auto link1 = new Link("Expression", {inheritance_handle, human_handle, mammal_handle}); auto link2 = new Link("Expression", {inheritance_handle, monkey_handle, mammal_handle}); - string link1_handle = backend->add_link(link1, false); - string link2_handle = backend->add_link(link2, false); - backend->re_index_patterns(true); + string link1_handle = backend->add_link(link1, "", false); + string link2_handle = backend->add_link(link2, "", false); + backend->re_index_patterns("", true); return {link1_handle, link2_handle}; } @@ -584,9 +605,9 @@ TEST(RemoteAtomDBFederationTest, MetadataAggregationFromNestedPeer) { auto db = make_shared(peers); // All peers are nested-indexing -> facade advertises nested indexing. - EXPECT_TRUE(db->allow_nested_indexing()); + EXPECT_TRUE(db->allow_nested_indexing("")); - auto result = db->query_for_pattern(inheritance_mammal_schema()); + auto result = db->query_for_pattern(inheritance_mammal_schema(), ""); ASSERT_NE(result, nullptr); EXPECT_EQ(result->size(), 2u); @@ -622,9 +643,9 @@ TEST(RemoteAtomDBFederationTest, MixedPeersDowngradeAndDeduplicate) { auto db = make_shared(peers); // Mixed nested/non-nested peers -> facade downgrades to false. - EXPECT_FALSE(db->allow_nested_indexing()); + EXPECT_FALSE(db->allow_nested_indexing("")); - auto result = db->query_for_pattern(inheritance_mammal_schema()); + auto result = db->query_for_pattern(inheritance_mammal_schema(), ""); ASSERT_NE(result, nullptr); // Same two handles from both peers, deduplicated to a unique count of 2. EXPECT_EQ(result->size(), 2u); @@ -684,7 +705,7 @@ TEST(RemoteAtomDBFederationTest, CacheFirstProbingAcrossPeers) { auto backend2 = make_shared("fed_cache_peer2_"); auto only_in_peer2 = new Node("Symbol", "\"only_in_peer2\""); - string handle = backend2->add_node(only_in_peer2, false); + string handle = backend2->add_node(only_in_peer2, "", false); map> peers; peers["peer1"] = make_shared(backend1, nullptr, "peer1"); @@ -694,22 +715,22 @@ TEST(RemoteAtomDBFederationTest, CacheFirstProbingAcrossPeers) { auto* peer2 = db->get_peer("peer2"); ASSERT_NE(peer2, nullptr); // Before any read, nothing is cached. - EXPECT_EQ(peer2->get_cached_atom(handle), nullptr); + EXPECT_EQ(peer2->get_cached_atom(handle, ""), nullptr); // Phase 1 (cache) misses everywhere; Phase 2 escalation resolves from peer2's backend. - auto first = db->get_atom(handle); + auto first = db->get_atom(handle, ""); ASSERT_NE(first, nullptr); EXPECT_EQ(first->handle(), handle); // peer2 must have warmed its cache, so a subsequent Phase 1 probe hits. - EXPECT_NE(peer2->get_cached_atom(handle), nullptr); + EXPECT_NE(peer2->get_cached_atom(handle, ""), nullptr); - auto second = db->get_atom(handle); + auto second = db->get_atom(handle, ""); ASSERT_NE(second, nullptr); EXPECT_EQ(second->handle(), handle); // A handle present in no peer resolves to nullptr. - EXPECT_EQ(db->get_atom("ffffffffffffffffffffffffffffffff"), nullptr); + EXPECT_EQ(db->get_atom("ffffffffffffffffffffffffffffffff", ""), nullptr); } int main(int argc, char** argv) { diff --git a/src/tests/cpp/test_commons/MockAnimalsData.cc b/src/tests/cpp/test_commons/MockAnimalsData.cc index c31b9ae38..51bb9fad0 100644 --- a/src/tests/cpp/test_commons/MockAnimalsData.cc +++ b/src/tests/cpp/test_commons/MockAnimalsData.cc @@ -86,7 +86,7 @@ void load_animals_data() { nodes.push_back(plant); LOG_INFO("Adding nodes to db..."); - db->add_nodes(nodes); + db->add_nodes(nodes, ""); nodes.clear(); // Links @@ -115,7 +115,7 @@ void load_animals_data() { links.push_back(inheritance_type); LOG_INFO("Adding Type links to db..."); - db->add_links(links); + db->add_links(links, ""); links.clear(); // Concepts @@ -206,7 +206,7 @@ void load_animals_data() { links.push_back(plant_concept); LOG_INFO("Adding Concept links to db..."); - db->add_links(links); + db->add_links(links, ""); links.clear(); // Similarity @@ -311,7 +311,7 @@ void load_animals_data() { links.push_back(similarity_ent_human); LOG_INFO("Adding similarity links to db..."); - db->add_links(links); + db->add_links(links, ""); links.clear(); // Inheritance @@ -403,7 +403,7 @@ void load_animals_data() { links.push_back(inheritance_ent_plant); LOG_INFO("Adding inheritance links to db..."); - db->add_links(links); + db->add_links(links, ""); links.clear(); // OddLinks @@ -482,5 +482,5 @@ void load_animals_data() { links.push_back(oddlink_ent_plant); LOG_INFO("Adding odd links to db..."); - db->add_links(links); + db->add_links(links, ""); } diff --git a/src/tests/cpp/test_commons/mocks/MockAtomDB.h b/src/tests/cpp/test_commons/mocks/MockAtomDB.h index bb9c8c720..e7da5b043 100644 --- a/src/tests/cpp/test_commons/mocks/MockAtomDB.h +++ b/src/tests/cpp/test_commons/mocks/MockAtomDB.h @@ -23,82 +23,132 @@ class MockAtomDocument : public atomdb_api_types::AtomDocument { class AtomDBMock : public AtomDB { public: - MOCK_METHOD(bool, allow_nested_indexing, (), (override)); + MOCK_METHOD(bool, allow_nested_indexing, (const string& public_key), (override)); MOCK_METHOD(bool, composite_type_enabled, (), (const, override)); - MOCK_METHOD(shared_ptr, get_atom, (const string& handle), (override)); - MOCK_METHOD(shared_ptr, get_node, (const string& handle), (override)); - MOCK_METHOD(shared_ptr, get_link, (const string& handle), (override)); + MOCK_METHOD(bool, is_protected, (), (const, override)); + MOCK_METHOD(shared_ptr, + get_atom, + (const string& handle, const string& public_key), + (override)); + MOCK_METHOD(shared_ptr, + get_node, + (const string& handle, const string& public_key), + (override)); + MOCK_METHOD(shared_ptr, + get_link, + (const string& handle, const string& public_key), + (override)); MOCK_METHOD(shared_ptr, query_for_pattern, - (const LinkSchema& link_template), + (const LinkSchema& link_template, const string& public_key), (override)); MOCK_METHOD(shared_ptr, query_for_targets, - (const string& handle), + (const string& handle, const string& public_key), (override)); MOCK_METHOD(shared_ptr, query_for_incoming_set, - (const string& handle), + (const string& handle, const string& public_key), (override)); - MOCK_METHOD(vector>, get_matching_atoms, (bool is_toplevel, Atom& key), (override)); + MOCK_METHOD(vector>, + get_matching_atoms, + (bool is_toplevel, Atom& key, const string& public_key), + (override)); - MOCK_METHOD(bool, atom_exists, (const string& handle), (override)); - MOCK_METHOD(bool, node_exists, (const string& handle), (override)); - MOCK_METHOD(bool, link_exists, (const string& handle), (override)); + MOCK_METHOD(bool, atom_exists, (const string& handle, const string& public_key), (override)); + MOCK_METHOD(bool, node_exists, (const string& handle, const string& public_key), (override)); + MOCK_METHOD(bool, link_exists, (const string& handle, const string& public_key), (override)); - MOCK_METHOD(set, atoms_exist, (const vector& handles), (override)); - MOCK_METHOD(set, nodes_exist, (const vector& handles), (override)); - MOCK_METHOD(set, links_exist, (const vector& link_handles), (override)); + MOCK_METHOD(set, + atoms_exist, + (const vector& handles, const string& public_key), + (override)); + MOCK_METHOD(set, + nodes_exist, + (const vector& handles, const string& public_key), + (override)); + MOCK_METHOD(set, + links_exist, + (const vector& link_handles, const string& public_key), + (override)); - MOCK_METHOD(string, add_node, (const Node* node, bool throw_if_exists), (override)); - MOCK_METHOD(string, add_link, (const Link* link, bool throw_if_exists), (override)); - MOCK_METHOD(string, add_atom, (const Atom* atom, bool throw_if_exists), (override)); + MOCK_METHOD(string, + add_node, + (const Node* node, const string& public_key, bool throw_if_exists), + (override)); + MOCK_METHOD(string, + add_link, + (const Link* link, const string& public_key, bool throw_if_exists), + (override)); + MOCK_METHOD(string, + add_atom, + (const Atom* atom, const string& public_key, bool throw_if_exists), + (override)); MOCK_METHOD(vector, add_atoms, - (const vector& atoms, bool throw_if_exists, bool is_transactional), + (const vector& atoms, + const string& public_key, + bool throw_if_exists, + bool is_transactional), (override)); MOCK_METHOD(vector, add_nodes, - (const vector& nodes, bool throw_if_exists, bool is_transactional), + (const vector& nodes, + const string& public_key, + bool throw_if_exists, + bool is_transactional), (override)); MOCK_METHOD(vector, add_links, - (const vector& links, bool throw_if_exists, bool is_transactional), + (const vector& links, + const string& public_key, + bool throw_if_exists, + bool is_transactional), (override)); - MOCK_METHOD(bool, delete_atom, (const string& handle, bool delete_link_targets), (override)); - MOCK_METHOD(bool, delete_node, (const string& handle, bool delete_link_targets), (override)); - MOCK_METHOD(bool, delete_link, (const string& handle, bool delete_link_targets), (override)); + MOCK_METHOD(bool, + delete_atom, + (const string& handle, const string& public_key, bool delete_link_targets), + (override)); + MOCK_METHOD(bool, + delete_node, + (const string& handle, const string& public_key, bool delete_link_targets), + (override)); + MOCK_METHOD(bool, + delete_link, + (const string& handle, const string& public_key, bool delete_link_targets), + (override)); MOCK_METHOD(uint, delete_atoms, - (const vector& handles, bool delete_link_targets), + (const vector& handles, const string& public_key, bool delete_link_targets), (override)); MOCK_METHOD(uint, delete_nodes, - (const vector& handles, bool delete_link_targets), + (const vector& handles, const string& public_key, bool delete_link_targets), (override)); MOCK_METHOD(uint, delete_links, - (const vector& handles, bool delete_link_targets), + (const vector& handles, const string& public_key, bool delete_link_targets), (override)); - MOCK_METHOD(void, re_index_patterns, (bool flush_patterns), (override)); + MOCK_METHOD(void, re_index_patterns, (const string& public_key, bool flush_patterns), (override)); - MOCK_METHOD(size_t, node_count, (), (const override)); - MOCK_METHOD(size_t, link_count, (), (const override)); - MOCK_METHOD(size_t, atom_count, (), (const override)); + MOCK_METHOD(size_t, node_count, (const string& public_key), (const, override)); + MOCK_METHOD(size_t, link_count, (const string& public_key), (const, override)); + MOCK_METHOD(size_t, atom_count, (const string& public_key), (const, override)); AtomDBMock() { ON_CALL(*this, composite_type_enabled()).WillByDefault(::testing::Return(true)); - ON_CALL(*this, get_atom(testing::_)) + ON_CALL(*this, is_protected()).WillByDefault(::testing::Return(false)); + ON_CALL(*this, get_atom(testing::_, testing::_)) .WillByDefault(::testing::Return(make_shared("Node", "TestNode"))); - ON_CALL(*this, get_node(testing::_)) + ON_CALL(*this, get_node(testing::_, testing::_)) .WillByDefault(::testing::Return(make_shared("Node", "TestNode"))); - ON_CALL(*this, get_link(testing::_)) + ON_CALL(*this, get_link(testing::_, testing::_)) .WillByDefault( ::testing::Return(make_shared("Link", vector({"TestNode", "TestNode"})))); } diff --git a/src/tests/main/evaluation_evolution.cc b/src/tests/main/evaluation_evolution.cc index 2cea63d75..84debadf9 100644 --- a/src/tests/main/evaluation_evolution.cc +++ b/src/tests/main/evaluation_evolution.cc @@ -145,7 +145,7 @@ static string hard_wired_metta_expression(const string& handle) { static double get_strength(const string& handle) { STACK_TRACE(); - auto atom = db->get_atom(handle); + auto atom = db->get_atom(handle, ""); return atom->custom_attributes.get_or(STRENGTH_TAG, 1.0); } @@ -173,9 +173,9 @@ static string answer_to_string_2(shared_ptr answer) { vector path_link = {" -> ", " -> "}; bool first = true; for (string& handle : answer->get_path_vector(i)) { - auto link = db->get_link(handle); - auto target1 = db->get_link(link->targets[1]); - auto target2 = db->get_link(link->targets[2]); + auto link = db->get_link(handle, ""); + auto target1 = db->get_link(link->targets[1], ""); + auto target2 = db->get_link(link->targets[2], ""); if (first) { first = false; path = target1->metta_representation(*DECODER) + path_link[i]; @@ -203,9 +203,9 @@ static string answer_to_string_1(shared_ptr answer) { string path_link = " -> "; bool first = true; for (string& handle : answer->get_path_vector(0)) { - auto link = db->get_link(handle); - auto target1 = db->get_link(link->targets[1]); - auto target2 = db->get_link(link->targets[2]); + auto link = db->get_link(handle, ""); + auto target1 = db->get_link(link->targets[1], ""); + auto target2 = db->get_link(link->targets[2], ""); if (first) { first = false; path = target1->metta_representation(*DECODER) + path_link; @@ -393,14 +393,14 @@ static shared_ptr add_or_update_link(const string& type_handle, new Link(EXPRESSION, {type_handle, target1, target2}, true, {{STRENGTH_TAG, strength}})); LOG_DEBUG("Add or update: " + new_link->to_string()); string handle = new_link->handle(); - if (db->link_exists(handle)) { - auto old_link = db->get_atom(handle); + if (db->link_exists(handle, "")) { + auto old_link = db->get_atom(handle, ""); LOG_DEBUG("Link already exists: " + old_link->to_string()); if (strength != old_link->custom_attributes.get_or(STRENGTH_TAG, 1)) { if (WRITE_CREATED_LINKS_TO_DB) { LOG_DEBUG("Updating Link in AtomDB"); - db->delete_link(handle, false); - db->add_link(new_link.get()); + db->delete_link(handle, "", false); + db->add_link(new_link.get(), ""); } if (WRITE_CREATED_LINKS_TO_FILE) { LOG_DEBUG("Writing Link to file: " + PRESET_LINKS_FILE); @@ -415,7 +415,7 @@ static shared_ptr add_or_update_link(const string& type_handle, LOG_INFO("ADD LINK: [" + std::to_string(strength) + "] " + new_link->metta_representation(*DECODER)); } - db->add_link(new_link.get()); + db->add_link(new_link.get(), ""); buffer_determiners.push_back({handle, target1, target2}); AttentionBrokerClient::correlate(set({target1, target2}), context); } @@ -431,10 +431,10 @@ static shared_ptr add_or_update_link(const string& type_handle, static void extract_mentioned_predicates(set& mentioned, const string& handle) { STACK_TRACE(); shared_ptr node; - shared_ptr link = db->get_link(handle); + shared_ptr link = db->get_link(handle, ""); if (link != nullptr) { for (string& target_handle : link->targets) { - if ((node = db->get_node(target_handle)) != nullptr) { + if ((node = db->get_node(target_handle, "")) != nullptr) { if ((node->name != PREDICATE) && (node->name != LOGICAL_AND)) { mentioned.insert(node->name); } @@ -457,8 +457,9 @@ static shared_ptr add_and_predicate(const string& handle1, extract_mentioned_predicates(mentioned_predicates1, handle1); extract_mentioned_predicates(mentioned_predicates2, handle2); if (Utils::intersects(mentioned_predicates1, mentioned_predicates2)) { - LOG_DEBUG("Disregarded AND predicate: " + db->get_atom(handle1)->metta_representation(*DECODER) + - " AND " + db->get_atom(handle2)->metta_representation(*DECODER)); + LOG_DEBUG( + "Disregarded AND predicate: " + db->get_atom(handle1, "")->metta_representation(*DECODER) + + " AND " + db->get_atom(handle2, "")->metta_representation(*DECODER)); return nullptr; } @@ -540,8 +541,8 @@ static bool build_implication_link(shared_ptr query_answer, extract_mentioned_predicates(mentioned_predicates2, predicates[1]); if (Utils::intersects(mentioned_predicates1, mentioned_predicates2)) { LOG_DEBUG("Disregarded IMPLICATION predicates: " + - db->get_atom(predicates[0])->metta_representation(*DECODER) + " <=> " + - db->get_atom(predicates[1])->metta_representation(*DECODER)); + db->get_atom(predicates[0], "")->metta_representation(*DECODER) + " <=> " + + db->get_atom(predicates[1], "")->metta_representation(*DECODER)); return false; } @@ -992,7 +993,7 @@ static void add_preset_links(const vector& implication_to_target_predica auto link = std::dynamic_pointer_cast(parser_handler->element_stack.top()); link->custom_attributes["strength"] = (double) Utils::string_to_float(line[0]); LOG_DEBUG("Adding Link: [" + line[0] + "] " + line[1]); - db->add_link(link.get(), false); + db->add_link(link.get(), "", false); count++; line.clear(); buffer_determiners.push_back({link->handle(), link->targets[1], link->targets[2]}); @@ -1390,7 +1391,7 @@ static void insert_type_symbols() { Node* node; for (string node_name : to_insert) { node = new Node(SYMBOL, node_name); - db->add_node(node, false); + db->add_node(node, "", false); delete (node); } } diff --git a/src/tests/main/link_creation_engine_main.cc b/src/tests/main/link_creation_engine_main.cc index bebc68e66..d56301d6f 100644 --- a/src/tests/main/link_creation_engine_main.cc +++ b/src/tests/main/link_creation_engine_main.cc @@ -175,7 +175,7 @@ void build_link(const string& link_type_tag, string handle_to_atom(const string& handle) { shared_ptr db = AtomDBSingleton::get_instance(); shared_ptr document = db->get_atom_document(handle); - shared_ptr targets = db->query_for_targets(handle); + shared_ptr targets = db->query_for_targets(handle, ""); string answer; if (targets != nullptr) { diff --git a/src/tests/main/word_query_evolution_main.cc b/src/tests/main/word_query_evolution_main.cc index 40586a40f..024f51769 100644 --- a/src/tests/main/word_query_evolution_main.cc +++ b/src/tests/main/word_query_evolution_main.cc @@ -72,7 +72,7 @@ class RemoteFitnessFunction : public FitnessFunction { string handle_to_atom(const string& handle) { shared_ptr db = AtomDBSingleton::get_instance(); - shared_ptr atom = db->get_atom(handle); + shared_ptr atom = db->get_atom(handle, ""); string answer; if (atom->arity() > 0) { @@ -325,9 +325,9 @@ void run(const string& client_id, } else { string handle = query_answer->assignment.get(sentence1.c_str()); float fitness = query_answer->strength; - shared_ptr sentence_link = db->get_link(handle); + shared_ptr sentence_link = db->get_link(handle, ""); handle = sentence_link->targets[1]; - shared_ptr sentence_name_node = db->get_node(handle); + shared_ptr sentence_name_node = db->get_node(handle, ""); set to_highlight = {word_tag1, word_tag2}; string sentence_name = sentence_name_node->name; string highlighted_sentence_name = highlight(sentence_name, to_highlight); diff --git a/src/tests/main/word_query_main.cc b/src/tests/main/word_query_main.cc index f96e1ff4d..ac857bba7 100644 --- a/src/tests/main/word_query_main.cc +++ b/src/tests/main/word_query_main.cc @@ -57,7 +57,7 @@ string highlight(const string& s, const set& highlighted) { string handle_to_atom(const string& handle) { shared_ptr db = AtomDBSingleton::get_instance(); - shared_ptr atom = db->get_atom(handle); + shared_ptr atom = db->get_atom(handle, ""); string answer; if (atom->arity() > 0) { @@ -146,9 +146,9 @@ void run(const string& client_id, Utils::sleep(); } else { string handle = query_answer->assignment.get(sentence1.c_str()); - sentence_link = db->get_link(handle); + sentence_link = db->get_link(handle, ""); handle = sentence_link->targets[1]; - sentence_name_node = db->get_node(handle); + sentence_name_node = db->get_node(handle, ""); set to_highlight; to_highlight.insert(word_tag); string sentence_name = sentence_name_node->name; diff --git a/src/tests/regression/adapterdb_main.cc b/src/tests/regression/adapterdb_main.cc index 2242f94ed..772ed52ed 100644 --- a/src/tests/regression/adapterdb_main.cc +++ b/src/tests/regression/adapterdb_main.cc @@ -87,9 +87,9 @@ int main(int argc, char* argv[]) { auto morkdb = make_shared("", morkdb_json_config()); - size_t nodes = morkdb->node_count(); - size_t links = morkdb->link_count(); - size_t atoms = morkdb->atom_count(); + size_t nodes = morkdb->node_count(""); + size_t links = morkdb->link_count(""); + size_t atoms = morkdb->atom_count(""); LOG_INFO("Node count: " << nodes); LOG_INFO("Link count: " << links);