1 /*
2 * Copyright (c) 2022 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
16 #include "resource_node_pool.h"
17
18 #include <mutex>
19 #include <set>
20 #include <unordered_map>
21
22 #include <singleton.h>
23
24 #include "iam_check.h"
25 #include "iam_logger.h"
26
27 #define LOG_TAG "USER_AUTH_SA"
28
29 namespace OHOS {
30 namespace UserIam {
31 namespace UserAuth {
32 class ResourceNodePoolImpl final : public ResourceNodePool, public Singleton<ResourceNodePoolImpl> {
33 public:
34 bool Insert(const std::shared_ptr<ResourceNode> &resource) override;
35 bool Delete(uint64_t executorIndex) override;
36 void DeleteAll() override;
37 std::weak_ptr<ResourceNode> Select(uint64_t executorIndex) const override;
38 uint32_t GetPoolSize() const override;
39 void Enumerate(std::function<void(const std::weak_ptr<ResourceNode> &)> action) const override;
40 bool RegisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> &listener) override;
41 bool DeregisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> &listener) override;
42 void GetResourceNodeByTypeAndRole(AuthType authType,
43 ExecutorRole role, std::vector<std::weak_ptr<ResourceNode>> &authTypeNodes) override;
44
45 private:
46 struct ResourceNodeParam {
47 uint32_t count = 0;
48 std::shared_ptr<ResourceNode> node = nullptr;
49 };
50 mutable std::recursive_mutex poolMutex_;
51 std::unordered_map<uint64_t, ResourceNodeParam> resourceNodeMap_;
52 std::set<std::shared_ptr<ResourceNodePoolListener>> listenerSet_;
53 };
54
Insert(const std::shared_ptr<ResourceNode> & resource)55 bool ResourceNodePoolImpl::Insert(const std::shared_ptr<ResourceNode> &resource)
56 {
57 if (resource == nullptr) {
58 IAM_LOGE("resource is nullptr");
59 return false;
60 }
61 std::lock_guard<std::recursive_mutex> lock(poolMutex_);
62 uint64_t executorIndex = resource->GetExecutorIndex();
63
64 ResourceNodeParam nodeParam = {1, resource};
65 auto iter = resourceNodeMap_.find(executorIndex);
66 if (iter != resourceNodeMap_.end()) {
67 if (nodeParam.count < UINT32_MAX) {
68 nodeParam.count = iter->second.count + 1;
69 }
70 if (iter->second.node != nullptr) {
71 iter->second.node->DetachFromDriver();
72 }
73 }
74
75 auto result = resourceNodeMap_.insert_or_assign(executorIndex, nodeParam);
76 auto tempListenerSet = listenerSet_;
77 if (result.second) {
78 IAM_LOGI("insert resource node success");
79 for (const auto &listener : tempListenerSet) {
80 if (listener != nullptr) {
81 listener->OnResourceNodePoolInsert(nodeParam.node);
82 }
83 }
84 } else {
85 IAM_LOGI("update resource node success, count: %{public}u", resourceNodeMap_[executorIndex].count);
86 for (const auto &listener : tempListenerSet) {
87 if (listener != nullptr) {
88 listener->OnResourceNodePoolUpdate(nodeParam.node);
89 }
90 }
91 }
92 return true;
93 }
94
Delete(uint64_t executorIndex)95 bool ResourceNodePoolImpl::Delete(uint64_t executorIndex)
96 {
97 std::lock_guard<std::recursive_mutex> lock(poolMutex_);
98 auto iter = resourceNodeMap_.find(executorIndex);
99 if (iter == resourceNodeMap_.end()) {
100 IAM_LOGE("executor not found");
101 return false;
102 }
103
104 if (iter->second.count > 1) {
105 iter->second.count--;
106 IAM_LOGI("resource node count %{public}u, no delete", iter->second.count);
107 return true;
108 }
109 IAM_LOGI("delete resource node");
110
111 auto tempResource = iter->second.node;
112 resourceNodeMap_.erase(iter);
113 IF_FALSE_LOGE_AND_RETURN_VAL(tempResource != nullptr, false);
114 tempResource->DeleteFromDriver();
115
116 auto tempListenerSet = listenerSet_;
117 for (const auto &listener : tempListenerSet) {
118 if (listener != nullptr) {
119 listener->OnResourceNodePoolDelete(tempResource);
120 }
121 }
122 return true;
123 }
124
DeleteAll()125 void ResourceNodePoolImpl::DeleteAll()
126 {
127 std::lock_guard<std::recursive_mutex> lock(poolMutex_);
128 IAM_LOGI("delete all resource node begin, node num %{public}zu", resourceNodeMap_.size());
129 for (const auto &pair : resourceNodeMap_) {
130 auto node = pair.second.node;
131 if (node != nullptr) {
132 node->DeleteFromDriver();
133 }
134 }
135 auto tempMap = resourceNodeMap_;
136 auto tempListenerSet = listenerSet_;
137 resourceNodeMap_.clear();
138 for (auto &node : tempMap) {
139 for (const auto &listener : tempListenerSet) {
140 if (listener != nullptr) {
141 listener->OnResourceNodePoolDelete(node.second.node);
142 }
143 }
144 }
145 IAM_LOGI("delete all resource node success");
146 }
147
Select(uint64_t executorIndex) const148 std::weak_ptr<ResourceNode> ResourceNodePoolImpl::Select(uint64_t executorIndex) const
149 {
150 std::lock_guard<std::recursive_mutex> lock(poolMutex_);
151 std::weak_ptr<ResourceNode> result;
152 auto iter = resourceNodeMap_.find(executorIndex);
153 if (iter != resourceNodeMap_.end()) {
154 result = iter->second.node;
155 }
156 return result;
157 }
158
Enumerate(std::function<void (const std::weak_ptr<ResourceNode> &)> action) const159 void ResourceNodePoolImpl::Enumerate(std::function<void(const std::weak_ptr<ResourceNode> &)> action) const
160 {
161 if (action == nullptr) {
162 IAM_LOGE("action is nullptr");
163 return;
164 }
165 std::lock_guard<std::recursive_mutex> lock(poolMutex_);
166 for (auto &node : resourceNodeMap_) {
167 action(node.second.node);
168 }
169 }
170
GetPoolSize() const171 uint32_t ResourceNodePoolImpl::GetPoolSize() const
172 {
173 std::lock_guard<std::recursive_mutex> lock(poolMutex_);
174 return resourceNodeMap_.size();
175 }
176
RegisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> & listener)177 bool ResourceNodePoolImpl::RegisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> &listener)
178 {
179 if (listener == nullptr) {
180 IAM_LOGE("listener is nullptr");
181 return false;
182 }
183 std::lock_guard<std::recursive_mutex> lock(poolMutex_);
184 listenerSet_.insert(listener);
185 return true;
186 }
187
DeregisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> & listener)188 bool ResourceNodePoolImpl::DeregisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> &listener)
189 {
190 std::lock_guard<std::recursive_mutex> lock(poolMutex_);
191 return listenerSet_.erase(listener) == 1;
192 }
193
GetResourceNodeByTypeAndRole(AuthType authType,ExecutorRole role,std::vector<std::weak_ptr<ResourceNode>> & authTypeNodes)194 void ResourceNodePoolImpl::GetResourceNodeByTypeAndRole(AuthType authType,
195 ExecutorRole role, std::vector<std::weak_ptr<ResourceNode>> &authTypeNodes)
196 {
197 IAM_LOGI("start");
198 authTypeNodes.clear();
199 ResourceNodePool::Instance().Enumerate(
200 [&authTypeNodes, role, authType](const std::weak_ptr<ResourceNode> &weakNode) {
201 auto node = weakNode.lock();
202 if (node == nullptr) {
203 return;
204 }
205 if (node->GetAuthType() != authType) {
206 return;
207 }
208 if (node->GetExecutorRole() != role) {
209 return;
210 }
211 authTypeNodes.push_back(node);
212 });
213 }
214
Instance()215 ResourceNodePool &ResourceNodePool::Instance()
216 {
217 return ResourceNodePoolImpl::GetInstance();
218 }
219 } // namespace UserAuth
220 } // namespace UserIam
221 } // namespace OHOS
222