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