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