class PluginCache {
public:
- PluginCache(ResultGetterInterfacePtr getter) : m_getter(getter) {}
+ PluginCache() {}
virtual int get(const std::string &session, const PolicyKey &key) = 0;
+ virtual int update(const std::string &session,
+ const PolicyKey &key,
+ const PolicyResult &result) = 0;
void registerPlugin(const PolicyType policyType, InterpreterInterfacePtr plugin) {
m_plugins[policyType] = plugin;
protected:
std::map<PolicyType, InterpreterInterfacePtr> m_plugins;
- ResultGetterInterfacePtr m_getter;
};
} // namespace Cynara
//This can be very time heavy. This part is welcomed to be optimized.
if (session != m_session) {
LOGD("Session changed from %s to %s.", m_session.c_str(), session.c_str());
- m_keyValue.clear();
- m_keyUsage.clear();
+ clear();
m_session = session;
+ return CYNARA_API_CACHE_MISS;
}
auto resultIt = m_keyValue.find(keyToString(key));
//Do we have entry in cache?
key.client().toString().c_str(),
key.user().toString().c_str(),
key.privilege().toString().c_str());
- return update(key);
+ return CYNARA_API_CACHE_MISS;
} else {
LOGD("Entry available for client=%s user=%s privilege=%s",
key.client().toString().c_str(),
LOGD("Entry usable.");
m_keyUsage.splice(m_keyUsage.begin(), m_keyUsage, resultIt->second.second);
return plugin->toResult(resultIt->second.first);
- } else {
- //remove from list and map and update
- LOGD("Entry not usable.");
- auto usage_it = resultIt->second.second;
- m_keyUsage.erase(usage_it);
- m_keyValue.erase(resultIt);
- return update(key);
}
+ //Remove unusable entry
+ LOGD("Entry not usable");
+ auto usageIt = resultIt->second.second;
+ m_keyUsage.erase(usageIt);
+ m_keyValue.erase(resultIt);
+ return CYNARA_API_CACHE_MISS;
}
}
m_keyValue.erase(value_it);
}
-int CapacityCache::update(const PolicyKey &key) {
- int ret;
- PolicyResult result;
- if ((ret = m_getter->requestResult(key, result)) != CYNARA_API_SUCCESS) {
- LOGE("Error fetching new entry.");
- return ret;
+int CapacityCache::update(const std::string &session,
+ const PolicyKey &key,
+ const PolicyResult &result) {
+ //This can be very time heavy. This part is welcomed to be optimized.
+ if (session != m_session) {
+ LOGD("Session changed from %s to %s.", m_session.c_str(), session.c_str());
+ clear();
+ m_session = session;
}
- LOGD("Fetched new entry.");
+
auto pluginIt = m_plugins.find(result.policyType());
//No registered plugin for returned type of policy
public:
static const std::size_t CACHE_DEFAULT_CAPACITY = 10000;
- CapacityCache(ResultGetterInterfacePtr getter,
- std::size_t capacity = CACHE_DEFAULT_CAPACITY) :
- PluginCache(getter),
+ CapacityCache(std::size_t capacity = CACHE_DEFAULT_CAPACITY) :
m_capacity(capacity) {}
int get(const std::string &session, const PolicyKey &key);
+ int update(const std::string& session,
+ const PolicyKey &key,
+ const PolicyResult &result);
void clear(void);
private:
static std::string keyToString(const PolicyKey &key);
void evict(void);
- int update(const PolicyKey &key);
+
std::size_t m_capacity;
std::string m_session;
Logic::Logic() {
m_socket = std::make_shared<SocketClient>(clientSocketPath, std::make_shared<ProtocolClient>());
- m_cache = std::make_shared<CapacityCache>(std::make_shared<PolicyGetter>(m_socket));
+ m_resultGetter = std::make_shared<PolicyGetter>(m_socket);
+ m_cache = std::make_shared<CapacityCache>();
auto naiveInterpreter = std::make_shared<NaiveInterpreter>();
m_cache->registerPlugin(PredefinedPolicyType::ALLOW, naiveInterpreter);
m_cache->registerPlugin(PredefinedPolicyType::DENY, naiveInterpreter);
int Logic::check(const std::string &client, const std::string &session, const std::string &user,
const std::string &privilege) noexcept
{
- PolicyKey key(client, user, privilege);
-
- if (!m_socket->isConnected())
+ if (!m_socket->isConnected()){
onDisconnected();
+ }
+ PolicyKey key(client, user, privilege);
auto ret = m_cache->get(session, key);
- if (ret == CYNARA_API_SERVICE_NOT_AVAILABLE)
- onDisconnected();
- return ret;
+ //Any other situation than cache miss
+ if (ret != CYNARA_API_CACHE_MISS) {
+ return ret;
+ }
+
+ //No value in Cache
+ PolicyResult result;
+ ret = m_resultGetter->requestResult(key, result);
+ if (ret != CYNARA_API_SUCCESS) {
+ LOGE("Error fetching new entry.");
+ return ret;
+ }
+
+ return m_cache->update(session, key, result);
}
void Logic::onDisconnected(void) {
class Logic : public ApiInterface {
private:
- PluginCachePtr m_cache;
SocketClientPtr m_socket;
+ ResultGetterInterfacePtr m_resultGetter;
+ PluginCachePtr m_cache;
void onDisconnected(void);