• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "sqlite_local_kvdb.h"
17 
18 #include <algorithm>
19 
20 #include "db_constant.h"
21 #include "db_common.h"
22 #include "log_print.h"
23 #include "platform_specific.h"
24 #include "package_file.h"
25 #include "kvdb_utils.h"
26 #include "local_database_oper.h"
27 #include "sqlite_local_kvdb_connection.h"
28 #include "sqlite_local_storage_engine.h"
29 
30 namespace DistributedDB {
31 namespace {
32     const std::string CREATE_SQL =
33         "CREATE TABLE IF NOT EXISTS data(key BLOB PRIMARY key, value BLOB);";
34 }
35 
SQLiteLocalKvDB()36 SQLiteLocalKvDB::SQLiteLocalKvDB()
37     : storageEngine_(nullptr)
38 {}
39 
~SQLiteLocalKvDB()40 SQLiteLocalKvDB::~SQLiteLocalKvDB()
41 {
42     if (storageEngine_ != nullptr) {
43         delete storageEngine_;
44         storageEngine_ = nullptr;
45     }
46 }
47 
Open(const KvDBProperties & kvDBProp)48 int SQLiteLocalKvDB::Open(const KvDBProperties &kvDBProp)
49 {
50     int databaseType = kvDBProp.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE);
51     if (databaseType == KvDBProperties::LOCAL_TYPE) {
52         std::unique_ptr<LocalDatabaseOper> operation = std::make_unique<LocalDatabaseOper>(this, nullptr);
53         (void)operation->ClearExportedTempFiles(kvDBProp);
54         int errCode = operation->RekeyRecover(kvDBProp);
55         if (errCode != E_OK) {
56             LOGE("Recover for open db failed in local db:%d", errCode);
57             return errCode;
58         }
59 
60         errCode = operation->ClearImportTempFile(kvDBProp);
61         if (errCode != E_OK) {
62             LOGE("Recover for open db failed in multi version:%d", errCode);
63             return errCode;
64         }
65     }
66 
67     bool createIfNecessary = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true);
68     std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType);
69     std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, "");
70     std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, "");
71     int errCode = DBCommon::CreateStoreDirectory(dataDir, identifierDir, subDir, createIfNecessary);
72     if (errCode != E_OK) {
73         LOGE("Create directory for local database failed:%d", errCode);
74         return errCode;
75     }
76 
77     errCode = InitStorageEngine(kvDBProp);
78     if (errCode != E_OK) {
79         return errCode;
80     }
81     MyProp() = kvDBProp;
82     return E_OK;
83 }
84 
NewConnection(int & errCode)85 GenericKvDBConnection *SQLiteLocalKvDB::NewConnection(int &errCode)
86 {
87     auto connection = new (std::nothrow) SQLiteLocalKvDBConnection(this);
88     if (connection == nullptr) {
89         errCode = -E_OUT_OF_MEMORY;
90         return nullptr;
91     }
92 
93     errCode = E_OK;
94     return connection;
95 }
96 
Close()97 void SQLiteLocalKvDB::Close() {}
98 
Rekey(const CipherPassword & passwd)99 int SQLiteLocalKvDB::Rekey(const CipherPassword &passwd)
100 {
101     if (storageEngine_ == nullptr) {
102         return -E_INVALID_DB;
103     }
104 
105     std::unique_ptr<LocalDatabaseOper> operation = std::make_unique<LocalDatabaseOper>(this, storageEngine_);
106     return operation->Rekey(passwd);
107 }
108 
Export(const std::string & filePath,const CipherPassword & passwd)109 int SQLiteLocalKvDB::Export(const std::string &filePath, const CipherPassword &passwd)
110 {
111     int errCode = E_OK;
112     // Exclusively write resources
113     SQLiteLocalStorageExecutor *handle = GetHandle(true, errCode);
114     if (handle == nullptr) {
115         return errCode;
116     }
117     std::string devId = "local";
118 
119     std::unique_ptr<LocalDatabaseOper> operation = std::make_unique<LocalDatabaseOper>(this, storageEngine_);
120     operation->SetLocalDevId(DBCommon::TransferHashString(devId));
121     errCode = operation->Export(filePath, passwd);
122 
123     ReleaseHandle(handle);
124     return errCode;
125 }
126 
Import(const std::string & filePath,const CipherPassword & passwd)127 int SQLiteLocalKvDB::Import(const std::string &filePath, const CipherPassword &passwd)
128 {
129     if (storageEngine_ == nullptr) {
130         return -E_INVALID_DB;
131     }
132 
133     int errCode = storageEngine_->TryToDisable(true, OperatePerm::IMPORT_MONOPOLIZE_PERM);
134     if (errCode != E_OK) {
135         LOGE("Failed to disable the database");
136         return errCode;
137     }
138 
139     // Need to monopolize the entire process
140     std::unique_ptr<LocalDatabaseOper> operation = std::make_unique<LocalDatabaseOper>(this, storageEngine_);
141     errCode = operation->Import(filePath, passwd);
142     // restore the storage engine and the syncer.
143     storageEngine_->Enable(OperatePerm::IMPORT_MONOPOLIZE_PERM);
144     return errCode;
145 }
146 
InitDatabaseContext(const KvDBProperties & kvDBProp)147 int SQLiteLocalKvDB::InitDatabaseContext(const KvDBProperties &kvDBProp)
148 {
149     return InitStorageEngine(kvDBProp);
150 }
151 
EnableAutonomicUpgrade()152 void SQLiteLocalKvDB::EnableAutonomicUpgrade()
153 {
154     isAutonomicUpgradeEnable_ = true;
155 }
156 
RunExportLogic(CipherType type,const CipherPassword & passwd,const std::string & newDbName)157 int SQLiteLocalKvDB::RunExportLogic(CipherType type, const CipherPassword &passwd, const std::string &newDbName)
158 {
159     OpenDbProperties option;
160     InitDataBaseOption(MyProp(), option);
161     option.createIfNecessary = true;
162     sqlite3 *db = nullptr;
163     int errCode = SQLiteUtils::OpenDatabase(option, db);
164     if (errCode != E_OK) {
165         LOGE("Open db for export error:%d", errCode);
166         return errCode;
167     }
168 
169     errCode = SQLiteUtils::ExportDatabase(db, type, passwd, newDbName);
170     if (errCode != E_OK) {
171         goto END;
172     }
173 
174 END:
175     (void)sqlite3_close_v2(db);
176     db = nullptr;
177     return errCode;
178 }
179 
RunRekeyLogic(CipherType type,const CipherPassword & passwd)180 int SQLiteLocalKvDB::RunRekeyLogic(CipherType type, const CipherPassword &passwd)
181 {
182     OpenDbProperties option;
183     InitDataBaseOption(MyProp(), option);
184     option.createIfNecessary = true;
185     sqlite3 *db = nullptr;
186     int errCode = SQLiteUtils::OpenDatabase(option, db);
187     if (errCode != E_OK) {
188         LOGE("Open db for rekey error:%d", errCode);
189         return errCode;
190     }
191 
192     errCode = SQLiteUtils::Rekey(db, passwd);
193     if (errCode != E_OK) {
194         (void)sqlite3_close_v2(db);
195         db = nullptr;
196         return errCode;
197     }
198     (void)sqlite3_close_v2(db);
199     db = nullptr;
200     MyProp().SetPassword(option.cipherType, passwd);
201     if (storageEngine_ != nullptr) {
202         storageEngine_->Release();
203     }
204 
205     return InitStorageEngine(MyProp());
206 }
207 
GetHandle(bool isWrite,int & errCode,OperatePerm perm) const208 SQLiteLocalStorageExecutor *SQLiteLocalKvDB::GetHandle(bool isWrite, int &errCode, OperatePerm perm) const
209 {
210     if (storageEngine_ == nullptr) {
211         errCode = -E_INVALID_DB;
212         return nullptr;
213     }
214 
215     return static_cast<SQLiteLocalStorageExecutor *>(storageEngine_->FindExecutor(isWrite, perm, errCode));
216 }
217 
GetVersion(const KvDBProperties & kvDBProp,int & version,bool & isDbExisted) const218 int SQLiteLocalKvDB::GetVersion(const KvDBProperties &kvDBProp, int &version, bool &isDbExisted) const
219 {
220     OpenDbProperties option;
221     InitDataBaseOption(kvDBProp, option);
222     isDbExisted = OS::CheckPathExistence(option.uri);
223 
224     int errCode = E_OK;
225     if (isDbExisted) {
226         errCode = SQLiteUtils::GetVersion(option, version);
227     }
228     return errCode;
229 }
230 
SetVersion(const KvDBProperties & kvDBProp,int version)231 int SQLiteLocalKvDB::SetVersion(const KvDBProperties &kvDBProp, int version)
232 {
233     OpenDbProperties option;
234     InitDataBaseOption(kvDBProp, option);
235     bool isDbExisted = OS::CheckPathExistence(option.uri);
236     if (!isDbExisted) {
237         return -E_NOT_FOUND;
238     }
239     return SQLiteUtils::SetUserVer(option, version);
240 }
241 
GetDbProperties() const242 const KvDBProperties &SQLiteLocalKvDB::GetDbProperties() const
243 {
244     return GetMyProperties();
245 }
246 
GetDbPropertyForUpdate()247 KvDBProperties &SQLiteLocalKvDB::GetDbPropertyForUpdate()
248 {
249     return MyProp();
250 }
251 
ReleaseHandle(SQLiteLocalStorageExecutor * & handle) const252 void SQLiteLocalKvDB::ReleaseHandle(SQLiteLocalStorageExecutor *&handle) const
253 {
254     if (storageEngine_ != nullptr) {
255         bool isCorrupted = handle->GetCorruptedStatus();
256         StorageExecutor *databaseHandle = handle;
257         storageEngine_->Recycle(databaseHandle);
258         handle = nullptr;
259         if (isCorrupted) {
260             CorruptNotify();
261         }
262     }
263 }
264 
InitStorageEngine(const KvDBProperties & kvDBProp)265 int SQLiteLocalKvDB::InitStorageEngine(const KvDBProperties &kvDBProp)
266 {
267     if (storageEngine_ == nullptr) {
268         // Create HandlePool
269         storageEngine_ = new (std::nothrow) SQLiteLocalStorageEngine();
270         if (storageEngine_ == nullptr) {
271             LOGE("Create local sqlite storage engine OOM");
272             return -E_OUT_OF_MEMORY;
273         }
274     }
275 
276     OpenDbProperties option;
277     InitDataBaseOption(kvDBProp, option);
278     StorageEngineAttr poolSize = {0, 1, 0, 4}; // 1 write 4 read at most.
279     int errCode = storageEngine_->InitSQLiteStorageEngine(poolSize, option);
280     if (errCode != E_OK) {
281         goto END;
282     }
283 
284     // We don't have to do version check here if the SQLiteLocalKvDB does not work as LocalStore.
285     // The isAutonomicUpgradeEnable_ true indicate that it work as LocalStore. Do version check in three case:
286     // Open the database, which call Open then InitStorageEngine.
287     // Import the database, which call InitDatabaseContext then InitStorageEngine.
288     // Rekey the database, which call RunRekeyLogic then InitStorageEngine. (This case is not necessary in fact)
289     errCode = CheckVersionAndUpgradeIfNeed(option);
290 END:
291     if (errCode != E_OK) {
292         LOGE("Init sqlite handler pool failed:%d", errCode);
293         // Transform the errCode.
294     }
295     return errCode;
296 }
297 
InitDataBaseOption(const KvDBProperties & kvDBProp,OpenDbProperties & option) const298 void SQLiteLocalKvDB::InitDataBaseOption(const KvDBProperties &kvDBProp, OpenDbProperties &option) const
299 {
300     std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, "");
301     std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, "");
302     std::string dbName = kvDBProp.GetStringProp(KvDBProperties::FILE_NAME, DBConstant::LOCAL_DATABASE_NAME);
303     int databaseType = kvDBProp.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE);
304     bool createIfNecessary = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true);
305     std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType);
306     // Table name "data" should not be changed in the future, otherwise when an older software open a newer database
307     // with table of other name, we will create an second table as result which is not expected.
308     std::vector<std::string> createTableSqls = {CREATE_SQL};
309     CipherType cipherType;
310     CipherPassword passwd;
311     kvDBProp.GetPassword(cipherType, passwd);
312     std::string uri = dataDir + "/" + identifierDir + "/" + subDir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION;
313     option = {uri, createIfNecessary, false, createTableSqls, cipherType, passwd};
314 }
315 
BackupCurrentDatabase(const KvDBProperties & properties,const std::string & dir)316 int SQLiteLocalKvDB::BackupCurrentDatabase(const KvDBProperties &properties, const std::string &dir)
317 {
318     std::string baseDir;
319     int errCode = GetWorkDir(properties, baseDir);
320     if (errCode != E_OK) {
321         LOGE("[SqlLocalDb][Backup] GetWorkDir fail, errCode=%d.", errCode);
322         return errCode;
323     }
324     std::string dbName = properties.GetStringProp(KvDBProperties::FILE_NAME, DBConstant::LOCAL_DATABASE_NAME);
325     int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE);
326     std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType);
327     std::string currentDb = baseDir + "/" + subDir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION;
328     std::string dstDb = dir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION;
329     errCode = DBCommon::CopyFile(currentDb, dstDb);
330     if (errCode != E_OK) {
331         LOGE("Copy the local current db error:%d", errCode);
332     }
333     return errCode;
334 }
335 
ImportDatabase(const KvDBProperties & properties,const std::string & dir,const CipherPassword & passwd)336 int SQLiteLocalKvDB::ImportDatabase(const KvDBProperties &properties, const std::string &dir,
337     const CipherPassword &passwd)
338 {
339     std::string baseDir;
340     int errCode = GetWorkDir(properties, baseDir);
341     if (errCode != E_OK) {
342         return errCode;
343     }
344     std::string dbName = properties.GetStringProp(KvDBProperties::FILE_NAME, DBConstant::LOCAL_DATABASE_NAME);
345     int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE);
346     std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType);
347     std::string dstDb = baseDir + "/" + subDir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION;
348     std::string currentDb = dir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION;
349     CipherType cipherType;
350     CipherPassword dstPasswd;
351     properties.GetPassword(cipherType, dstPasswd);
352     return SQLiteUtils::ExportDatabase(currentDb, cipherType, passwd, dstDb, dstPasswd);
353 }
354 
RemoveKvDB(const KvDBProperties & properties)355 int SQLiteLocalKvDB::RemoveKvDB(const KvDBProperties &properties)
356 {
357     // Only care the data directory and the db name.
358     std::string storeOnlyDir;
359     std::string storeDir;
360     GenericKvDB::GetStoreDirectory(properties, KvDBProperties::LOCAL_TYPE, storeDir, storeOnlyDir);
361     int dbType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE);
362     return KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, KvDBProperties::GetStoreSubDirectory(dbType));
363 }
364 
GetKvDBSize(const KvDBProperties & properties,uint64_t & size) const365 int SQLiteLocalKvDB::GetKvDBSize(const KvDBProperties &properties, uint64_t &size) const
366 {
367     std::string storeOnlyDir;
368     std::string storeDir;
369     GenericKvDB::GetStoreDirectory(properties, KvDBProperties::LOCAL_TYPE, storeDir, storeOnlyDir);
370     int dbType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE);
371     return KvDBUtils::GetKvDbSize(storeDir, storeOnlyDir, KvDBProperties::GetStoreSubDirectory(dbType), size);
372 }
373 
CheckVersionAndUpgradeIfNeed(const OpenDbProperties & openProp)374 int SQLiteLocalKvDB::CheckVersionAndUpgradeIfNeed(const OpenDbProperties &openProp)
375 {
376     if (!isAutonomicUpgradeEnable_) {
377         return E_OK;
378     }
379     int dbVersion = 0;
380     int errCode = SQLiteUtils::GetVersion(openProp, dbVersion);
381     if (errCode != E_OK) {
382         LOGE("[SqlLocalDb][CheckUpgrade] GetVersion fail, errCode=%d.", errCode);
383         return errCode;
384     }
385     LOGD("[SqlLocalDb][CheckUpgrade] DbFile Version=%d, CurVersion=%d.", dbVersion, LOCAL_STORE_VERSION_CURRENT);
386     if (dbVersion > LOCAL_STORE_VERSION_CURRENT) {
387         return -E_VERSION_NOT_SUPPORT;
388     }
389     // For version equal or less LOCAL_STORE_VERSION_CURRENT except zero, we can do nothing currently
390     if (dbVersion != 0) {
391         return E_OK;
392     }
393     errCode = SQLiteUtils::SetUserVer(openProp, LOCAL_STORE_VERSION_CURRENT);
394     if (errCode != E_OK) {
395         LOGE("[SqlLocalDb][CheckUpgrade] SetUserVer fail, errCode=%d.", errCode);
396         return errCode;
397     }
398     return E_OK;
399 }
400 
401 DEFINE_OBJECT_TAG_FACILITIES(SQLiteLocalKvDB)
402 } // namespace DistributedDB
403