• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "PublishedData"
16 #include "published_data.h"
17 
18 #include "log_print.h"
19 #include "subscriber_managers/published_data_subscriber_manager.h"
20 #include "utils/base64_utils.h"
21 #include "utils.h"
22 
23 namespace OHOS::DataShare {
HasVersion() const24 bool PublishedData::HasVersion() const
25 {
26     return true;
27 }
28 
GetVersion() const29 int PublishedData::GetVersion() const
30 {
31     return value.GetVersion();
32 }
33 
GetValue() const34 std::string PublishedData::GetValue() const
35 {
36     return DistributedData::Serializable::Marshall(value);
37 }
38 
PublishedData(const PublishedDataNode & node,const int version)39 PublishedData::PublishedData(const PublishedDataNode &node, const int version) : PublishedData(node)
40 {
41     value.SetVersion(version);
42 }
43 
PublishedData(const PublishedDataNode & node)44 PublishedData::PublishedData(const PublishedDataNode &node)
45     : KvData(Id(GenId(node.key, node.bundleName, node.subscriberId), node.userId)), value(node)
46 {
47 }
48 
Query(const std::string & bundleName,int32_t userId)49 std::vector<PublishedData> PublishedData::Query(const std::string &bundleName, int32_t userId)
50 {
51     auto delegate = KvDBDelegate::GetInstance();
52     if (delegate == nullptr) {
53         ZLOGE("db open failed");
54         return std::vector<PublishedData>();
55     }
56     std::vector<std::string> queryResults;
57     int32_t status = delegate->GetBatch(KvDBDelegate::DATA_TABLE,
58         "{\"bundleName\":\"" + bundleName + "\", \"userId\": " + std::to_string(userId) + "}", "{}", queryResults);
59     if (status != E_OK) {
60         ZLOGE("db GetBatch failed, %{public}s %{public}d", bundleName.c_str(), status);
61         return std::vector<PublishedData>();
62     }
63     std::vector<PublishedData> results;
64     for (auto &result : queryResults) {
65         PublishedDataNode data;
66         if (PublishedDataNode::Unmarshall(result, data)) {
67             results.emplace_back(data, userId);
68         }
69     }
70     return results;
71 }
72 
Marshal(DistributedData::Serializable::json & node) const73 bool PublishedDataNode::Marshal(DistributedData::Serializable::json &node) const
74 {
75     bool ret = SetValue(node[GET_NAME(key)], key);
76     ret = ret && SetValue(node[GET_NAME(bundleName)], bundleName);
77     ret = ret && SetValue(node[GET_NAME(subscriberId)], subscriberId);
78     ret = ret && SetValue(node[GET_NAME(value)], value);
79     ret = ret && SetValue(node[GET_NAME(timestamp)], timestamp);
80     ret = ret && SetValue(node[GET_NAME(userId)], userId);
81     return ret && VersionData::Marshal(node);
82 }
83 
Unmarshal(const DistributedData::Serializable::json & node)84 bool PublishedDataNode::Unmarshal(const DistributedData::Serializable::json &node)
85 {
86     bool ret = GetValue(node, GET_NAME(key), key);
87     ret = ret && GetValue(node, GET_NAME(bundleName), bundleName);
88     ret = ret && GetValue(node, GET_NAME(subscriberId), subscriberId);
89     if (ret) {
90         GetValue(node, GET_NAME(value), value);
91         VersionData::Unmarshal(node);
92     }
93     ret = ret && GetValue(node, GET_NAME(timestamp), timestamp);
94     ret = ret && GetValue(node, GET_NAME(userId), userId);
95     return ret;
96 }
97 
PublishedDataNode(const std::string & key,const std::string & bundleName,int64_t subscriberId,const int32_t userId,const Data & value)98 PublishedDataNode::PublishedDataNode(const std::string &key, const std::string &bundleName, int64_t subscriberId,
99     const int32_t userId, const Data &value)
100     : VersionData(-1), key(key), bundleName(bundleName), subscriberId(subscriberId), value(std::move(value)),
101       userId(userId)
102 {
103     auto now = time(nullptr);
104     if (now > 0) {
105         timestamp = now;
106     }
107 }
108 
PublishedDataNode()109 PublishedDataNode::PublishedDataNode() : VersionData(-1) {}
110 
MoveTo(const PublishedDataNode::Data & data)111 std::variant<std::vector<uint8_t>, std::string> PublishedDataNode::MoveTo(const PublishedDataNode::Data &data)
112 {
113     auto *valueStr = std::get_if<std::string>(&data);
114     if (valueStr != nullptr) {
115         return *valueStr;
116     }
117     auto *valueBytes = std::get_if<PublishedDataNode::BytesData>(&data);
118     if (valueBytes != nullptr) {
119         return DistributedData::Base64::Decode(valueBytes->data);
120     }
121     ZLOGE("error");
122     return "";
123 }
124 
MoveTo(std::variant<std::vector<uint8_t>,std::string> & data)125 PublishedDataNode::Data PublishedDataNode::MoveTo(std::variant<std::vector<uint8_t>, std::string> &data)
126 {
127     auto *valueStr = std::get_if<std::string>(&data);
128     if (valueStr != nullptr) {
129         return *valueStr;
130     }
131     auto *valueBytes = std::get_if<std::vector<uint8_t>>(&data);
132     if (valueBytes != nullptr) {
133         std::string valueEncode = DistributedData::Base64::Encode(*valueBytes);
134         return BytesData(std::move(valueEncode));
135     }
136     ZLOGE("error");
137     return "";
138 }
139 
Query(const std::string & filter,PublishedDataNode::Data & publishedData)140 int32_t PublishedData::Query(const std::string &filter, PublishedDataNode::Data &publishedData)
141 {
142     auto delegate = KvDBDelegate::GetInstance();
143     if (delegate == nullptr) {
144         ZLOGE("db open failed");
145         return E_ERROR;
146     }
147     std::string queryResult;
148     int32_t status = delegate->Get(KvDBDelegate::DATA_TABLE, filter, "{}", queryResult);
149     if (status != E_OK) {
150         ZLOGE("db Get failed, %{public}s %{public}d", filter.c_str(), status);
151         return status;
152     }
153     PublishedDataNode data;
154     if (!PublishedDataNode::Unmarshall(queryResult, data)) {
155         ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str());
156         return E_ERROR;
157     }
158     publishedData = std::move(data.value);
159     return E_OK;
160 }
161 
GenId(const std::string & key,const std::string & bundleName,int64_t subscriberId)162 std::string PublishedData::GenId(const std::string &key, const std::string &bundleName, int64_t subscriberId)
163 {
164     return key + "_" + std::to_string(subscriberId) + "_" + bundleName;
165 }
166 
Delete(const std::string & bundleName,const int32_t userId)167 void PublishedData::Delete(const std::string &bundleName, const int32_t userId)
168 {
169     auto delegate = KvDBDelegate::GetInstance();
170     if (delegate == nullptr) {
171         ZLOGE("db open failed");
172         return;
173     }
174     auto [status, count] = delegate->Delete(KvDBDelegate::DATA_TABLE,
175         "{\"bundleName\":\"" + bundleName + "\", \"userId\": " + std::to_string(userId) + "}");
176     if (status != E_OK) {
177         ZLOGE("db Delete failed, %{public}s %{public}d", bundleName.c_str(), status);
178     }
179 }
180 
ClearAging()181 void PublishedData::ClearAging()
182 {
183     // published data is valid in 240 hours
184     auto lastValidData =
185         std::chrono::system_clock::now() - std::chrono::duration_cast<std::chrono::seconds>(std::chrono::hours(240));
186     auto lastValidTime = std::chrono::system_clock::to_time_t(lastValidData);
187     if (lastValidTime <= 0) {
188         return;
189     }
190     auto delegate = KvDBDelegate::GetInstance();
191     if (delegate == nullptr) {
192         ZLOGE("db open failed");
193         return;
194     }
195     std::vector<std::string> queryResults;
196     int32_t status = delegate->GetBatch(KvDBDelegate::DATA_TABLE, "{}",
197         "{\"id_\": true, \"timestamp\": true, \"key\": true, \"bundleName\": true, \"subscriberId\": true, "
198         "\"userId\": true}",
199         queryResults);
200     if (status != E_OK) {
201         ZLOGE("db GetBatch failed %{public}d", status);
202         return;
203     }
204     int32_t agingSize = 0;
205     for (auto &result : queryResults) {
206         PublishedDataNode data;
207         if (!PublishedDataNode::Unmarshall(result, data)) {
208             ZLOGE("Unmarshall %{public}s failed", result.c_str());
209             continue;
210         }
211         if (data.timestamp < lastValidTime && PublishedDataSubscriberManager::GetInstance()
212             .GetCount(PublishedDataKey(data.key, data.bundleName, data.subscriberId)) == 0) {
213             auto [errorCode, count] = delegate->Delete(KvDBDelegate::DATA_TABLE,
214                 Id(PublishedData::GenId(data.key, data.bundleName, data.subscriberId), data.userId));
215             if (errorCode != E_OK) {
216                 ZLOGE("db Delete failed, %{public}s %{public}s", data.key.c_str(), data.bundleName.c_str());
217             }
218             agingSize++;
219         }
220     }
221     if (agingSize > 0) {
222         ZLOGI("aging count %{public}d", agingSize);
223     }
224     return;
225 }
226 
UpdateTimestamp(const std::string & key,const std::string & bundleName,int64_t subscriberId,const int32_t userId)227 void PublishedData::UpdateTimestamp(
228     const std::string &key, const std::string &bundleName, int64_t subscriberId, const int32_t userId)
229 {
230     auto delegate = KvDBDelegate::GetInstance();
231     if (delegate == nullptr) {
232         ZLOGE("db open failed");
233         return;
234     }
235     std::string queryResult;
236     int32_t status =
237         delegate->Get(KvDBDelegate::DATA_TABLE, Id(GenId(key, bundleName, subscriberId), userId), queryResult);
238     if (status != E_OK) {
239         ZLOGE("db Get failed, %{public}s %{public}d", StringUtils::GeneralAnonymous(queryResult).c_str(), status);
240         return;
241     }
242     PublishedDataNode data;
243     if (!PublishedDataNode::Unmarshall(queryResult, data)) {
244         ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str());
245         return;
246     }
247     auto now = time(nullptr);
248     if (now <= 0) {
249         ZLOGE("time failed");
250         return;
251     }
252     data.timestamp = now;
253     auto [errorCode, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, PublishedData(data));
254     if (errorCode == E_OK) {
255         ZLOGI("update timestamp %{public}s", StringUtils::GeneralAnonymous(data.key).c_str());
256     }
257 }
258 
BytesData(std::string && data)259 PublishedDataNode::BytesData::BytesData(std::string &&data) : data(std::move(data))
260 {
261 }
262 
Marshal(DistributedData::Serializable::json & node) const263 bool PublishedDataNode::BytesData::Marshal(DistributedData::Serializable::json &node) const
264 {
265     return SetValue(node[GET_NAME(data)], data);
266 }
267 
Unmarshal(const DistributedData::Serializable::json & node)268 bool PublishedDataNode::BytesData::Unmarshal(const DistributedData::Serializable::json &node)
269 {
270     bool ret = GetValue(node, GET_NAME(data), data);
271     return ret;
272 }
273 } // namespace OHOS::DataShare