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 "RdbAdaptor"
16 #include "rdb_delegate.h"
17 
18 #include "crypto_manager.h"
19 #include "datashare_errno.h"
20 #include "datashare_radar_reporter.h"
21 #include "device_manager_adapter.h"
22 #include "extension_connect_adaptor.h"
23 #include "int_wrapper.h"
24 #include "metadata/meta_data_manager.h"
25 #include "metadata/store_meta_data.h"
26 #include "metadata/secret_key_meta_data.h"
27 #include "resultset_json_formatter.h"
28 #include "log_print.h"
29 #include "rdb_errno.h"
30 #include "rdb_utils.h"
31 #include "scheduler_manager.h"
32 #include "string_wrapper.h"
33 #include "utils/anonymous.h"
34 #include "want_params.h"
35 
36 namespace OHOS::DataShare {
37 constexpr static int32_t MAX_RESULTSET_COUNT = 32;
38 constexpr static int64_t TIMEOUT_TIME = 500;
39 std::atomic<int32_t> RdbDelegate::resultSetCount = 0;
40 ConcurrentMap<uint32_t, int32_t> RdbDelegate::resultSetCallingPids;
41 enum REMIND_TIMER_ARGS : int32_t {
42     ARG_DB_PATH = 0,
43     ARG_VERSION,
44     ARG_URI,
45     ARG_SUBSCRIBER_ID,
46     ARG_BUNDLE_NAME,
47     ARG_USER_ID,
48     ARG_TIME,
49     ARGS_SIZE
50 };
RemindTimerFunc(const std::vector<std::string> & args)51 std::string RemindTimerFunc(const std::vector<std::string> &args)
52 {
53     size_t size = args.size();
54     if (size != ARGS_SIZE) {
55         ZLOGE("RemindTimerFunc args size error, %{public}zu", size);
56         return "";
57     }
58     std::string dbPath = args[ARG_DB_PATH];
59     int version = std::strtol(args[ARG_VERSION].c_str(), nullptr, 0);
60     Key key(args[ARG_URI], std::strtoll(args[ARG_SUBSCRIBER_ID].c_str(), nullptr, 0), args[ARG_BUNDLE_NAME]);
61     int64_t reminderTime = std::strtoll(args[ARG_TIME].c_str(), nullptr, 0);
62     int32_t userId = std::strtol(args[ARG_USER_ID].c_str(), nullptr, 0);
63     SchedulerManager::GetInstance().SetTimer(dbPath, userId, version, key, reminderTime);
64     return args[ARG_TIME];
65 }
66 
GetConfig(const DistributedData::StoreMetaData & meta,bool registerFunction)67 std::pair<int, RdbStoreConfig> RdbDelegate::GetConfig(const DistributedData::StoreMetaData &meta,
68     bool registerFunction)
69 {
70     RdbStoreConfig config(meta.dataDir);
71     config.SetCreateNecessary(false);
72     config.SetHaMode(meta.haMode);
73     config.SetBundleName(meta.bundleName);
74     if (meta.isEncrypt) {
75         DistributedData::SecretKeyMetaData secretKeyMeta;
76         if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKeyMeta, true)) {
77             return std::make_pair(E_DB_NOT_EXIST, config);
78         }
79         std::vector<uint8_t> decryptKey;
80         if (!DistributedData::CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptKey)) {
81             return std::make_pair(E_ERROR, config);
82         };
83         config.SetEncryptKey(decryptKey);
84         std::fill(decryptKey.begin(), decryptKey.end(), 0);
85     }
86     if (registerFunction) {
87         config.SetScalarFunction("remindTimer", ARGS_SIZE, RemindTimerFunc);
88     }
89     return std::make_pair(E_OK, config);
90 }
91 
RdbDelegate(const DistributedData::StoreMetaData & meta,int version,bool registerFunction,const std::string & extUriData,const std::string & backup)92 RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version,
93     bool registerFunction, const std::string &extUriData, const std::string &backup)
94 {
95     tokenId_ = meta.tokenId;
96     bundleName_ = meta.bundleName;
97     storeName_ = meta.storeId;
98     extUri_ = extUriData;
99     haMode_ = meta.haMode;
100     backup_ = backup;
101 
102     auto [err, config] = GetConfig(meta, registerFunction);
103     if (err != E_OK) {
104         ZLOGW("Get rdbConfig failed, errCode is %{public}d, dir is %{public}s", err,
105             DistributedData::Anonymous::Change(meta.dataDir).c_str());
106         return;
107     }
108     DefaultOpenCallback callback;
109     store_ = RdbHelper::GetRdbStore(config, version, callback, errCode_);
110     if (errCode_ != E_OK) {
111         ZLOGW("GetRdbStore failed, errCode is %{public}d, dir is %{public}s", errCode_,
112             DistributedData::Anonymous::Change(meta.dataDir).c_str());
113         RdbDelegate::TryAndSend(errCode_);
114     }
115 }
116 
TryAndSend(int errCode)117 void RdbDelegate::TryAndSend(int errCode)
118 {
119     if (errCode != E_SQLITE_CORRUPT || (haMode_ == HAMode::SINGLE && (backup_ != DUAL_WRITE && backup_ != PERIODIC))) {
120         return;
121     }
122     ZLOGE("Database corruption. BundleName: %{public}s. StoreName: %{public}s. ExtUri: %{public}s",
123         bundleName_.c_str(), storeName_.c_str(), DistributedData::Anonymous::Change(extUri_).c_str());
124     AAFwk::WantParams params;
125     params.SetParam("BundleName", AAFwk::String::Box(bundleName_));
126     params.SetParam("StoreName", AAFwk::String::Box(storeName_));
127     params.SetParam("StoreStatus", AAFwk::Integer::Box(1));
128     ExtensionConnectAdaptor::TryAndWait(extUri_, bundleName_, params);
129 }
130 
Insert(const std::string & tableName,const DataShareValuesBucket & valuesBucket)131 int64_t RdbDelegate::Insert(const std::string &tableName, const DataShareValuesBucket &valuesBucket)
132 {
133     if (store_ == nullptr) {
134         ZLOGE("store is null");
135         return 0;
136     }
137     int64_t rowId = 0;
138     ValuesBucket bucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(valuesBucket);
139     int ret = store_->Insert(rowId, tableName, bucket);
140     if (ret != E_OK) {
141         ZLOGE("Insert failed %{public}s %{public}d", tableName.c_str(), ret);
142         RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB,
143             RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::INSERT_RDB_ERROR);
144         if (ret == E_SQLITE_ERROR) {
145             EraseStoreCache(tokenId_);
146         }
147     }
148     return rowId;
149 }
Update(const std::string & tableName,const DataSharePredicates & predicate,const DataShareValuesBucket & valuesBucket)150 int64_t RdbDelegate::Update(
151     const std::string &tableName, const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket)
152 {
153     if (store_ == nullptr) {
154         ZLOGE("store is null");
155         return 0;
156     }
157     int changeCount = 0;
158     ValuesBucket bucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(valuesBucket);
159     RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName);
160     int ret = store_->Update(changeCount, bucket, predicates);
161     if (ret != E_OK) {
162         ZLOGE("Update failed  %{public}s %{public}d", tableName.c_str(), ret);
163         RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB,
164             RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::UPDATE_RDB_ERROR);
165         if (ret == E_SQLITE_ERROR) {
166             EraseStoreCache(tokenId_);
167         }
168     }
169     return changeCount;
170 }
Delete(const std::string & tableName,const DataSharePredicates & predicate)171 int64_t RdbDelegate::Delete(const std::string &tableName, const DataSharePredicates &predicate)
172 {
173     if (store_ == nullptr) {
174         ZLOGE("store is null");
175         return 0;
176     }
177     int changeCount = 0;
178     RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName);
179     int ret = store_->Delete(changeCount, predicates);
180     if (ret != E_OK) {
181         ZLOGE("Delete failed  %{public}s %{public}d", tableName.c_str(), ret);
182         RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB,
183             RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::DELETE_RDB_ERROR);
184         if (ret == E_SQLITE_ERROR) {
185             EraseStoreCache(tokenId_);
186         }
187     }
188     return changeCount;
189 }
190 
InsertEx(const std::string & tableName,const DataShareValuesBucket & valuesBucket)191 std::pair<int64_t, int64_t> RdbDelegate::InsertEx(const std::string &tableName,
192     const DataShareValuesBucket &valuesBucket)
193 {
194     if (store_ == nullptr) {
195         ZLOGE("store is null");
196         return std::make_pair(E_DB_ERROR, 0);
197     }
198     int64_t rowId = 0;
199     ValuesBucket bucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(valuesBucket);
200     int ret = store_->Insert(rowId, tableName, bucket);
201     if (ret != E_OK) {
202         ZLOGE("Insert failed %{public}s %{public}d", tableName.c_str(), ret);
203         RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB,
204             RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::INSERT_RDB_ERROR);
205         if (ret == E_SQLITE_ERROR) {
206             EraseStoreCache(tokenId_);
207         }
208         RdbDelegate::TryAndSend(ret);
209         return std::make_pair(E_DB_ERROR, rowId);
210     }
211     return std::make_pair(E_OK, rowId);
212 }
213 
UpdateEx(const std::string & tableName,const DataSharePredicates & predicate,const DataShareValuesBucket & valuesBucket)214 std::pair<int64_t, int64_t> RdbDelegate::UpdateEx(
215     const std::string &tableName, const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket)
216 {
217     if (store_ == nullptr) {
218         ZLOGE("store is null");
219         return std::make_pair(E_DB_ERROR, 0);
220     }
221     int changeCount = 0;
222     ValuesBucket bucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(valuesBucket);
223     RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName);
224     int ret = store_->Update(changeCount, bucket, predicates);
225     if (ret != E_OK) {
226         ZLOGE("Update failed  %{public}s %{public}d", tableName.c_str(), ret);
227         RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB,
228             RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::UPDATE_RDB_ERROR);
229         if (ret == E_SQLITE_ERROR) {
230             EraseStoreCache(tokenId_);
231         }
232         RdbDelegate::TryAndSend(ret);
233         return std::make_pair(E_DB_ERROR, changeCount);
234     }
235     return std::make_pair(E_OK, changeCount);
236 }
237 
DeleteEx(const std::string & tableName,const DataSharePredicates & predicate)238 std::pair<int64_t, int64_t> RdbDelegate::DeleteEx(const std::string &tableName, const DataSharePredicates &predicate)
239 {
240     if (store_ == nullptr) {
241         ZLOGE("store is null");
242         return std::make_pair(E_DB_ERROR, 0);
243     }
244     int changeCount = 0;
245     RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName);
246     int ret = store_->Delete(changeCount, predicates);
247     if (ret != E_OK) {
248         ZLOGE("Delete failed  %{public}s %{public}d", tableName.c_str(), ret);
249         RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB,
250             RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::DELETE_RDB_ERROR);
251         if (ret == E_SQLITE_ERROR) {
252             EraseStoreCache(tokenId_);
253         }
254         RdbDelegate::TryAndSend(ret);
255         return std::make_pair(E_DB_ERROR, changeCount);
256     }
257     return std::make_pair(E_OK, changeCount);
258 }
259 
Query(const std::string & tableName,const DataSharePredicates & predicates,const std::vector<std::string> & columns,int32_t callingPid,uint32_t callingTokenId)260 std::pair<int, std::shared_ptr<DataShareResultSet>> RdbDelegate::Query(const std::string &tableName,
261     const DataSharePredicates &predicates, const std::vector<std::string> &columns,
262     int32_t callingPid, uint32_t callingTokenId)
263 {
264     if (store_ == nullptr) {
265         ZLOGE("store is null");
266         return std::make_pair(errCode_, nullptr);
267     }
268     int count = resultSetCount.fetch_add(1);
269     ZLOGD("start query %{public}d", count);
270     if (count > MAX_RESULTSET_COUNT && IsLimit(count, callingPid, callingTokenId)) {
271         resultSetCount--;
272         return std::make_pair(E_RESULTSET_BUSY, nullptr);
273     }
274     RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicates, tableName);
275     std::shared_ptr<NativeRdb::ResultSet> resultSet = store_->QueryByStep(rdbPredicates, columns);
276     if (resultSet == nullptr) {
277         RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB,
278             RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::QUERY_RDB_ERROR);
279         ZLOGE("Query failed %{public}s, pid: %{public}d", tableName.c_str(), callingPid);
280         resultSetCount--;
281         return std::make_pair(E_ERROR, nullptr);
282     }
283     int err = resultSet->GetRowCount(count);
284     RdbDelegate::TryAndSend(err);
285     if (err == E_SQLITE_ERROR) {
286         ZLOGE("query failed, err:%{public}d, pid:%{public}d", E_SQLITE_ERROR, callingPid);
287         EraseStoreCache(tokenId_);
288     }
289     resultSetCallingPids.Compute(callingPid, [](const uint32_t &, int32_t &value) {
290         ++value;
291         return true;
292     });
293     int64_t beginTime = std::chrono::duration_cast<std::chrono::milliseconds>(
294         std::chrono::system_clock::now().time_since_epoch()).count();
295     auto bridge = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet);
296     std::shared_ptr<DataShareResultSet> result = { new DataShareResultSet(bridge), [callingPid, beginTime](auto p) {
297         ZLOGD("release resultset");
298         resultSetCount--;
299         int64_t endTime = std::chrono::duration_cast<std::chrono::milliseconds>(
300             std::chrono::system_clock::now().time_since_epoch()).count();
301         if (endTime - beginTime > TIMEOUT_TIME) {
302             ZLOGE("pid %{public}d query time is %{public}" PRId64 ", %{public}d resultSet is used.", callingPid,
303                 (endTime - beginTime), resultSetCount.load());
304         }
305         resultSetCallingPids.ComputeIfPresent(callingPid, [](const uint32_t &, int32_t &value) {
306             --value;
307             return value > 0;
308         });
309         delete p;
310     }};
311     return std::make_pair(E_OK, result);
312 }
313 
Query(const std::string & sql,const std::vector<std::string> & selectionArgs)314 std::string RdbDelegate::Query(const std::string &sql, const std::vector<std::string> &selectionArgs)
315 {
316     if (store_ == nullptr) {
317         ZLOGE("store is null");
318         return "";
319     }
320     auto resultSet = store_->QueryByStep(sql, selectionArgs);
321     if (resultSet == nullptr) {
322         ZLOGE("Query failed %{private}s", sql.c_str());
323         return "";
324     }
325     int rowCount;
326     if (resultSet->GetRowCount(rowCount) == E_SQLITE_ERROR) {
327         ZLOGE("query failed, err:%{public}d", E_SQLITE_ERROR);
328         EraseStoreCache(tokenId_);
329     }
330     ResultSetJsonFormatter formatter(std::move(resultSet));
331     return DistributedData::Serializable::Marshall(formatter);
332 }
333 
QuerySql(const std::string & sql)334 std::shared_ptr<NativeRdb::ResultSet> RdbDelegate::QuerySql(const std::string &sql)
335 {
336     if (store_ == nullptr) {
337         ZLOGE("store is null");
338         return nullptr;
339     }
340     auto resultSet = store_->QuerySql(sql);
341     if (resultSet == nullptr) {
342         ZLOGE("Query failed %{private}s", sql.c_str());
343         return resultSet;
344     }
345     int rowCount;
346     if (resultSet->GetRowCount(rowCount) == E_SQLITE_ERROR) {
347         ZLOGE("query failed, err:%{public}d", E_SQLITE_ERROR);
348         EraseStoreCache(tokenId_);
349     }
350     return resultSet;
351 }
352 
IsInvalid()353 bool RdbDelegate::IsInvalid()
354 {
355     return store_ == nullptr;
356 }
357 
IsLimit(int count,int32_t callingPid,uint32_t callingTokenId)358 bool RdbDelegate::IsLimit(int count, int32_t callingPid, uint32_t callingTokenId)
359 {
360     bool isFull = true;
361     for (int32_t retryCount = 0; retryCount < RETRY; retryCount++) {
362         std::this_thread::sleep_for(WAIT_TIME);
363         if (resultSetCount.load() <= MAX_RESULTSET_COUNT) {
364             isFull = false;
365             break;
366         }
367     }
368     if (!isFull) {
369         return false;
370     }
371     std::string logStr;
372     resultSetCallingPids.ForEach([&logStr](const uint32_t &key, const int32_t &value) {
373         logStr += std::to_string(key) + ":" + std::to_string(value) + ";";
374         return false;
375     });
376     ZLOGE("resultSetCount is full, pid: %{public}d, owner is %{public}s", callingPid, logStr.c_str());
377     std::string appendix = "callingName:" + HiViewFaultAdapter::GetCallingName(callingTokenId).first;
378     DataShareFaultInfo faultInfo{RESULTSET_FULL, "callingTokenId:" + std::to_string(callingTokenId),
379         "Pid:" + std::to_string(callingPid), "owner:" + logStr, __FUNCTION__, E_RESULTSET_BUSY, appendix};
380     HiViewFaultAdapter::ReportDataFault(faultInfo);
381     return true;
382 }
383 } // namespace OHOS::DataShare