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