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