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 "profile_data_rdb_adapter.h"
17
18 #include <mutex>
19 #include <chrono>
20 #include <unistd.h>
21
22 #include "rdb_errno.h"
23
24 #include "distributed_device_profile_constants.h"
25 #include "distributed_device_profile_errors.h"
26 #include "distributed_device_profile_log.h"
27 #include "profile_utils.h"
28
29 namespace OHOS {
30 namespace DistributedDeviceProfile {
31 IMPLEMENT_SINGLE_INSTANCE(ProfileDataRdbAdapter);
32 using namespace std::chrono_literals;
33 namespace {
34 const std::set<std::string> TABLES = {
35 "device_profile",
36 "service_profile",
37 "characteristic_profile",
38 "device_icon_info",
39 "product_info"
40 };
41 const std::string TAG = "ProfileDatardbAdapter";
42 }
43
Init()44 int32_t ProfileDataRdbAdapter::Init()
45 {
46 int32_t retryTimes = RDB_INIT_MAX_TIMES;
47 while (retryTimes > 0) {
48 if (GetRDBPtr() == DP_SUCCESS) {
49 HILOGI("ProfileDatardbAdapter init success");
50 return DP_SUCCESS;
51 }
52 usleep(RDB_INIT_INTERVAL_TIME);
53 retryTimes--;
54 }
55 HILOGE("ProfileDatardbAdapter init failed");
56 return DP_RDBADAPTER_INIT_FAIL;
57 }
58
UnInit()59 int32_t ProfileDataRdbAdapter::UnInit()
60 {
61 HILOGI("ProfileDatardbAdapter unInit");
62 {
63 std::lock_guard<std::mutex> lock(ProfileDataRdbAdapterMtx_);
64 store_ = nullptr;
65 }
66 return DP_SUCCESS;
67 }
68
Put(int64_t & outRowId,const std::string & table,const ValuesBucket & values)69 int32_t ProfileDataRdbAdapter::Put(int64_t& outRowId, const std::string& table, const ValuesBucket& values)
70 {
71 if (TABLES.find(table) == TABLES.end()) {
72 HILOGE("table does not exist");
73 return DP_RDBADAPTER_TABLE_NOT_EXIST;
74 }
75 {
76 std::lock_guard<std::mutex> lock(ProfileDataRdbAdapterMtx_);
77 if (store_ == nullptr) {
78 HILOGE("RDBStore_ is null");
79 return DP_RDB_DB_PTR_NULL;
80 }
81 int32_t ret = store_->Insert(outRowId, table, values);
82 if (ret == E_SQLITE_CORRUPT) {
83 HILOGE("database corrupt ret:%{public}d", ret);
84 int32_t restoreRet = store_->Restore("");
85 if (restoreRet != E_OK) {
86 HILOGE("Restore failed restoreRet:%{public}d", restoreRet);
87 return DP_RDB_DATABASE_RESTORE_FAIL;
88 }
89 ret = store_->Insert(outRowId, table, values);
90 }
91 if (ret != E_OK) {
92 HILOGE("ProfileDatardbAdapter put failed ret:%{public}d", ret);
93 return DP_RDBADAPTER_PUT_FAIL;
94 }
95 }
96 return DP_SUCCESS;
97 }
98
Delete(int32_t & deleteRows,const std::string & table,const std::string & whereClause,const std::vector<ValueObject> & bindArgs)99 int32_t ProfileDataRdbAdapter::Delete(int32_t& deleteRows, const std::string& table, const std::string& whereClause,
100 const std::vector<ValueObject>& bindArgs)
101 {
102 if (TABLES.find(table) == TABLES.end()) {
103 HILOGE("table does not exist");
104 return DP_RDBADAPTER_TABLE_NOT_EXIST;
105 }
106 {
107 std::lock_guard<std::mutex> lock(ProfileDataRdbAdapterMtx_);
108 if (store_ == nullptr) {
109 HILOGE("RDBStore_ is null");
110 return DP_RDB_DB_PTR_NULL;
111 }
112 int32_t ret = store_->Delete(deleteRows, table, whereClause, bindArgs);
113 if (ret == E_SQLITE_CORRUPT) {
114 HILOGE("database corrupt ret:%{public}d", ret);
115 int32_t restoreRet = store_->Restore("");
116 if (restoreRet != E_OK) {
117 HILOGE("Restore failed restoreRet:%{public}d", restoreRet);
118 return DP_RDB_DATABASE_RESTORE_FAIL;
119 }
120 ret = store_->Delete(deleteRows, table, whereClause, bindArgs);
121 }
122 if (ret != E_OK) {
123 HILOGE("ProfileDatardbAdapter delete failed ret:%{public}d", ret);
124 return DP_RDBADAPTER_DELETE_FAIL;
125 }
126 }
127 return DP_SUCCESS;
128 }
129
Update(int32_t & changedRows,const std::string & table,const ValuesBucket & values,const std::string & whereClause,const std::vector<ValueObject> & bindArgs)130 int32_t ProfileDataRdbAdapter::Update(int32_t& changedRows, const std::string& table, const ValuesBucket& values,
131 const std::string& whereClause, const std::vector<ValueObject>& bindArgs)
132 {
133 if (TABLES.find(table) == TABLES.end()) {
134 HILOGE("table does not exist");
135 return DP_RDBADAPTER_TABLE_NOT_EXIST;
136 }
137 {
138 std::lock_guard<std::mutex> lock(ProfileDataRdbAdapterMtx_);
139 if (store_ == nullptr) {
140 HILOGE("RDBStore_ is null");
141 return DP_RDB_DB_PTR_NULL;
142 }
143 int32_t ret = store_->Update(changedRows, table, values, whereClause, bindArgs);
144 if (ret == E_SQLITE_CORRUPT) {
145 HILOGE("database corrupt ret:%{public}d", ret);
146 int32_t restoreRet = store_->Restore("");
147 if (restoreRet != E_OK) {
148 HILOGE("Restore failed restoreRet:%{public}d", restoreRet);
149 return DP_RDB_DATABASE_RESTORE_FAIL;
150 }
151 ret = store_->Update(changedRows, table, values, whereClause, bindArgs);
152 }
153 if (ret != E_OK) {
154 HILOGE("ProfileDatardbAdapter update failed ret:%{public}d", ret);
155 return DP_RDBADAPTER_UPDATE_FAIL;
156 }
157 }
158 return DP_SUCCESS;
159 }
160
Get(const std::string & sql,const std::vector<ValueObject> & args)161 std::shared_ptr<ResultSet> ProfileDataRdbAdapter::Get(const std::string& sql, const std::vector<ValueObject>& args)
162 {
163 std::shared_ptr<ResultSet> resultSet = nullptr;
164 {
165 std::lock_guard<std::mutex> lock(ProfileDataRdbAdapterMtx_);
166 if (store_ == nullptr) {
167 HILOGE("RDBStore_ is null");
168 return nullptr;
169 }
170 resultSet = store_->QueryByStep(sql, args);
171 if (resultSet == nullptr) {
172 HILOGE("resultSet is null");
173 return nullptr;
174 }
175 int32_t rowCount = ROWCOUNT_INIT;
176 int32_t ret = resultSet->GetRowCount(rowCount);
177 if (ret == E_SQLITE_CORRUPT) {
178 HILOGE("database corrupt ret:%{public}d", ret);
179 resultSet->Close();
180 ret = store_->Restore("");
181 if (ret != E_OK) {
182 HILOGE("Restore failed ret:%{public}d", ret);
183 return nullptr;
184 }
185 resultSet = store_->QueryByStep(sql, args);
186 }
187 }
188 return resultSet;
189 }
190
GetRDBPtr()191 int32_t ProfileDataRdbAdapter::GetRDBPtr()
192 {
193 int32_t version = RDB_VERSION_5_1;
194 ProfileDataOpenCallback helper;
195 RdbStoreConfig config(PROFILE_DATA_RDB_PATH + PROFILE_DATA_DATABASE_NAME);
196 config.SetSecurityLevel(SecurityLevel::S2);
197 config.SetHaMode(HAMode::MAIN_REPLICA);
198 config.SetAllowRebuild(true);
199 int32_t errCode = E_OK;
200 {
201 std::lock_guard<std::mutex> lock(ProfileDataRdbAdapterMtx_);
202 store_ = RdbHelper::GetRdbStore(config, version, helper, errCode);
203 if (store_ == nullptr) {
204 HILOGE("RDBStore_ is null");
205 return DP_RDB_DB_PTR_NULL;
206 }
207 NativeRdb::RebuiltType rebuiltType = NativeRdb::RebuiltType::NONE;
208 errCode = store_->GetRebuilt(rebuiltType);
209 if (errCode != E_OK) {
210 HILOGE("getRDBPtr failed errCode:%{public}d", errCode);
211 return DP_GET_RDBSTORE_FAIL;
212 }
213 if (rebuiltType == NativeRdb::RebuiltType::REBUILT) {
214 HILOGE("database corrupt");
215 int32_t restoreRet = store_->Restore("");
216 if (restoreRet != E_OK) {
217 HILOGE("Restore failed restoreRet:%{public}d", restoreRet);
218 return DP_RDB_DATABASE_RESTORE_FAIL;
219 }
220 }
221 }
222 return DP_SUCCESS;
223 }
224
IsInit()225 bool ProfileDataRdbAdapter::IsInit()
226 {
227 {
228 std::lock_guard<std::mutex> lock(ProfileDataRdbAdapterMtx_);
229 if (store_ == nullptr) {
230 return false;
231 }
232 }
233 return true;
234 }
235
CreateTable(const std::string & sql)236 int32_t ProfileDataRdbAdapter::CreateTable(const std::string& sql)
237 {
238 {
239 std::lock_guard<std::mutex> lock(ProfileDataRdbAdapterMtx_);
240 if (store_ == nullptr) {
241 HILOGE("RDBStore_ is null");
242 return DP_RDB_DB_PTR_NULL;
243 }
244 if (store_->ExecuteSql(sql) != E_OK) {
245 HILOGE("ProfileDatardbAdapter create table failed");
246 return DP_RDBADAPTER_TABLE_NOT_EXIST;
247 }
248 }
249 return DP_SUCCESS;
250 }
251
OnCreate(RdbStore & store)252 int32_t ProfileDataOpenCallback::OnCreate(RdbStore& store)
253 {
254 HILOGI("rdbStore create");
255 return NativeRdb::E_OK;
256 }
257
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)258 int32_t ProfileDataOpenCallback::OnUpgrade(RdbStore& store, int oldVersion, int newVersion)
259 {
260 HILOGI("rdbStore upgrade : %{public}d -> %{public}d", oldVersion, newVersion);
261 if (oldVersion == RDB_VERSION && newVersion == RDB_VERSION_5_1) {
262 return UpdateFromVer1To2(store);
263 }
264 return NativeRdb::E_OK;
265 }
266
CheckAndAlterTable(RdbStore & store,const RdbTableAlterInfo & info)267 int32_t ProfileDataOpenCallback::CheckAndAlterTable(RdbStore& store, const RdbTableAlterInfo& info)
268 {
269 int32_t ret = RET_INIT;
270 bool isExistColumn = ProfileUtils::IsExistColumn(store, info.tabName, info.colName, info.colType, ret);
271 if (ret != DP_SUCCESS) {
272 HILOGE("IsExistColumn failed,reason:%{public}d", ret);
273 return ret;
274 }
275 if (isExistColumn) {
276 HILOGW("already exist,tableName:%{public}s,columnName:%{public}s,columnType:%{public}s",
277 ProfileUtils::GetAnonyString(info.tabName).c_str(), info.colName.c_str(), info.colType.c_str());
278 return DP_SUCCESS;
279 }
280 ret = store.ExecuteSql(info.sql);
281 if (ret != NativeRdb::E_OK) {
282 HILOGE("ExecuteSql failed,reason:%{public}d", ret);
283 return ret;
284 }
285 HILOGI("succeed,tableName:%{public}s,columnName:%{public}s,columnType:%{public}s",
286 ProfileUtils::GetAnonyString(info.tabName).c_str(), info.colName.c_str(), info.colType.c_str());
287 return DP_SUCCESS;
288 }
289
UpdateFromVer1To2(RdbStore & store)290 int32_t ProfileDataOpenCallback::UpdateFromVer1To2(RdbStore& store)
291 {
292 RdbTableAlterInfo deviceProfileAddProductNameColumn {
293 .tabName = DEVICE_PROFILE_TABLE,
294 .colName = PRODUCT_NAME,
295 .colType = RDB_TYPE_TEXT,
296 .sql = ALTER_TABLE_DP_ADD_COLUMN_PRODUCT_NAME_SQL
297 };
298 int32_t ret = CheckAndAlterTable(store, deviceProfileAddProductNameColumn);
299 if (ret != DP_SUCCESS) {
300 HILOGE("CheckAndAlterTable failed,reason:%{public}d,tableName:%{public}s,columnName:%{public}s", ret,
301 ProfileUtils::GetAnonyString(deviceProfileAddProductNameColumn.tabName).c_str(),
302 deviceProfileAddProductNameColumn.colName.c_str());
303 return ret;
304 }
305 RdbTableAlterInfo deviceProfileRenameInterModelColumn {
306 .tabName = DEVICE_PROFILE_TABLE,
307 .colName = INTERNAL_MODEL,
308 .colType = RDB_TYPE_TEXT,
309 .sql = ALTER_TABLE_DP_RENAME_COLUMN_INTERNAL_MODEL_SQL
310 };
311 ret = CheckAndAlterTable(store, deviceProfileRenameInterModelColumn);
312 if (ret != DP_SUCCESS) {
313 HILOGE("CheckAndAlterTable failed,reason:%{public}d,tableName:%{public}s,columnName:%{public}s", ret,
314 ProfileUtils::GetAnonyString(deviceProfileRenameInterModelColumn.tabName).c_str(),
315 deviceProfileRenameInterModelColumn.colName.c_str());
316 return ret;
317 }
318 RdbTableAlterInfo deviceIconInfoAddInterModelColumn {
319 .tabName = DEVICE_ICON_INFO_TABLE,
320 .colName = INTERNAL_MODEL,
321 .colType = RDB_TYPE_TEXT,
322 .sql = ALTER_TABLE_DEVICE_ICON_INFO_ADD_COLUMN_INTENAL_MODEL_SQL
323 };
324 ret = CheckAndAlterTable(store, deviceIconInfoAddInterModelColumn);
325 if (ret != DP_SUCCESS) {
326 HILOGE("CheckAndAlterTable failed,reason:%{public}d,tableName:%{public}s,columnName:%{public}s", ret,
327 ProfileUtils::GetAnonyString(deviceIconInfoAddInterModelColumn.tabName).c_str(),
328 deviceIconInfoAddInterModelColumn.colName.c_str());
329 return ret;
330 }
331 HILOGI("succeed");
332 return NativeRdb::E_OK;
333 }
334 } // namespace DistributedDeviceProfile
335 } // namespace OHOS
336