• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "KvStoreMetaManager"
16 
17 #include "kvstore_meta_manager.h"
18 
19 #include <ipc_skeleton.h>
20 #include <thread>
21 #include <unistd.h>
22 
23 #include "account_delegate.h"
24 #include "bootstrap.h"
25 #include "communication_provider.h"
26 #include "communication_strategy.h"
27 #include "crypto_manager.h"
28 #include "device_manager_adapter.h"
29 #include "device_matrix.h"
30 #include "directory/directory_manager.h"
31 #include "dump_helper.h"
32 #include "eventcenter/event_center.h"
33 #include "kvstore_data_service.h"
34 #include "log_print.h"
35 #include "matrix_event.h"
36 #include "metadata/meta_data_manager.h"
37 #include "utils/anonymous.h"
38 #include "utils/block_integer.h"
39 #include "utils/crypto.h"
40 #include "utils/ref_count.h"
41 
42 namespace OHOS {
43 namespace DistributedKv {
44 using Commu = AppDistributedKv::CommunicationProvider;
45 using DmAdapter = DistributedData::DeviceManagerAdapter;
46 using namespace std::chrono;
47 using namespace OHOS::DistributedData;
48 using namespace DistributedDB;
49 using namespace OHOS::AppDistributedKv;
50 
51 KvStoreMetaManager::MetaDeviceChangeListenerImpl KvStoreMetaManager::listener_;
52 
KvStoreMetaManager()53 KvStoreMetaManager::KvStoreMetaManager()
54     : metaDelegate_(nullptr), metaDBDirectory_(DirectoryManager::GetInstance().GetMetaStorePath()),
55       label_(Bootstrap::GetInstance().GetProcessLabel()),
56       delegateManager_(Bootstrap::GetInstance().GetProcessLabel(), "default")
57 {
58     ZLOGI("begin.");
59     CommunicationStrategy::GetInstance().RegGetSyncDataSize("meta_store", [this](const std::string &deviceId) {
60         return this->GetSyncDataSize(deviceId);
61     });
62 }
63 
~KvStoreMetaManager()64 KvStoreMetaManager::~KvStoreMetaManager()
65 {
66 }
67 
GetInstance()68 KvStoreMetaManager &KvStoreMetaManager::GetInstance()
69 {
70     static KvStoreMetaManager instance;
71     return instance;
72 }
73 
SubscribeMeta(const std::string & keyPrefix,const ChangeObserver & observer)74 void KvStoreMetaManager::SubscribeMeta(const std::string &keyPrefix, const ChangeObserver &observer)
75 {
76     metaObserver_.handlerMap_[keyPrefix] = observer;
77 }
78 
InitMetaListener()79 void KvStoreMetaManager::InitMetaListener()
80 {
81     InitMetaData();
82     auto status = DmAdapter::GetInstance().StartWatchDeviceChange(&listener_, { "metaMgr" });
83     if (status != AppDistributedKv::Status::SUCCESS) {
84         ZLOGW("register failed.");
85         return;
86     }
87     ZLOGI("register meta device change success.");
88     SubscribeMetaKvStore();
89     SyncMeta();
90     InitBroadcast();
91     InitDeviceOnline();
92 }
93 
InitBroadcast()94 void KvStoreMetaManager::InitBroadcast()
95 {
96     auto pipe = Bootstrap::GetInstance().GetProcessLabel() + "-" + "default";
97     auto result = Commu::GetInstance().ListenBroadcastMsg({ pipe },
98         [](const std::string &device, uint16_t mask) { DeviceMatrix::GetInstance().OnBroadcast(device, mask); });
99 
100     EventCenter::GetInstance().Subscribe(DeviceMatrix::MATRIX_BROADCAST, [pipe](const Event &event) {
101         auto &matrixEvent = static_cast<const MatrixEvent &>(event);
102         Commu::GetInstance().Broadcast({ pipe }, matrixEvent.GetMask());
103     });
104 
105     ZLOGI("observer matrix broadcast %{public}d.", result);
106 }
107 
InitDeviceOnline()108 void KvStoreMetaManager::InitDeviceOnline()
109 {
110     ZLOGI("observer matrix online event.");
111     using DBStatuses = std::map<std::string, DBStatus>;
112     EventCenter::GetInstance().Subscribe(DeviceMatrix::MATRIX_ONLINE, [this](const Event &event) {
113         auto &matrixEvent = static_cast<const MatrixEvent &>(event);
114         auto mask = matrixEvent.GetMask();
115         auto deviceId = matrixEvent.GetDeviceId();
116         auto store = GetMetaKvStore();
117         auto onComplete = [deviceId, mask, refCount = matrixEvent.StealRefCount()](const DBStatuses &) mutable {
118             ZLOGD("matrix 0x%{public}08x device:%{public}s online", mask, Anonymous::Change(deviceId).c_str());
119             auto finEvent = std::make_unique<MatrixEvent>(DeviceMatrix::MATRIX_META_FINISHED, deviceId, mask);
120             finEvent->SetRefCount(std::move(refCount));
121             DeviceMatrix::GetInstance().OnExchanged(deviceId, DeviceMatrix::META_STORE_MASK);
122             EventCenter::GetInstance().PostEvent(std::move(finEvent));
123         };
124         if (((mask & DeviceMatrix::META_STORE_MASK) != 0) && store != nullptr) {
125             auto status = store->Sync({ deviceId }, DistributedDB::SyncMode::SYNC_MODE_PUSH_PULL, onComplete);
126             if (status == OK) {
127                 return;
128             }
129             ZLOGW("meta online sync error 0x%{public}08x device:%{public}s %{public}d", mask,
130                 Anonymous::Change(deviceId).c_str(), status);
131         }
132         onComplete({ });
133     });
134 }
135 
InitMetaData()136 void KvStoreMetaManager::InitMetaData()
137 {
138     ZLOGI("start.");
139     auto metaDelegate = GetMetaKvStore();
140     if (metaDelegate == nullptr) {
141         ZLOGI("get meta failed.");
142         return;
143     }
144     auto uid = getuid();
145     auto tokenId = IPCSkeleton::GetCallingTokenID();
146     const std::string accountId = AccountDelegate::GetInstance()->GetCurrentAccountId();
147     auto userId = AccountDelegate::GetInstance()->GetUserByToken(tokenId);
148     StoreMetaData data;
149     data.appId = label_;
150     data.appType = "default";
151     data.bundleName = label_;
152     data.dataDir = metaDBDirectory_;
153     data.user = std::to_string(userId);
154     data.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
155     data.isAutoSync = false;
156     data.isBackup = false;
157     data.isEncrypt = false;
158     data.storeType = KvStoreType::SINGLE_VERSION;
159     data.schema = "";
160     data.storeId = Bootstrap::GetInstance().GetMetaDBName();
161     data.account = accountId;
162     data.uid = static_cast<int32_t>(uid);
163     data.version = META_STORE_VERSION;
164     data.securityLevel = SecurityLevel::S1;
165     data.area = EL1;
166     data.tokenId = tokenId;
167     if (!MetaDataManager::GetInstance().SaveMeta(data.GetKey(), data)) {
168         ZLOGE("save meta fail");
169     }
170     ZLOGI("end.");
171 }
172 
InitMetaParameter()173 void KvStoreMetaManager::InitMetaParameter()
174 {
175     ZLOGI("start.");
176     executors_->Execute(GetTask(0));
177     DistributedDB::KvStoreConfig kvStoreConfig{ metaDBDirectory_ };
178     delegateManager_.SetKvStoreConfig(kvStoreConfig);
179 }
180 
GetTask(uint32_t retry)181 ExecutorPool::Task KvStoreMetaManager::GetTask(uint32_t retry)
182 {
183     return [this, retry] {
184         auto status = CryptoManager::GetInstance().CheckRootKey();
185         if (status == CryptoManager::ErrCode::SUCCESS) {
186             ZLOGI("root key exist.");
187             return;
188         }
189         if (status == CryptoManager::ErrCode::NOT_EXIST &&
190             CryptoManager::GetInstance().GenerateRootKey() == CryptoManager::ErrCode::SUCCESS) {
191             ZLOGI("GenerateRootKey success.");
192             return;
193         }
194         ZLOGW("GenerateRootKey failed, retry times:%{public}d.", static_cast<int>(retry));
195         if (retry + 1 > RETRY_MAX_TIMES) {
196             ZLOGE("fail to register subscriber!");
197             return;
198         }
199         executors_->Schedule(std::chrono::seconds(RETRY_INTERVAL), GetTask(retry + 1));
200     };
201 }
202 
GetMetaKvStore()203 KvStoreMetaManager::NbDelegate KvStoreMetaManager::GetMetaKvStore()
204 {
205     if (metaDelegate_ != nullptr) {
206         return metaDelegate_;
207     }
208 
209     std::lock_guard<decltype(mutex_)> lock(mutex_);
210     if (metaDelegate_ == nullptr) {
211         metaDelegate_ = CreateMetaKvStore();
212     }
213     ConfigMetaDataManager();
214     return metaDelegate_;
215 }
216 
CreateMetaKvStore()217 KvStoreMetaManager::NbDelegate KvStoreMetaManager::CreateMetaKvStore()
218 {
219     DistributedDB::DBStatus dbStatusTmp = DistributedDB::DBStatus::NOT_SUPPORT;
220     DistributedDB::KvStoreNbDelegate::Option option;
221     option.createIfNecessary = true;
222     option.isMemoryDb = false;
223     option.createDirByStoreIdOnly = true;
224     option.isEncryptedDb = false;
225     option.isNeedRmCorruptedDb = true;
226     DistributedDB::KvStoreNbDelegate *delegate = nullptr;
227     delegateManager_.GetKvStore(Bootstrap::GetInstance().GetMetaDBName(), option,
228         [&delegate, &dbStatusTmp](DistributedDB::DBStatus dbStatus, DistributedDB::KvStoreNbDelegate *nbDelegate) {
229             delegate = nbDelegate;
230             dbStatusTmp = dbStatus;
231         });
232 
233     if (dbStatusTmp != DistributedDB::DBStatus::OK) {
234         ZLOGE("GetKvStore return error status: %{public}d", static_cast<int>(dbStatusTmp));
235         return nullptr;
236     }
237     delegate->SetRemotePushFinishedNotify([](const RemotePushNotifyInfo &info) {
238         DeviceMatrix::GetInstance().OnExchanged(info.deviceId, DeviceMatrix::META_STORE_MASK);
239     });
240     auto release = [this](DistributedDB::KvStoreNbDelegate *delegate) {
241         ZLOGI("release meta data  kv store");
242         if (delegate == nullptr) {
243             return;
244         }
245 
246         auto result = delegateManager_.CloseKvStore(delegate);
247         if (result != DistributedDB::DBStatus::OK) {
248             ZLOGE("CloseMetaKvStore return error status: %{public}d", static_cast<int>(result));
249         }
250     };
251     return NbDelegate(delegate, release);
252 }
253 
ConfigMetaDataManager()254 void KvStoreMetaManager::ConfigMetaDataManager()
255 {
256     auto fullName = GetBackupPath();
257     auto backup = [fullName](const auto &store) -> int32_t {
258         DistributedDB::CipherPassword password;
259         return store->Export(fullName, password);
260     };
261     auto syncer = [](const auto &store, int32_t status) {
262         ZLOGI("Syncer status: %{public}d", status);
263         DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK);
264         std::vector<std::string> devs;
265         auto devices = DmAdapter::GetInstance().GetRemoteDevices();
266         for (auto const &dev : devices) {
267             devs.push_back(dev.uuid);
268         }
269 
270         if (devs.empty()) {
271             ZLOGW("no devices need sync meta data.");
272             return;
273         }
274 
275         status = store->Sync(devs, DistributedDB::SyncMode::SYNC_MODE_PUSH_PULL, [](auto &results) {
276             ZLOGD("meta data sync completed.");
277             for (auto &[uuid, status] : results) {
278                 if (status != DistributedDB::OK) {
279                     continue;
280                 }
281                 DeviceMatrix::GetInstance().OnExchanged(uuid, DeviceMatrix::META_STORE_MASK);
282             }
283         });
284 
285         if (status != DistributedDB::OK) {
286             ZLOGW("meta data sync error %{public}d.", status);
287         }
288     };
289     MetaDataManager::GetInstance().Initialize(metaDelegate_, backup, syncer);
290 }
291 
SyncMeta()292 void KvStoreMetaManager::SyncMeta()
293 {
294     std::vector<std::string> devs;
295     auto deviceList = DmAdapter::GetInstance().GetRemoteDevices();
296     for (auto const &dev : deviceList) {
297         devs.push_back(dev.uuid);
298     }
299 
300     if (devs.empty()) {
301         ZLOGW("meta db sync fail, devices is empty.");
302         return;
303     }
304 
305     auto metaDelegate = GetMetaKvStore();
306     if (metaDelegate == nullptr) {
307         ZLOGW("meta db sync failed.");
308         return;
309     }
310     auto onComplete = [this](const std::map<std::string, DistributedDB::DBStatus> &) {
311         ZLOGD("meta db sync complete end.");
312     };
313     auto dbStatus = metaDelegate->Sync(devs, DistributedDB::SyncMode::SYNC_MODE_PUSH_PULL, onComplete);
314     if (dbStatus != DistributedDB::OK) {
315         ZLOGW("meta db sync failed, error is %{public}d.", dbStatus);
316     }
317 }
318 
SubscribeMetaKvStore()319 void KvStoreMetaManager::SubscribeMetaKvStore()
320 {
321     auto metaDelegate = GetMetaKvStore();
322     if (metaDelegate == nullptr) {
323         ZLOGW("register meta observer failed.");
324         return;
325     }
326 
327     int mode = DistributedDB::OBSERVER_CHANGES_NATIVE | DistributedDB::OBSERVER_CHANGES_FOREIGN;
328     auto dbStatus = metaDelegate->RegisterObserver(DistributedDB::Key(), mode, &metaObserver_);
329     if (dbStatus != DistributedDB::DBStatus::OK) {
330         ZLOGW("register meta observer failed :%{public}d.", dbStatus);
331     }
332 }
333 
~KvStoreMetaObserver()334 KvStoreMetaManager::KvStoreMetaObserver::~KvStoreMetaObserver()
335 {
336     ZLOGW("meta observer destruct.");
337 }
338 
OnChange(const DistributedDB::KvStoreChangedData & data)339 void KvStoreMetaManager::KvStoreMetaObserver::OnChange(const DistributedDB::KvStoreChangedData &data)
340 {
341     ZLOGD("on data change.");
342     HandleChanges(CHANGE_FLAG::INSERT, data.GetEntriesInserted());
343     HandleChanges(CHANGE_FLAG::UPDATE, data.GetEntriesUpdated());
344     HandleChanges(CHANGE_FLAG::DELETE, data.GetEntriesDeleted());
345 }
346 
HandleChanges(CHANGE_FLAG flag,const std::list<DistributedDB::Entry> & entries)347 void KvStoreMetaManager::KvStoreMetaObserver::HandleChanges(CHANGE_FLAG flag,
348     const std::list<DistributedDB::Entry> &entries)
349 {
350     for (const auto &entry : entries) {
351         std::string key(entry.key.begin(), entry.key.end());
352         for (const auto &item : handlerMap_) {
353             ZLOGI("flag:%{public}d, key:%{public}s", flag, Anonymous::Change(key).c_str());
354             if (key.find(item.first) == 0) {
355                 item.second(entry.key, entry.value, flag);
356             }
357         }
358     }
359 }
360 
OnDeviceChanged(const AppDistributedKv::DeviceInfo & info,const AppDistributedKv::DeviceChangeType & type) const361 void KvStoreMetaManager::MetaDeviceChangeListenerImpl::OnDeviceChanged(const AppDistributedKv::DeviceInfo &info,
362     const AppDistributedKv::DeviceChangeType &type) const
363 {
364     if (info.uuid == DmAdapter::CLOUD_DEVICE_UUID) {
365         return;
366     }
367     EventCenter::Defer defer;
368     switch (type) {
369         case AppDistributedKv::DeviceChangeType::DEVICE_OFFLINE:
370             DeviceMatrix::GetInstance().Offline(info.uuid);
371             break;
372         case AppDistributedKv::DeviceChangeType::DEVICE_ONLINE:
373             DeviceMatrix::GetInstance().Online(info.uuid, RefCount([deviceId = info.uuid]() {
374                 DmAdapter::GetInstance().NotifyReadyEvent(deviceId);
375             }));
376             break;
377         default:
378             ZLOGI("flag:%{public}d", type);
379             break;
380     }
381 }
382 
GetChangeLevelType() const383 AppDistributedKv::ChangeLevelType KvStoreMetaManager::MetaDeviceChangeListenerImpl::GetChangeLevelType() const
384 {
385     return AppDistributedKv::ChangeLevelType::LOW;
386 }
387 
GetBackupPath() const388 std::string KvStoreMetaManager::GetBackupPath() const
389 {
390     return (DirectoryManager::GetInstance().GetMetaBackupPath() + "/" +
391             Crypto::Sha256(label_ + "_" + Bootstrap::GetInstance().GetMetaDBName()));
392 }
393 
GetSyncDataSize(const std::string & deviceId)394 size_t KvStoreMetaManager::GetSyncDataSize(const std::string &deviceId)
395 {
396     auto metaDelegate = GetMetaKvStore();
397     if (metaDelegate == nullptr) {
398         return 0;
399     }
400 
401     return metaDelegate->GetSyncDataSize(deviceId);
402 }
403 
BindExecutor(std::shared_ptr<ExecutorPool> executors)404 void KvStoreMetaManager::BindExecutor(std::shared_ptr<ExecutorPool> executors)
405 {
406     executors_ = executors;
407 }
408 } // namespace DistributedKv
409 } // namespace OHOS
410