• 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 #ifdef RELATIONAL_STORE
16 #include "sqlite_relational_store.h"
17 
18 #include "db_common.h"
19 #include "db_constant.h"
20 #include "db_dump_helper.h"
21 #include "db_errno.h"
22 #include "log_print.h"
23 #include "db_types.h"
24 #include "sqlite_log_table_manager.h"
25 #include "sqlite_relational_store_connection.h"
26 #include "storage_engine_manager.h"
27 
28 namespace DistributedDB {
29 namespace {
30     constexpr const char *DISTRIBUTED_TABLE_MODE = "distributed_table_mode";
31 }
32 
~SQLiteRelationalStore()33 SQLiteRelationalStore::~SQLiteRelationalStore()
34 {
35     sqliteStorageEngine_ = nullptr;
36 }
37 
38 // Called when a new connection created.
IncreaseConnectionCounter()39 void SQLiteRelationalStore::IncreaseConnectionCounter()
40 {
41     connectionCount_.fetch_add(1, std::memory_order_seq_cst);
42     if (connectionCount_.load() > 0) {
43         sqliteStorageEngine_->SetConnectionFlag(true);
44     }
45 }
46 
GetDBConnection(int & errCode)47 RelationalStoreConnection *SQLiteRelationalStore::GetDBConnection(int &errCode)
48 {
49     std::lock_guard<std::mutex> lock(connectMutex_);
50     RelationalStoreConnection* connection = new (std::nothrow) SQLiteRelationalStoreConnection(this);
51     if (connection == nullptr) {
52         errCode = -E_OUT_OF_MEMORY;
53         return nullptr;
54     }
55     IncObjRef(this);
56     IncreaseConnectionCounter();
57     return connection;
58 }
59 
InitDataBaseOption(const RelationalDBProperties & properties,OpenDbProperties & option)60 static void InitDataBaseOption(const RelationalDBProperties &properties, OpenDbProperties &option)
61 {
62     option.uri = properties.GetStringProp(DBProperties::DATA_DIR, "");
63     option.createIfNecessary = properties.GetBoolProp(DBProperties::CREATE_IF_NECESSARY, false);
64     if (properties.IsEncrypted()) {
65         option.cipherType = properties.GetCipherType();
66         option.passwd = properties.GetPasswd();
67         option.iterTimes = properties.GetIterTimes();
68     }
69 }
70 
InitStorageEngine(const RelationalDBProperties & properties)71 int SQLiteRelationalStore::InitStorageEngine(const RelationalDBProperties &properties)
72 {
73     OpenDbProperties option;
74     InitDataBaseOption(properties, option);
75     std::string identifier = properties.GetStringProp(DBProperties::IDENTIFIER_DATA, "");
76 
77     StorageEngineAttr poolSize = {1, 1, 0, 16}; // at most 1 write 16 read.
78     int errCode = sqliteStorageEngine_->InitSQLiteStorageEngine(poolSize, option, identifier);
79     if (errCode != E_OK) {
80         LOGE("Init the sqlite storage engine failed:%d", errCode);
81     }
82     return errCode;
83 }
84 
ReleaseResources()85 void SQLiteRelationalStore::ReleaseResources()
86 {
87     if (sqliteStorageEngine_ != nullptr) {
88         sqliteStorageEngine_->ClearEnginePasswd();
89         sqliteStorageEngine_ = nullptr;
90     }
91     if (cloudSyncer_ != nullptr) {
92         cloudSyncer_->Close();
93         RefObject::KillAndDecObjRef(cloudSyncer_);
94         cloudSyncer_ = nullptr;
95     }
96     RefObject::DecObjRef(storageEngine_);
97 }
98 
CheckDBMode()99 int SQLiteRelationalStore::CheckDBMode()
100 {
101     int errCode = E_OK;
102     auto *handle = GetHandle(true, errCode);
103     if (handle == nullptr) {
104         return errCode;
105     }
106     errCode = handle->CheckDBModeForRelational();
107     if (errCode != E_OK) {
108         LOGE("check relational DB mode failed. %d", errCode);
109     }
110 
111     ReleaseHandle(handle);
112     return errCode;
113 }
114 
GetSchemaFromMeta(RelationalSchemaObject & schema)115 int SQLiteRelationalStore::GetSchemaFromMeta(RelationalSchemaObject &schema)
116 {
117     Key schemaKey;
118     DBCommon::StringToVector(DBConstant::RELATIONAL_SCHEMA_KEY, schemaKey);
119     Value schemaVal;
120     int errCode = storageEngine_->GetMetaData(schemaKey, schemaVal);
121     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
122         LOGE("Get relational schema from meta table failed. %d", errCode);
123         return errCode;
124     } else if (errCode == -E_NOT_FOUND || schemaVal.empty()) {
125         LOGW("No relational schema info was found.");
126         return -E_NOT_FOUND;
127     }
128 
129     std::string schemaStr;
130     DBCommon::VectorToString(schemaVal, schemaStr);
131     errCode = schema.ParseFromSchemaString(schemaStr);
132     if (errCode != E_OK) {
133         LOGE("Parse schema string from meta table failed.");
134         return errCode;
135     }
136 
137     sqliteStorageEngine_->SetSchema(schema);
138     return E_OK;
139 }
140 
CheckTableModeFromMeta(DistributedTableMode mode,bool isUnSet)141 int SQLiteRelationalStore::CheckTableModeFromMeta(DistributedTableMode mode, bool isUnSet)
142 {
143     const Key modeKey(DISTRIBUTED_TABLE_MODE, DISTRIBUTED_TABLE_MODE + strlen(DISTRIBUTED_TABLE_MODE));
144     Value modeVal;
145     int errCode = storageEngine_->GetMetaData(modeKey, modeVal);
146     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
147         LOGE("Get distributed table mode from meta table failed. errCode=%d", errCode);
148         return errCode;
149     }
150 
151     DistributedTableMode orgMode = DistributedTableMode::SPLIT_BY_DEVICE;
152     if (!modeVal.empty()) {
153         std::string value(modeVal.begin(), modeVal.end());
154         orgMode = static_cast<DistributedTableMode>(strtoll(value.c_str(), nullptr, 10)); // 10: decimal
155     } else if (isUnSet) {
156         return E_OK; // First set table mode.
157     }
158 
159     if (orgMode != mode) {
160         LOGE("Check distributed table mode mismatch, orgMode=%d, openMode=%d", orgMode, mode);
161         return -E_INVALID_ARGS;
162     }
163     return E_OK;
164 }
165 
CheckProperties(RelationalDBProperties properties)166 int SQLiteRelationalStore::CheckProperties(RelationalDBProperties properties)
167 {
168     RelationalSchemaObject schema;
169     int errCode = GetSchemaFromMeta(schema);
170     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
171         LOGE("Get relational schema from meta failed. errcode=%d", errCode);
172         return errCode;
173     }
174     properties.SetSchema(schema);
175 
176     // Empty schema means no distributed table has been used, we may set DB to any table mode
177     // If there is a schema but no table mode, it is the 'SPLIT_BY_DEVICE' mode of old version
178     bool isSchemaEmpty = (errCode == -E_NOT_FOUND);
179     auto mode = static_cast<DistributedTableMode>(properties.GetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE,
180         DistributedTableMode::SPLIT_BY_DEVICE));
181     errCode = CheckTableModeFromMeta(mode, isSchemaEmpty);
182     if (errCode != E_OK) {
183         LOGE("Get distributed table mode from meta failed. errcode=%d", errCode);
184         return errCode;
185     }
186 
187     errCode = SaveTableModeToMeta(mode);
188     if (errCode != E_OK) {
189         LOGE("Save table mode to meta failed. errCode=%d", errCode);
190         return errCode;
191     }
192 
193     return E_OK;
194 }
195 
SaveSchemaToMeta()196 int SQLiteRelationalStore::SaveSchemaToMeta()
197 {
198     Key schemaKey;
199     DBCommon::StringToVector(DBConstant::RELATIONAL_SCHEMA_KEY, schemaKey);
200     Value schemaVal;
201     DBCommon::StringToVector(sqliteStorageEngine_->GetSchema().ToSchemaString(), schemaVal);
202     int errCode = storageEngine_->PutMetaData(schemaKey, schemaVal);
203     if (errCode != E_OK) {
204         LOGE("Save relational schema to meta table failed. %d", errCode);
205     }
206     return errCode;
207 }
208 
SaveTableModeToMeta(DistributedTableMode mode)209 int SQLiteRelationalStore::SaveTableModeToMeta(DistributedTableMode mode)
210 {
211     const Key modeKey(DISTRIBUTED_TABLE_MODE, DISTRIBUTED_TABLE_MODE + strlen(DISTRIBUTED_TABLE_MODE));
212     Value modeVal;
213     DBCommon::StringToVector(std::to_string(mode), modeVal);
214     int errCode = storageEngine_->PutMetaData(modeKey, modeVal);
215     if (errCode != E_OK) {
216         LOGE("Save relational schema to meta table failed. %d", errCode);
217     }
218     return errCode;
219 }
220 
SaveLogTableVersionToMeta()221 int SQLiteRelationalStore::SaveLogTableVersionToMeta()
222 {
223     LOGD("save log table version to meta table, version: %s", DBConstant::LOG_TABLE_VERSION_CURRENT.c_str());
224     const Key logVersionKey(DBConstant::LOG_TABLE_VERSION_KEY.begin(), DBConstant::LOG_TABLE_VERSION_KEY.end());
225     Value logVersionVal(DBConstant::LOG_TABLE_VERSION_CURRENT.begin(), DBConstant::LOG_TABLE_VERSION_CURRENT.end());
226     int errCode = storageEngine_->PutMetaData(logVersionKey, logVersionVal);
227     if (errCode != E_OK) {
228         LOGE("save log table version to meta table failed. %d", errCode);
229     }
230     return errCode;
231 }
232 
CleanDistributedDeviceTable()233 int SQLiteRelationalStore::CleanDistributedDeviceTable()
234 {
235     std::vector<std::string> missingTables;
236     int errCode = sqliteStorageEngine_->CleanDistributedDeviceTable(missingTables);
237     if (errCode != E_OK) {
238         LOGE("Clean distributed device table failed. %d", errCode);
239     }
240     for (const auto &deviceTableName : missingTables) {
241         std::string deviceHash;
242         std::string tableName;
243         DBCommon::GetDeviceFromName(deviceTableName, deviceHash, tableName);
244         syncAbleEngine_->EraseDeviceWaterMark(deviceHash, false, tableName);
245         if (errCode != E_OK) {
246             LOGE("Erase water mark failed:%d", errCode);
247             return errCode;
248         }
249     }
250     return errCode;
251 }
252 
Open(const RelationalDBProperties & properties)253 int SQLiteRelationalStore::Open(const RelationalDBProperties &properties)
254 {
255     std::lock_guard<std::mutex> lock(initalMutex_);
256     if (isInitialized_) {
257         LOGD("[RelationalStore][Open] relational db was already initialized.");
258         return E_OK;
259     }
260 
261     sqliteStorageEngine_ = std::make_shared<SQLiteSingleRelationalStorageEngine>(properties);
262     if (sqliteStorageEngine_ == nullptr) {
263         LOGE("[RelationalStore][Open] Create storage engine failed");
264         return -E_OUT_OF_MEMORY;
265     }
266 
267     int errCode = E_OK;
268     do {
269         errCode = InitStorageEngine(properties);
270         if (errCode != E_OK) {
271             LOGE("[RelationalStore][Open] Init database context fail! errCode = [%d]", errCode);
272             break;
273         }
274 
275         storageEngine_ = new (std::nothrow) RelationalSyncAbleStorage(sqliteStorageEngine_);
276         if (storageEngine_ == nullptr) {
277             LOGE("[RelationalStore][Open] Create syncable storage failed");
278             errCode = -E_OUT_OF_MEMORY;
279             break;
280         }
281 
282         syncAbleEngine_ = std::make_shared<SyncAbleEngine>(storageEngine_);
283         // to guarantee the life cycle of sync module and syncAbleEngine_ are the same, then the sync module will not
284         // be destructed when close store
285         storageEngine_->SetSyncAbleEngine(syncAbleEngine_);
286         cloudSyncer_ = new(std::nothrow) CloudSyncer(StorageProxy::GetCloudDb(storageEngine_));
287 
288         errCode = CheckDBMode();
289         if (errCode != E_OK) {
290             break;
291         }
292 
293         errCode = CheckProperties(properties);
294         if (errCode != E_OK) {
295             break;
296         }
297 
298         errCode = SaveLogTableVersionToMeta();
299         if (errCode != E_OK) {
300             break;
301         }
302 
303         errCode = CleanDistributedDeviceTable();
304         if (errCode != E_OK) {
305             break;
306         }
307 
308         isInitialized_ = true;
309         return E_OK;
310     } while (false);
311 
312     ReleaseResources();
313     return errCode;
314 }
315 
OnClose(const std::function<void (void)> & notifier)316 void SQLiteRelationalStore::OnClose(const std::function<void(void)> &notifier)
317 {
318     AutoLock lockGuard(this);
319     if (notifier) {
320         closeNotifiers_.push_back(notifier);
321     } else {
322         LOGW("Register 'Close()' notifier failed, notifier is null.");
323     }
324 }
325 
GetHandle(bool isWrite,int & errCode) const326 SQLiteSingleVerRelationalStorageExecutor *SQLiteRelationalStore::GetHandle(bool isWrite, int &errCode) const
327 {
328     if (sqliteStorageEngine_ == nullptr) {
329         errCode = -E_INVALID_DB;
330         return nullptr;
331     }
332 
333     return static_cast<SQLiteSingleVerRelationalStorageExecutor *>(sqliteStorageEngine_->FindExecutor(isWrite,
334         OperatePerm::NORMAL_PERM, errCode));
335 }
ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor * & handle) const336 void SQLiteRelationalStore::ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor *&handle) const
337 {
338     if (handle == nullptr) {
339         return;
340     }
341 
342     if (sqliteStorageEngine_ != nullptr) {
343         StorageExecutor *databaseHandle = handle;
344         sqliteStorageEngine_->Recycle(databaseHandle);
345         handle = nullptr;
346     }
347 }
348 
Sync(const ISyncer::SyncParma & syncParam,uint64_t connectionId)349 int SQLiteRelationalStore::Sync(const ISyncer::SyncParma &syncParam, uint64_t connectionId)
350 {
351     return syncAbleEngine_->Sync(syncParam, connectionId);
352 }
353 
354 // Called when a connection released.
DecreaseConnectionCounter(uint64_t connectionId)355 void SQLiteRelationalStore::DecreaseConnectionCounter(uint64_t connectionId)
356 {
357     int count = connectionCount_.fetch_sub(1, std::memory_order_seq_cst);
358     if (count <= 0) {
359         LOGF("Decrease db connection counter failed, count <= 0.");
360         return;
361     }
362     if (storageEngine_ != nullptr) {
363         storageEngine_->EraseDataChangeCallback(connectionId);
364     }
365     if (count != 1) {
366         return;
367     }
368 
369     LockObj();
370     auto notifiers = std::move(closeNotifiers_);
371     UnlockObj();
372     for (const auto &notifier : notifiers) {
373         if (notifier) {
374             notifier();
375         }
376     }
377 
378     // Sync Close
379     syncAbleEngine_->Close();
380 
381     if (cloudSyncer_ != nullptr) {
382         cloudSyncer_->Close();
383         RefObject::KillAndDecObjRef(cloudSyncer_);
384         cloudSyncer_ = nullptr;
385     }
386 
387     if (sqliteStorageEngine_ != nullptr) {
388         sqliteStorageEngine_ = nullptr;
389     }
390     {
391         if (storageEngine_ != nullptr) {
392             storageEngine_->RegisterHeartBeatListener(nullptr);
393         }
394         std::lock_guard<std::mutex> lock(lifeCycleMutex_);
395         StopLifeCycleTimer();
396         lifeCycleNotifier_ = nullptr;
397     }
398     // close will dec sync ref of storageEngine_
399     DecObjRef(storageEngine_);
400 }
401 
ReleaseDBConnection(uint64_t connectionId,RelationalStoreConnection * connection)402 void SQLiteRelationalStore::ReleaseDBConnection(uint64_t connectionId, RelationalStoreConnection *connection)
403 {
404     if (connectionCount_.load() == 1) {
405         sqliteStorageEngine_->SetConnectionFlag(false);
406     }
407 
408     connectMutex_.lock();
409     if (connection != nullptr) {
410         KillAndDecObjRef(connection);
411         DecreaseConnectionCounter(connectionId);
412         connectMutex_.unlock();
413         KillAndDecObjRef(this);
414     } else {
415         connectMutex_.unlock();
416     }
417 }
418 
WakeUpSyncer()419 void SQLiteRelationalStore::WakeUpSyncer()
420 {
421     syncAbleEngine_->WakeUpSyncer();
422 }
423 
CreateDistributedTable(const std::string & tableName,TableSyncType syncType)424 int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName, TableSyncType syncType)
425 {
426     auto mode = static_cast<DistributedTableMode>(sqliteStorageEngine_->GetProperties().GetIntProp(
427         RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE));
428 
429     std::string localIdentity; // collaboration mode need local identify
430     if (mode == DistributedTableMode::COLLABORATION) {
431         int errCode = syncAbleEngine_->GetLocalIdentity(localIdentity);
432         if (errCode != E_OK || localIdentity.empty()) {
433             LOGD("Get local identity failed, can not create.");
434             return -E_NOT_SUPPORT;
435         }
436     }
437 
438     bool schemaChanged = false;
439     int errCode = sqliteStorageEngine_->CreateDistributedTable(tableName, DBCommon::TransferStringToHex(localIdentity),
440         schemaChanged, syncType);
441     if (errCode != E_OK) {
442         LOGE("Create distributed table failed. %d", errCode);
443     }
444     if (schemaChanged) {
445         LOGD("Notify schema changed.");
446         storageEngine_->NotifySchemaChanged();
447     }
448     return errCode;
449 }
450 
GetCloudSyncTaskCount()451 int32_t SQLiteRelationalStore::GetCloudSyncTaskCount()
452 {
453     if (cloudSyncer_ == nullptr) {
454         LOGE("[RelationalStore] cloudSyncer was not initialized when get cloud sync task count.");
455         return -1;
456     }
457     return cloudSyncer_->GetCloudSyncTaskCount();
458 }
459 
CleanCloudData(ClearMode mode)460 int SQLiteRelationalStore::CleanCloudData(ClearMode mode)
461 {
462     auto tableMode = static_cast<DistributedTableMode>(sqliteStorageEngine_->GetProperties().GetIntProp(
463         RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE));
464     if (tableMode == DistributedTableMode::COLLABORATION) {
465         LOGE("Not support remove device data in collaboration mode.");
466         return -E_NOT_SUPPORT;
467     }
468     RelationalSchemaObject localSchema = sqliteStorageEngine_->GetSchema();
469     TableInfoMap tables = localSchema.GetTables();
470     std::vector<std::string> cloudTableNameList;
471     for (const auto &tableInfo : tables) {
472         if (tableInfo.second.GetTableSyncType() == CLOUD_COOPERATION) {
473             cloudTableNameList.push_back(tableInfo.first);
474         }
475     }
476     if (cloudTableNameList.empty()) {
477         LOGI("[RelationalStore] device doesn't has cloud table, clean cloud data finished.");
478         return E_OK;
479     }
480 
481     if (cloudSyncer_ == nullptr) {
482         LOGE("[RelationalStore] cloudSyncer was not initialized when clean cloud data");
483         return -E_INVALID_DB;
484     }
485     int errCode = cloudSyncer_->CleanCloudData(mode, cloudTableNameList, localSchema);
486     if (errCode != E_OK) {
487         LOGE("[RelationalStore] failed to clean cloud data, %d.", errCode);
488     }
489 
490     return errCode;
491 }
492 
RemoveDeviceData()493 int SQLiteRelationalStore::RemoveDeviceData()
494 {
495     auto mode = static_cast<DistributedTableMode>(sqliteStorageEngine_->GetProperties().GetIntProp(
496         RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE));
497     if (mode == DistributedTableMode::COLLABORATION) {
498         LOGE("Not support remove device data in collaboration mode.");
499         return -E_NOT_SUPPORT;
500     }
501 
502     std::vector<std::string> tableNameList = GetAllDistributedTableName();
503     if (tableNameList.empty()) {
504         return E_OK;
505     }
506     // erase watermark first
507     int errCode = EraseAllDeviceWatermark(tableNameList);
508     if (errCode != E_OK) {
509         return errCode;
510     }
511     auto *handle = GetHandleAndStartTransaction(errCode);
512     if (handle == nullptr) {
513         return errCode;
514     }
515 
516     for (const auto &table: tableNameList) {
517         errCode = handle->DeleteDistributedDeviceTable("", table);
518         if (errCode != E_OK) {
519             LOGE("delete device data failed. %d", errCode);
520             break;
521         }
522 
523         errCode = handle->DeleteDistributedAllDeviceTableLog(table);
524         if (errCode != E_OK) {
525             LOGE("delete device data failed. %d", errCode);
526             break;
527         }
528     }
529 
530     if (errCode != E_OK) {
531         (void)handle->Rollback();
532         ReleaseHandle(handle);
533         return errCode;
534     }
535 
536     errCode = handle->Commit();
537     ReleaseHandle(handle);
538     storageEngine_->NotifySchemaChanged();
539     return errCode;
540 }
541 
RemoveDeviceData(const std::string & device,const std::string & tableName)542 int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std::string &tableName)
543 {
544     auto mode = static_cast<DistributedTableMode>(sqliteStorageEngine_->GetProperties().GetIntProp(
545         RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE));
546     if (mode == DistributedTableMode::COLLABORATION) {
547         LOGE("Not support remove device data in collaboration mode.");
548         return -E_NOT_SUPPORT;
549     }
550 
551     TableInfoMap tables = sqliteStorageEngine_->GetSchema().GetTables(); // TableInfoMap
552     auto iter = tables.find(tableName);
553     if (tables.empty() || (!tableName.empty() && iter == tables.end())) {
554         LOGE("Remove device data with table name which is not a distributed table or no distributed table found.");
555         return -E_DISTRIBUTED_SCHEMA_NOT_FOUND;
556     }
557     // cloud mode is not permit
558     if (iter->second.GetTableSyncType() == CLOUD_COOPERATION) {
559         LOGE("Remove device data with cloud sync table name.");
560         return -E_NOT_SUPPORT;
561     }
562     bool isNeedHash = false;
563     std::string hashDeviceId;
564     int errCode = syncAbleEngine_->GetHashDeviceId(device, hashDeviceId);
565     if (errCode == -E_NOT_SUPPORT) {
566         isNeedHash = true;
567         hashDeviceId = device;
568         errCode = E_OK;
569     }
570     if (errCode != E_OK) {
571         return errCode;
572     }
573     if (isNeedHash) {
574         // check device is uuid in meta
575         std::set<std::string> hashDevices;
576         errCode = GetExistDevices(hashDevices);
577         if (errCode != E_OK) {
578             return errCode;
579         }
580         if (hashDevices.find(DBCommon::TransferHashString(device)) == hashDevices.end()) {
581             LOGD("[SQLiteRelationalStore] not match device, just return");
582             return E_OK;
583         }
584     }
585     return RemoveDeviceDataInner(hashDeviceId, device, tableName, isNeedHash);
586 }
587 
RegisterObserverAction(uint64_t connectionId,const RelationalObserverAction & action)588 void SQLiteRelationalStore::RegisterObserverAction(uint64_t connectionId, const RelationalObserverAction &action)
589 {
590     storageEngine_->RegisterObserverAction(connectionId, action);
591 }
592 
StopLifeCycleTimer()593 int SQLiteRelationalStore::StopLifeCycleTimer()
594 {
595     auto runtimeCxt = RuntimeContext::GetInstance();
596     if (runtimeCxt == nullptr) {
597         return -E_INVALID_ARGS;
598     }
599     if (lifeTimerId_ != 0) {
600         TimerId timerId = lifeTimerId_;
601         lifeTimerId_ = 0;
602         runtimeCxt->RemoveTimer(timerId, false);
603     }
604     return E_OK;
605 }
606 
StartLifeCycleTimer(const DatabaseLifeCycleNotifier & notifier)607 int SQLiteRelationalStore::StartLifeCycleTimer(const DatabaseLifeCycleNotifier &notifier)
608 {
609     auto runtimeCxt = RuntimeContext::GetInstance();
610     if (runtimeCxt == nullptr) {
611         return -E_INVALID_ARGS;
612     }
613     RefObject::IncObjRef(this);
614     TimerId timerId = 0;
615     int errCode = runtimeCxt->SetTimer(DBConstant::DEF_LIFE_CYCLE_TIME,
616         [this](TimerId id) -> int {
617             std::lock_guard<std::mutex> lock(lifeCycleMutex_);
618             if (lifeCycleNotifier_) {
619                 // normal identifier mode
620                 std::string identifier;
621                 if (sqliteStorageEngine_->GetProperties().GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false)) {
622                     identifier = sqliteStorageEngine_->GetProperties().GetStringProp(
623                         DBProperties::DUAL_TUPLE_IDENTIFIER_DATA, "");
624                 } else {
625                     identifier = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::IDENTIFIER_DATA, "");
626                 }
627                 auto userId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, "");
628                 lifeCycleNotifier_(identifier, userId);
629             }
630             return 0;
631         },
632         [this]() {
633             int ret = RuntimeContext::GetInstance()->ScheduleTask([this]() {
634                 RefObject::DecObjRef(this);
635             });
636             if (ret != E_OK) {
637                 LOGE("SQLiteSingleVerNaturalStore timer finalizer ScheduleTask, errCode %d", ret);
638             }
639         },
640         timerId);
641     if (errCode != E_OK) {
642         lifeTimerId_ = 0;
643         LOGE("SetTimer failed:%d", errCode);
644         RefObject::DecObjRef(this);
645         return errCode;
646     }
647 
648     lifeCycleNotifier_ = notifier;
649     lifeTimerId_ = timerId;
650     return E_OK;
651 }
652 
RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier & notifier)653 int SQLiteRelationalStore::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier &notifier)
654 {
655     int errCode;
656     {
657         std::lock_guard<std::mutex> lock(lifeCycleMutex_);
658         if (lifeTimerId_ != 0) {
659             errCode = StopLifeCycleTimer();
660             if (errCode != E_OK) {
661                 LOGE("Stop the life cycle timer failed:%d", errCode);
662                 return errCode;
663             }
664         }
665 
666         if (!notifier) {
667             return E_OK;
668         }
669         errCode = StartLifeCycleTimer(notifier);
670         if (errCode != E_OK) {
671             LOGE("Register life cycle timer failed:%d", errCode);
672             return errCode;
673         }
674     }
675     auto listener = std::bind(&SQLiteRelationalStore::HeartBeat, this);
676     storageEngine_->RegisterHeartBeatListener(listener);
677     return errCode;
678 }
679 
HeartBeat()680 void SQLiteRelationalStore::HeartBeat()
681 {
682     std::lock_guard<std::mutex> lock(lifeCycleMutex_);
683     int errCode = ResetLifeCycleTimer();
684     if (errCode != E_OK) {
685         LOGE("Heart beat for life cycle failed:%d", errCode);
686     }
687 }
688 
ResetLifeCycleTimer()689 int SQLiteRelationalStore::ResetLifeCycleTimer()
690 {
691     if (lifeTimerId_ == 0) {
692         return E_OK;
693     }
694     auto lifeNotifier = lifeCycleNotifier_;
695     lifeCycleNotifier_ = nullptr;
696     int errCode = StopLifeCycleTimer();
697     if (errCode != E_OK) {
698         LOGE("[Reset timer]Stop the life cycle timer failed:%d", errCode);
699     }
700     return StartLifeCycleTimer(lifeNotifier);
701 }
702 
GetStorePath() const703 std::string SQLiteRelationalStore::GetStorePath() const
704 {
705     return sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::DATA_DIR, "");
706 }
707 
GetProperties() const708 RelationalDBProperties SQLiteRelationalStore::GetProperties() const
709 {
710     return sqliteStorageEngine_->GetProperties();
711 }
712 
StopSync(uint64_t connectionId)713 void SQLiteRelationalStore::StopSync(uint64_t connectionId)
714 {
715     return syncAbleEngine_->StopSync(connectionId);
716 }
717 
Dump(int fd)718 void SQLiteRelationalStore::Dump(int fd)
719 {
720     std::string userId = "";
721     std::string appId = "";
722     std::string storeId = "";
723     std::string label = "";
724     if (sqliteStorageEngine_ != nullptr) {
725         userId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, "");
726         appId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, "");
727         storeId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "");
728         label = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::IDENTIFIER_DATA, "");
729     }
730     label = DBCommon::TransferStringToHex(label);
731     DBDumpHelper::Dump(fd, "\tdb userId = %s, appId = %s, storeId = %s, label = %s\n",
732         userId.c_str(), appId.c_str(), storeId.c_str(), label.c_str());
733     if (syncAbleEngine_ != nullptr) {
734         syncAbleEngine_->Dump(fd);
735     }
736 }
737 
RemoteQuery(const std::string & device,const RemoteCondition & condition,uint64_t timeout,uint64_t connectionId,std::shared_ptr<ResultSet> & result)738 int SQLiteRelationalStore::RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout,
739     uint64_t connectionId, std::shared_ptr<ResultSet> &result)
740 {
741     if (sqliteStorageEngine_ == nullptr) {
742         return -E_INVALID_DB;
743     }
744     if (condition.sql.size() > DBConstant::REMOTE_QUERY_MAX_SQL_LEN) {
745         LOGE("remote query sql len is larger than %" PRIu32, DBConstant::REMOTE_QUERY_MAX_SQL_LEN);
746         return -E_MAX_LIMITS;
747     }
748 
749     if (!sqliteStorageEngine_->GetSchema().IsSchemaValid()) {
750         LOGW("not a distributed relational store.");
751         return -E_NOT_SUPPORT;
752     }
753     const auto &properties = sqliteStorageEngine_->GetProperties();
754     int tableMode = properties.GetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE,
755         DistributedTableMode::SPLIT_BY_DEVICE);
756     if (tableMode != DistributedTableMode::SPLIT_BY_DEVICE) {
757         LOGW("only support split mode.");
758         return -E_NOT_SUPPORT;
759     }
760 
761     // Check whether to be able to operate the db.
762     int errCode = E_OK;
763     auto *handle = GetHandle(false, errCode);
764     if (handle == nullptr) {
765         return errCode;
766     }
767     errCode = handle->CheckEncryptedOrCorrupted();
768     ReleaseHandle(handle);
769     if (errCode != E_OK) {
770         return errCode;
771     }
772 
773     return syncAbleEngine_->RemoteQuery(device, condition, timeout, connectionId, result);
774 }
775 
EraseAllDeviceWatermark(const std::vector<std::string> & tableNameList)776 int SQLiteRelationalStore::EraseAllDeviceWatermark(const std::vector<std::string> &tableNameList)
777 {
778     std::set<std::string> devices;
779     int errCode = GetExistDevices(devices);
780     if (errCode != E_OK) {
781         return errCode;
782     }
783     for (const auto &tableName: tableNameList) {
784         for (const auto &device: devices) {
785             errCode = syncAbleEngine_->EraseDeviceWaterMark(device, false, tableName);
786             if (errCode != E_OK) {
787                 return errCode;
788             }
789         }
790     }
791     return errCode;
792 }
793 
GetDevTableName(const std::string & device,const std::string & hashDev) const794 std::string SQLiteRelationalStore::GetDevTableName(const std::string &device, const std::string &hashDev) const
795 {
796     std::string devTableName;
797     StoreInfo info = {
798         sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""),
799         sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""),
800         sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "")
801     };
802     if (RuntimeContext::GetInstance()->TranslateDeviceId(device, info, devTableName) != E_OK) {
803         devTableName = hashDev;
804     }
805     return devTableName;
806 }
807 
GetHandleAndStartTransaction(int & errCode) const808 SQLiteSingleVerRelationalStorageExecutor *SQLiteRelationalStore::GetHandleAndStartTransaction(int &errCode) const
809 {
810     auto *handle = GetHandle(true, errCode);
811     if (handle == nullptr) {
812         return nullptr;
813     }
814 
815     errCode = handle->StartTransaction(TransactType::IMMEDIATE);
816     if (errCode != E_OK) {
817         ReleaseHandle(handle);
818         return nullptr;
819     }
820     return handle;
821 }
822 
RemoveDeviceDataInner(const std::string & mappingDev,const std::string & device,const std::string & tableName,bool isNeedHash)823 int SQLiteRelationalStore::RemoveDeviceDataInner(const std::string &mappingDev, const std::string &device,
824     const std::string &tableName, bool isNeedHash)
825 {
826     std::string hashHexDev;
827     std::string hashDev;
828     std::string devTableName;
829     if (!isNeedHash) {
830         // if is not need hash mappingDev mean hash(uuid) device is param device
831         hashHexDev = DBCommon::TransferStringToHex(mappingDev);
832         hashDev = mappingDev;
833         devTableName = device;
834     } else {
835         // if is need hash mappingDev mean uuid
836         hashDev = DBCommon::TransferHashString(mappingDev);
837         hashHexDev = DBCommon::TransferStringToHex(hashDev);
838         devTableName = GetDevTableName(mappingDev, hashHexDev);
839     }
840     // erase watermark first
841     int errCode = syncAbleEngine_->EraseDeviceWaterMark(hashDev, false, tableName);
842     if (errCode != E_OK) {
843         return errCode;
844     }
845     auto *handle = GetHandleAndStartTransaction(errCode);
846     if (handle == nullptr) {
847         return errCode;
848     }
849 
850     errCode = handle->DeleteDistributedDeviceTable(devTableName, tableName);
851     TableInfoMap tables = sqliteStorageEngine_->GetSchema().GetTables(); // TableInfoMap
852     if (errCode != E_OK) {
853         LOGE("delete device data failed. %d", errCode);
854         goto END;
855     }
856 
857     for (const auto &it : tables) {
858         if (tableName.empty() || it.second.GetTableName() == tableName) {
859             errCode = handle->DeleteDistributedDeviceTableLog(hashHexDev, it.second.GetTableName());
860             if (errCode != E_OK) {
861                 LOGE("delete device data failed. %d", errCode);
862                 break;
863             }
864         }
865     }
866 
867 END:
868     if (errCode != E_OK) {
869         (void)handle->Rollback();
870         ReleaseHandle(handle);
871         return errCode;
872     }
873     errCode = handle->Commit();
874     ReleaseHandle(handle);
875     storageEngine_->NotifySchemaChanged();
876     return errCode;
877 }
878 
GetExistDevices(std::set<std::string> & hashDevices) const879 int SQLiteRelationalStore::GetExistDevices(std::set<std::string> &hashDevices) const
880 {
881     int errCode = E_OK;
882     auto *handle = GetHandle(true, errCode);
883     if (handle == nullptr) {
884         LOGE("[SingleVerRDBStore] GetExistsDeviceList get handle failed:%d", errCode);
885         return errCode;
886     }
887     errCode = handle->GetExistsDeviceList(hashDevices);
888     if (errCode != E_OK) {
889         LOGE("[SingleVerRDBStore] Get remove device list from meta failed. err=%d", errCode);
890     }
891     ReleaseHandle(handle);
892     return errCode;
893 }
894 
GetAllDistributedTableName()895 std::vector<std::string> SQLiteRelationalStore::GetAllDistributedTableName()
896 {
897     TableInfoMap tables = sqliteStorageEngine_->GetSchema().GetTables(); // TableInfoMap
898     std::vector<std::string> tableNames;
899     for (const auto &table: tables) {
900         tableNames.push_back(table.second.GetTableName());
901     }
902     return tableNames;
903 }
904 
SetCloudDB(const std::shared_ptr<ICloudDb> & cloudDb)905 int SQLiteRelationalStore::SetCloudDB(const std::shared_ptr<ICloudDb> &cloudDb)
906 {
907     if (cloudSyncer_ == nullptr) {
908         LOGE("[RelationalStore][SetCloudDB] cloudSyncer was not initialized");
909         return -E_INVALID_DB;
910     }
911     cloudSyncer_->SetCloudDB(cloudDb);
912     return E_OK;
913 }
914 
SetCloudDbSchema(const DataBaseSchema & schema)915 int SQLiteRelationalStore::SetCloudDbSchema(const DataBaseSchema &schema)
916 {
917     if (storageEngine_ == nullptr) {
918         LOGE("[RelationalStore][SetCloudDbSchema] storageEngine was not initialized");
919         return -E_INVALID_DB;
920     }
921     return storageEngine_->SetCloudDbSchema(schema);
922 }
923 
SetIAssetLoader(const std::shared_ptr<IAssetLoader> & loader)924 int SQLiteRelationalStore::SetIAssetLoader(const std::shared_ptr<IAssetLoader> &loader)
925 {
926     if (cloudSyncer_ == nullptr) {
927         LOGE("[RelationalStore][SetIAssetLoader] cloudSyncer was not initialized");
928         return -E_INVALID_DB;
929     }
930     cloudSyncer_->SetIAssetLoader(loader);
931     return E_OK;
932 }
933 
ChkSchema(const TableName & tableName)934 int SQLiteRelationalStore::ChkSchema(const TableName &tableName)
935 {
936     if (storageEngine_ == nullptr) {
937         LOGE("[RelationalStore][ChkSchema] storageEngine was not initialized");
938         return -E_INVALID_DB;
939     }
940     return storageEngine_->ChkSchema(tableName);
941 }
942 
Sync(const std::vector<std::string> & devices,SyncMode mode,const Query & query,const SyncProcessCallback & onProcess,int64_t waitTime)943 int SQLiteRelationalStore::Sync(const std::vector<std::string> &devices, SyncMode mode,
944     const Query &query, const SyncProcessCallback &onProcess, int64_t waitTime)
945 {
946     if (cloudSyncer_ == nullptr) {
947         LOGE("[RelationalStore] cloudSyncer was not initialized when sync");
948         return -E_INVALID_DB;
949     }
950     QuerySyncObject querySyncObject(query);
951     if (querySyncObject.GetIsDeviceSyncQuery()) {
952         LOGE("[RelationalStore] cloudSyncer was not support other query");
953         return -E_NOT_SUPPORT;
954     }
955     const auto tableNames = querySyncObject.GetRelationTableNames();
956     if (tableNames.empty()) {
957         LOGE("[RelationalStore] sync with empty table");
958         return -E_INVALID_ARGS;
959     }
960     SecurityOption option;
961     int errCode = storageEngine_->GetSecurityOption(option);
962     if (errCode != E_OK && errCode != -E_NOT_SUPPORT) {
963         return -E_SECURITY_OPTION_CHECK_ERROR;
964     }
965     if (errCode == E_OK && option.securityLabel == S4) {
966         return -E_SECURITY_OPTION_CHECK_ERROR;
967     }
968     for (const auto &table: tableNames) {
969         errCode = ChkSchema(table);
970         if (errCode != E_OK) {
971             LOGE("[RelationalStore] schema check failed when sync");
972             return errCode;
973         }
974     }
975     std::vector<std::string> syncTable;
976     std::set<std::string> addTable;
977     for (const auto &table: tableNames) {
978         if (addTable.find(table) == addTable.end()) {
979             addTable.insert(table);
980             syncTable.push_back(table);
981         }
982     }
983     return cloudSyncer_->Sync(devices, mode, syncTable, onProcess, waitTime);
984 }
985 }
986 #endif
987