2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file CapacityCache.cpp
18 * @author Zofia Abramowska <z.abramowska@samsung.com>
20 * @brief This file contains capacity cache implementation.
25 #include <cynara-client-error.h>
28 #include <cache/CapacityCache.h>
32 int CapacityCache::get(const ClientSession &session, const PolicyKey &key) {
33 //This can be very time heavy. This part is welcomed to be optimized.
34 if (session != m_session) {
35 LOGD("Session changed from %s to %s.", m_session.c_str(), session.c_str());
38 return CYNARA_API_CACHE_MISS;
40 auto resultIt = m_keyValue.find(keyToString(key));
41 //Do we have entry in cache?
42 if (resultIt == m_keyValue.end()) {
43 LOGD("No entry for client=%s user=%s privilege=%s.",
44 key.client().toString().c_str(),
45 key.user().toString().c_str(),
46 key.privilege().toString().c_str());
47 return CYNARA_API_CACHE_MISS;
49 LOGD("Entry available for client=%s user=%s privilege=%s",
50 key.client().toString().c_str(),
51 key.user().toString().c_str(),
52 key.privilege().toString().c_str());
54 auto pluginIt = m_plugins.find(resultIt->second.first.policyType());
55 if (pluginIt == m_plugins.end()) {
56 LOGE("No plugin registered for given PolicyType : %" PRIu16,
57 resultIt->second.first.policyType());
58 return CYNARA_API_ACCESS_DENIED;
62 InterpreterInterfacePtr plugin = pluginIt->second;
63 if (plugin->isUsable(resultIt->second.first)) {
64 LOGD("Entry usable.");
65 m_keyUsage.splice(m_keyUsage.begin(), m_keyUsage, resultIt->second.second);
66 return plugin->toResult(resultIt->second.first);
68 //Remove unusable entry
69 LOGD("Entry not usable");
70 auto usageIt = resultIt->second.second;
71 m_keyUsage.erase(usageIt);
72 m_keyValue.erase(resultIt);
73 return CYNARA_API_CACHE_MISS;
77 void CapacityCache::clear(void) {
83 std::string CapacityCache::keyToString(const PolicyKey &key) {
84 const char separator = '\1';
85 auto clientStr = key.client().toString();
86 auto privilegeStr = key.privilege().toString();
87 auto userStr = key.user().toString();
88 return clientStr + privilegeStr + userStr + separator +
89 std::to_string(clientStr.size()) + separator +
90 std::to_string(privilegeStr.size()) + separator +
91 std::to_string(userStr.size());
94 void CapacityCache::evict(void) {
96 auto lastUsedKey = m_keyUsage.back();
97 m_keyUsage.pop_back();
99 auto value_it = m_keyValue.find(lastUsedKey);
100 m_keyValue.erase(value_it);
103 int CapacityCache::update(const ClientSession &session,
104 const PolicyKey &key,
105 const PolicyResult &result) {
106 //This can be very time heavy. This part is welcomed to be optimized.
107 if (session != m_session) {
108 LOGD("Session changed from %s to %s.", m_session.c_str(), session.c_str());
113 auto pluginIt = m_plugins.find(result.policyType());
115 //No registered plugin for returned type of policy
116 if (pluginIt == m_plugins.end()) {
117 LOGE("No registered plugin for given PolicyType: %" PRIu16,
118 result.policyType());
119 return CYNARA_API_ACCESS_DENIED;
121 auto plugin = pluginIt->second;
123 if (m_capacity != 0) {
124 if (plugin->isCacheable(result)) {
125 LOGD("Entry cacheable");
126 if (m_keyValue.size() == m_capacity) {
127 LOGD("Capacity reached.");
130 m_keyUsage.push_front(keyToString(key));
131 m_keyValue[keyToString(key)] = std::make_pair(result, m_keyUsage.begin());
134 return plugin->toResult(result);
137 } // namespace Cynara