• 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(),
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 &param)
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