Skip to content

Commit

Permalink
feat: Basic model speedup (#245)
Browse files Browse the repository at this point in the history
* feat: [basic_model_speedup] option to use unordered_set<vector> instead of vector<vector> for policies storage

* feat: [basic_model_speedup] ability unordered_set / vector be used as base collection on compilation

* feat: [basic_model_speedup] expalin work with collection

* feat: [basic_model_speedup] using hashes instead of vectors for basic model (allow) on enforcement

* feat: [basic_model_speedup] new fare benchmark for large basic model

* feat: [basic_model_speedup] cmake option to compile vector/unordered_set policy storage

* feat: [basic_model_speedup] filter test fix

* feat: [basic_model_speedup] new policy_collection that abstract vector/unordered_set

* feat: [basic_model_speedup] automatic usage of hashset when appropriated

* feat: [basic_model_speedup] automatic detection of hash usage without compilation option

* feat: [basic_model_speedup] CI fixes for linux

* feat: [basic_model_speedup] CI fix for Windows
  • Loading branch information
AlexeyChashchegorov committed Mar 18, 2024
1 parent 4deab3b commit cbeed65
Show file tree
Hide file tree
Showing 38 changed files with 714 additions and 267 deletions.
2 changes: 2 additions & 0 deletions casbin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(CASBIN_SOURCE_FILES
enforcer.cpp
enforcer_cached.cpp
enforcer_synced.cpp
selected_policies.cpp
internal_api.cpp
logger.cpp
management_api.cpp
Expand All @@ -42,6 +43,7 @@ set(CASBIN_SOURCE_FILES
model/function.cpp
model/model.cpp
model/evaluator.cpp
model/policy_collection.cpp
persist/file_adapter/batch_file_adapter.cpp
persist/file_adapter/file_adapter.cpp
persist/file_adapter/filtered_file_adapter.cpp
Expand Down
25 changes: 13 additions & 12 deletions casbin/enforcer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@
#define ENFORCER_CPP

#include <algorithm>
#include <regex>

#include "casbin/effect/default_effector.h"
#include "casbin/enforcer.h"
#include "casbin/selected_policies.h"
#include "casbin/exception/casbin_adapter_exception.h"
#include "casbin/exception/casbin_enforcer_exception.h"
#include "casbin/persist/file_adapter/batch_file_adapter.h"
#include "casbin/persist/file_adapter/file_adapter.h"
#include "casbin/persist/watcher_ex.h"
#include "casbin/model/policy_collection.hpp"
#include "casbin/rbac/default_role_manager.h"
#include "casbin/util/util.h"

Expand Down Expand Up @@ -90,15 +93,15 @@ bool Enforcer::m_enforce(const std::string& matcher, std::vector<std::string>& e
Effect effect;
int explainIndex;

std::vector<std::vector<std::string>>& p_policy = m_model->m["p"].assertion_map["p"]->policy;
SelectedPolicies selected_policies(evalator, matcher, m_model);
PoliciesValues& p_policy = *selected_policies;

if (auto policy_len = p_policy.size(); policy_len != 0) {
policy_effects = std::vector<Effect>(policy_len, Effect::Indeterminate);
matcher_results = std::vector<float>(policy_len, 0.0f);

for (int policy_index = 0; policy_index < policy_len; policy_index++) {
std::vector<std::string>& p_vals = m_model->m["p"].assertion_map["p"]->policy[policy_index];

int policy_index = 0;
for (auto& p_vals : p_policy ) {
casbin::LogUtil::LogPrint("Policy Rule: ", p_vals);
if (p_tokens.size() != p_vals.size()) {
throw CasbinEnforcerException("invalid policy size");
Expand Down Expand Up @@ -174,6 +177,7 @@ bool Enforcer::m_enforce(const std::string& matcher, std::vector<std::string>& e
if (effect != Effect::Indeterminate) {
break;
}
policy_index++;
}

casbin::LogUtil::LogPrint("Rule Results: ", policy_effects);
Expand Down Expand Up @@ -214,12 +218,12 @@ bool Enforcer::m_enforce(const std::string& matcher, std::vector<std::string>& e
casbin::LogUtil::LogPrint("Rule Results: ", policy_effects);
}

std::vector<std::vector<std::string>> logExplains;
PoliciesValues logExplains;

logExplains.push_back(explains);
logExplains.emplace(explains);
if (explainIndex != -1 && (p_policy.size() > explainIndex)) {
explains = p_policy[explainIndex];
logExplains.push_back(explains);
explains = *std::next(p_policy.begin(), explainIndex);
logExplains.emplace(explains);
}

// effect --> result
Expand All @@ -228,9 +232,6 @@ bool Enforcer::m_enforce(const std::string& matcher, std::vector<std::string>& e
result = true;
}

// TODO
// m_log.LogPrint(exp_string, evalator, result, logExplains);

return result;
}

Expand Down Expand Up @@ -508,7 +509,7 @@ void Enforcer::BuildRoleLinks() {
}

// BuildIncrementalRoleLinks provides incremental build the role inheritance relations.
void Enforcer::BuildIncrementalRoleLinks(policy_op op, const std::string& p_type, const std::vector<std::vector<std::string>>& rules) {
void Enforcer::BuildIncrementalRoleLinks(policy_op op, const std::string& p_type, const PoliciesValues& rules) {
return m_model->BuildIncrementalRoleLinks(this->rm, op, "g", p_type, rules);
}

Expand Down
34 changes: 17 additions & 17 deletions casbin/enforcer_synced.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,43 +280,43 @@ std::vector<std::string> SyncedEnforcer ::GetAllNamedRoles(const std::string& pt
}

// GetPolicy gets all the authorization rules in the policy.
std::vector<std::vector<std::string>> SyncedEnforcer ::GetPolicy() {
PoliciesValues SyncedEnforcer ::GetPolicy() {
std::shared_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::GetPolicy();
}

// GetNamedPolicy gets all the authorization rules in the name:x::d policy.
std::vector<std::vector<std::string>> SyncedEnforcer ::GetNamedPolicy(const std::string& ptype) {
PoliciesValues SyncedEnforcer ::GetNamedPolicy(const std::string& ptype) {
std::shared_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::GetNamedPolicy(ptype);
}

// GetFilteredNamedPolicy gets all the authorization rules in the named policy, field filters can be specified.
std::vector<std::vector<std::string>> SyncedEnforcer ::GetFilteredNamedPolicy(const std::string& ptype, int fieldIndex, const std::vector<std::string>& fieldValues) {
PoliciesValues SyncedEnforcer ::GetFilteredNamedPolicy(const std::string& ptype, int fieldIndex, const std::vector<std::string>& fieldValues) {
std::shared_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::GetFilteredNamedPolicy(ptype, fieldIndex, fieldValues);
}

// GetGroupingPolicy gets all the role inheritance rules in the policy.
std::vector<std::vector<std::string>> SyncedEnforcer ::GetGroupingPolicy() {
PoliciesValues SyncedEnforcer ::GetGroupingPolicy() {
std::shared_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::GetGroupingPolicy();
}

// GetFilteredGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified.
std::vector<std::vector<std::string>> SyncedEnforcer ::GetFilteredGroupingPolicy(int fieldIndex, const std::vector<std::string>& fieldValues) {
PoliciesValues SyncedEnforcer ::GetFilteredGroupingPolicy(int fieldIndex, const std::vector<std::string>& fieldValues) {
std::shared_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::GetFilteredGroupingPolicy(fieldIndex, fieldValues);
}

// GetNamedGroupingPolicy gets all the role inheritance rules in the policy.
std::vector<std::vector<std::string>> SyncedEnforcer ::GetNamedGroupingPolicy(const std::string& ptype) {
PoliciesValues SyncedEnforcer ::GetNamedGroupingPolicy(const std::string& ptype) {
std::shared_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::GetNamedGroupingPolicy(ptype);
}

// GetFilteredNamedGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified.
std::vector<std::vector<std::string>> SyncedEnforcer ::GetFilteredNamedGroupingPolicy(const std::string& ptype, int fieldIndex, const std::vector<std::string>& fieldValues) {
PoliciesValues SyncedEnforcer ::GetFilteredNamedGroupingPolicy(const std::string& ptype, int fieldIndex, const std::vector<std::string>& fieldValues) {
std::shared_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::GetFilteredNamedGroupingPolicy(ptype, fieldIndex, fieldValues);
}
Expand Down Expand Up @@ -344,7 +344,7 @@ bool SyncedEnforcer ::AddPolicy(const std::vector<std::string>& params) {
// AddPolicies adds authorization rules to the current policy.
// If the rule already exists, the function returns false for the corresponding rule and the rule will not be added.
// Otherwise the function returns true for the corresponding rule by adding the new rule.
bool SyncedEnforcer ::AddPolicies(const std::vector<std::vector<std::string>>& rules) {
bool SyncedEnforcer ::AddPolicies(const PoliciesValues& rules) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::AddPolicies(rules);
}
Expand All @@ -360,7 +360,7 @@ bool SyncedEnforcer ::AddNamedPolicy(const std::string& ptype, const std::vector
// AddNamedPolicies adds authorization rules to the current named policy.
// If the rule already exists, the function returns false for the corresponding rule and the rule will not be added.
// Otherwise the function returns true for the corresponding by adding the new rule.
bool SyncedEnforcer ::AddNamedPolicies(const std::string& ptype, const std::vector<std::vector<std::string>>& rules) {
bool SyncedEnforcer ::AddNamedPolicies(const std::string& ptype, const PoliciesValues& rules) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::AddNamedPolicies(ptype, rules);
}
Expand All @@ -383,18 +383,18 @@ bool SyncedEnforcer ::UpdateNamedPolicy(const std::string& ptype, const std::vec
}

// UpdatePolicies updates authorization rules from the current policies.
bool SyncedEnforcer ::UpdatePolicies(const std::vector<std::vector<std::string>>& oldPolices, const std::vector<std::vector<std::string>>& newPolicies) {
bool SyncedEnforcer ::UpdatePolicies(const PoliciesValues& oldPolices, const PoliciesValues& newPolicies) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::UpdatePolicies(oldPolices, newPolicies);
}

bool SyncedEnforcer ::UpdateNamedPolicies(const std::string& ptype, const std::vector<std::vector<std::string>>& p1, const std::vector<std::vector<std::string>>& p2) {
bool SyncedEnforcer ::UpdateNamedPolicies(const std::string& ptype, const PoliciesValues& p1, const PoliciesValues& p2) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::UpdateNamedPolicies(ptype, p1, p2);
}

// RemovePolicies removes authorization rules from the current policy.
bool SyncedEnforcer ::RemovePolicies(const std::vector<std::vector<std::string>>& rules) {
bool SyncedEnforcer ::RemovePolicies(const PoliciesValues& rules) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::RemovePolicies(rules);
}
Expand All @@ -412,7 +412,7 @@ bool SyncedEnforcer ::RemoveNamedPolicy(const std::string& ptype, const std::vec
}

// RemoveNamedPolicies removes authorization rules from the current named policy.
bool SyncedEnforcer ::RemoveNamedPolicies(const std::string& ptype, const std::vector<std::vector<std::string>>& rules) {
bool SyncedEnforcer ::RemoveNamedPolicies(const std::string& ptype, const PoliciesValues& rules) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::RemoveNamedPolicies(ptype, rules);
}
Expand Down Expand Up @@ -446,7 +446,7 @@ bool SyncedEnforcer ::AddGroupingPolicy(const std::vector<std::string>& params)
// AddGroupingPolicies adds role inheritance rulea to the current policy.
// If the rule already exists, the function returns false for the corresponding policy rule and the rule will not be added.
// Otherwise the function returns true for the corresponding policy rule by adding the new rule.
bool SyncedEnforcer ::AddGroupingPolicies(const std::vector<std::vector<std::string>>& rules) {
bool SyncedEnforcer ::AddGroupingPolicies(const PoliciesValues& rules) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::AddGroupingPolicies(rules);
}
Expand All @@ -462,7 +462,7 @@ bool SyncedEnforcer ::AddNamedGroupingPolicy(const std::string& ptype, const std
// AddNamedGroupingPolicies adds named role inheritance rules to the current policy.
// If the rule already exists, the function returns false for the corresponding policy rule and the rule will not be added.
// Otherwise the function returns true for the corresponding policy rule by adding the new rule.
bool SyncedEnforcer ::AddNamedGroupingPolicies(const std::string& ptype, const std::vector<std::vector<std::string>>& rules) {
bool SyncedEnforcer ::AddNamedGroupingPolicies(const std::string& ptype, const PoliciesValues& rules) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::AddNamedGroupingPolicies(ptype, rules);
}
Expand All @@ -474,7 +474,7 @@ bool SyncedEnforcer ::RemoveGroupingPolicy(const std::vector<std::string>& param
}

// RemoveGroupingPolicies removes role inheritance rules from the current policy.
bool SyncedEnforcer ::RemoveGroupingPolicies(const std::vector<std::vector<std::string>>& rules) {
bool SyncedEnforcer ::RemoveGroupingPolicies(const PoliciesValues& rules) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::RemoveGroupingPolicies(rules);
}
Expand All @@ -492,7 +492,7 @@ bool SyncedEnforcer ::RemoveNamedGroupingPolicy(const std::string& ptype, const
}

// RemoveNamedGroupingPolicies removes role inheritance rules from the current named policy.
bool SyncedEnforcer ::RemoveNamedGroupingPolicies(const std::string& ptype, const std::vector<std::vector<std::string>>& rules) {
bool SyncedEnforcer ::RemoveNamedGroupingPolicies(const std::string& ptype, const PoliciesValues& rules) {
std::unique_lock<std::shared_mutex> lock(policyMutex);
return Enforcer::RemoveNamedGroupingPolicies(ptype, rules);
}
Expand Down
18 changes: 9 additions & 9 deletions casbin/internal_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ bool Enforcer::addPolicy(const std::string& sec, const std::string& p_type, cons
return rule_added;

if (sec == "g") {
std::vector<std::vector<std::string>> rules{rule};
PoliciesValues rules({rule});
this->BuildIncrementalRoleLinks(policy_add, p_type, rules);
}

Expand All @@ -57,7 +57,7 @@ bool Enforcer::addPolicy(const std::string& sec, const std::string& p_type, cons
}

// addPolicies adds rules to the current policy.
bool Enforcer::addPolicies(const std::string& sec, const std::string& p_type, const std::vector<std::vector<std::string>>& rules) {
bool Enforcer::addPolicies(const std::string& sec, const std::string& p_type, const PoliciesValues& rules) {
bool rules_added = m_model->AddPolicies(sec, p_type, rules);
if (!rules_added)
return rules_added;
Expand Down Expand Up @@ -85,7 +85,7 @@ bool Enforcer::removePolicy(const std::string& sec, const std::string& p_type, c
return rule_removed;

if (sec == "g") {
std::vector<std::vector<std::string>> rules{rule};
PoliciesValues rules({rule});
this->BuildIncrementalRoleLinks(policy_add, p_type, rules);
}

Expand All @@ -107,7 +107,7 @@ bool Enforcer::removePolicy(const std::string& sec, const std::string& p_type, c
}

// removePolicies removes rules from the current policy.
bool Enforcer::removePolicies(const std::string& sec, const std::string& p_type, const std::vector<std::vector<std::string>>& rules) {
bool Enforcer::removePolicies(const std::string& sec, const std::string& p_type, const PoliciesValues& rules) {
bool rules_removed = m_model->AddPolicies(sec, p_type, rules);
if (!rules_removed)
return rules_removed;
Expand All @@ -130,9 +130,9 @@ bool Enforcer::removePolicies(const std::string& sec, const std::string& p_type,

// removeFilteredPolicy removes rules based on field filters from the current policy.
bool Enforcer::removeFilteredPolicy(const std::string& sec, const std::string& p_type, int field_index, const std::vector<std::string>& field_values) {
std::pair<int, std::vector<std::vector<std::string>>> p = m_model->RemoveFilteredPolicy(sec, p_type, field_index, field_values);
std::pair<int, PoliciesValues> p = m_model->RemoveFilteredPolicy(sec, p_type, field_index, field_values);
bool rule_removed = p.first;
std::vector<std::vector<std::string>> effects = p.second;
PoliciesValues effects = p.second;

if (!rule_removed)
return rule_removed;
Expand Down Expand Up @@ -163,8 +163,8 @@ bool Enforcer::updatePolicy(const std::string& sec, const std::string& p_type, c
return false;

if (sec == "g") {
this->BuildIncrementalRoleLinks(policy_remove, p_type, {oldRule});
this->BuildIncrementalRoleLinks(policy_add, p_type, {newRule});
this->BuildIncrementalRoleLinks(policy_remove, p_type, PoliciesValues({oldRule}));
this->BuildIncrementalRoleLinks(policy_add, p_type, PoliciesValues({newRule}));
}
if (m_watcher && m_auto_notify_watcher) {
if (IsInstanceOf<WatcherUpdatable>(m_watcher.get())) {
Expand All @@ -176,7 +176,7 @@ bool Enforcer::updatePolicy(const std::string& sec, const std::string& p_type, c
return is_rule_updated;
}

bool Enforcer::updatePolicies(const std::string& sec, const std::string& p_type, const std::vector<std::vector<std::string>>& oldRules, const std::vector<std::vector<std::string>>& newRules) {
bool Enforcer::updatePolicies(const std::string& sec, const std::string& p_type, const PoliciesValues& oldRules, const PoliciesValues& newRules) {
bool is_rules_updated = m_model->UpdatePolicies(sec, p_type, oldRules, newRules);
if (!is_rules_updated)
return false;
Expand Down
Loading

0 comments on commit cbeed65

Please sign in to comment.