1 /*
2  * Copyright (c) 2024 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 
16 #include "cm_rdb_data_manager.h"
17 
18 #include "cm_log.h"
19 #include "cm_rdb_open_callback.h"
20 #include "cm_scope_guard.h"
21 
22 namespace OHOS {
23 namespace Security {
24 namespace CertManager {
25 const int32_t CLOSE_RDB_TIME = 20; // delay 20s stop rdbStore
CmRdbDataManager(const RdbConfig & rdbConfig)26 CmRdbDataManager::CmRdbDataManager(const RdbConfig &rdbConfig) : rdbConfig_(rdbConfig) {}
27 
~CmRdbDataManager()28 CmRdbDataManager::~CmRdbDataManager()
29 {
30     std::lock_guard<std::mutex> lock(rdbMutex_);
31     rdbStore_ = nullptr;
32 }
33 
InsertData(const NativeRdb::ValuesBucket & valuesBucket)34 bool CmRdbDataManager::InsertData(const NativeRdb::ValuesBucket &valuesBucket)
35 {
36     CM_LOG_D("enter CmRdbDataManager InsertData");
37     auto rdbStore = GetRdbStore();
38     if (rdbStore == nullptr) {
39         CM_LOG_E("rdbStore is nullptr");
40         return false;
41     }
42 
43     int64_t rowId = -1;
44     auto ret = rdbStore->InsertWithConflictResolution(rowId, rdbConfig_.tableName, valuesBucket,
45         NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
46     return ret == NativeRdb::E_OK;
47 }
48 
UpdateData(const std::string & primKey,const std::string & keyColumn,const NativeRdb::ValuesBucket & valuesBucket)49 bool CmRdbDataManager::UpdateData(const std::string &primKey, const std::string &keyColumn,
50     const NativeRdb::ValuesBucket &valuesBucket)
51 {
52     CM_LOG_D("enter CmRdbDataManager UpdateData");
53     auto rdbStore = GetRdbStore();
54     if (rdbStore == nullptr) {
55         CM_LOG_E("rdbStore is nullptr");
56         return false;
57     }
58 
59     NativeRdb::AbsRdbPredicates updatePredicates(rdbConfig_.tableName);
60     updatePredicates.EqualTo(keyColumn, primKey);
61     int32_t rowId = -1;
62     auto ret = rdbStore->Update(rowId, valuesBucket, updatePredicates);
63     return ret == NativeRdb::E_OK;
64 }
65 
DeleteData(const std::string & primKey,const std::string & keyColumn)66 bool CmRdbDataManager::DeleteData(const std::string &primKey, const std::string &keyColumn)
67 {
68     CM_LOG_D("enter CmRdbDataManager DeleteData");
69     auto rdbStore = GetRdbStore();
70     if (rdbStore == nullptr) {
71         CM_LOG_E("rdbStore is nullptr");
72         return false;
73     }
74 
75     NativeRdb::AbsRdbPredicates deletePredicates(rdbConfig_.tableName);
76     deletePredicates.EqualTo(keyColumn, primKey);
77     int32_t rowId = -1;
78     auto ret = rdbStore->Delete(rowId, deletePredicates);
79     return ret == NativeRdb::E_OK;
80 }
81 
QueryData(const std::string & primKey,const std::string & keyColumn)82 std::shared_ptr<NativeRdb::AbsSharedResultSet> CmRdbDataManager::QueryData(const std::string &primKey,
83     const std::string &keyColumn)
84 {
85     CM_LOG_D("enter CmRdbDataManager QueryData");
86     auto rdbStore = GetRdbStore();
87     if (rdbStore == nullptr) {
88         CM_LOG_E("rdbStore is nullptr");
89         return nullptr;
90     }
91 
92     NativeRdb::AbsRdbPredicates queryPredicates(rdbConfig_.tableName);
93     queryPredicates.EqualTo(keyColumn, primKey);
94     auto absSharedResultSet = rdbStore->Query(queryPredicates, std::vector<std::string>());
95     if ((absSharedResultSet == nullptr) || (!absSharedResultSet->HasBlock())) {
96         CM_LOG_E("absSharedResultSet is invalid");
97         return nullptr;
98     }
99     return absSharedResultSet;
100 }
101 
CreateTable()102 bool CmRdbDataManager::CreateTable()
103 {
104     CM_LOG_D("enter CmRdbDataManager CreateTable");
105     auto rdbStore = GetRdbStore();
106     if (rdbStore == nullptr) {
107         CM_LOG_E("rdbStore is nullptr");
108         return false;
109     }
110 
111     if (rdbConfig_.createTableSql.empty()) {
112         CM_LOG_E("createTableSql is nullptr");
113         return false;
114     }
115 
116     int ret = rdbStore->ExecuteSql(rdbConfig_.createTableSql);
117     if (ret != NativeRdb::E_OK) {
118         CM_LOG_E("Failed to create table, ret: %{public}d", ret);
119         return false;
120     }
121     return true;
122 }
123 
DelayCloseRdbStore()124 void CmRdbDataManager::DelayCloseRdbStore()
125 {
126     CM_LOG_D("enter CmRdbDataManager DelayCloseRdbStore");
127     std::weak_ptr<CmRdbDataManager> weakPtr = shared_from_this();
128     auto closeTask = [weakPtr]() {
129         CM_LOG_D("DelayCloseRdbStore thread begin");
130         std::this_thread::sleep_for(std::chrono::seconds(CLOSE_RDB_TIME));
131         auto sharedPtr = weakPtr.lock();
132         if (sharedPtr == nullptr) {
133             return;
134         }
135         std::lock_guard<std::mutex> lock(sharedPtr->rdbMutex_);
136         sharedPtr->rdbStore_ = nullptr;
137         CM_LOG_D("DelayCloseRdbStore thread end");
138     };
139     std::thread closeRdbStoreThread(closeTask);
140     closeRdbStoreThread.detach();
141 }
142 
ClearCache()143 void CmRdbDataManager::CmRdbDataManager::ClearCache()
144 {
145     NativeRdb::RdbHelper::ClearCache();
146 }
147 
GetRdbStore()148 std::shared_ptr<NativeRdb::RdbStore> CmRdbDataManager::GetRdbStore()
149 {
150     CM_LOG_D("enter CmRdbDataManager GetRdbStore");
151     std::lock_guard<std::mutex> lock(rdbMutex_);
152     if (rdbStore_ != nullptr) {
153         return rdbStore_;
154     }
155 
156     int32_t errCode = NativeRdb::E_OK;
157     NativeRdb::RdbStoreConfig rdbStoreConfig(rdbConfig_.dbPath + rdbConfig_.dbName);
158     rdbStoreConfig.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
159     CmRdbOpenCallback cmRdbOpenCallback(rdbConfig_);
160     rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, rdbConfig_.version, cmRdbOpenCallback, errCode);
161     if (rdbStore_ == nullptr) {
162         CM_LOG_E("Failed to init cert manager rdbStore");
163     }
164     DelayCloseRdbStore();
165     return rdbStore_;
166 }
167 } // namespace CertManager
168 } // namespace Security
169 } // namespace OHOS