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 
43 private:
44     struct ResourceNodeParam {
45         uint32_t count = 0;
46         std::shared_ptr<ResourceNode> node = nullptr;
47     };
48     mutable std::recursive_mutex poolMutex_;
49     std::unordered_map<uint64_t, ResourceNodeParam> resourceNodeMap_;
50     std::set<std::shared_ptr<ResourceNodePoolListener>> listenerSet_;
51 };
52 
Insert(const std::shared_ptr<ResourceNode> & resource)53 bool ResourceNodePoolImpl::Insert(const std::shared_ptr<ResourceNode> &resource)
54 {
55     if (resource == nullptr) {
56         IAM_LOGE("resource is nullptr");
57         return false;
58     }
59     std::lock_guard<std::recursive_mutex> lock(poolMutex_);
60     uint64_t executorIndex = resource->GetExecutorIndex();
61 
62     ResourceNodeParam nodeParam = {1, resource};
63     auto iter = resourceNodeMap_.find(executorIndex);
64     if (iter != resourceNodeMap_.end()) {
65         if (nodeParam.count < UINT32_MAX) {
66             nodeParam.count = iter->second.count + 1;
67         }
68         if (iter->second.node != nullptr) {
69             iter->second.node->DetachFromDriver();
70         }
71     }
72 
73     auto result = resourceNodeMap_.insert_or_assign(executorIndex, nodeParam);
74     if (result.second) {
75         IAM_LOGI("insert resource node success");
76         for (const auto &listener : listenerSet_) {
77             if (listener != nullptr) {
78                 listener->OnResourceNodePoolInsert(nodeParam.node);
79             }
80         }
81     } else {
82         IAM_LOGI("update resource node success, count: %{public}u", resourceNodeMap_[executorIndex].count);
83         for (const auto &listener : listenerSet_) {
84             if (listener != nullptr) {
85                 listener->OnResourceNodePoolUpdate(nodeParam.node);
86             }
87         }
88     }
89     return true;
90 }
91 
Delete(uint64_t executorIndex)92 bool ResourceNodePoolImpl::Delete(uint64_t executorIndex)
93 {
94     std::lock_guard<std::recursive_mutex> lock(poolMutex_);
95     auto iter = resourceNodeMap_.find(executorIndex);
96     if (iter == resourceNodeMap_.end()) {
97         IAM_LOGE("executor not found");
98         return false;
99     }
100 
101     if (iter->second.count > 1) {
102         iter->second.count--;
103         IAM_LOGI("resource node count %{public}u, no delete", iter->second.count);
104         return true;
105     }
106     IAM_LOGI("delete resource node");
107 
108     auto tempResource = iter->second.node;
109     IF_FALSE_LOGE_AND_RETURN_VAL(tempResource != nullptr, false);
110     tempResource->DeleteFromDriver();
111 
112     resourceNodeMap_.erase(iter);
113     for (const auto &listener : listenerSet_) {
114         if (listener != nullptr) {
115             listener->OnResourceNodePoolDelete(tempResource);
116         }
117     }
118     return true;
119 }
120 
DeleteAll()121 void ResourceNodePoolImpl::DeleteAll()
122 {
123     std::lock_guard<std::recursive_mutex> lock(poolMutex_);
124     IAM_LOGI("delete all resource node begin, node num %{public}zu", resourceNodeMap_.size());
125     for (const auto &pair : resourceNodeMap_) {
126         auto node = pair.second.node;
127         if (node != nullptr) {
128             node->DeleteFromDriver();
129         }
130     }
131     auto tempMap = resourceNodeMap_;
132     resourceNodeMap_.clear();
133     for (auto &node : tempMap) {
134         for (const auto &listener : listenerSet_) {
135             if (listener != nullptr) {
136                 listener->OnResourceNodePoolDelete(node.second.node);
137             }
138         }
139     }
140     IAM_LOGI("delete all resource node success");
141 }
142 
Select(uint64_t executorIndex) const143 std::weak_ptr<ResourceNode> ResourceNodePoolImpl::Select(uint64_t executorIndex) const
144 {
145     std::lock_guard<std::recursive_mutex> lock(poolMutex_);
146     std::weak_ptr<ResourceNode> result;
147     auto iter = resourceNodeMap_.find(executorIndex);
148     if (iter != resourceNodeMap_.end()) {
149         result = iter->second.node;
150     }
151     return result;
152 }
153 
Enumerate(std::function<void (const std::weak_ptr<ResourceNode> &)> action) const154 void ResourceNodePoolImpl::Enumerate(std::function<void(const std::weak_ptr<ResourceNode> &)> action) const
155 {
156     if (action == nullptr) {
157         IAM_LOGE("action is nullptr");
158         return;
159     }
160     std::lock_guard<std::recursive_mutex> lock(poolMutex_);
161     for (auto &node : resourceNodeMap_) {
162         action(node.second.node);
163     }
164 }
165 
GetPoolSize() const166 uint32_t ResourceNodePoolImpl::GetPoolSize() const
167 {
168     std::lock_guard<std::recursive_mutex> lock(poolMutex_);
169     return resourceNodeMap_.size();
170 }
171 
RegisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> & listener)172 bool ResourceNodePoolImpl::RegisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> &listener)
173 {
174     if (listener == nullptr) {
175         IAM_LOGE("listener is nullptr");
176         return false;
177     }
178     std::lock_guard<std::recursive_mutex> lock(poolMutex_);
179     listenerSet_.insert(listener);
180     return true;
181 }
182 
DeregisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> & listener)183 bool ResourceNodePoolImpl::DeregisterResourceNodePoolListener(const std::shared_ptr<ResourceNodePoolListener> &listener)
184 {
185     std::lock_guard<std::recursive_mutex> lock(poolMutex_);
186     return listenerSet_.erase(listener) == 1;
187 }
188 
Instance()189 ResourceNodePool &ResourceNodePool::Instance()
190 {
191     return ResourceNodePoolImpl::GetInstance();
192 }
193 } // namespace UserAuth
194 } // namespace UserIam
195 } // namespace OHOS
196