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_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 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>(metaData, NO_CHANGE_VERSION, true, extUri, backup);
50 if (store->IsInvalid()) {
51 store = nullptr;
52 ZLOGE("creator failed, storeName: %{public}s", metaData.GetStoreAlias().c_str());
53 return false;
54 }
55 auto entity = std::make_shared<Entity>(store, metaData);
56 stores.emplace(metaData.storeId, entity);
57 StartTimer(metaData.isEncrypt);
58 return !stores.empty();
59 };
60 if (metaData.isEncrypt) {
61 storesEncrypt_.Compute(metaData.tokenId, storeFunc);
62 } else {
63 stores_.Compute(metaData.tokenId, storeFunc);
64 }
65 return store;
66 }
67
SetExecutorPool(std::shared_ptr<ExecutorPool> executor)68 void DBDelegate::SetExecutorPool(std::shared_ptr<ExecutorPool> executor)
69 {
70 executor_ = std::move(executor);
71 }
72
Close(const DBDelegate::Filter & filter)73 void DBDelegate::Close(const DBDelegate::Filter &filter)
74 {
75 if (filter == nullptr) {
76 return;
77 }
78 std::list<std::shared_ptr<DBDelegate::Entity>> closeStores;
79 auto eraseFunc = [&closeStores, &filter](auto &, std::map<std::string, std::shared_ptr<Entity>> &stores) {
80 for (auto it = stores.begin(); it != stores.end();) {
81 if (it->second == nullptr || filter(it->second->user)) {
82 closeStores.push_back(it->second);
83 it = stores.erase(it);
84 } else {
85 ++it;
86 }
87 }
88 return stores.empty();
89 };
90 stores_.EraseIf(eraseFunc);
91 storesEncrypt_.EraseIf(eraseFunc);
92 }
93
GarbageCollect(bool encrypt)94 void DBDelegate::GarbageCollect(bool encrypt)
95 {
96 std::list<std::shared_ptr<DBDelegate::Entity>> closeStores;
97 auto eraseFunc = [&closeStores](auto &, std::map<std::string, std::shared_ptr<Entity>> &stores) {
98 auto current = std::chrono::steady_clock::now();
99 for (auto it = stores.begin(); it != stores.end();) {
100 if (it->second->time_ < current) {
101 closeStores.push_back(it->second);
102 it = stores.erase(it);
103 } else {
104 ++it;
105 }
106 }
107 return stores.empty();
108 };
109 if (encrypt) {
110 storesEncrypt_.EraseIf(eraseFunc);
111 } else {
112 stores_.EraseIf(eraseFunc);
113 }
114 }
115
StartTimer(bool encrypt)116 void DBDelegate::StartTimer(bool encrypt)
117 {
118 ExecutorPool::TaskId& dstTaskId = encrypt ? taskIdEncrypt_ : taskId_;
119
120 if (executor_ == nullptr || dstTaskId != Executor::INVALID_TASK_ID) {
121 return;
122 }
123 dstTaskId = executor_->Schedule(
124 [encrypt]() {
125 GarbageCollect(encrypt);
126 auto task = [encrypt]() {
127 ExecutorPool::TaskId& dstTaskIdTemp = encrypt ? taskIdEncrypt_ : taskId_;
128 if (executor_ == nullptr || dstTaskIdTemp == Executor::INVALID_TASK_ID) {
129 return;
130 }
131 executor_->Remove(dstTaskIdTemp);
132 ZLOGD_MACRO("remove timer, taskId: %{public}" PRIu64, dstTaskIdTemp);
133 dstTaskIdTemp = Executor::INVALID_TASK_ID;
134 };
135 if (encrypt) {
136 stores_.DoActionIfEmpty(task);
137 } else {
138 storesEncrypt_.DoActionIfEmpty(task);
139 }
140 },
141 std::chrono::seconds(INTERVAL), std::chrono::seconds(INTERVAL));
142 ZLOGD_MACRO("start timer, taskId: %{public}" PRIu64, dstTaskId);
143 }
144
Entity(std::shared_ptr<DBDelegate> store,const DistributedData::StoreMetaData & meta)145 DBDelegate::Entity::Entity(std::shared_ptr<DBDelegate> store, const DistributedData::StoreMetaData &meta)
146 {
147 store_ = std::move(store);
148 time_ = std::chrono::steady_clock::now() + std::chrono::seconds(INTERVAL);
149 user = meta.user;
150 }
151
EraseStoreCache(const int32_t tokenId)152 void DBDelegate::EraseStoreCache(const int32_t tokenId)
153 {
154 stores_.Erase(tokenId);
155 storesEncrypt_.Erase(tokenId);
156 }
157
GetInstance(bool reInit,const std::string & dir,const std::shared_ptr<ExecutorPool> & executors)158 std::shared_ptr<KvDBDelegate> KvDBDelegate::GetInstance(
159 bool reInit, const std::string &dir, const std::shared_ptr<ExecutorPool> &executors)
160 {
161 static std::shared_ptr<KvDBDelegate> delegate = nullptr;
162 static std::mutex mutex;
163 std::lock_guard<decltype(mutex)> lock(mutex);
164 if ((delegate == nullptr || reInit) && executors != nullptr) {
165 delegate = std::make_shared<KvDelegate>(dir, executors);
166 }
167 return delegate;
168 }
169
Marshal(DistributedData::Serializable::json & node) const170 bool Id::Marshal(DistributedData::Serializable::json &node) const
171 {
172 auto ret = false;
173 if (userId == INVALID_USER) {
174 ret = SetValue(node[GET_NAME(_id)], _id);
175 } else {
176 ret = SetValue(node[GET_NAME(_id)], _id + "_" + std::to_string(userId));
177 }
178 return ret;
179 }
180
Unmarshal(const DistributedData::Serializable::json & node)181 bool Id::Unmarshal(const DistributedData::Serializable::json &node)
182 {
183 return false;
184 }
185
Id(const std::string & id,const int32_t userId)186 Id::Id(const std::string &id, const int32_t userId) : _id(id), userId(userId) {}
187
VersionData(int version)188 VersionData::VersionData(int version) : version(version) {}
189
Unmarshal(const DistributedData::Serializable::json & node)190 bool VersionData::Unmarshal(const DistributedData::Serializable::json &node)
191 {
192 return GetValue(node, GET_NAME(version), version);
193 }
194
Marshal(DistributedData::Serializable::json & node) const195 bool VersionData::Marshal(DistributedData::Serializable::json &node) const
196 {
197 return SetValue(node[GET_NAME(version)], version);
198 }
199
GetId() const200 const std::string &KvData::GetId() const
201 {
202 return id;
203 }
204
KvData(const Id & id)205 KvData::KvData(const Id &id) : id(DistributedData::Serializable::Marshall(id)) {}
206 } // namespace OHOS::DataShare