1 /*
2  * Copyright (c) 2024 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 
16 #define LOG_TAG "AutoSyncMatrix"
17 
18 #include "auto_sync_matrix.h"
19 
20 #include "bootstrap.h"
21 #include "checker/checker_manager.h"
22 #include "device_manager_adapter.h"
23 #include "device_matrix.h"
24 #include "log_print.h"
25 #include "metadata/meta_data_manager.h"
26 #include "utils/anonymous.h"
27 #include "utils/converter.h"
28 
29 namespace OHOS::DistributedData {
30 using DMAdapter = DeviceManagerAdapter;
GetInstance()31 AutoSyncMatrix &AutoSyncMatrix::GetInstance()
32 {
33     static AutoSyncMatrix instance;
34     return instance;
35 }
36 
AutoSyncMatrix()37 AutoSyncMatrix::AutoSyncMatrix()
38 {
39     auto deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
40     MetaDataManager::GetInstance().Subscribe(StoreMetaData::GetPrefix({ deviceId }),
41         [this](const std::string &key, const std::string &meta, int32_t action) -> bool {
42             StoreMetaData metaData;
43             if (meta.empty()) {
44                 MetaDataManager::GetInstance().LoadMeta(key, metaData);
45             } else {
46                 StoreMetaData::Unmarshall(meta, metaData);
47             }
48             if (!IsAutoSync(metaData)) {
49                 return true;
50             }
51             ZLOGI("bundleName:%{public}s storeId:%{public}s action:%{public}d",
52                 metaData.bundleName.c_str(), Anonymous::Change(metaData.storeId).c_str(), action);
53             auto act = static_cast<MetaDataManager::Action>(action);
54             switch (act) {
55                 case MetaDataManager::INSERT:
56                     AddStore(metaData);
57                     break;
58                 case MetaDataManager::DELETE:
59                     DelStore(metaData);
60                     break;
61                 case MetaDataManager::UPDATE:
62                     UpdateStore(metaData);
63                     break;
64                 default:
65                     break;
66             }
67             return true;
68         });
69 }
70 
~AutoSyncMatrix()71 AutoSyncMatrix::~AutoSyncMatrix()
72 {
73 }
74 
Initialize()75 void AutoSyncMatrix::Initialize()
76 {
77     auto deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
78     std::vector<StoreMetaData> metas;
79     if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ deviceId }), metas)) {
80         ZLOGE("load meta failed.");
81         return;
82     }
83     for (const auto &meta : metas) {
84         if (!IsAutoSync(meta)) {
85             continue;
86         }
87         AddStore(meta);
88     }
89 }
90 
IsAutoSync(const StoreMetaData & meta)91 bool AutoSyncMatrix::IsAutoSync(const StoreMetaData &meta)
92 {
93     if (meta.bundleName == Bootstrap::GetInstance().GetProcessLabel()) {
94         return false;
95     }
96     if (meta.dataType != DataType::DYNAMICAL || DeviceMatrix::GetInstance().IsDynamic(meta)) {
97         return false;
98     }
99     return meta.isAutoSync;
100 }
101 
AddStore(const StoreMetaData & meta)102 void AutoSyncMatrix::AddStore(const StoreMetaData &meta)
103 {
104     std::lock_guard<decltype(mutex_)> lock(mutex_);
105     auto it = std::find(metas_.begin(), metas_.end(), meta);
106     if (it != metas_.end()) {
107         return;
108     }
109     metas_.emplace_back(std::move(meta));
110     size_t pos = metas_.size() - 1;
111     for (auto &[device, mask] : onlines_) {
112         mask.Set(pos);
113     }
114     for (auto &[device, mask] : offlines_) {
115         mask.Set(pos);
116     }
117 }
118 
DelStore(const StoreMetaData & meta)119 void AutoSyncMatrix::DelStore(const StoreMetaData &meta)
120 {
121     std::lock_guard<decltype(mutex_)> lock(mutex_);
122     auto it = metas_.begin();
123     for (; it < metas_.end(); it++) {
124         if ((*it) != meta) {
125             continue;
126         }
127         metas_.erase(it);
128         break;
129     }
130     size_t pos = static_cast<size_t>(it - metas_.begin());
131     if (pos == metas_.size()) {
132         return;
133     }
134     for (auto &[device, mask] : onlines_) {
135         mask.Delete(pos);
136     }
137     for (auto &[device, mask] : offlines_) {
138         mask.Delete(pos);
139     }
140 }
141 
Delete(size_t pos)142 void AutoSyncMatrix::Mask::Delete(size_t pos)
143 {
144     if (pos >= MAX_SIZE) {
145         ZLOGE("pos:%{public}zu exceeds maximum value:%{public}d", pos, MAX_SIZE);
146         return;
147     }
148     std::bitset<MAX_SIZE> tmp;
149     for (size_t i = 0; i < pos; i++) {
150         tmp.set(i);
151     }
152     tmp = tmp & data;
153     data >>= pos + 1;
154     data <<= pos;
155     data = data | tmp;
156 }
157 
Set(size_t pos)158 void AutoSyncMatrix::Mask::Set(size_t pos)
159 {
160     if (pos >= MAX_SIZE) {
161         ZLOGE("pos:%{public}zu exceeds maximum value:%{public}d", pos, MAX_SIZE);
162         return;
163     }
164     data.set(pos);
165 }
166 
Init(size_t size)167 void AutoSyncMatrix::Mask::Init(size_t size)
168 {
169     if (size >= MAX_SIZE) {
170         ZLOGE("pos:%{public}zu exceeds maximum value:%{public}d", size, MAX_SIZE);
171         return;
172     }
173     for (size_t i = 0; i < size; i++) {
174         data.set(i);
175     }
176 }
177 
Reset(size_t pos)178 void AutoSyncMatrix::Mask::Reset(size_t pos)
179 {
180     if (pos >= MAX_SIZE) {
181         ZLOGE("pos:%{public}zu exceeds maximum value:%{public}d", pos, MAX_SIZE);
182         return;
183     }
184     data.reset(pos);
185 }
186 
UpdateStore(const StoreMetaData & meta)187 void AutoSyncMatrix::UpdateStore(const StoreMetaData &meta)
188 {
189     std::lock_guard<decltype(mutex_)> lock(mutex_);
190     for (auto &store : metas_) {
191         if (store.GetKey() != meta.GetKey()) {
192             continue;
193         }
194         store = meta;
195         break;
196     }
197 }
198 
Online(const std::string & device)199 void AutoSyncMatrix::Online(const std::string &device)
200 {
201     if (device.empty()) {
202         return;
203     }
204     std::lock_guard<decltype(mutex_)> lock(mutex_);
205     Mask mask;
206     mask.Init(metas_.size());
207     auto it = offlines_.find(device);
208     if (it != offlines_.end()) {
209         mask = it->second;
210         offlines_.erase(it);
211     }
212     onlines_.insert_or_assign(device, mask);
213 }
214 
Offline(const std::string & device)215 void AutoSyncMatrix::Offline(const std::string &device)
216 {
217     if (device.empty()) {
218         return;
219     }
220     std::lock_guard<decltype(mutex_)> lock(mutex_);
221     Mask mask;
222     mask.Init(metas_.size());
223     auto it = onlines_.find(device);
224     if (it != onlines_.end()) {
225         mask = it->second;
226         onlines_.erase(it);
227     }
228     offlines_.insert_or_assign(device, mask);
229 }
230 
OnChanged(const StoreMetaData & metaData)231 void AutoSyncMatrix::OnChanged(const StoreMetaData &metaData)
232 {
233     std::lock_guard<decltype(mutex_)> lock(mutex_);
234     auto it = std::find(metas_.begin(), metas_.end(), metaData);
235     if (it == metas_.end()) {
236         return;
237     }
238     size_t pos = static_cast<size_t>(it - metas_.begin());
239     for (auto &[device, mask] : onlines_) {
240         mask.Set(pos);
241     }
242     for (auto &[device, mask] : offlines_) {
243         mask.Set(pos);
244     }
245 }
246 
OnExchanged(const std::string & device,const StoreMetaData & metaData)247 void AutoSyncMatrix::OnExchanged(const std::string &device, const StoreMetaData &metaData)
248 {
249     std::lock_guard<decltype(mutex_)> lock(mutex_);
250     auto it = std::find(metas_.begin(), metas_.end(), metaData);
251     if (it == metas_.end()) {
252         return;
253     }
254     size_t pos = static_cast<size_t>(it - metas_.begin());
255     auto iter = onlines_.find(device);
256     if (iter != onlines_.end()) {
257         iter->second.Reset(pos);
258     }
259     iter = offlines_.find(device);
260     if (iter != offlines_.end()) {
261         iter->second.Reset(pos);
262     }
263 }
264 
GetChangedStore(const std::string & device)265 std::vector<StoreMetaData> AutoSyncMatrix::GetChangedStore(const std::string &device)
266 {
267     if (device.empty()) {
268         return {};
269     }
270     std::lock_guard<decltype(mutex_)> lock(mutex_);
271     auto it = onlines_.find(device);
272     if (it == onlines_.end()) {
273         return {};
274     }
275     auto mask = it->second;
276     size_t size = metas_.size();
277     Mask tmp;
278     tmp.Set(0);
279     std::vector<StoreMetaData> result;
280     for (size_t i = 0; i < size; i++) {
281         if (tmp.data == (mask.data & tmp.data)) {
282             result.emplace_back(metas_[i]);
283         }
284         mask.data >>= 1;
285     }
286     return result;
287 }
288 } // namespace OHOS::DistributedData