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 #define LOG_TAG "KVDBServiceImpl"
16 #include "kvdb_service_impl.h"
17
18 #include <chrono>
19 #include <cinttypes>
20
21 #include "accesstoken_kit.h"
22 #include "account/account_delegate.h"
23 #include "backup_manager.h"
24 #include "checker/checker_manager.h"
25 #include "communication_provider.h"
26 #include "communication_strategy.h"
27 #include "crypto_manager.h"
28 #include "device_manager_adapter.h"
29 #include "directory/directory_manager.h"
30 #include "eventcenter/event_center.h"
31 #include "ipc_skeleton.h"
32 #include "log_print.h"
33 #include "matrix_event.h"
34 #include "metadata/appid_meta_data.h"
35 #include "metadata/meta_data_manager.h"
36 #include "permit_delegate.h"
37 #include "query_helper.h"
38 #include "upgrade.h"
39 #include "utils/anonymous.h"
40 #include "utils/constant.h"
41 #include "utils/converter.h"
42 namespace OHOS::DistributedKv {
43 using namespace OHOS::DistributedData;
44 using namespace OHOS::AppDistributedKv;
45 using namespace OHOS::Security::AccessToken;
46 using system_clock = std::chrono::system_clock;
47 using DMAdapter = DistributedData::DeviceManagerAdapter;
48 __attribute__((used)) KVDBServiceImpl::Factory KVDBServiceImpl::factory_;
Factory()49 KVDBServiceImpl::Factory::Factory()
50 {
51 FeatureSystem::GetInstance().RegisterCreator("kv_store", [this]() {
52 if (product_ == nullptr) {
53 product_ = std::make_shared<KVDBServiceImpl>();
54 }
55 return product_;
56 });
57 }
58
~Factory()59 KVDBServiceImpl::Factory::~Factory()
60 {
61 product_ = nullptr;
62 }
63
KVDBServiceImpl()64 KVDBServiceImpl::KVDBServiceImpl()
65 {
66 CommunicationStrategy::GetInstance().RegGetSyncDataSize("kv_store", [this](const std::string &deviceId) {
67 return GetSyncDataSize(deviceId);
68 });
69
70 EventCenter::GetInstance().Subscribe(DeviceMatrix::MATRIX_META_FINISHED, [this](const Event &event) {
71 auto &matrixEvent = static_cast<const MatrixEvent &>(event);
72 auto deviceId = matrixEvent.GetDeviceId();
73 auto refCount = matrixEvent.StealRefCount();
74 std::vector<StoreMetaData> metaData;
75 auto prefix = StoreMetaData::GetPrefix({ DMAdapter::GetInstance().GetLocalDevice().uuid });
76 if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) {
77 ZLOGE("load meta failed!");
78 return;
79 }
80
81 auto mask = matrixEvent.GetMask();
82 for (const auto &data : metaData) {
83 StoreMetaDataLocal localMetaData;
84 MetaDataManager::GetInstance().LoadMeta(data.GetKeyLocal(), localMetaData, true);
85 if (!localMetaData.HasPolicy(PolicyType::IMMEDIATE_SYNC_ON_ONLINE)) {
86 continue;
87 }
88
89 auto code = DeviceMatrix::GetInstance().GetCode(data);
90 if ((mask & code) != code) {
91 continue;
92 }
93
94 auto policy = localMetaData.GetPolicy(PolicyType::IMMEDIATE_SYNC_ON_ONLINE);
95 SyncInfo syncInfo;
96 syncInfo.mode = PUSH_PULL;
97 syncInfo.delay = 0;
98 syncInfo.devices = { deviceId };
99 if (policy.IsValueEffect()) {
100 syncInfo.delay = policy.valueUint;
101 }
102 ZLOGI("[online] appId:%{public}s, storeId:%{public}s", data.bundleName.c_str(),
103 Anonymous::Change(data.storeId).c_str());
104 auto delay = GetSyncDelayTime(syncInfo.delay, { data.storeId });
105 KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(data.tokenId), delay,
106 std::bind(&KVDBServiceImpl::DoSync, this, data, syncInfo, std::placeholders::_1, ACTION_SYNC),
107 std::bind(&KVDBServiceImpl::DoComplete, this, data, syncInfo, refCount, std::placeholders::_1));
108 }
109 });
110 }
111
~KVDBServiceImpl()112 KVDBServiceImpl::~KVDBServiceImpl()
113 {
114 }
115
GetStoreIds(const AppId & appId,std::vector<StoreId> & storeIds)116 Status KVDBServiceImpl::GetStoreIds(const AppId &appId, std::vector<StoreId> &storeIds)
117 {
118 std::vector<StoreMetaData> metaData;
119 auto user = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID());
120 auto deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
121 auto prefix = StoreMetaData::GetPrefix({ deviceId, std::to_string(user), "default", appId.appId });
122 auto instanceId = GetInstIndex(IPCSkeleton::GetCallingTokenID(), appId);
123 MetaDataManager::GetInstance().LoadMeta(prefix, metaData);
124 for (auto &item : metaData) {
125 if (item.storeType > KvStoreType::MULTI_VERSION || item.instanceId != instanceId) {
126 continue;
127 }
128 storeIds.push_back({ item.storeId });
129 }
130 ZLOGD("appId:%{public}s store size:%{public}zu", appId.appId.c_str(), storeIds.size());
131 return SUCCESS;
132 }
133
Delete(const AppId & appId,const StoreId & storeId)134 Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId)
135 {
136 StoreMetaData metaData = GetStoreMetaData(appId, storeId);
137 if (metaData.instanceId < 0) {
138 return ILLEGAL_STATE;
139 }
140
141 auto tokenId = IPCSkeleton::GetCallingTokenID();
142 syncAgents_.ComputeIfPresent(tokenId, [&appId, &storeId](auto &key, SyncAgent &syncAgent) {
143 if (syncAgent.pid_ != IPCSkeleton::GetCallingPid()) {
144 ZLOGW("agent already changed! old pid:%{public}d new pid:%{public}d appId:%{public}s",
145 IPCSkeleton::GetCallingPid(), syncAgent.pid_, appId.appId.c_str());
146 return true;
147 }
148 syncAgent.delayTimes_.erase(storeId);
149 syncAgent.observers_.erase(storeId);
150 return true;
151 });
152 MetaDataManager::GetInstance().DelMeta(metaData.GetKey());
153 MetaDataManager::GetInstance().DelMeta(metaData.GetSecretKey(), true);
154 MetaDataManager::GetInstance().DelMeta(metaData.GetStrategyKey());
155 MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true);
156 PermitDelegate::GetInstance().DelCache(metaData.GetKey());
157 storeCache_.CloseStore(tokenId, storeId);
158 ZLOGD("appId:%{public}s storeId:%{public}s instanceId:%{public}d", appId.appId.c_str(),
159 Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId);
160 return SUCCESS;
161 }
162
Sync(const AppId & appId,const StoreId & storeId,const SyncInfo & syncInfo)163 Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo)
164 {
165 StoreMetaData metaData = GetStoreMetaData(appId, storeId);
166 MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData);
167 auto delay = GetSyncDelayTime(syncInfo.delay, storeId);
168 if (metaData.isAutoSync && syncInfo.seqId == std::numeric_limits<uint64_t>::max()) {
169 DeviceMatrix::GetInstance().OnChanged(metaData);
170 StoreMetaDataLocal localMeta;
171 MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocal(), localMeta, true);
172 if (!localMeta.HasPolicy(IMMEDIATE_SYNC_ON_CHANGE)) {
173 ZLOGW("appId:%{public}s storeId:%{public}s no IMMEDIATE_SYNC_ON_CHANGE ", appId.appId.c_str(),
174 Anonymous::Change(storeId.storeId).c_str());
175 return Status::SUCCESS;
176 }
177 }
178 return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay,
179 std::bind(&KVDBServiceImpl::DoSync, this, metaData, syncInfo, std::placeholders::_1, ACTION_SYNC),
180 std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1));
181 }
182
RegisterSyncCallback(const AppId & appId,sptr<IKvStoreSyncCallback> callback)183 Status KVDBServiceImpl::RegisterSyncCallback(const AppId &appId, sptr<IKvStoreSyncCallback> callback)
184 {
185 auto tokenId = IPCSkeleton::GetCallingTokenID();
186 syncAgents_.Compute(tokenId, [&appId, callback](const auto &, SyncAgent &value) {
187 if (value.pid_ != IPCSkeleton::GetCallingPid()) {
188 value.ReInit(IPCSkeleton::GetCallingPid(), appId);
189 }
190 value.callback_ = callback;
191 return true;
192 });
193 return SUCCESS;
194 }
195
UnregisterSyncCallback(const AppId & appId)196 Status KVDBServiceImpl::UnregisterSyncCallback(const AppId &appId)
197 {
198 syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), [&appId](const auto &key, SyncAgent &value) {
199 if (value.pid_ != IPCSkeleton::GetCallingPid()) {
200 ZLOGW("agent already changed! old pid:%{public}d, new pid:%{public}d, appId:%{public}s",
201 IPCSkeleton::GetCallingPid(), value.pid_, appId.appId.c_str());
202 return true;
203 }
204 value.callback_ = nullptr;
205 return true;
206 });
207 return SUCCESS;
208 }
209
SetSyncParam(const AppId & appId,const StoreId & storeId,const KvSyncParam & syncParam)210 Status KVDBServiceImpl::SetSyncParam(const AppId &appId, const StoreId &storeId, const KvSyncParam &syncParam)
211 {
212 if (syncParam.allowedDelayMs > 0 && syncParam.allowedDelayMs < KvStoreSyncManager::SYNC_MIN_DELAY_MS) {
213 return Status::INVALID_ARGUMENT;
214 }
215 if (syncParam.allowedDelayMs > KvStoreSyncManager::SYNC_MAX_DELAY_MS) {
216 return Status::INVALID_ARGUMENT;
217 }
218 auto tokenId = IPCSkeleton::GetCallingTokenID();
219 syncAgents_.Compute(tokenId, [&appId, &storeId, &syncParam](auto &key, SyncAgent &value) {
220 if (value.pid_ != IPCSkeleton::GetCallingPid()) {
221 value.ReInit(IPCSkeleton::GetCallingPid(), appId);
222 }
223 value.delayTimes_[storeId] = syncParam.allowedDelayMs;
224 return true;
225 });
226 return SUCCESS;
227 }
228
GetSyncParam(const AppId & appId,const StoreId & storeId,KvSyncParam & syncParam)229 Status KVDBServiceImpl::GetSyncParam(const AppId &appId, const StoreId &storeId, KvSyncParam &syncParam)
230 {
231 syncParam.allowedDelayMs = 0;
232 auto tokenId = IPCSkeleton::GetCallingTokenID();
233 syncAgents_.ComputeIfPresent(tokenId, [&appId, &storeId, &syncParam](auto &key, SyncAgent &value) {
234 if (value.pid_ != IPCSkeleton::GetCallingPid()) {
235 ZLOGW("agent already changed! old pid:%{public}d, new pid:%{public}d, appId:%{public}s",
236 IPCSkeleton::GetCallingPid(), value.pid_, appId.appId.c_str());
237 return true;
238 }
239
240 auto it = value.delayTimes_.find(storeId);
241 if (it != value.delayTimes_.end()) {
242 syncParam.allowedDelayMs = it->second;
243 }
244 return true;
245 });
246 return SUCCESS;
247 }
248
EnableCapability(const AppId & appId,const StoreId & storeId)249 Status KVDBServiceImpl::EnableCapability(const AppId &appId, const StoreId &storeId)
250 {
251 StrategyMeta strategyMeta = GetStrategyMeta(appId, storeId);
252 if (strategyMeta.instanceId < 0) {
253 return ILLEGAL_STATE;
254 }
255 MetaDataManager::GetInstance().LoadMeta(strategyMeta.GetKey(), strategyMeta);
256 strategyMeta.capabilityEnabled = true;
257 MetaDataManager::GetInstance().SaveMeta(strategyMeta.GetKey(), strategyMeta);
258 return SUCCESS;
259 }
260
DisableCapability(const AppId & appId,const StoreId & storeId)261 Status KVDBServiceImpl::DisableCapability(const AppId &appId, const StoreId &storeId)
262 {
263 StrategyMeta strategyMeta = GetStrategyMeta(appId, storeId);
264 if (strategyMeta.instanceId < 0) {
265 return ILLEGAL_STATE;
266 }
267 MetaDataManager::GetInstance().LoadMeta(strategyMeta.GetKey(), strategyMeta);
268 strategyMeta.capabilityEnabled = false;
269 MetaDataManager::GetInstance().SaveMeta(strategyMeta.GetKey(), strategyMeta);
270 return SUCCESS;
271 }
272
SetCapability(const AppId & appId,const StoreId & storeId,const std::vector<std::string> & local,const std::vector<std::string> & remote)273 Status KVDBServiceImpl::SetCapability(const AppId &appId, const StoreId &storeId,
274 const std::vector<std::string> &local, const std::vector<std::string> &remote)
275 {
276 StrategyMeta strategy = GetStrategyMeta(appId, storeId);
277 if (strategy.instanceId < 0) {
278 return ILLEGAL_STATE;
279 }
280 MetaDataManager::GetInstance().LoadMeta(strategy.GetKey(), strategy);
281 strategy.capabilityRange.localLabel = local;
282 strategy.capabilityRange.remoteLabel = remote;
283 MetaDataManager::GetInstance().SaveMeta(strategy.GetKey(), strategy);
284 return SUCCESS;
285 }
286
AddSubscribeInfo(const AppId & appId,const StoreId & storeId,const SyncInfo & syncInfo)287 Status KVDBServiceImpl::AddSubscribeInfo(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo)
288 {
289 StoreMetaData metaData = GetStoreMetaData(appId, storeId);
290 MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData);
291 auto delay = GetSyncDelayTime(syncInfo.delay, storeId);
292 return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay,
293 std::bind(&KVDBServiceImpl::DoSync, this, metaData, syncInfo, std::placeholders::_1, ACTION_SUBSCRIBE),
294 std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1));
295 }
296
RmvSubscribeInfo(const AppId & appId,const StoreId & storeId,const SyncInfo & syncInfo)297 Status KVDBServiceImpl::RmvSubscribeInfo(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo)
298 {
299 StoreMetaData metaData = GetStoreMetaData(appId, storeId);
300 MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData);
301 auto delay = GetSyncDelayTime(syncInfo.delay, storeId);
302 return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay,
303 std::bind(&KVDBServiceImpl::DoSync, this, metaData, syncInfo, std::placeholders::_1, ACTION_UNSUBSCRIBE),
304 std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1));
305 }
306
Subscribe(const AppId & appId,const StoreId & storeId,sptr<IKvStoreObserver> observer)307 Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, sptr<IKvStoreObserver> observer)
308 {
309 auto tokenId = IPCSkeleton::GetCallingTokenID();
310 ZLOGI("appId:%{public}s storeId:%{public}s tokenId:0x%{public}x", appId.appId.c_str(),
311 Anonymous::Change(storeId.storeId).c_str(), tokenId);
312 syncAgents_.Compute(tokenId, [&appId, &storeId, &observer](auto &key, SyncAgent &value) {
313 if (value.pid_ != IPCSkeleton::GetCallingPid()) {
314 value.ReInit(IPCSkeleton::GetCallingPid(), appId);
315 }
316 auto it = value.observers_.find(storeId);
317 if (it == value.observers_.end()) {
318 value.observers_[storeId] = std::make_shared<StoreCache::Observers>();
319 }
320 value.observers_[storeId]->insert(observer);
321 return true;
322 });
323 auto observers = GetObservers(tokenId, storeId);
324 storeCache_.SetObserver(tokenId, storeId, observers);
325 return SUCCESS;
326 }
327
Unsubscribe(const AppId & appId,const StoreId & storeId,sptr<IKvStoreObserver> observer)328 Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, sptr<IKvStoreObserver> observer)
329 {
330 auto tokenId = IPCSkeleton::GetCallingTokenID();
331 ZLOGI("appId:%{public}s storeId:%{public}s tokenId:0x%{public}x", appId.appId.c_str(),
332 Anonymous::Change(storeId.storeId).c_str(), tokenId);
333 syncAgents_.ComputeIfPresent(tokenId, [&appId, &storeId, &observer](auto &key, SyncAgent &value) {
334 if (value.pid_ != IPCSkeleton::GetCallingPid()) {
335 ZLOGW("agent already changed! old pid:%{public}d new pid:%{public}d appId:%{public}s",
336 IPCSkeleton::GetCallingPid(), value.pid_, appId.appId.c_str());
337 return true;
338 }
339 auto it = value.observers_.find(storeId);
340 if (it != value.observers_.end()) {
341 it->second->erase(observer);
342 }
343 return true;
344 });
345 return SUCCESS;
346 }
347
GetBackupPassword(const AppId & appId,const StoreId & storeId,std::vector<uint8_t> & password)348 Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector<uint8_t> &password)
349 {
350 StoreMetaData metaData = GetStoreMetaData(appId, storeId);
351 return (BackupManager::GetInstance().GetPassWord(metaData, password)) ? SUCCESS : ERROR;
352 }
353
BeforeCreate(const AppId & appId,const StoreId & storeId,const Options & options)354 Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, const Options &options)
355 {
356 ZLOGD("appId:%{public}s storeId:%{public}s to export data", appId.appId.c_str(),
357 Anonymous::Change(storeId.storeId).c_str());
358 StoreMetaData meta = GetStoreMetaData(appId, storeId);
359 AddOptions(options, meta);
360
361 StoreMetaData old;
362 auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old);
363 if (!isCreated) {
364 return SUCCESS;
365 }
366 if (old.storeType != meta.storeType || Constant::NotEqual(old.isEncrypt, meta.isEncrypt) ||
367 old.area != meta.area || !options.persistent) {
368 ZLOGE("meta appId:%{public}s storeId:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d "
369 "area:%{public}d->%{public}d persistent:%{public}d",
370 appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), old.storeType, meta.storeType,
371 old.isEncrypt, meta.isEncrypt, old.area, meta.area, options.persistent);
372 return Status::STORE_META_CHANGED;
373 }
374
375 auto dbStatus = DBStatus::OK;
376 if (old != meta) {
377 dbStatus = Upgrade::GetInstance().ExportStore(old, meta);
378 }
379 return dbStatus == DBStatus::OK ? SUCCESS : DB_ERROR;
380 }
381
AfterCreate(const AppId & appId,const StoreId & storeId,const Options & options,const std::vector<uint8_t> & password)382 Status KVDBServiceImpl::AfterCreate(const AppId &appId, const StoreId &storeId, const Options &options,
383 const std::vector<uint8_t> &password)
384 {
385 if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) {
386 ZLOGE("failed please check type:%{public}d appId:%{public}s storeId:%{public}s", options.kvStoreType,
387 appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str());
388 return INVALID_ARGUMENT;
389 }
390
391 StoreMetaData metaData = GetStoreMetaData(appId, storeId);
392 AddOptions(options, metaData);
393
394 StoreMetaData oldMeta;
395 auto isCreated = MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), oldMeta);
396 Status status = SUCCESS;
397 if (isCreated && oldMeta != metaData) {
398 auto dbStatus = Upgrade::GetInstance().UpdateStore(oldMeta, metaData, password);
399 ZLOGI("update status:%{public}d appId:%{public}s storeId:%{public}s inst:%{public}d "
400 "type:%{public}d->%{public}d dir:%{public}s",
401 dbStatus, appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId,
402 oldMeta.storeType, metaData.storeType, metaData.dataDir.c_str());
403 if (dbStatus != DBStatus::OK) {
404 status = STORE_UPGRADE_FAILED;
405 }
406 }
407
408 if (!isCreated || oldMeta != metaData) {
409 MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData);
410 }
411 AppIDMetaData appIdMeta;
412 appIdMeta.bundleName = metaData.bundleName;
413 appIdMeta.appId = metaData.appId;
414 MetaDataManager::GetInstance().SaveMeta(appIdMeta.GetKey(), appIdMeta, true);
415 SaveLocalMetaData(options, metaData);
416 Upgrade::GetInstance().UpdatePassword(metaData, password);
417 ZLOGI("appId:%{public}s storeId:%{public}s instanceId:%{public}d type:%{public}d dir:%{public}s",
418 appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId, metaData.storeType,
419 metaData.dataDir.c_str());
420 return status;
421 }
422
OnAppExit(pid_t uid,pid_t pid,uint32_t tokenId,const std::string & appId)423 int32_t KVDBServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &appId)
424 {
425 ZLOGI("pid:%{public}d uid:%{public}d appId:%{public}s", pid, uid, appId.c_str());
426 std::vector<std::string> storeIds;
427 syncAgents_.ComputeIfPresent(tokenId, [pid, &storeIds](auto &, SyncAgent &value) {
428 if (value.pid_ != pid) {
429 return true;
430 }
431
432 for (auto &[key, value] : value.observers_) {
433 storeIds.push_back(key);
434 }
435 return false;
436 });
437
438 for (auto &storeId : storeIds) {
439 storeCache_.CloseStore(tokenId, storeId);
440 }
441 return SUCCESS;
442 }
443
ResolveAutoLaunch(const std::string & identifier,DBLaunchParam & param)444 int32_t KVDBServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaunchParam ¶m)
445 {
446 ZLOGI("user:%{public}s appId:%{public}s storeId:%{public}s identifier:%{public}s", param.userId.c_str(),
447 param.appId.c_str(), Anonymous::Change(param.storeId).c_str(), Anonymous::Change(identifier).c_str());
448 std::vector<StoreMetaData> metaData;
449 auto prefix = StoreMetaData::GetPrefix({ DMAdapter::GetInstance().GetLocalDevice().uuid, param.userId });
450 if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) {
451 ZLOGE("no store in user:%{public}s", param.userId.c_str());
452 return STORE_NOT_FOUND;
453 }
454
455 for (const auto &storeMeta : metaData) {
456 if (storeMeta.storeType < StoreMetaData::StoreType::STORE_KV_BEGIN
457 || storeMeta.storeType > StoreMetaData::StoreType::STORE_KV_END) {
458 continue;
459 }
460 auto identifierTag = DBManager::GetKvStoreIdentifier("", storeMeta.appId, storeMeta.storeId, true);
461 if (identifier != identifierTag) {
462 continue;
463 }
464
465 auto observers = GetObservers(storeMeta.tokenId, storeMeta.storeId);
466 ZLOGD("user:%{public}s appId:%{public}s storeId:%{public}s observers:%{public}zu", storeMeta.user.c_str(),
467 storeMeta.bundleName.c_str(), Anonymous::Change(storeMeta.storeId).c_str(),
468 (observers) ? observers->size() : size_t(0));
469 DBStatus status;
470 storeCache_.GetStore(storeMeta, observers, status);
471 }
472 return SUCCESS;
473 }
OnUserChange(uint32_t code,const std::string & user,const std::string & account)474 int32_t KVDBServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account)
475 {
476 (void)code;
477 (void)user;
478 (void)account;
479 std::vector<int32_t> users;
480 AccountDelegate::GetInstance()->QueryUsers(users);
481 std::set<int32_t> userIds(users.begin(), users.end());
482 storeCache_.CloseExcept(userIds);
483 return SUCCESS;
484 }
485
OnReady(const std::string & device)486 int32_t KVDBServiceImpl::OnReady(const std::string &device)
487 {
488 std::vector<StoreMetaData> metaData;
489 auto prefix = StoreMetaData::GetPrefix({ DMAdapter::GetInstance().GetLocalDevice().uuid });
490 if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) {
491 ZLOGE("load meta failed!");
492 return STORE_NOT_FOUND;
493 }
494 for (const auto &data : metaData) {
495 if (!data.isAutoSync) {
496 continue;
497 }
498 ZLOGI("[onReady] appId:%{public}s, storeId:%{public}s", data.bundleName.c_str(), data.storeId.c_str());
499 StoreMetaDataLocal localMetaData;
500 MetaDataManager::GetInstance().LoadMeta(data.GetKeyLocal(), localMetaData, true);
501 if (!localMetaData.HasPolicy(PolicyType::IMMEDIATE_SYNC_ON_READY) &&
502 (!localMetaData.HasPolicy(PolicyType::TERM_OF_SYNC_VALIDITY) ||
503 !DeviceMatrix::GetInstance().IsChangedInTerm(data,
504 localMetaData.GetPolicy(PolicyType::TERM_OF_SYNC_VALIDITY).valueUint))) {
505 continue;
506 }
507 SyncInfo syncInfo;
508 syncInfo.delay = localMetaData.HasPolicy(PolicyType::IMMEDIATE_SYNC_ON_READY) ?
509 localMetaData.GetPolicy(PolicyType::IMMEDIATE_SYNC_ON_READY).valueUint : 0;
510 syncInfo.devices = { device };
511 auto delay = GetSyncDelayTime(syncInfo.delay, { data.storeId });
512 KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(data.tokenId), delay,
513 std::bind(&KVDBServiceImpl::DoSync, this, data, syncInfo, std::placeholders::_1, ACTION_SYNC),
514 std::bind(&KVDBServiceImpl::DoComplete, this, data, syncInfo, RefCount(), std::placeholders::_1));
515 }
516 return SUCCESS;
517 }
518
AddOptions(const Options & options,StoreMetaData & metaData)519 void KVDBServiceImpl::AddOptions(const Options &options, StoreMetaData &metaData)
520 {
521 metaData.isAutoSync = options.autoSync;
522 metaData.isBackup = options.backup;
523 metaData.isEncrypt = options.encrypt;
524 metaData.storeType = options.kvStoreType;
525 metaData.securityLevel = options.securityLevel;
526 metaData.area = options.area;
527 metaData.appId = CheckerManager::GetInstance().GetAppId(Converter::ConvertToStoreInfo(metaData));
528 metaData.appType = "harmony";
529 metaData.hapName = options.hapName;
530 metaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData);
531 metaData.schema = options.schema;
532 metaData.account = AccountDelegate::GetInstance()->GetCurrentAccountId();
533 }
534
SaveLocalMetaData(const Options & options,const StoreMetaData & metaData)535 void KVDBServiceImpl::SaveLocalMetaData(const Options &options, const StoreMetaData &metaData)
536 {
537 StoreMetaDataLocal localMetaData;
538 localMetaData.isAutoSync = options.autoSync;
539 localMetaData.isBackup = options.backup;
540 localMetaData.isEncrypt = options.encrypt;
541 localMetaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData);
542 localMetaData.schema = options.schema;
543 for (auto &policy : options.policies) {
544 OHOS::DistributedData::PolicyValue value;
545 value.type = policy.type;
546 value.index = policy.value.index();
547 if (const uint32_t *pval = std::get_if<uint32_t>(&policy.value)) {
548 value.valueUint = *pval;
549 }
550 localMetaData.policies.emplace_back(value);
551 }
552 MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocal(), localMetaData, true);
553 }
554
GetStoreMetaData(const AppId & appId,const StoreId & storeId)555 StoreMetaData KVDBServiceImpl::GetStoreMetaData(const AppId &appId, const StoreId &storeId)
556 {
557 StoreMetaData metaData;
558 metaData.uid = IPCSkeleton::GetCallingUid();
559 metaData.tokenId = IPCSkeleton::GetCallingTokenID();
560 metaData.instanceId = GetInstIndex(metaData.tokenId, appId);
561 metaData.bundleName = appId.appId;
562 metaData.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
563 metaData.storeId = storeId.storeId;
564 auto user = AccountDelegate::GetInstance()->GetUserByToken(metaData.tokenId);
565 metaData.user = std::to_string(user);
566 return metaData;
567 }
568
GetStrategyMeta(const AppId & appId,const StoreId & storeId)569 StrategyMeta KVDBServiceImpl::GetStrategyMeta(const AppId &appId, const StoreId &storeId)
570 {
571 auto tokenId = IPCSkeleton::GetCallingTokenID();
572 auto userId = AccountDelegate::GetInstance()->GetUserByToken(tokenId);
573 auto deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
574 StrategyMeta strategyMeta(deviceId, std::to_string(userId), appId.appId, storeId.storeId);
575 strategyMeta.instanceId = GetInstIndex(tokenId, appId);
576 return strategyMeta;
577 }
578
GetInstIndex(uint32_t tokenId,const AppId & appId)579 int32_t KVDBServiceImpl::GetInstIndex(uint32_t tokenId, const AppId &appId)
580 {
581 if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
582 return 0;
583 }
584
585 HapTokenInfo tokenInfo;
586 tokenInfo.instIndex = -1;
587 int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
588 if (errCode != RET_SUCCESS) {
589 ZLOGE("GetHapTokenInfo error:%{public}d, tokenId:0x%{public}x appId:%{public}s", errCode, tokenId,
590 appId.appId.c_str());
591 return -1;
592 }
593 return tokenInfo.instIndex;
594 }
595
DoSync(const StoreMetaData & meta,const SyncInfo & info,const SyncEnd & complete,int32_t type)596 Status KVDBServiceImpl::DoSync(const StoreMetaData &meta, const SyncInfo &info, const SyncEnd &complete, int32_t type)
597 {
598 ZLOGD("seqId:0x%{public}" PRIx64 " type:%{public}d remote:%{public}zu appId:%{public}s storeId:%{public}s",
599 info.seqId, type, info.devices.size(), meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str());
600 auto uuids = ConvertDevices(info.devices);
601 if (uuids.empty()) {
602 ZLOGW("no device online seqId:0x%{public}" PRIx64 " remote:%{public}zu appId:%{public}s storeId:%{public}s",
603 info.seqId, info.devices.size(), meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str());
604 return Status::ERROR;
605 }
606
607 DistributedDB::DBStatus status;
608 auto observers = GetObservers(meta.tokenId, meta.storeId);
609 auto store = storeCache_.GetStore(meta, observers, status);
610 if (store == nullptr) {
611 ZLOGE("failed! status:%{public}d appId:%{public}s storeId:%{public}s dir:%{public}s", status,
612 meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), meta.dataDir.c_str());
613 return ConvertDbStatus(status);
614 }
615 bool isSuccess = false;
616 auto dbQuery = QueryHelper::StringToDbQuery(info.query, isSuccess);
617 if (!isSuccess && !info.query.empty()) {
618 ZLOGE("failed DBQuery:%{public}s", Anonymous::Change(info.query).c_str());
619 return Status::INVALID_ARGUMENT;
620 }
621
622 switch (type) {
623 case ACTION_SYNC:
624 status = store->Sync(uuids, ConvertDBMode(SyncMode(info.mode)), complete, dbQuery, false);
625 break;
626 case ACTION_SUBSCRIBE:
627 status = store->SubscribeRemoteQuery(uuids, complete, dbQuery, false);
628 break;
629 case ACTION_UNSUBSCRIBE:
630 status = store->UnSubscribeRemoteQuery(uuids, complete, dbQuery, false);
631 break;
632 default:
633 status = DBStatus::INVALID_ARGS;
634 break;
635 }
636 return ConvertDbStatus(status);
637 }
638
DoComplete(const StoreMetaData & meta,const SyncInfo & info,RefCount refCount,const DBResult & dbResult)639 Status KVDBServiceImpl::DoComplete(const StoreMetaData &meta, const SyncInfo &info, RefCount refCount,
640 const DBResult &dbResult)
641 {
642 ZLOGD("seqId:0x%{public}" PRIx64 " tokenId:0x%{public}x remote:%{public}zu", info.seqId, meta.tokenId,
643 dbResult.size());
644 if (refCount) {
645 DeviceMatrix::GetInstance().OnExchanged(info.devices[0], DeviceMatrix::GetInstance().GetCode(meta));
646 }
647 if (info.seqId == std::numeric_limits<uint64_t>::max()) {
648 return SUCCESS;
649 }
650 sptr<IKvStoreSyncCallback> callback;
651 syncAgents_.ComputeIfPresent(meta.tokenId, [&callback](auto &key, SyncAgent &agent) {
652 callback = agent.callback_;
653 return true;
654 });
655 if (callback == nullptr) {
656 return SUCCESS;
657 }
658
659 std::map<std::string, Status> result;
660 for (auto &[key, status] : dbResult) {
661 result[key] = ConvertDbStatus(status);
662 }
663 callback->SyncCompleted(result, info.seqId);
664 return SUCCESS;
665 }
666
GetSyncDelayTime(uint32_t delay,const StoreId & storeId)667 uint32_t KVDBServiceImpl::GetSyncDelayTime(uint32_t delay, const StoreId &storeId)
668 {
669 if (delay != 0) {
670 return std::min(std::max(delay, KvStoreSyncManager::SYNC_MIN_DELAY_MS), KvStoreSyncManager::SYNC_MAX_DELAY_MS);
671 }
672
673 bool isBackground = Constant::IsBackground(IPCSkeleton::GetCallingPid());
674 if (!isBackground) {
675 return delay;
676 }
677 delay = KvStoreSyncManager::SYNC_DEFAULT_DELAY_MS;
678 syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), [&delay, &storeId](auto &, SyncAgent &agent) {
679 auto it = agent.delayTimes_.find(storeId);
680 if (it != agent.delayTimes_.end() && it->second != 0) {
681 delay = it->second;
682 }
683 return true;
684 });
685 return delay;
686 }
687
ConvertDbStatus(DBStatus status) const688 Status KVDBServiceImpl::ConvertDbStatus(DBStatus status) const
689 {
690 switch (status) {
691 case DBStatus::BUSY: // fallthrough
692 case DBStatus::DB_ERROR:
693 return Status::DB_ERROR;
694 case DBStatus::OK:
695 return Status::SUCCESS;
696 case DBStatus::INVALID_ARGS:
697 return Status::INVALID_ARGUMENT;
698 case DBStatus::NOT_FOUND:
699 return Status::KEY_NOT_FOUND;
700 case DBStatus::INVALID_VALUE_FIELDS:
701 return Status::INVALID_VALUE_FIELDS;
702 case DBStatus::INVALID_FIELD_TYPE:
703 return Status::INVALID_FIELD_TYPE;
704 case DBStatus::CONSTRAIN_VIOLATION:
705 return Status::CONSTRAIN_VIOLATION;
706 case DBStatus::INVALID_FORMAT:
707 return Status::INVALID_FORMAT;
708 case DBStatus::INVALID_QUERY_FORMAT:
709 return Status::INVALID_QUERY_FORMAT;
710 case DBStatus::INVALID_QUERY_FIELD:
711 return Status::INVALID_QUERY_FIELD;
712 case DBStatus::NOT_SUPPORT:
713 return Status::NOT_SUPPORT;
714 case DBStatus::TIME_OUT:
715 return Status::TIME_OUT;
716 case DBStatus::OVER_MAX_LIMITS:
717 return Status::OVER_MAX_LIMITS;
718 case DBStatus::EKEYREVOKED_ERROR: // fallthrough
719 case DBStatus::SECURITY_OPTION_CHECK_ERROR:
720 return Status::SECURITY_LEVEL_ERROR;
721 default:
722 break;
723 }
724 return Status::ERROR;
725 }
726
ConvertDBMode(SyncMode syncMode) const727 KVDBServiceImpl::DBMode KVDBServiceImpl::ConvertDBMode(SyncMode syncMode) const
728 {
729 DBMode dbMode;
730 if (syncMode == SyncMode::PUSH) {
731 dbMode = DBMode::SYNC_MODE_PUSH_ONLY;
732 } else if (syncMode == SyncMode::PULL) {
733 dbMode = DBMode::SYNC_MODE_PULL_ONLY;
734 } else {
735 dbMode = DBMode::SYNC_MODE_PUSH_PULL;
736 }
737 return dbMode;
738 }
739
ConvertDevices(const std::vector<std::string> & deviceIds) const740 std::vector<std::string> KVDBServiceImpl::ConvertDevices(const std::vector<std::string> &deviceIds) const
741 {
742 if (deviceIds.empty()) {
743 return DMAdapter::ToUUID(DMAdapter::GetInstance().GetRemoteDevices());
744 }
745 return DMAdapter::ToUUID(deviceIds);
746 }
747
GetObservers(uint32_t tokenId,const std::string & storeId)748 std::shared_ptr<StoreCache::Observers> KVDBServiceImpl::GetObservers(uint32_t tokenId, const std::string &storeId)
749 {
750 std::shared_ptr<StoreCache::Observers> observers;
751 syncAgents_.ComputeIfPresent(tokenId, [&storeId, &observers](auto, SyncAgent &agent) {
752 auto it = agent.observers_.find(storeId);
753 if (it != agent.observers_.end()) {
754 observers = it->second;
755 }
756 return true;
757 });
758 return observers;
759 }
760
ReInit(pid_t pid,const AppId & appId)761 void KVDBServiceImpl::SyncAgent::ReInit(pid_t pid, const AppId &appId)
762 {
763 ZLOGW("pid:%{public}d->%{public}d appId:%{public}s callback:%{public}d observer:%{public}zu", pid, pid_,
764 appId_.appId.c_str(), callback_ == nullptr, observers_.size());
765 pid_ = pid;
766 appId_ = appId;
767 callback_ = nullptr;
768 delayTimes_.clear();
769 observers_.clear();
770 }
771
GetSyncDataSize(const std::string & deviceId)772 size_t KVDBServiceImpl::GetSyncDataSize(const std::string &deviceId)
773 {
774 std::vector<StoreMetaData> metaData;
775 auto prefix = StoreMetaData::GetPrefix({DMAdapter::GetInstance().GetLocalDevice().uuid});
776 if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) {
777 ZLOGE("load meta failed!");
778 return 0;
779 }
780
781 size_t totalSize = 0;
782 for (const auto &data : metaData) {
783 DistributedDB::DBStatus status;
784 auto observers = GetObservers(data.tokenId, data.storeId);
785 auto store = storeCache_.GetStore(data, observers, status);
786 if (store == nullptr) {
787 ZLOGE("failed! status:%{public}d appId:%{public}s storeId:%{public}s dir:%{public}s", status,
788 data.bundleName.c_str(), Anonymous::Change(data.storeId).c_str(), data.dataDir.c_str());
789 continue;
790 }
791 totalSize += store->GetSyncDataSize(deviceId);
792 }
793
794 return totalSize;
795 }
OnBind(const BindInfo & bindInfo)796 int32_t KVDBServiceImpl::OnBind(const BindInfo &bindInfo)
797 {
798 executors_ = bindInfo.executors;
799 storeCache_.SetThreadPool(bindInfo.executors);
800 KvStoreSyncManager::GetInstance()->SetThreadPool(bindInfo.executors);
801 return 0;
802 }
803 } // namespace OHOS::DistributedKv