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