• 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_connection.h"
17 
18 #include <cstring>
19 
20 #include "log_print.h"
21 #include "db_constant.h"
22 #include "sqlite_utils.h"
23 #include "sqlite_local_kvdb.h"
24 #include "sqlite_local_kvdb_snapshot.h"
25 #include "kvdb_commit_notify_filterable_data.h"
26 #include "sqlite_local_storage_executor.h"
27 
28 namespace DistributedDB {
SQLiteLocalKvDBConnection(SQLiteLocalKvDB * kvDB)29 SQLiteLocalKvDBConnection::SQLiteLocalKvDBConnection(SQLiteLocalKvDB *kvDB)
30     : GenericKvDBConnection(kvDB),
31       writeHandle_(nullptr)
32 {}
33 
~SQLiteLocalKvDBConnection()34 SQLiteLocalKvDBConnection::~SQLiteLocalKvDBConnection()
35 {}
36 
Get(const IOption & option,const Key & key,Value & value) const37 int SQLiteLocalKvDBConnection::Get(const IOption &option, const Key &key, Value &value) const
38 {
39     if (kvDB_ == nullptr) {
40         return -E_INVALID_DB;
41     }
42     if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE) {
43         return -E_INVALID_ARGS;
44     }
45     {
46         std::lock_guard<std::mutex> lock(transactionMutex_);
47         if (writeHandle_ != nullptr) {
48             return writeHandle_->Get(key, value);
49         }
50     }
51     int errCode = E_OK;
52     SQLiteLocalStorageExecutor *handle = GetDB<SQLiteLocalKvDB>()->GetHandle(false, errCode);
53     if (handle == nullptr) {
54         return errCode;
55     }
56 
57     errCode = handle->Get(key, value);
58     GetDB<SQLiteLocalKvDB>()->ReleaseHandle(handle);
59     return errCode;
60 }
61 
Put(const IOption & option,const Key & key,const Value & value)62 int SQLiteLocalKvDBConnection::Put(const IOption &option, const Key &key, const Value &value)
63 {
64     int errCode = CheckDataStatus(key, value, false);
65     if (errCode != E_OK) {
66         return errCode;
67     }
68     std::lock_guard<std::mutex> lock(transactionMutex_);
69     bool isAuto = false;
70     errCode = StartTransactionInner(isAuto);
71     if (errCode != E_OK) {
72         LOGE("StartTransaction failed when Put error:%d", errCode);
73         return errCode;
74     }
75 
76     errCode = writeHandle_->Put(key, value);
77     if (errCode != E_OK) {
78         if (isAuto) {
79             int errCodeRollBack = RollBackInner();
80             LOGI("Put failed,need rollback! errCode:[%d]", errCodeRollBack);
81         }
82         return errCode;
83     }
84     if (isAuto) {
85         errCode = CommitInner();
86         if (errCode != E_OK) {
87             LOGE("CommitTransaction failed when Put error:%d", errCode);
88             return errCode;
89         }
90     }
91 
92     return errCode;
93 }
94 
Delete(const IOption & option,const Key & key)95 int SQLiteLocalKvDBConnection::Delete(const IOption &option, const Key &key)
96 {
97     int errCode = CheckDataStatus(key, {}, true);
98     if (errCode != E_OK) {
99         return errCode;
100     }
101     std::lock_guard<std::mutex> lock(transactionMutex_);
102     bool isAuto = false;
103     errCode = StartTransactionInner(isAuto);
104     if (errCode != E_OK) {
105         LOGE("StartTransaction failed when Delete error:%d", errCode);
106         return errCode;
107     }
108 
109     errCode = writeHandle_->Delete(key);
110     if (errCode != E_OK) {
111         if (isAuto) {
112             int errCodeRollBack = RollBackInner();
113             LOGI("Delete failed, need rollback! errcode:[%d]", errCodeRollBack);
114         }
115         return errCode;
116     }
117 
118     if (isAuto) {
119         errCode = CommitInner();
120         if (errCode != E_OK) {
121             LOGE("CommitInner failed while delete:%d", errCode);
122             return errCode;
123         }
124     }
125     return E_OK;
126 }
127 
Clear(const IOption & option)128 int SQLiteLocalKvDBConnection::Clear(const IOption &option)
129 {
130     std::lock_guard<std::mutex> lock(transactionMutex_);
131     bool isAuto = false;
132     int errCode = StartTransactionInner(isAuto);
133     if (errCode != E_OK) {
134         LOGE("StartTransaction failed when Clear error:%d", errCode);
135         return errCode;
136     }
137 
138     errCode = writeHandle_->Clear();
139     if (errCode != E_OK) {
140         if (isAuto) {
141             int errCodeRollBack = RollBackInner();
142             LOGI("Clear failed, need rollback! RollBack result is [%d]", errCodeRollBack);
143         }
144         return errCode;
145     }
146 
147     if (isAuto) {
148         errCode = CommitInner();
149         if (errCode != E_OK) {
150             LOGE("CommitInner failed when Clear error:%d", errCode);
151             return errCode;
152         }
153     }
154 
155     return E_OK;
156 }
157 
GetEntries(const IOption & option,const Key & keyPrefix,std::vector<Entry> & entries) const158 int SQLiteLocalKvDBConnection::GetEntries(const IOption &option, const Key &keyPrefix,
159     std::vector<Entry> &entries) const
160 {
161     if (kvDB_ == nullptr) {
162         return -E_INVALID_DB;
163     }
164     if (keyPrefix.size() > DBConstant::MAX_KEY_SIZE) {
165         return -E_INVALID_ARGS;
166     }
167     {
168         std::lock_guard<std::mutex> lock(transactionMutex_);
169         if (writeHandle_ != nullptr) {
170             return writeHandle_->GetEntries(keyPrefix, entries);
171         }
172     }
173     int errCode = E_OK;
174     SQLiteLocalStorageExecutor *handle = GetDB<SQLiteLocalKvDB>()->GetHandle(false, errCode);
175     if (handle == nullptr) {
176         return errCode;
177     }
178     errCode = handle->GetEntries(keyPrefix, entries);
179     GetDB<SQLiteLocalKvDB>()->ReleaseHandle(handle);
180     return errCode;
181 }
182 
PutBatch(const IOption & option,const std::vector<Entry> & entries)183 int SQLiteLocalKvDBConnection::PutBatch(const IOption &option, const std::vector<Entry> &entries)
184 {
185     if (entries.empty() || entries.size() > DBConstant::MAX_BATCH_SIZE) {
186         return -E_INVALID_ARGS;
187     }
188     for (const auto &item : entries) {
189         if (CheckDataStatus(item.key, item.value, false) != E_OK) {
190             return -E_INVALID_ARGS;
191         }
192     }
193 
194     bool isAuto = false;
195     std::lock_guard<std::mutex> lock(transactionMutex_);
196     int errCode = StartTransactionInner(isAuto);
197     if (errCode != E_OK) {
198         LOGE("StartTransaction failed when PutBatch error:%d", errCode);
199         return errCode;
200     }
201 
202     for (const auto &entry : entries) {
203         // first argument is key and second argument is value.
204         errCode = writeHandle_->Put(entry.key, entry.value);
205         if (errCode != E_OK) {
206             if (isAuto) {
207                 int errCodeRollBack = RollBackInner();
208                 LOGI("PutBatch failed,need rollback! RollBack result is %d", errCodeRollBack);
209             }
210             return errCode;
211         }
212     }
213 
214     if (isAuto) {
215         errCode = CommitInner();
216         if (errCode != E_OK) {
217             LOGE("CommitTransaction failed when PutBatch error:%d", errCode);
218             return errCode;
219         }
220     }
221 
222     return E_OK;
223 }
224 
DeleteBatch(const IOption & option,const std::vector<Key> & keys)225 int SQLiteLocalKvDBConnection::DeleteBatch(const IOption &option, const std::vector<Key> &keys)
226 {
227     if (keys.empty() || keys.size() > DBConstant::MAX_BATCH_SIZE) {
228         LOGE("[Local]DeleteBatch size[%zu]!", keys.size());
229         return -E_INVALID_ARGS;
230     }
231     for (const auto &item : keys) {
232         if (item.empty() || item.size() > DBConstant::MAX_KEY_SIZE) {
233             return -E_INVALID_ARGS;
234         }
235     }
236 
237     bool isAuto = false;
238     std::lock_guard<std::mutex> lock(transactionMutex_);
239     int errCode = StartTransactionInner(isAuto);
240     if (errCode != E_OK) {
241         LOGE("StartTransaction failed when DeleteBatch error:%d", errCode);
242         return errCode;
243     }
244 
245     errCode = writeHandle_->DeleteBatch(keys);
246 
247     if (isAuto) {
248         if (errCode == E_OK) {
249             errCode = CommitInner();
250             if (errCode != E_OK) {
251                 LOGE("CommitTransaction failed when DeleteBatch error:%d", errCode);
252                 return errCode;
253             }
254         } else {
255             int errCodeRollBack = RollBackInner();
256             LOGI("DeleteBatchm need rollback! RollBack result is [%d]", errCodeRollBack);
257             return errCode;
258         }
259     }
260 
261     return errCode;
262 }
263 
264 // when GetSnapshot successfully, you must delete snapshot by ReleaseSnapshot
GetSnapshot(IKvDBSnapshot * & snapshot) const265 int SQLiteLocalKvDBConnection::GetSnapshot(IKvDBSnapshot *&snapshot) const
266 {
267     if (kvDB_ == nullptr) {
268         snapshot = nullptr;
269         return -E_INVALID_DB;
270     }
271 
272     int errCode = E_OK;
273     IKvDBConnection *newConnect = kvDB_->GetDBConnection(errCode);
274     if (errCode != E_OK) {
275         LOGE("failed to get the new connection");
276         return errCode;
277     }
278 
279     SQLiteLocalKvDBSnapshot *dbSnapshot = new (std::nothrow) SQLiteLocalKvDBSnapshot(newConnect);
280     if (dbSnapshot == nullptr) {
281         newConnect->Close();
282         delete newConnect;
283         return -E_OUT_OF_MEMORY;
284     }
285 
286     snapshot = dbSnapshot;
287     {
288         std::lock_guard<std::mutex> lock(snapshotMutex_);
289         snapshots_.insert(dbSnapshot);
290     }
291 
292     return E_OK;
293 }
294 
ReleaseSnapshot(IKvDBSnapshot * & snapshot)295 void SQLiteLocalKvDBConnection::ReleaseSnapshot(IKvDBSnapshot *&snapshot)
296 {
297     if (snapshot != nullptr && kvDB_ != nullptr) {
298         std::lock_guard<std::mutex> lock(snapshotMutex_);
299         SQLiteLocalKvDBSnapshot *sqliteSnapshot = static_cast<SQLiteLocalKvDBSnapshot *>(snapshot);
300         sqliteSnapshot->Close();
301         snapshots_.erase(snapshot);
302         delete snapshot;
303         snapshot = nullptr;
304     }
305 }
306 
StartTransaction()307 int SQLiteLocalKvDBConnection::StartTransaction()
308 {
309     std::lock_guard<std::mutex> lock(transactionMutex_);
310     if (writeHandle_ != nullptr) {
311         return -E_TRANSACT_STATE;
312     }
313     bool isAuto = false;
314     return StartTransactionInner(isAuto);
315 }
316 
Commit()317 int SQLiteLocalKvDBConnection::Commit()
318 {
319     std::lock_guard<std::mutex> lock(transactionMutex_);
320     return CommitInner();
321 }
322 
RollBack()323 int SQLiteLocalKvDBConnection::RollBack()
324 {
325     std::lock_guard<std::mutex> lock(transactionMutex_);
326     return RollBackInner();
327 }
328 
IsTransactionStarted() const329 bool SQLiteLocalKvDBConnection::IsTransactionStarted() const
330 {
331     std::lock_guard<std::mutex> lock(transactionMutex_);
332     if (writeHandle_ != nullptr) {
333         return true;
334     }
335     return false;
336 }
337 
PreClose()338 int SQLiteLocalKvDBConnection::PreClose()
339 {
340     {
341         std::lock_guard<std::mutex> snapshotLock(snapshotMutex_);
342         if (snapshots_.size() != 0) {
343             LOGE("Close failed, the connection have unreleased snapshot.");
344             return -E_BUSY;
345         }
346     }
347     std::lock_guard<std::mutex> transactionLock(transactionMutex_);
348     if (writeHandle_ != nullptr) {
349         writeHandle_->RollBack();
350         GetDB<SQLiteLocalKvDB>()->ReleaseHandle(writeHandle_);
351     }
352     return E_OK;
353 }
354 
TranslateObserverModeToEventTypes(unsigned mode,std::list<int> & eventTypes) const355 int SQLiteLocalKvDBConnection::TranslateObserverModeToEventTypes(unsigned mode,
356     std::list<int> &eventTypes) const
357 {
358     return E_OK;
359 }
360 
StartTransactionInner(bool & isAuto)361 int SQLiteLocalKvDBConnection::StartTransactionInner(bool &isAuto)
362 {
363     // if the transaction has been started, writeHandle wouldn't be nullptr.
364     if (writeHandle_ != nullptr) {
365         return E_OK;
366     }
367 
368     if (kvDB_ == nullptr) {
369         LOGE("local database is null");
370         return -E_INVALID_DB;
371     }
372 
373     int errCode = E_OK;
374     SQLiteLocalStorageExecutor *handle = GetDB<SQLiteLocalKvDB>()->GetHandle(true, errCode);
375     if (handle == nullptr) {
376         return errCode;
377     }
378 
379     errCode = handle->StartTransaction();
380     if (errCode != E_OK) {
381         GetDB<SQLiteLocalKvDB>()->ReleaseHandle(handle);
382         return errCode;
383     }
384     writeHandle_ = handle;
385     // only the transaction has not been started before, set the flag to true.
386     // the manual operation would ignore the flag.
387     isAuto = true;
388     return E_OK;
389 }
390 
CommitInner()391 int SQLiteLocalKvDBConnection::CommitInner()
392 {
393     if (writeHandle_ == nullptr) {
394         LOGE("local database is null or the transaction has not been started");
395         return -E_INVALID_DB;
396     }
397 
398     int errCode = writeHandle_->Commit();
399     if (kvDB_ == nullptr) {
400         return -E_INVALID_DB;
401     }
402     GetDB<SQLiteLocalKvDB>()->ReleaseHandle(writeHandle_);
403     return errCode;
404 }
405 
RollBackInner()406 int SQLiteLocalKvDBConnection::RollBackInner()
407 {
408     if (writeHandle_ == nullptr) {
409         LOGE("Invalid handle for rollback or the transaction has not been started.");
410         return -E_INVALID_DB;
411     }
412 
413     int errCode = writeHandle_->RollBack();
414     if (kvDB_ == nullptr) {
415         return -E_INVALID_DB;
416     }
417     GetDB<SQLiteLocalKvDB>()->ReleaseHandle(writeHandle_);
418     return errCode;
419 }
420 
Rekey(const CipherPassword & passwd)421 int SQLiteLocalKvDBConnection::Rekey(const CipherPassword &passwd)
422 {
423     if (kvDB_ == nullptr) {
424         return -E_INVALID_DB;
425     }
426     std::lock_guard<std::mutex> lock(transactionMutex_);
427     // return BUSY if in transaction
428     if (writeHandle_ != nullptr) {
429         LOGE("Transaction exists for rekey failed");
430         return -E_BUSY;
431     }
432     // Check the connection number.
433     int errCode = kvDB_->TryToDisableConnection(OperatePerm::REKEY_MONOPOLIZE_PERM);
434     if (errCode != E_OK) {
435         return errCode;
436     }
437 
438     // Check the observer.
439     errCode = GenericKvDBConnection::PreCheckExclusiveStatus();
440     if (errCode != E_OK) {
441         kvDB_->ReEnableConnection(OperatePerm::REKEY_MONOPOLIZE_PERM);
442         return errCode;
443     }
444     // If only have one connection, just have the transactionMutex_;
445     // It means there would not be another operation on this connection.
446     errCode = kvDB_->Rekey(passwd);
447 
448     GenericKvDBConnection::ResetExclusiveStatus();
449     kvDB_->ReEnableConnection(OperatePerm::REKEY_MONOPOLIZE_PERM);
450     return errCode;
451 }
452 
Export(const std::string & filePath,const CipherPassword & passwd)453 int SQLiteLocalKvDBConnection::Export(const std::string &filePath, const CipherPassword &passwd)
454 {
455     if (kvDB_ == nullptr) {
456         return -E_INVALID_DB;
457     }
458     return kvDB_->Export(filePath, passwd);
459 }
460 
Import(const std::string & filePath,const CipherPassword & passwd)461 int SQLiteLocalKvDBConnection::Import(const std::string &filePath, const CipherPassword &passwd)
462 {
463     if (kvDB_ == nullptr) {
464         return -E_INVALID_DB;
465     }
466     {
467         std::lock_guard<std::mutex> lock(transactionMutex_);
468         // return BUSY if in transaction
469         if (writeHandle_ != nullptr) {
470             LOGE("Transaction exists for rekey failed");
471             return -E_BUSY;
472         }
473     }
474     std::lock_guard<std::mutex> importLock(importMutex_);
475     int errCode = kvDB_->TryToDisableConnection(OperatePerm::IMPORT_MONOPOLIZE_PERM);
476     if (errCode != E_OK) {
477         return errCode;
478     }
479 
480     errCode = GenericKvDBConnection::PreCheckExclusiveStatus();
481     if (errCode != E_OK) {
482         kvDB_->ReEnableConnection(OperatePerm::IMPORT_MONOPOLIZE_PERM);
483         return errCode;
484     }
485     errCode = kvDB_->Import(filePath, passwd);
486     GenericKvDBConnection::ResetExclusiveStatus();
487     kvDB_->ReEnableConnection(OperatePerm::IMPORT_MONOPOLIZE_PERM);
488     return errCode;
489 }
490 
CheckDataStatus(const Key & key,const Value & value,bool isDeleted) const491 int SQLiteLocalKvDBConnection::CheckDataStatus(const Key &key, const Value &value, bool isDeleted) const
492 {
493     if (kvDB_ == nullptr) {
494         return -E_INVALID_DB;
495     }
496     return static_cast<SQLiteLocalKvDB *>(kvDB_)->CheckDataStatus(key, value, isDeleted);
497 }
498 } // namespace DistributedDB
499