1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <utility>
16 #include <memory>
17 #include <unistd.h>
18 #include "safwk_log.h"
19 #include "string_ex.h"
20 #include "api_cache_manager.h"
21
22 namespace OHOS {
23 namespace {
24 const std::string TAG = "ApiCacheManager";
25 }
26
GetInstance()27 ApiCacheManager& ApiCacheManager::GetInstance()
28 {
29 static ApiCacheManager instance;
30 return instance;
31 }
32
AddCacheApi(const std::u16string & descriptor,uint32_t apiCode,int64_t expireTimeSec)33 void ApiCacheManager::AddCacheApi(const std::u16string& descriptor, uint32_t apiCode, int64_t expireTimeSec)
34 {
35 constexpr size_t defaultCacheSize = 8;
36 auto apiPair = std::make_pair(descriptor, apiCode);
37
38 std::lock_guard<std::mutex> lock(cachesMutex_);
39 auto iter = caches_.find(apiPair);
40 if (iter == caches_.end()) {
41 auto obj = new ExpireLruCache<std::vector<uint8_t>, std::vector<uint8_t>> (defaultCacheSize, expireTimeSec);
42 caches_[apiPair] = obj;
43 return;
44 }
45
46 HILOGD(TAG, "Cache api(%{public}s, apiCode:%{public}u) already exists", Str16ToStr8(descriptor).c_str(), apiCode);
47 return;
48 }
49
DelCacheApi(const std::u16string & descriptor,uint32_t apiCode)50 void ApiCacheManager::DelCacheApi(const std::u16string& descriptor, uint32_t apiCode)
51 {
52 auto apiPair = std::make_pair(descriptor, apiCode);
53 std::lock_guard<std::mutex> lock(cachesMutex_);
54 auto iter = caches_.find(apiPair);
55 if (iter != caches_.end()) {
56 if (iter->second != nullptr) {
57 delete iter->second;
58 }
59 caches_.erase(apiPair);
60 HILOGD(TAG, "Delete cache api(%{public}s, apiCode:%{public}u)", Str16ToStr8(descriptor).c_str(), apiCode);
61 }
62
63 return;
64 }
65
ClearCache()66 void ApiCacheManager::ClearCache()
67 {
68 std::lock_guard<std::mutex> lock(cachesMutex_);
69 for (auto &iter : caches_) {
70 if (iter.second != nullptr) {
71 iter.second->Clear();
72 HILOGD(TAG, "Clear the api(%{public}s, apiCode:%{public}u) cache",
73 Str16ToStr8(iter.first.first).c_str(), iter.first.second);
74 }
75 }
76 return;
77 }
78
ClearCache(const std::u16string & descriptor)79 void ApiCacheManager::ClearCache(const std::u16string& descriptor)
80 {
81 std::lock_guard<std::mutex> lock(cachesMutex_);
82 for (auto &iter : caches_) {
83 if ((iter.first.first == descriptor) && (iter.second != nullptr)) {
84 HILOGD(TAG, "Clear the api(%{public}s, apiCode:%{public}u) cache",
85 Str16ToStr8(descriptor).c_str(), iter.first.second);
86 iter.second->Clear();
87 }
88 }
89 return;
90 }
91
ClearCache(const std::u16string & descriptor,int32_t apiCode)92 void ApiCacheManager::ClearCache(const std::u16string& descriptor, int32_t apiCode)
93 {
94 std::lock_guard<std::mutex> lock(cachesMutex_);
95 auto iter = caches_.find(std::make_pair(descriptor, apiCode));
96 if ((iter != caches_.end()) && (iter->second != nullptr)) {
97 HILOGD(TAG, "Clear the api(%{public}s, apiCode:%{public}u) cache",
98 Str16ToStr8(descriptor).c_str(), apiCode);
99 iter->second->Clear();
100 }
101
102 return;
103 }
104
PreSendRequest(const std::u16string & descriptor,uint32_t apiCode,const MessageParcel & data,MessageParcel & reply)105 bool ApiCacheManager::PreSendRequest(const std::u16string& descriptor, uint32_t apiCode, const MessageParcel& data,
106 MessageParcel& reply)
107 {
108 uint8_t *key = reinterpret_cast<uint8_t *>(data.GetData());
109 size_t keySize = data.GetDataSize();
110 std::vector<uint8_t> keyVec(key, key + keySize);
111
112 std::pair<std::u16string, uint32_t> myPair = std::make_pair(descriptor, apiCode);
113 std::lock_guard<std::mutex> lock(cachesMutex_);
114 auto cache = caches_.find(myPair);
115 if ((cache == caches_.end()) || (cache->second == nullptr)) {
116 HILOGD(TAG, "Find cache api(%{public}s, apiCode:%{public}u) from map failed, maybe this api is no cacheable",
117 Str16ToStr8(descriptor).c_str(), apiCode);
118 return false;
119 }
120
121 std::shared_ptr<std::vector<uint8_t>> valueVec = cache->second->Get(keyVec);
122 if (valueVec == nullptr) {
123 HILOGD(TAG, "Cache hit failure");
124 return false;
125 }
126
127 reply.WriteBuffer(reinterpret_cast<void *>(&(*valueVec)[0]), valueVec->size());
128 HILOGD(TAG, "Cache hit success");
129 return true;
130 }
131
PostSendRequest(const std::u16string & descriptor,uint32_t apiCode,const MessageParcel & data,MessageParcel & reply)132 bool ApiCacheManager::PostSendRequest(const std::u16string& descriptor, uint32_t apiCode, const MessageParcel& data,
133 MessageParcel& reply)
134 {
135 uint8_t *key = reinterpret_cast<uint8_t *>(data.GetData());
136 size_t keySize = data.GetDataSize();
137 std::vector<uint8_t> keyVec(key, key + keySize);
138
139 std::pair<std::u16string, uint32_t> myPair = std::make_pair(descriptor, apiCode);
140 std::lock_guard<std::mutex> lock(cachesMutex_);
141 auto cache = caches_.find(myPair);
142 if ((cache == caches_.end()) || (cache->second == nullptr)) {
143 HILOGD(TAG, "Find cache api(%{public}s, apiCode:%{public}u) from map failed, maybe this api is no cacheable",
144 Str16ToStr8(descriptor).c_str(), apiCode);
145 return false;
146 }
147
148 uint8_t *value = reinterpret_cast<uint8_t *>(reply.GetData());
149 size_t valueSize = reply.GetDataSize();
150 std::vector<uint8_t> valueVec(value, value + valueSize);
151
152 cache->second->Add(keyVec, valueVec);
153 HILOGD(TAG, "Cache the reply of this call");
154
155 return true;
156 }
157 }