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 #ifndef OHOS_DISTRIBUTED_DATA_SERVICE_MATRIX_DEVICE_MATRIX_H
16 #define OHOS_DISTRIBUTED_DATA_SERVICE_MATRIX_DEVICE_MATRIX_H
17 #include <map>
18 #include <mutex>
19 
20 #include "eventcenter/event.h"
21 #include "executor_pool.h"
22 #include "lru_bucket.h"
23 #include "matrix_event.h"
24 #include "metadata/matrix_meta_data.h"
25 #include "metadata/store_meta_data.h"
26 #include "utils/ref_count.h"
27 #include "visibility.h"
28 
29 namespace OHOS::DistributedData {
30 class API_EXPORT DeviceMatrix {
31 public:
32     using TimePoint = std::chrono::steady_clock::time_point;
33     using Origin = OHOS::DistributedData::MatrixMetaData::Origin;
34     static constexpr uint16_t META_STORE_MASK = 0x0001;
35     static constexpr uint16_t INVALID_HIGH = 0xFFF0;
36     static constexpr uint16_t INVALID_LEVEL = 0xFFFF;
37     static constexpr uint16_t INVALID_LENGTH = 0;
38     static constexpr uint32_t INVALID_VALUE = 0xFFFFFFFF;
39     static constexpr uint16_t INVALID_MASK = 0;
40     enum : int32_t {
41         MATRIX_ONLINE = Event::EVT_CUSTOM,
42         MATRIX_META_FINISHED,
43         MATRIX_BROADCAST,
44         MATRIX_BUTT
45     };
46     enum LevelType : int32_t {
47         STATICS = 0,
48         DYNAMIC,
49         BUTT,
50     };
51     enum ChangeType : uint32_t {
52         CHANGE_LOCAL = 0x1,
53         CHANGE_REMOTE = 0x2,
54         CHANGE_ALL = 0x3,
55         CHANGE_BUTT
56     };
57     struct DataLevel {
58         uint16_t dynamic = INVALID_LEVEL;
59         uint16_t statics = INVALID_LEVEL;
60         uint32_t switches = INVALID_VALUE;
61         uint16_t switchesLen = INVALID_LENGTH;
62         bool IsValid() const;
63     };
64 
65     static DeviceMatrix &GetInstance();
66     bool Initialize(uint32_t token, std::string storeId);
67     void Online(const std::string &device, RefCount refCount = {});
68     void Offline(const std::string &device);
69     std::pair<uint16_t, uint16_t> OnBroadcast(const std::string &device, const DataLevel &dataLevel);
70     void Broadcast(const DataLevel &dataLevel);
71     void OnChanged(uint16_t code, LevelType type = LevelType::DYNAMIC);
72     void OnChanged(const StoreMetaData &metaData);
73     void OnExchanged(const std::string &device, uint16_t code,
74         LevelType type = LevelType::DYNAMIC, ChangeType changeType = ChangeType::CHANGE_ALL);
75     void OnExchanged(const std::string &device,
76         const StoreMetaData &metaData, ChangeType type = ChangeType::CHANGE_ALL);
77     void UpdateLevel(const std::string &device, uint16_t level, LevelType type, bool isConsistent = false);
78     void Clear();
79     void SetExecutor(std::shared_ptr<ExecutorPool> executors);
80     uint16_t GetCode(const StoreMetaData &metaData);
81     std::pair<bool, uint16_t> GetMask(const std::string &device, LevelType type = LevelType::DYNAMIC);
82     std::pair<bool, uint16_t> GetRemoteMask(const std::string &device, LevelType type = LevelType::DYNAMIC);
83     std::pair<bool, uint16_t> GetRecvLevel(const std::string &device, LevelType type);
84     std::pair<bool, uint16_t> GetConsLevel(const std::string &device, LevelType type);
85     std::pair<bool, bool> IsConsistent(const std::string &device);
86     std::pair<bool, MatrixMetaData> GetMatrixMeta(const std::string &device, bool isConsistent = false);
87     std::map<std::string, uint16_t> GetRemoteDynamicMask();
88     bool IsDynamic(const StoreMetaData &metaData);
89     bool IsStatics(const StoreMetaData &metaData);
90     bool IsSupportMatrix();
91     bool IsConsistent();
92 
93 private:
94     static constexpr uint32_t RESET_MASK_DELAY = 10; // min
95     static constexpr uint32_t CURRENT_VERSION = 3;
96     static constexpr uint16_t CURRENT_DYNAMIC_MASK = 0x0006;
97     static constexpr uint16_t CURRENT_STATICS_MASK = 0x0003;
98     static constexpr size_t MAX_DEVICES = 64;
99 
100     DeviceMatrix();
101     ~DeviceMatrix();
102     DeviceMatrix(const DeviceMatrix &) = delete;
103     DeviceMatrix(DeviceMatrix &&) noexcept = delete;
104     DeviceMatrix &operator=(const DeviceMatrix &) = delete;
105     DeviceMatrix &operator=(DeviceMatrix &&) noexcept = delete;
SetMask(size_t index)106     static inline uint16_t SetMask(size_t index)
107     {
108         return 0x1 << index;
109     }
Low(uint16_t data)110     static inline uint16_t Low(uint16_t data)
111     {
112         return data & 0x000F;
113     }
High(uint16_t data)114     static inline uint16_t High(uint16_t data)
115     {
116         return data & 0xFFF0;
117     }
Merge(uint16_t high,uint16_t low)118     static inline uint16_t Merge(uint16_t high, uint16_t low)
119     {
120         return High(high) | Low(low);
121     }
ResetMask(uint16_t data)122     static inline uint16_t ResetMask(uint16_t data)
123     {
124         return data &= 0xFFF0;
125     }
126     struct Mask {
127         uint16_t dynamic = META_STORE_MASK | CURRENT_DYNAMIC_MASK;
128         uint16_t statics = CURRENT_STATICS_MASK;
129         void SetDynamicMask(uint16_t mask);
130         void SetStaticsMask(uint16_t mask);
131     };
132     using TaskId = ExecutorPool::TaskId;
133     using Task = ExecutorPool::Task;
134 
135     void UpdateMask(Mask &mask);
136     void UpdateConsistentMeta(const std::string &device, const Mask &remote);
137     void SaveSwitches(const std::string &device, const DataLevel &dataLevel);
138     void UpdateRemoteMeta(const std::string &device, Mask &mask, MatrixMetaData &newMeta);
139     Task GenResetTask();
140     std::pair<uint16_t, uint16_t> ConvertMask(const std::string &device, const DataLevel &dataLevel);
141     uint16_t ConvertDynamic(const MatrixMetaData &meta, uint16_t mask);
142     uint16_t ConvertStatics(const MatrixMetaData &meta, uint16_t mask);
143     MatrixMetaData GetMatrixInfo(const std::string &device);
144     MatrixMetaData GetMatrixMetaData(const std::string &device, const Mask &mask);
145     static inline uint16_t ConvertIndex(uint16_t code);
146 
147     MatrixEvent::MatrixData lasts_;
148     std::mutex taskMutex_;
149     std::shared_ptr<ExecutorPool> executors_;
150     TaskId task_ = ExecutorPool::INVALID_TASK_ID;
151 
152     bool isSupportBroadcast_ = true;
153     uint32_t tokenId_ = 0;
154     std::string storeId_;
155     std::mutex mutex_;
156     std::map<std::string, Mask> onLines_;
157     std::map<std::string, Mask> offLines_;
158     std::map<std::string, Mask> remotes_;
159     std::vector<std::string> dynamicApps_;
160     std::vector<std::string> staticsApps_;
161     std::function<void(bool, bool)> observer_;
162     LRUBucket<std::string, MatrixMetaData> matrices_{ MAX_DEVICES };
163     LRUBucket<std::string, MatrixMetaData> versions_{ MAX_DEVICES };
164 };
165 } // namespace OHOS::DistributedData
166 #endif // OHOS_DISTRIBUTED_DATA_SERVICE_MATRIX_DEVICE_MATRIX_H