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