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 "DeviceMatrix"
16 #include "device_matrix.h"
17
18 #include "bootstrap.h"
19 #include "checker/checker_manager.h"
20 #include "communication_provider.h"
21 #include "device_manager_adapter.h"
22 #include "eventcenter/event_center.h"
23 #include "log_print.h"
24 #include "metadata/matrix_meta_data.h"
25 #include "metadata/meta_data_manager.h"
26 #include "metadata/switches_meta_data.h"
27 #include "types.h"
28 #include "utils/anonymous.h"
29 namespace OHOS::DistributedData {
30 using DMAdapter = DeviceManagerAdapter;
31 using Commu = AppDistributedKv::CommunicationProvider;
GetInstance()32 DeviceMatrix &DeviceMatrix::GetInstance()
33 {
34 static DeviceMatrix instance;
35 return instance;
36 }
37
DeviceMatrix()38 DeviceMatrix::DeviceMatrix()
39 {
40 MetaDataManager::GetInstance().Subscribe(MatrixMetaData::GetPrefix({}),
41 [this](const std::string &, const std::string &meta, int32_t action) {
42 if (action != MetaDataManager::INSERT && action != MetaDataManager::UPDATE) {
43 return true;
44 }
45 MatrixMetaData metaData;
46 if (!MatrixMetaData::Unmarshall(meta, metaData)) {
47 ZLOGE("unmarshall meta failed, action:%{public}d", action);
48 return true;
49 }
50 auto deviceId = std::move(metaData.deviceId);
51 ZLOGI("matrix version:%{public}u origin:%{public}d device:%{public}s",
52 metaData.version, metaData.origin, Anonymous::Change(deviceId).c_str());
53 if (metaData.origin == MatrixMetaData::Origin::REMOTE_CONSISTENT) {
54 return true;
55 }
56 matrices_.Set(deviceId, metaData);
57 return true;
58 }, true);
59 MetaDataManager::GetInstance().Subscribe(MatrixMetaData::GetPrefix({}),
60 [this](const std::string &key, const std::string &meta, int32_t action) {
61 if (action != MetaDataManager::INSERT && action != MetaDataManager::UPDATE) {
62 return true;
63 }
64 MatrixMetaData metaData;
65 if (meta.empty()) {
66 MetaDataManager::GetInstance().LoadMeta(key, metaData);
67 } else {
68 MatrixMetaData::Unmarshall(meta, metaData);
69 }
70 auto deviceId = std::move(metaData.deviceId);
71 versions_.Set(deviceId, metaData);
72 ZLOGI("matrix version:%{public}u device:%{public}s",
73 metaData.version, Anonymous::Change(deviceId).c_str());
74 return true;
75 });
76 }
77
~DeviceMatrix()78 DeviceMatrix::~DeviceMatrix()
79 {
80 MetaDataManager::GetInstance().Unsubscribe(MatrixMetaData::GetPrefix({}));
81 }
82
Initialize(uint32_t token,std::string storeId)83 bool DeviceMatrix::Initialize(uint32_t token, std::string storeId)
84 {
85 auto stores = CheckerManager::GetInstance().GetDynamicStores();
86 dynamicApps_.clear();
87 auto metaName = Bootstrap::GetInstance().GetProcessLabel();
88 dynamicApps_.push_back(std::move(metaName));
89 for (auto &store : stores) {
90 dynamicApps_.push_back(std::move(store.bundleName));
91 }
92 stores = CheckerManager::GetInstance().GetStaticStores();
93 staticsApps_.clear();
94 for (auto &store : stores) {
95 staticsApps_.push_back(std::move(store.bundleName));
96 }
97 auto pipe = metaName + "-" + "default";
98 auto status = Commu::GetInstance().Broadcast(
99 { pipe }, { INVALID_LEVEL, INVALID_LEVEL, INVALID_VALUE, INVALID_LENGTH });
100 isSupportBroadcast_ = (status != DistributedKv::Status::NOT_SUPPORT_BROADCAST);
101 ZLOGI("Is support broadcast:%{public}d", isSupportBroadcast_);
102 tokenId_ = token;
103 storeId_ = std::move(storeId);
104 MatrixMetaData oldMeta;
105 MatrixMetaData newMeta;
106 newMeta.version = CURRENT_VERSION;
107 newMeta.dynamic = CURRENT_DYNAMIC_MASK | META_STORE_MASK;
108 newMeta.statics = CURRENT_STATICS_MASK;
109 newMeta.dynamicInfo = dynamicApps_;
110 newMeta.staticsInfo = staticsApps_;
111 newMeta.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
112 auto key = newMeta.GetKey();
113 auto loaded = MetaDataManager::GetInstance().LoadMeta(key, oldMeta);
114 if (loaded && newMeta.version == oldMeta.version) {
115 return true;
116 }
117 if (loaded && newMeta.version != oldMeta.version) {
118 newMeta.dynamic = Merge(oldMeta.dynamic, newMeta.dynamic);
119 newMeta.statics = Merge(oldMeta.statics, newMeta.statics);
120 }
121 ZLOGI("Save Matrix, oldMeta.version:%{public}u , newMeta.version:%{public}u ", oldMeta.version, newMeta.version);
122 MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta, true);
123 return MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta);
124 }
125
Online(const std::string & device,RefCount refCount)126 void DeviceMatrix::Online(const std::string &device, RefCount refCount)
127 {
128 Mask mask;
129 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
130 auto it = offLines_.find(device);
131 if (it != offLines_.end()) {
132 mask = it->second;
133 offLines_.erase(it);
134 } else {
135 UpdateMask(mask);
136 }
137 onLines_.insert_or_assign(device, mask);
138 }
139
IsConsistent(const std::string & device)140 std::pair<bool, bool> DeviceMatrix::IsConsistent(const std::string &device)
141 {
142 std::pair<bool, bool> isConsistent = { false, false };
143 auto [dynamicSaved, dynamicRecvLevel] = GetRecvLevel(device, LevelType::DYNAMIC);
144 auto [dynamicExist, dynamicConsLevel] = GetConsLevel(device, LevelType::DYNAMIC);
145 ZLOGI("device:%{public}s, dynamicSaved:%{public}d, dynamicRecvLevel:%{public}d, dynamicExist:%{public}d, "
146 "dynamicConsLevel:%{public}d",
147 Anonymous::Change(device).c_str(), dynamicSaved, dynamicRecvLevel, dynamicExist, dynamicConsLevel);
148 isConsistent.first =
149 (dynamicSaved && dynamicExist && (dynamicRecvLevel <= dynamicConsLevel) && (dynamicRecvLevel != INVALID_MASK));
150 auto [staticsSaved, staticsRecvLevel] = GetRecvLevel(device, LevelType::STATICS);
151 auto [staticsExist, staticsConsLevel] = GetConsLevel(device, LevelType::STATICS);
152 ZLOGI("device:%{public}s, staticsSaved:%{public}d, staticsRecvLevel:%{public}d, staticsExist:%{public}d, "
153 "staticsConsLevel:%{public}d",
154 Anonymous::Change(device).c_str(), staticsSaved, staticsRecvLevel, staticsExist, staticsConsLevel);
155 isConsistent.second =
156 (staticsSaved && staticsExist && (staticsRecvLevel <= staticsConsLevel) && (staticsRecvLevel != INVALID_MASK));
157 return isConsistent;
158 }
159
Offline(const std::string & device)160 void DeviceMatrix::Offline(const std::string &device)
161 {
162 Mask mask;
163 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
164 auto it = onLines_.find(device);
165 if (it != onLines_.end()) {
166 mask = it->second;
167 onLines_.erase(it);
168 } else {
169 UpdateMask(mask);
170 }
171 offLines_.insert_or_assign(device, mask);
172 }
173
UpdateMask(Mask & mask)174 void DeviceMatrix::UpdateMask(Mask &mask)
175 {
176 auto device = DMAdapter::GetInstance().GetLocalDevice().uuid;
177 auto [exist, meta] = GetMatrixMeta(device);
178 mask.dynamic = Merge(meta.dynamic, mask.dynamic);
179 mask.statics = Merge(meta.statics, mask.statics);
180 }
181
OnBroadcast(const std::string & device,const DataLevel & dataLevel)182 std::pair<uint16_t, uint16_t> DeviceMatrix::OnBroadcast(const std::string &device, const DataLevel &dataLevel)
183 {
184 if (device.empty() || !dataLevel.IsValid()) {
185 ZLOGE("invalid args, device:%{public}s, dataLevel valid:%{public}d",
186 Anonymous::Change(device).c_str(), dataLevel.IsValid());
187 return { INVALID_LEVEL, INVALID_LEVEL };
188 }
189 SaveSwitches(device, dataLevel);
190 auto result = ConvertMask(device, dataLevel);
191 Mask mask;
192 if (dataLevel.dynamic != INVALID_LEVEL) {
193 mask.dynamic &= Low(result.first);
194 if (High(dataLevel.dynamic) != INVALID_HIGH) {
195 mask.dynamic |= High(dataLevel.dynamic);
196 }
197 } else {
198 mask.dynamic &= ~dataLevel.dynamic;
199 }
200 if (dataLevel.statics != INVALID_LEVEL) {
201 mask.statics &= Low(result.second);
202 if (High(dataLevel.statics) != INVALID_HIGH) {
203 mask.statics |= High(dataLevel.statics);
204 }
205 } else {
206 mask.statics &= ~dataLevel.statics;
207 }
208 auto meta = GetMatrixMetaData(device, mask);
209 UpdateRemoteMeta(device, mask, meta);
210 {
211 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
212 auto it = remotes_.find(device);
213 if (it != remotes_.end()) {
214 mask.dynamic |= Low(it->second.dynamic);
215 mask.statics |= Low(it->second.statics);
216 }
217 remotes_.insert_or_assign(device, mask);
218 }
219 return { mask.dynamic, mask.statics };
220 }
221
ConvertMask(const std::string & device,const DataLevel & dataLevel)222 std::pair<uint16_t, uint16_t> DeviceMatrix::ConvertMask(const std::string &device, const DataLevel &dataLevel)
223 {
224 Mask mask;
225 auto meta = GetMatrixInfo(device);
226 if (meta.version == CURRENT_VERSION) {
227 return { mask.dynamic & dataLevel.dynamic, mask.statics & dataLevel.statics };
228 }
229 return { ConvertDynamic(meta, dataLevel.dynamic), ConvertStatics(meta, dataLevel.statics) };
230 }
231
ConvertDynamic(const MatrixMetaData & meta,uint16_t mask)232 uint16_t DeviceMatrix::ConvertDynamic(const MatrixMetaData &meta, uint16_t mask)
233 {
234 uint16_t result = Low(mask) & META_STORE_MASK;
235 uint16_t code = Low(mask) & (~META_STORE_MASK);
236 while (code != 0) {
237 uint16_t index = ConvertIndex(code);
238 if (index >= meta.dynamicInfo.size()) {
239 return result;
240 }
241 const auto &app = meta.dynamicInfo[index];
242 for (size_t i = 0; i < dynamicApps_.size(); i++) {
243 if (dynamicApps_[i] == app) {
244 result |= SetMask(i);
245 break;
246 }
247 }
248 code &= code - 1;
249 }
250 return result;
251 }
252
ConvertStatics(const MatrixMetaData & meta,uint16_t mask)253 uint16_t DeviceMatrix::ConvertStatics(const MatrixMetaData &meta, uint16_t mask)
254 {
255 uint16_t result = 0;
256 uint16_t code = Low(mask);
257 while (code != 0) {
258 uint16_t index = ConvertIndex(code);
259 if (index >= meta.staticsInfo.size()) {
260 return result;
261 }
262 const auto &app = meta.staticsInfo[index];
263 for (size_t i = 0; i < staticsApps_.size(); i++) {
264 if (staticsApps_[i] == app) {
265 result |= SetMask(i);
266 break;
267 }
268 }
269 code &= code - 1;
270 }
271 return result;
272 }
273
ConvertIndex(uint16_t code)274 uint16_t DeviceMatrix::ConvertIndex(uint16_t code)
275 {
276 uint16_t index = (~code) & (code - 1);
277 // 0xAAAA: 1010101010101010 0x5555: 0101010101010101 1: move the high(0xAAAA) to low(0x5555) bits
278 index = ((index & 0xAAAA) >> 1) + (index & 0x5555);
279 // 0xCCCC: 1100110011001100 0x3333: 0011001100110011 2: the count save at 2 bits
280 index = ((index & 0xCCCC) >> 2) + (index & 0x3333);
281 // 0xF0F0: 1111000011110000 0x0F0F: 0000111100001111 4: the count save at 4 bits
282 index = ((index & 0xF0F0) >> 4) + (index & 0x0F0F);
283 // 0xFF00: 1111000011110000 0x00FF: 0000111100001111 8: the count save at 8 bits
284 index = ((index & 0xFF00) >> 8) + (index & 0x00FF);
285 index--;
286 return index;
287 }
288
GetMatrixMetaData(const std::string & device,const Mask & mask)289 MatrixMetaData DeviceMatrix::GetMatrixMetaData(const std::string &device, const Mask &mask)
290 {
291 MatrixMetaData meta;
292 meta.dynamic = mask.dynamic;
293 meta.statics = mask.statics;
294 meta.deviceId = device;
295 meta.origin = Origin::REMOTE_RECEIVED;
296 meta.dynamicInfo = dynamicApps_;
297 meta.staticsInfo = staticsApps_;
298 return meta;
299 }
300
UpdateRemoteMeta(const std::string & device,Mask & mask,MatrixMetaData & newMeta)301 void DeviceMatrix::UpdateRemoteMeta(const std::string &device, Mask &mask, MatrixMetaData &newMeta)
302 {
303 auto [exist, oldMeta] = GetMatrixMeta(device);
304 if (exist && oldMeta == newMeta) {
305 return;
306 }
307 if (exist) {
308 if (High(newMeta.dynamic) < High(oldMeta.dynamic)) {
309 newMeta.dynamic &= 0x000F;
310 newMeta.dynamic |= High(oldMeta.dynamic);
311 } else if ((High(newMeta.dynamic) - High(oldMeta.dynamic)) > 1) {
312 newMeta.dynamic |= 0x000F;
313 mask.dynamic |= 0x000F;
314 }
315 if (High(newMeta.statics) < High(oldMeta.statics)) {
316 newMeta.statics &= 0x000F;
317 newMeta.statics |= High(oldMeta.statics);
318 } else if ((High(newMeta.statics) - High(oldMeta.statics)) > 1) {
319 newMeta.statics |= 0x000F;
320 mask.statics |= 0x000F;
321 }
322 } else {
323 if (High(newMeta.dynamic) != 0x0010) {
324 newMeta.dynamic |= 0x000F;
325 mask.dynamic |= 0x000F;
326 }
327 if (High(newMeta.statics) != 0x0010) {
328 newMeta.statics |= 0x000F;
329 mask.statics |= 0x000F;
330 }
331 }
332 MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta, true);
333 }
334
SaveSwitches(const std::string & device,const DataLevel & dataLevel)335 void DeviceMatrix::SaveSwitches(const std::string &device, const DataLevel &dataLevel)
336 {
337 if (device.empty() || dataLevel.switches == INVALID_VALUE ||
338 dataLevel.switchesLen == INVALID_LENGTH) {
339 ZLOGW("switches data invalid, device:%{public}s", Anonymous::Change(device).c_str());
340 return;
341 }
342 SwitchesMetaData newMeta;
343 newMeta.deviceId = device;
344 newMeta.value = dataLevel.switches;
345 newMeta.length = dataLevel.switchesLen;
346 SwitchesMetaData oldMeta;
347 auto saved = MetaDataManager::GetInstance().LoadMeta(newMeta.GetKey(), oldMeta, true);
348 if (!saved || newMeta != oldMeta) {
349 MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta, true);
350 }
351 ZLOGI("exist:%{public}d, changed:%{public}d", saved, newMeta != oldMeta);
352 }
353
Broadcast(const DataLevel & dataLevel)354 void DeviceMatrix::Broadcast(const DataLevel &dataLevel)
355 {
356 EventCenter::Defer defer;
357 MatrixEvent::MatrixData matrix = {
358 .dynamic = ResetMask(dataLevel.dynamic),
359 .statics = ResetMask(dataLevel.statics),
360 .switches = dataLevel.switches,
361 .switchesLen = dataLevel.switchesLen,
362 };
363 std::lock_guard<decltype(taskMutex_)> lock(taskMutex_);
364 if (!lasts_.IsValid()) {
365 EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", matrix));
366 return;
367 }
368 matrix.dynamic |= Low(lasts_.dynamic);
369 matrix.statics |= Low(lasts_.statics);
370 if (High(matrix.dynamic) != INVALID_HIGH && High(lasts_.dynamic) != INVALID_HIGH &&
371 High(matrix.dynamic) < High(lasts_.dynamic)) {
372 matrix.dynamic &= 0x000F;
373 matrix.dynamic |= High(matrix.dynamic);
374 }
375 if (High(matrix.statics) != INVALID_HIGH && High(lasts_.statics) != INVALID_HIGH &&
376 High(matrix.statics) < High(lasts_.statics)) {
377 matrix.statics &= 0x000F;
378 matrix.statics |= High(matrix.statics);
379 }
380 EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", matrix));
381 lasts_ = matrix;
382 auto executor = executors_;
383 if (executor != nullptr && task_ != ExecutorPool::INVALID_TASK_ID) {
384 task_ = executor->Reset(task_, std::chrono::minutes(RESET_MASK_DELAY));
385 }
386 }
387
OnChanged(uint16_t code,LevelType type)388 void DeviceMatrix::OnChanged(uint16_t code, LevelType type)
389 {
390 if (type < LevelType::STATICS || type > LevelType::DYNAMIC) {
391 return;
392 }
393 uint16_t low = Low(code);
394 uint16_t codes[LevelType::BUTT] = { 0, 0 };
395 codes[type] |= low;
396 EventCenter::Defer defer;
397 {
398 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
399 for (auto &[key, mask] : onLines_) {
400 mask.statics |= codes[LevelType::STATICS];
401 mask.dynamic |= codes[LevelType::DYNAMIC];
402 }
403 for (auto &[key, mask] : offLines_) {
404 mask.statics |= codes[LevelType::STATICS];
405 mask.dynamic |= codes[LevelType::DYNAMIC];
406 }
407 }
408 if (low == 0) {
409 return;
410 }
411 Mask mask;
412 UpdateMask(mask);
413 mask.SetStaticsMask(codes[LevelType::STATICS]);
414 mask.SetDynamicMask(codes[LevelType::DYNAMIC]);
415 MatrixEvent::MatrixData matrixData = {
416 .dynamic = mask.dynamic,
417 .statics = mask.statics,
418 };
419 SwitchesMetaData switchesData;
420 switchesData.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
421 if (MetaDataManager::GetInstance().LoadMeta(switchesData.GetKey(), switchesData, true)) {
422 matrixData.switches = switchesData.value;
423 matrixData.switchesLen = switchesData.length;
424 }
425 EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", matrixData));
426 std::lock_guard<decltype(taskMutex_)> lock(taskMutex_);
427 lasts_ = matrixData;
428 auto executor = executors_;
429 if (executor != nullptr) {
430 if (task_ != ExecutorPool::INVALID_TASK_ID) {
431 task_ = executor->Reset(task_, std::chrono::minutes(RESET_MASK_DELAY));
432 } else {
433 task_ = executor->Schedule(std::chrono::minutes(RESET_MASK_DELAY), GenResetTask());
434 }
435 }
436 }
437
SetDynamicMask(uint16_t mask)438 void DeviceMatrix::Mask::SetDynamicMask(uint16_t mask)
439 {
440 dynamic = ResetMask(dynamic);
441 dynamic |= Low(mask);
442 }
443
SetStaticsMask(uint16_t mask)444 void DeviceMatrix::Mask::SetStaticsMask(uint16_t mask)
445 {
446 statics = ResetMask(statics);
447 statics |= Low(mask);
448 }
449
OnChanged(const StoreMetaData & metaData)450 void DeviceMatrix::OnChanged(const StoreMetaData &metaData)
451 {
452 if (metaData.dataType < LevelType::STATICS || metaData.dataType > LevelType::DYNAMIC) {
453 return;
454 }
455 auto code = GetCode(metaData);
456 if (code != 0) {
457 OnChanged(code, static_cast<LevelType>(metaData.dataType));
458 }
459 }
460
OnExchanged(const std::string & device,uint16_t code,LevelType type,ChangeType changeType)461 void DeviceMatrix::OnExchanged(const std::string &device, uint16_t code, LevelType type, ChangeType changeType)
462 {
463 if (device.empty() || type < LevelType::STATICS || type > LevelType::DYNAMIC) {
464 ZLOGE("invalid args, device:%{public}s, code:%{public}d, type:%{public}d", Anonymous::Change(device).c_str(),
465 code, type);
466 return;
467 }
468 uint16_t low = Low(code);
469 uint16_t codes[LevelType::BUTT] = { 0 };
470 codes[type] |= low;
471 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
472 if ((changeType & CHANGE_LOCAL) == CHANGE_LOCAL) {
473 auto it = onLines_.find(device);
474 if (it != onLines_.end()) {
475 it->second.statics &= ~codes[LevelType::STATICS];
476 it->second.dynamic &= ~codes[LevelType::DYNAMIC];
477 }
478 it = offLines_.find(device);
479 if (it != offLines_.end()) {
480 it->second.statics &= ~codes[LevelType::STATICS];
481 it->second.dynamic &= ~codes[LevelType::DYNAMIC];
482 }
483 }
484 if ((changeType & CHANGE_REMOTE) == CHANGE_REMOTE) {
485 auto it = remotes_.find(device);
486 if (it == remotes_.end()) {
487 return;
488 }
489 it->second.statics &= ~codes[LevelType::STATICS];
490 it->second.dynamic &= ~codes[LevelType::DYNAMIC];
491 UpdateConsistentMeta(device, it->second);
492 }
493 }
494
UpdateConsistentMeta(const std::string & device,const Mask & remote)495 void DeviceMatrix::UpdateConsistentMeta(const std::string &device, const Mask &remote)
496 {
497 uint16_t statics = Low(remote.statics);
498 uint16_t dynamic = Low(remote.dynamic);
499 if (statics != 0 && dynamic != 0) {
500 return;
501 }
502 auto [exist, meta] = GetMatrixMeta(device);
503 if (!exist) {
504 meta.dynamic = remote.dynamic;
505 meta.statics = remote.statics;
506 meta.origin = Origin::REMOTE_RECEIVED;
507 meta.dynamicInfo = dynamicApps_;
508 meta.staticsInfo = staticsApps_;
509 meta.deviceId = device;
510 MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true);
511 }
512 auto [saved, metaData] = GetMatrixMeta(device, true);
513 if (!saved) {
514 meta.origin = Origin::REMOTE_CONSISTENT;
515 meta.deviceId = device;
516 MetaDataManager::GetInstance().SaveMeta(meta.GetConsistentKey(), meta, true);
517 return;
518 }
519 if (statics == 0 && High(meta.statics) > High(metaData.statics)) {
520 metaData.statics = meta.statics;
521 }
522 if (dynamic == 0 && High(meta.dynamic) > High(metaData.dynamic)) {
523 metaData.dynamic = meta.dynamic;
524 }
525 MetaDataManager::GetInstance().SaveMeta(metaData.GetConsistentKey(), metaData, true);
526 }
527
OnExchanged(const std::string & device,const StoreMetaData & metaData,ChangeType type)528 void DeviceMatrix::OnExchanged(const std::string &device, const StoreMetaData &metaData, ChangeType type)
529 {
530 if (metaData.dataType < LevelType::STATICS || metaData.dataType > LevelType::DYNAMIC) {
531 return;
532 }
533 auto code = GetCode(metaData);
534 if (code != 0) {
535 OnExchanged(device, code, static_cast<LevelType>(metaData.dataType), type);
536 }
537 }
538
GetCode(const StoreMetaData & metaData)539 uint16_t DeviceMatrix::GetCode(const StoreMetaData &metaData)
540 {
541 if (metaData.tokenId == tokenId_ && metaData.storeId == storeId_) {
542 return META_STORE_MASK;
543 }
544 if (metaData.dataType == LevelType::STATICS) {
545 for (size_t i = 0; i < staticsApps_.size(); i++) {
546 if (staticsApps_[i] == metaData.appId) {
547 return SetMask(i);
548 }
549 }
550 }
551 if (metaData.dataType == LevelType::DYNAMIC) {
552 for (size_t i = 0; i < dynamicApps_.size(); i++) {
553 if (dynamicApps_[i] == metaData.appId) {
554 return SetMask(i);
555 }
556 }
557 }
558 return 0;
559 }
560
GetMask(const std::string & device,LevelType type)561 std::pair<bool, uint16_t> DeviceMatrix::GetMask(const std::string &device, LevelType type)
562 {
563 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
564 auto it = onLines_.find(device);
565 if (it == onLines_.end()) {
566 return { false, 0 };
567 }
568 switch (type) {
569 case LevelType::STATICS:
570 return { true, Low(it->second.statics) };
571 case LevelType::DYNAMIC:
572 return { true, Low(it->second.dynamic) };
573 default:
574 break;
575 }
576 return { false, 0 };
577 }
578
GetRemoteMask(const std::string & device,LevelType type)579 std::pair<bool, uint16_t> DeviceMatrix::GetRemoteMask(const std::string &device, LevelType type)
580 {
581 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
582 auto it = remotes_.find(device);
583 if (it == remotes_.end()) {
584 return { false, 0 };
585 }
586 switch (type) {
587 case LevelType::STATICS:
588 return { true, Low(it->second.statics) };
589 case LevelType::DYNAMIC:
590 return { true, Low(it->second.dynamic) };
591 default:
592 break;
593 }
594 return { false, 0 };
595 }
596
GetRemoteDynamicMask()597 std::map<std::string, uint16_t> DeviceMatrix::GetRemoteDynamicMask()
598 {
599 std::map<std::string, uint16_t> masks;
600 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
601 for (const auto &[device, mask] : remotes_) {
602 masks.insert_or_assign(device, Low(mask.dynamic));
603 }
604 return masks;
605 }
606
GetRecvLevel(const std::string & device,LevelType type)607 std::pair<bool, uint16_t> DeviceMatrix::GetRecvLevel(const std::string &device, LevelType type)
608 {
609 auto [exist, meta] = GetMatrixMeta(device);
610 if (!exist) {
611 return { false, High(INVALID_LEVEL) };
612 }
613 switch (type) {
614 case LevelType::STATICS:
615 return { true, High(meta.statics) };
616 case LevelType::DYNAMIC:
617 return { true, High(meta.dynamic) };
618 default:
619 break;
620 }
621 return { false, High(INVALID_LEVEL) };
622 }
623
GetConsLevel(const std::string & device,LevelType type)624 std::pair<bool, uint16_t> DeviceMatrix::GetConsLevel(const std::string &device, LevelType type)
625 {
626 auto [exist, meta] = GetMatrixMeta(device, true);
627 if (!exist) {
628 return { false, High(INVALID_LEVEL) };
629 }
630 switch (type) {
631 case LevelType::STATICS:
632 return { true, High(meta.statics) };
633 case LevelType::DYNAMIC:
634 return { true, High(meta.dynamic) };
635 default:
636 break;
637 }
638 return { false, High(INVALID_LEVEL) };
639 }
640
Clear()641 void DeviceMatrix::Clear()
642 {
643 matrices_.ResetCapacity(0);
644 matrices_.ResetCapacity(MAX_DEVICES);
645 versions_.ResetCapacity(0);
646 versions_.ResetCapacity(MAX_DEVICES);
647 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
648 onLines_.clear();
649 offLines_.clear();
650 remotes_.clear();
651 }
652
GetMatrixMeta(const std::string & device,bool isConsistent)653 std::pair<bool, MatrixMetaData> DeviceMatrix::GetMatrixMeta(const std::string &device, bool isConsistent)
654 {
655 MatrixMetaData meta;
656 if (!isConsistent && matrices_.Get(device, meta)) {
657 return { true, meta };
658 }
659 meta.deviceId = device;
660 std::string key;
661 if (isConsistent) {
662 key = meta.GetConsistentKey();
663 } else {
664 key = meta.GetKey();
665 }
666 auto success = MetaDataManager::GetInstance().LoadMeta(key, meta, true);
667 if (success && !isConsistent) {
668 meta.deviceId = "";
669 matrices_.Set(device, meta);
670 }
671 return { success, meta };
672 }
673
UpdateLevel(const std::string & device,uint16_t level,DeviceMatrix::LevelType type,bool isConsistent)674 void DeviceMatrix::UpdateLevel(const std::string &device, uint16_t level, DeviceMatrix::LevelType type,
675 bool isConsistent)
676 {
677 if (device.empty() || type < 0 || type >= LevelType::BUTT) {
678 ZLOGE("invalid args, device:%{public}s, level:%{public}d, type:%{public}d", Anonymous::Change(device).c_str(),
679 level, type);
680 return;
681 }
682 auto [exist, meta] = GetMatrixMeta(device, isConsistent);
683 if (!exist) {
684 if (device == DMAdapter::GetInstance().GetLocalDevice().uuid) {
685 meta.origin = Origin::LOCAL;
686 } else {
687 meta.origin = isConsistent ? Origin::REMOTE_CONSISTENT : Origin::REMOTE_RECEIVED;
688 }
689 meta.dynamicInfo = dynamicApps_;
690 meta.staticsInfo = staticsApps_;
691 }
692 meta.deviceId = device;
693 meta.dynamic = type == DYNAMIC ? Merge(level, meta.dynamic) : meta.dynamic;
694 meta.statics = type == STATICS ? Merge(level, meta.statics) : meta.statics;
695 MetaDataManager::GetInstance().SaveMeta(isConsistent ? meta.GetConsistentKey() : meta.GetKey(), meta, true);
696 if (!isConsistent) {
697 meta.deviceId = "";
698 matrices_.Set(device, meta);
699 }
700 }
701
GetMatrixInfo(const std::string & device)702 MatrixMetaData DeviceMatrix::GetMatrixInfo(const std::string &device)
703 {
704 MatrixMetaData meta;
705 if (versions_.Get(device, meta)) {
706 return meta;
707 }
708 meta.deviceId = device;
709 if (MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) {
710 meta.deviceId = "";
711 versions_.Set(device, meta);
712 }
713 return meta;
714 }
715
IsDynamic(const StoreMetaData & metaData)716 bool DeviceMatrix::IsDynamic(const StoreMetaData &metaData)
717 {
718 if (metaData.dataType != LevelType::DYNAMIC) {
719 return false;
720 }
721 if (metaData.tokenId == tokenId_ && metaData.storeId == storeId_) {
722 return true;
723 }
724 return std::find(dynamicApps_.begin(), dynamicApps_.end(), metaData.appId) != dynamicApps_.end();
725 }
726
IsStatics(const StoreMetaData & metaData)727 bool DeviceMatrix::IsStatics(const StoreMetaData &metaData)
728 {
729 if (metaData.dataType != LevelType::STATICS) {
730 return false;
731 }
732 return std::find(staticsApps_.begin(), staticsApps_.end(), metaData.appId) != staticsApps_.end();
733 }
734
SetExecutor(std::shared_ptr<ExecutorPool> executors)735 void DeviceMatrix::SetExecutor(std::shared_ptr<ExecutorPool> executors)
736 {
737 executors_ = executors;
738 }
739
GenResetTask()740 DeviceMatrix::Task DeviceMatrix::GenResetTask()
741 {
742 return [this]() {
743 MatrixEvent::MatrixData matrixData;
744 {
745 std::lock_guard<decltype(taskMutex_)> lock(taskMutex_);
746 matrixData = lasts_;
747 task_ = ExecutorPool::INVALID_TASK_ID;
748 }
749 matrixData.dynamic = ResetMask(matrixData.dynamic);
750 matrixData.statics = ResetMask(matrixData.statics);
751 EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", matrixData));
752 };
753 }
754
IsValid() const755 bool DeviceMatrix::DataLevel::IsValid() const
756 {
757 return !(dynamic == INVALID_LEVEL && statics == INVALID_LEVEL &&
758 switches == INVALID_VALUE && switchesLen == INVALID_LENGTH);
759 }
760
IsSupportMatrix()761 bool DeviceMatrix::IsSupportMatrix()
762 {
763 return isSupportBroadcast_;
764 }
765
IsConsistent()766 bool DeviceMatrix::IsConsistent()
767 {
768 std::vector<MatrixMetaData> metas;
769 if (!MetaDataManager::GetInstance().LoadMeta(MatrixMetaData::GetPrefix({}), metas, true)) {
770 return true;
771 }
772 for (const auto &meta : metas) {
773 if (meta.origin == MatrixMetaData::Origin::REMOTE_RECEIVED) {
774 MatrixMetaData consistentMeta;
775 consistentMeta.deviceId = meta.deviceId;
776 if (!MetaDataManager::GetInstance().LoadMeta(consistentMeta.GetConsistentKey(), consistentMeta, true)) {
777 return false;
778 }
779 if ((High(meta.statics) > High(consistentMeta.statics)) ||
780 (High(meta.dynamic) > High(consistentMeta.dynamic))) {
781 return false;
782 }
783 }
784 }
785 return true;
786 }
787 } // namespace OHOS::DistributedData