• 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_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