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