• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #define LOG_TAG "DBAdaptor"
17 #include "db_delegate.h"
18 
19 #include "account/account_delegate.h"
20 #include "kv_delegate.h"
21 #include "log_print.h"
22 #include "rdb_delegate.h"
23 #include "log_debug.h"
24 
25 namespace OHOS::DataShare {
26 using Account = DistributedData::AccountDelegate;
27 ExecutorPool::TaskId DBDelegate::taskId_ = ExecutorPool::INVALID_TASK_ID;
28 ExecutorPool::TaskId DBDelegate::taskIdEncrypt_ = ExecutorPool::INVALID_TASK_ID;
29 ConcurrentMap<uint32_t, std::map<std::string, std::shared_ptr<DBDelegate::Entity>>> DBDelegate::stores_ = {};
30 ConcurrentMap<uint32_t, std::map<std::string, std::shared_ptr<DBDelegate::Entity>>> DBDelegate::storesEncrypt_ = {};
31 std::shared_ptr<ExecutorPool> DBDelegate::executor_ = nullptr;
Create(DistributedData::StoreMetaData & metaData,const std::string & extUri,const std::string & backup)32 std::shared_ptr<DBDelegate> DBDelegate::Create(DistributedData::StoreMetaData &metaData,
33     const std::string &extUri, const std::string &backup)
34 {
35     if (Account::GetInstance()->IsDeactivating(atoi(metaData.user.c_str()))) {
36         ZLOGW("user %{public}s is deactivating, storeName: %{public}s", metaData.user.c_str(),
37               StringUtils::GeneralAnonymous(metaData.GetStoreAlias()).c_str());
38         return nullptr;
39     }
40     std::shared_ptr<DBDelegate> store;
41     auto storeFunc = [&metaData, &store, extUri, &backup]
42         (auto &, std::map<std::string, std::shared_ptr<Entity>> &stores) -> bool {
43         auto it = stores.find(metaData.storeId);
44         if (it != stores.end()) {
45             store = it->second->store_;
46             it->second->time_ = std::chrono::steady_clock::now() + std::chrono::seconds(INTERVAL);
47             return !stores.empty();
48         }
49         store = std::make_shared<RdbDelegate>();
50         auto entity = std::make_shared<Entity>(store, metaData);
51         stores.emplace(metaData.storeId, entity);
52         StartTimer(metaData.isEncrypt);
53         return !stores.empty();
54     };
55     if (metaData.isEncrypt) {
56         storesEncrypt_.Compute(metaData.tokenId, storeFunc);
57     } else {
58         stores_.Compute(metaData.tokenId, storeFunc);
59     }
60 
61     // rdbStore is initialized outside the ConcurrentMap, because this maybe a time-consuming operation.
62     bool success = store->Init(metaData, NO_CHANGE_VERSION, true, extUri, backup);
63     if (success) {
64         return store;
65     }
66     ZLOGE("creator failed, storeName: %{public}s", StringUtils::GeneralAnonymous(metaData.GetStoreAlias()).c_str());
67     auto eraseFunc = [&metaData]
68         (auto &, std::map<std::string, std::shared_ptr<Entity>> &stores) -> bool {
69         stores.erase(metaData.storeId);
70         return !stores.empty();
71     };
72     if (metaData.isEncrypt) {
73         storesEncrypt_.Compute(metaData.tokenId, eraseFunc);
74     } else {
75         stores_.Compute(metaData.tokenId, eraseFunc);
76     }
77     return nullptr;
78 }
79 
SetExecutorPool(std::shared_ptr<ExecutorPool> executor)80 void DBDelegate::SetExecutorPool(std::shared_ptr<ExecutorPool> executor)
81 {
82     executor_ = std::move(executor);
83 }
84 
Close(const DBDelegate::Filter & filter)85 void DBDelegate::Close(const DBDelegate::Filter &filter)
86 {
87     if (filter == nullptr) {
88         return;
89     }
90     std::list<std::shared_ptr<DBDelegate::Entity>> closeStores;
91     auto eraseFunc = [&closeStores, &filter](auto &, std::map<std::string, std::shared_ptr<Entity>> &stores) {
92         for (auto it = stores.begin(); it != stores.end();) {
93             if (it->second == nullptr || filter(it->second->user)) {
94                 closeStores.push_back(it->second);
95                 it = stores.erase(it);
96             } else {
97                 ++it;
98             }
99         }
100         return stores.empty();
101     };
102     stores_.EraseIf(eraseFunc);
103     storesEncrypt_.EraseIf(eraseFunc);
104 }
105 
GarbageCollect(bool encrypt)106 void DBDelegate::GarbageCollect(bool encrypt)
107 {
108     std::list<std::shared_ptr<DBDelegate::Entity>> closeStores;
109     auto eraseFunc = [&closeStores](auto &, std::map<std::string, std::shared_ptr<Entity>> &stores) {
110         auto current = std::chrono::steady_clock::now();
111         for (auto it = stores.begin(); it != stores.end();) {
112             if (it->second->time_ < current) {
113                 closeStores.push_back(it->second);
114                 it = stores.erase(it);
115             } else {
116                 ++it;
117             }
118         }
119         return stores.empty();
120     };
121     if (encrypt) {
122         storesEncrypt_.EraseIf(eraseFunc);
123     } else {
124         stores_.EraseIf(eraseFunc);
125     }
126 }
127 
StartTimer(bool encrypt)128 void DBDelegate::StartTimer(bool encrypt)
129 {
130     ExecutorPool::TaskId& dstTaskId = encrypt ? taskIdEncrypt_ : taskId_;
131 
132     if (executor_ == nullptr || dstTaskId != Executor::INVALID_TASK_ID) {
133         return;
134     }
135     dstTaskId = executor_->Schedule(
136         [encrypt]() {
137             GarbageCollect(encrypt);
138             auto task = [encrypt]() {
139                 ExecutorPool::TaskId& dstTaskIdTemp = encrypt ? taskIdEncrypt_ : taskId_;
140                 if (executor_ == nullptr || dstTaskIdTemp == Executor::INVALID_TASK_ID) {
141                     return;
142                 }
143                 executor_->Remove(dstTaskIdTemp);
144                 ZLOGD_MACRO("remove timer, taskId: %{public}" PRIu64, dstTaskIdTemp);
145                 dstTaskIdTemp = Executor::INVALID_TASK_ID;
146             };
147             if (encrypt) {
148                 stores_.DoActionIfEmpty(task);
149             } else {
150                 storesEncrypt_.DoActionIfEmpty(task);
151             }
152         },
153         std::chrono::seconds(INTERVAL), std::chrono::seconds(INTERVAL));
154     ZLOGD_MACRO("start timer, taskId: %{public}" PRIu64, dstTaskId);
155 }
156 
Entity(std::shared_ptr<DBDelegate> store,const DistributedData::StoreMetaData & meta)157 DBDelegate::Entity::Entity(std::shared_ptr<DBDelegate> store, const DistributedData::StoreMetaData &meta)
158 {
159     store_ = std::move(store);
160     time_ = std::chrono::steady_clock::now() + std::chrono::seconds(INTERVAL);
161     user = meta.user;
162 }
163 
EraseStoreCache(const int32_t tokenId)164 void DBDelegate::EraseStoreCache(const int32_t tokenId)
165 {
166     stores_.Erase(tokenId);
167     storesEncrypt_.Erase(tokenId);
168 }
169 
GetInstance(const std::string & dir,const std::shared_ptr<ExecutorPool> & executors)170 std::shared_ptr<KvDBDelegate> KvDBDelegate::GetInstance(const std::string &dir,
171     const std::shared_ptr<ExecutorPool> &executors)
172 {
173     static std::shared_ptr<KvDBDelegate> delegate = nullptr;
174     static std::mutex mutex;
175     std::lock_guard<decltype(mutex)> lock(mutex);
176     if (delegate == nullptr && executors != nullptr) {
177         delegate = std::make_shared<KvDelegate>(dir, executors);
178     }
179     return delegate;
180 }
181 
Marshal(DistributedData::Serializable::json & node) const182 bool Id::Marshal(DistributedData::Serializable::json &node) const
183 {
184     auto ret = false;
185     if (userId == INVALID_USER) {
186         ret = SetValue(node[GET_NAME(_id)], _id);
187     } else {
188         ret = SetValue(node[GET_NAME(_id)], _id + "_" + std::to_string(userId));
189     }
190     return ret;
191 }
192 
Unmarshal(const DistributedData::Serializable::json & node)193 bool Id::Unmarshal(const DistributedData::Serializable::json &node)
194 {
195     return false;
196 }
197 
Id(const std::string & id,const int32_t userId)198 Id::Id(const std::string &id, const int32_t userId) : _id(id), userId(userId) {}
199 
VersionData(int version)200 VersionData::VersionData(int version) : version(version) {}
201 
Unmarshal(const DistributedData::Serializable::json & node)202 bool VersionData::Unmarshal(const DistributedData::Serializable::json &node)
203 {
204     return GetValue(node, GET_NAME(version), version);
205 }
206 
Marshal(DistributedData::Serializable::json & node) const207 bool VersionData::Marshal(DistributedData::Serializable::json &node) const
208 {
209     return SetValue(node[GET_NAME(version)], version);
210 }
211 
GetId() const212 const std::string &KvData::GetId() const
213 {
214     return id;
215 }
216 
KvData(const Id & id)217 KvData::KvData(const Id &id) : id(DistributedData::Serializable::Marshall(id)) {}
218 } // namespace OHOS::DataShare
219