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 #ifdef RELATIONAL_STORE
16 #include "sqlite_relational_store_connection.h"
17 #include "db_errno.h"
18 #include "log_print.h"
19 
20 namespace DistributedDB {
SQLiteRelationalStoreConnection(SQLiteRelationalStore * store)21 SQLiteRelationalStoreConnection::SQLiteRelationalStoreConnection(SQLiteRelationalStore *store)
22     : RelationalStoreConnection(store)
23 {
24     OnKill([this]() {
25         auto *store = GetDB<SQLiteRelationalStore>();
26         if (store == nullptr) {
27             return;
28         }
29         UnlockObj();
30         store->StopSync(GetConnectionId());
31         LockObj();
32     });
33 }
34 // Close and release the connection.
Close()35 int SQLiteRelationalStoreConnection::Close()
36 {
37     if (store_ == nullptr) {
38         return -E_INVALID_CONNECTION;
39     }
40 
41     if (isExclusive_.load()) {
42         return -E_BUSY;
43     }
44 
45     // check if transaction closed
46     {
47         std::lock_guard<std::mutex> transactionLock(transactionMutex_);
48         if (writeHandle_ != nullptr) {
49             LOGW("Transaction started, need to rollback before close.");
50             int errCode = RollBack();
51             if (errCode != E_OK) {
52                 LOGE("Rollback transaction failed, %d.", errCode);
53             }
54             ReleaseExecutor(writeHandle_);
55         }
56     }
57 
58     static_cast<SQLiteRelationalStore *>(store_)->ReleaseDBConnection(GetConnectionId(), this);
59     return E_OK;
60 }
61 
GetIdentifier()62 std::string SQLiteRelationalStoreConnection::GetIdentifier()
63 {
64     if (store_ == nullptr) {
65         return {};
66     }
67     return store_->GetProperties().GetStringProp(RelationalDBProperties::IDENTIFIER_DATA, "");
68 }
69 
GetExecutor(bool isWrite,int & errCode) const70 SQLiteSingleVerRelationalStorageExecutor *SQLiteRelationalStoreConnection::GetExecutor(bool isWrite, int &errCode) const
71 {
72     auto *store = GetDB<SQLiteRelationalStore>();
73     if (store == nullptr) { // LCOV_EXCL_BR_LINE
74         errCode = -E_NOT_INIT;
75         LOGE("[RelationalConnection] store is null, get executor failed! errCode = [%d]", errCode);
76         return nullptr;
77     }
78 
79     return store->GetHandle(isWrite, errCode);
80 }
81 
ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor * & executor) const82 void SQLiteRelationalStoreConnection::ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor *&executor) const
83 {
84     auto *store = GetDB<SQLiteRelationalStore>();
85     if (store != nullptr) { // LCOV_EXCL_BR_LINE
86         store->ReleaseHandle(executor);
87     }
88 }
89 
StartTransaction()90 int SQLiteRelationalStoreConnection::StartTransaction()
91 {
92     std::lock_guard<std::mutex> lock(transactionMutex_);
93     if (writeHandle_ != nullptr) { // LCOV_EXCL_BR_LINE
94         LOGD("Transaction started already.");
95         return -E_TRANSACT_STATE;
96     }
97 
98     int errCode = E_OK;
99     auto *handle = GetExecutor(true, errCode);
100     if (handle == nullptr) { // LCOV_EXCL_BR_LINE
101         return errCode;
102     }
103 
104     errCode = handle->StartTransaction(TransactType::DEFERRED);
105     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
106         ReleaseExecutor(handle);
107         return errCode;
108     }
109 
110     writeHandle_ = handle;
111     return E_OK;
112 }
113 
114 // Commit the transaction
Commit()115 int SQLiteRelationalStoreConnection::Commit()
116 {
117     std::lock_guard<std::mutex> lock(transactionMutex_);
118     if (writeHandle_ == nullptr) { // LCOV_EXCL_BR_LINE
119         LOGE("single version database is null or the transaction has not been started");
120         return -E_INVALID_DB;
121     }
122 
123     int errCode = writeHandle_->Commit();
124     ReleaseExecutor(writeHandle_);
125     LOGD("connection commit transaction!");
126     return errCode;
127 }
128 
129 // Roll back the transaction
RollBack()130 int SQLiteRelationalStoreConnection::RollBack()
131 {
132     std::lock_guard<std::mutex> lock(transactionMutex_);
133     if (writeHandle_ == nullptr) { // LCOV_EXCL_BR_LINE
134         LOGE("Invalid handle for rollback or the transaction has not been started.");
135         return -E_INVALID_DB;
136     }
137 
138     int errCode = writeHandle_->Rollback();
139     ReleaseExecutor(writeHandle_);
140     LOGI("connection rollback transaction!");
141     return errCode;
142 }
143 
CreateDistributedTable(const std::string & tableName,TableSyncType syncType)144 int SQLiteRelationalStoreConnection::CreateDistributedTable(const std::string &tableName, TableSyncType syncType)
145 {
146     auto *store = GetDB<SQLiteRelationalStore>();
147     if (store == nullptr) {
148         LOGE("[RelationalConnection] store is null, get DB failed!");
149         return -E_INVALID_CONNECTION;
150     }
151 
152     int errCode = store->CreateDistributedTable(tableName, syncType);
153     if (errCode != E_OK) {
154         LOGE("[RelationalConnection] create distributed table failed. %d", errCode);
155     }
156     return errCode;
157 }
158 
RemoveDeviceData()159 int SQLiteRelationalStoreConnection::RemoveDeviceData()
160 {
161     auto *store = GetDB<SQLiteRelationalStore>();
162     if (store == nullptr) {
163         LOGE("[RelationalConnection] store is null, get DB failed!");
164         return -E_INVALID_CONNECTION;
165     }
166 
167     int errCode = store->RemoveDeviceData();
168     if (errCode != E_OK) {
169         LOGE("[RelationalConnection] remove device data failed. %d", errCode);
170     }
171     return errCode;
172 }
173 
GetCloudSyncTaskCount()174 int32_t SQLiteRelationalStoreConnection::GetCloudSyncTaskCount()
175 {
176     auto *store = GetDB<SQLiteRelationalStore>();
177     if (store == nullptr) {
178         LOGE("[RelationalConnection] store is null, get DB failed!");
179         return -1;
180     }
181     int32_t count = store->GetCloudSyncTaskCount();
182     if (count == -1) {
183         LOGE("[RelationalConnection] failed to get cloud sync task count");
184     }
185     return count;
186 }
187 
DoClean(ClearMode mode)188 int SQLiteRelationalStoreConnection::DoClean(ClearMode mode)
189 {
190     auto *store = GetDB<SQLiteRelationalStore>();
191     if (store == nullptr) {
192         LOGE("[RelationalConnection] store is null, get DB failed!");
193         return -E_INVALID_CONNECTION;
194     }
195 
196     int errCode = store->CleanCloudData(mode);
197     if (errCode != E_OK) {
198         LOGE("[RelationalConnection] failed to clean cloud data, %d.", errCode);
199     }
200     return errCode;
201 }
202 
RemoveDeviceData(const std::string & device)203 int SQLiteRelationalStoreConnection::RemoveDeviceData(const std::string &device)
204 {
205     return RemoveDeviceData(device, {});
206 }
207 
RemoveDeviceData(const std::string & device,const std::string & tableName)208 int SQLiteRelationalStoreConnection::RemoveDeviceData(const std::string &device, const std::string &tableName)
209 {
210     auto *store = GetDB<SQLiteRelationalStore>();
211     if (store == nullptr) {
212         LOGE("[RelationalConnection] store is null, get DB failed!");
213         return -E_INVALID_CONNECTION;
214     }
215 
216     int errCode = store->RemoveDeviceData(device, tableName);
217     if (errCode != E_OK) {
218         LOGE("[RelationalConnection] remove device data failed. %d", errCode);
219     }
220     return errCode;
221 }
222 
Pragma(int cmd,void * parameter)223 int SQLiteRelationalStoreConnection::Pragma(int cmd, void *parameter) // reserve for interface function fix
224 {
225     (void)cmd;
226     (void)parameter;
227     return E_OK;
228 }
229 
SyncToDevice(SyncInfo & info)230 int SQLiteRelationalStoreConnection::SyncToDevice(SyncInfo &info)
231 {
232     auto *store = GetDB<SQLiteRelationalStore>();
233     if (store == nullptr) {
234         LOGE("[RelationalConnection] store is null, get executor failed!");
235         return -E_INVALID_CONNECTION;
236     }
237 
238     {
239         AutoLock lockGuard(this);
240         if (IsKilled()) {
241             // If this happens, users are using a closed connection.
242             LOGE("Sync on a closed connection.");
243             return -E_STALE;
244         }
245         IncObjRef(this);
246     }
247     ISyncer::SyncParma syncParam;
248     syncParam.devices = info.devices;
249     syncParam.mode = info.mode;
250     syncParam.wait = info.wait;
251     syncParam.isQuerySync = true;
252     syncParam.relationOnComplete = info.onComplete;
253     syncParam.syncQuery = QuerySyncObject(info.query);
254     syncParam.onFinalize =  [this]() {
255         DecObjRef(this);
256     };
257     if (syncParam.syncQuery.GetSortType() != SortType::NONE) {
258         LOGE("not support order by timestamp");
259         DecObjRef(this);
260         return -E_NOT_SUPPORT;
261     }
262     int errCode = store->Sync(syncParam, GetConnectionId());
263     if (errCode != E_OK) {
264         DecObjRef(this);
265         return errCode;
266     }
267     return E_OK;
268 }
269 
RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier & notifier)270 int SQLiteRelationalStoreConnection::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier &notifier)
271 {
272     auto *store = GetDB<SQLiteRelationalStore>();
273     if (store == nullptr) {
274         LOGE("[RelationalConnection] store is null, get executor failed!");
275         return -E_INVALID_CONNECTION;
276     }
277 
278     return store->RegisterLifeCycleCallback(notifier);
279 }
280 
RegisterObserverAction(const StoreObserver * observer,const RelationalObserverAction & action)281 int SQLiteRelationalStoreConnection::RegisterObserverAction(const StoreObserver *observer,
282     const RelationalObserverAction &action)
283 {
284     return static_cast<SQLiteRelationalStore *>(store_)->RegisterObserverAction(GetConnectionId(), observer, action);
285 }
286 
UnRegisterObserverAction(const StoreObserver * observer)287 int SQLiteRelationalStoreConnection::UnRegisterObserverAction(const StoreObserver *observer)
288 {
289     return static_cast<SQLiteRelationalStore *>(store_)->UnRegisterObserverAction(GetConnectionId(), observer);
290 }
291 
RemoteQuery(const std::string & device,const RemoteCondition & condition,uint64_t timeout,std::shared_ptr<ResultSet> & result)292 int SQLiteRelationalStoreConnection::RemoteQuery(const std::string &device, const RemoteCondition &condition,
293     uint64_t timeout, std::shared_ptr<ResultSet> &result)
294 {
295     auto *store = GetDB<SQLiteRelationalStore>();
296     if (store == nullptr) {
297         LOGE("[RelationalConnection] store is null, get executor failed!");
298         return -E_INVALID_CONNECTION;
299     }
300     return store->RemoteQuery(device, condition, timeout, GetConnectionId(), result);
301 }
302 
SetCloudDB(const std::shared_ptr<ICloudDb> & cloudDb)303 int SQLiteRelationalStoreConnection::SetCloudDB(const std::shared_ptr<ICloudDb> &cloudDb)
304 {
305     auto *store = GetDB<SQLiteRelationalStore>();
306     if (store == nullptr) {
307         LOGE("[RelationalConnection] store is null, get DB failed!");
308         return -E_INVALID_CONNECTION;
309     }
310 
311     return store->SetCloudDB(cloudDb);
312 }
313 
PrepareAndSetCloudDbSchema(const DataBaseSchema & schema)314 int SQLiteRelationalStoreConnection::PrepareAndSetCloudDbSchema(const DataBaseSchema &schema)
315 {
316     auto *store = GetDB<SQLiteRelationalStore>();
317     if (store == nullptr) {
318         LOGE("[RelationalConnection] store is null, get DB failed!");
319         return -E_INVALID_CONNECTION;
320     }
321 
322     int ret = store->PrepareAndSetCloudDbSchema(schema);
323     if (ret != E_OK) {
324         LOGE("[RelationalConnection] PrepareAndSetCloudDbSchema failed. %d", ret);
325     }
326     return ret;
327 }
328 
SetIAssetLoader(const std::shared_ptr<IAssetLoader> & loader)329 int SQLiteRelationalStoreConnection::SetIAssetLoader(const std::shared_ptr<IAssetLoader> &loader)
330 {
331     auto *store = GetDB<SQLiteRelationalStore>();
332     if (store == nullptr) {
333         LOGE("[RelationalConnection] store is null, get DB failed!");
334         return -E_INVALID_CONNECTION;
335     }
336 
337     int ret = store->SetIAssetLoader(loader);
338     if (ret != E_OK) {
339         LOGE("[RelationalConnection] Set asset loader failed. %d", ret);
340     }
341     return ret;
342 }
343 
GetStoreInfo(std::string & userId,std::string & appId,std::string & storeId)344 int SQLiteRelationalStoreConnection::GetStoreInfo(std::string &userId, std::string &appId, std::string &storeId)
345 {
346     auto *store = GetDB<SQLiteRelationalStore>();
347     if (store == nullptr) {
348         LOGE("[RelationalConnection] store is null, get storeInfo failed!");
349         return -E_INVALID_CONNECTION;
350     }
351     auto properties = store->GetProperties();
352     userId = properties.GetStringProp(RelationalDBProperties::USER_ID, "");
353     appId = properties.GetStringProp(RelationalDBProperties::APP_ID, "");
354     storeId = properties.GetStringProp(RelationalDBProperties::STORE_ID, "");
355     return E_OK;
356 }
357 
SetTrackerTable(const TrackerSchema & schema)358 int SQLiteRelationalStoreConnection::SetTrackerTable(const TrackerSchema &schema)
359     {
360     auto *store = GetDB<SQLiteRelationalStore>();
361     if (store == nullptr) {
362         LOGE("[RelationalConnection] store is null, get DB failed!");
363         return -E_INVALID_CONNECTION;
364     }
365     int errCode = store->SetTrackerTable(schema);
366     if (errCode != E_OK && errCode != -E_WITH_INVENTORY_DATA) {
367         LOGE("[RelationalConnection] set tracker table failed. %d", errCode);
368     }
369     return errCode;
370 }
371 
ExecuteSql(const SqlCondition & condition,std::vector<VBucket> & records)372 int SQLiteRelationalStoreConnection::ExecuteSql(const SqlCondition &condition, std::vector<VBucket> &records)
373 {
374     auto *store = GetDB<SQLiteRelationalStore>();
375     if (store == nullptr) {
376         LOGE("[RelationalConnection] store is null, get executor failed!");
377         return -E_INVALID_CONNECTION;
378     }
379     return store->ExecuteSql(condition, records);
380 }
381 
SetReference(const std::vector<TableReferenceProperty> & tableReferenceProperty)382 int SQLiteRelationalStoreConnection::SetReference(const std::vector<TableReferenceProperty> &tableReferenceProperty)
383 {
384     auto *store = GetDB<SQLiteRelationalStore>();
385     if (store == nullptr) {
386         LOGE("[SetReference] store is null, get DB failed!");
387         return -E_INVALID_CONNECTION;
388     }
389     return store->SetReference(tableReferenceProperty);
390 }
391 
CleanTrackerData(const std::string & tableName,int64_t cursor)392 int SQLiteRelationalStoreConnection::CleanTrackerData(const std::string &tableName, int64_t cursor)
393 {
394     auto *store = GetDB<SQLiteRelationalStore>();
395     if (store == nullptr) { // LCOV_EXCL_BR_LINE
396         LOGE("[RelationalConnection] store is null, get executor failed!");
397         return -E_INVALID_CONNECTION;
398     }
399     return store->CleanTrackerData(tableName, cursor);
400 }
401 
Pragma(PragmaCmd cmd,PragmaData & pragmaData)402 int SQLiteRelationalStoreConnection::Pragma(PragmaCmd cmd, PragmaData &pragmaData)
403 {
404     auto *store = GetDB<SQLiteRelationalStore>();
405     if (store == nullptr) {
406         LOGE("[RelationalConnection] store is null, get executor failed!");
407         return -E_INVALID_CONNECTION;
408     }
409     return store->Pragma(cmd, pragmaData);
410 }
411 
UpsertData(RecordStatus status,const std::string & tableName,const std::vector<VBucket> & records)412 int SQLiteRelationalStoreConnection::UpsertData(RecordStatus status, const std::string &tableName,
413     const std::vector<VBucket> &records)
414 {
415     auto *store = GetDB<SQLiteRelationalStore>();
416     if (store == nullptr) {
417         LOGE("[RelationalConnection] store is null, upsert dara failed!");
418         return -E_INVALID_CONNECTION;
419     }
420     return store->UpsertData(status, tableName, records);
421 }
422 
SetCloudSyncConfig(const CloudSyncConfig & config)423 int SQLiteRelationalStoreConnection::SetCloudSyncConfig(const CloudSyncConfig &config)
424 {
425     auto *store = GetDB<SQLiteRelationalStore>();
426     if (store == nullptr) { // LCOV_EXCL_BR_LINE
427         LOGE("[RelationalConnection] store is null, set cloud sync config failed!");
428         return -E_INVALID_CONNECTION;
429     }
430     return store->SetCloudSyncConfig(config);
431 }
432 
Sync(const CloudSyncOption & option,const SyncProcessCallback & onProcess,uint64_t taskId)433 int SQLiteRelationalStoreConnection::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess,
434     uint64_t taskId)
435 {
436     auto *store = GetDB<SQLiteRelationalStore>();
437     if (store == nullptr) {
438         LOGE("[RelationalConnection] store is null, get executor failed!");
439         return -E_INVALID_CONNECTION;
440     }
441     {
442         AutoLock lockGuard(this);
443         if (IsKilled()) {
444             // If this happens, users are using a closed connection.
445             LOGE("[RelationalConnection] Sync on a closed connection.");
446             return -E_STALE;
447         }
448         IncObjRef(this);
449     }
450     int errCode = store->Sync(option, onProcess, taskId);
451     DecObjRef(this);
452     return errCode;
453 }
454 
GetCloudTaskStatus(uint64_t taskId)455 SyncProcess SQLiteRelationalStoreConnection::GetCloudTaskStatus(uint64_t taskId)
456 {
457     auto *store = GetDB<SQLiteRelationalStore>();
458     if (store == nullptr) {
459         LOGE("[RelationalConnection] store is null, get executor failed!");
460         SyncProcess process;
461         process.errCode = DB_ERROR;
462         return process;
463     }
464     {
465         AutoLock lockGuard(this);
466         if (IsKilled()) {
467             // If this happens, users are using a closed connection.
468             LOGE("[RelationalConnection] Get sync task on a closed connection.");
469             SyncProcess process;
470             process.errCode = DB_ERROR;
471             return process;
472         }
473         IncObjRef(this);
474     }
475     SyncProcess process = store->GetCloudTaskStatus(taskId);
476     DecObjRef(this);
477     return process;
478 }
479 }
480 #endif