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)> ¬ifier)
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 ¬ifier : 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 ¬ifier)
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 ¬ifier)
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