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