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