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_errno.h"
20 #include "log_print.h"
21 #include "db_types.h"
22 #include "sqlite_relational_store_connection.h"
23 #include "storage_engine_manager.h"
24
25 namespace DistributedDB {
26 namespace {
27 constexpr const char *RELATIONAL_SCHEMA_KEY = "relational_schema";
28 constexpr const char *LOG_TABLE_VERSION_KEY = "log_table_version";
29 constexpr const char *LOG_TABLE_VERSION_1 = "1.0";
30 }
31
~SQLiteRelationalStore()32 SQLiteRelationalStore::~SQLiteRelationalStore()
33 {
34 delete sqliteStorageEngine_;
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 }
65
InitStorageEngine(const RelationalDBProperties & properties)66 int SQLiteRelationalStore::InitStorageEngine(const RelationalDBProperties &properties)
67 {
68 OpenDbProperties option;
69 InitDataBaseOption(properties, option);
70 std::string identifier = properties.GetStringProp(DBProperties::IDENTIFIER_DATA, "");
71
72 StorageEngineAttr poolSize = {1, 1, 0, 16}; // at most 1 write 16 read.
73 int errCode = sqliteStorageEngine_->InitSQLiteStorageEngine(poolSize, option, identifier);
74 if (errCode != E_OK) {
75 LOGE("Init the sqlite storage engine failed:%d", errCode);
76 }
77 return errCode;
78 }
79
ReleaseResources()80 void SQLiteRelationalStore::ReleaseResources()
81 {
82 if (sqliteStorageEngine_ != nullptr) {
83 sqliteStorageEngine_->ClearEnginePasswd();
84 (void)StorageEngineManager::ReleaseStorageEngine(sqliteStorageEngine_);
85 }
86 RefObject::DecObjRef(storageEngine_);
87 }
88
CheckDBMode()89 int SQLiteRelationalStore::CheckDBMode()
90 {
91 int errCode = E_OK;
92 auto *handle = GetHandle(false, errCode);
93 if (handle == nullptr) {
94 return errCode;
95 }
96 errCode = handle->CheckDBModeForRelational();
97 if (errCode != E_OK) {
98 LOGE("check relational DB mode failed. %d", errCode);
99 }
100
101 ReleaseHandle(handle);
102 return errCode;
103 }
104
GetSchemaFromMeta()105 int SQLiteRelationalStore::GetSchemaFromMeta()
106 {
107 const Key schemaKey(RELATIONAL_SCHEMA_KEY, RELATIONAL_SCHEMA_KEY + strlen(RELATIONAL_SCHEMA_KEY));
108 Value schemaVal;
109 int errCode = storageEngine_->GetMetaData(schemaKey, schemaVal);
110 if (errCode != E_OK && errCode != -E_NOT_FOUND) {
111 LOGE("Get relational schema from meta table failed. %d", errCode);
112 return errCode;
113 } else if (errCode == -E_NOT_FOUND || schemaVal.empty()) {
114 LOGW("No relational schema info was found.");
115 return E_OK;
116 }
117
118 std::string schemaStr;
119 DBCommon::VectorToString(schemaVal, schemaStr);
120 RelationalSchemaObject schema;
121 errCode = schema.ParseFromSchemaString(schemaStr);
122 if (errCode != E_OK) {
123 LOGE("Parse schema string from meta table failed.");
124 return errCode;
125 }
126
127 sqliteStorageEngine_->SetSchema(schema);
128 return E_OK;
129 }
130
SaveSchemaToMeta()131 int SQLiteRelationalStore::SaveSchemaToMeta()
132 {
133 const Key schemaKey(RELATIONAL_SCHEMA_KEY, RELATIONAL_SCHEMA_KEY + strlen(RELATIONAL_SCHEMA_KEY));
134 Value schemaVal;
135 DBCommon::StringToVector(sqliteStorageEngine_->GetSchemaRef().ToSchemaString(), schemaVal);
136 int errCode = storageEngine_->PutMetaData(schemaKey, schemaVal);
137 if (errCode != E_OK) {
138 LOGE("Save relational schema to meta table failed. %d", errCode);
139 }
140 return errCode;
141 }
142
SaveLogTableVersionToMeta()143 int SQLiteRelationalStore::SaveLogTableVersionToMeta()
144 {
145 LOGD("save log table version to meta table, key: %s, val: %s", LOG_TABLE_VERSION_KEY, LOG_TABLE_VERSION_1);
146 const Key logVersionKey(LOG_TABLE_VERSION_KEY, LOG_TABLE_VERSION_KEY + strlen(LOG_TABLE_VERSION_KEY));
147 Value logVersionVal(LOG_TABLE_VERSION_1, LOG_TABLE_VERSION_1 + strlen(LOG_TABLE_VERSION_1));
148 int errCode = storageEngine_->PutMetaData(logVersionKey, logVersionVal);
149 if (errCode != E_OK) {
150 LOGE("save log table version to meta table failed. %d", errCode);
151 }
152 return errCode;
153 }
154
CleanDistributedDeviceTable()155 int SQLiteRelationalStore::CleanDistributedDeviceTable()
156 {
157 std::vector<std::string> missingTables;
158 int errCode = sqliteStorageEngine_->CleanDistributedDeviceTable(missingTables);
159 if (errCode != E_OK) {
160 LOGE("Clean distributed device table failed. %d", errCode);
161 }
162 for (const auto &deviceTableName : missingTables) {
163 std::string deviceHash;
164 std::string tableName;
165 DBCommon::GetDeviceFromName(deviceTableName, deviceHash, tableName);
166 syncAbleEngine_->EraseDeviceWaterMark(deviceHash, false, tableName);
167 if (errCode != E_OK) {
168 LOGE("Erase water mark failed:%d", errCode);
169 return errCode;
170 }
171 }
172 return errCode;
173 }
174
Open(const RelationalDBProperties & properties)175 int SQLiteRelationalStore::Open(const RelationalDBProperties &properties)
176 {
177 std::lock_guard<std::mutex> lock(initalMutex_);
178 if (isInitialized_) {
179 LOGD("[RelationalStore][Open] relational db was already initialized.");
180 return E_OK;
181 }
182
183 sqliteStorageEngine_ = new (std::nothrow) SQLiteSingleRelationalStorageEngine();
184 if (sqliteStorageEngine_ == nullptr) {
185 LOGE("[RelationalStore][Open] Create storage engine failed");
186 return -E_OUT_OF_MEMORY;
187 }
188
189 int errCode = E_OK;
190 do {
191 errCode = InitStorageEngine(properties);
192 if (errCode != E_OK) {
193 LOGE("[RelationalStore][Open] Init database context fail! errCode = [%d]", errCode);
194 break;
195 }
196
197 storageEngine_ = new (std::nothrow) RelationalSyncAbleStorage(sqliteStorageEngine_);
198 if (storageEngine_ == nullptr) {
199 LOGE("[RelationalStore][Open] Create syncable storage failed");
200 errCode = -E_OUT_OF_MEMORY;
201 break;
202 }
203
204 syncAbleEngine_ = std::make_unique<SyncAbleEngine>(storageEngine_);
205
206 errCode = CheckDBMode();
207 if (errCode != E_OK) {
208 break;
209 }
210
211 properties_ = properties;
212 errCode = GetSchemaFromMeta();
213 if (errCode != E_OK) {
214 break;
215 }
216
217 errCode = SaveLogTableVersionToMeta();
218 if (errCode != E_OK) {
219 break;
220 }
221
222 errCode = CleanDistributedDeviceTable();
223 if (errCode != E_OK) {
224 break;
225 }
226
227 isInitialized_ = true;
228 return E_OK;
229 } while (false);
230
231 ReleaseResources();
232 return errCode;
233 }
234
OnClose(const std::function<void (void)> & notifier)235 void SQLiteRelationalStore::OnClose(const std::function<void(void)> ¬ifier)
236 {
237 AutoLock lockGuard(this);
238 if (notifier) {
239 closeNotifiers_.push_back(notifier);
240 } else {
241 LOGW("Register 'Close()' notifier failed, notifier is null.");
242 }
243 }
244
GetHandle(bool isWrite,int & errCode) const245 SQLiteSingleVerRelationalStorageExecutor *SQLiteRelationalStore::GetHandle(bool isWrite, int &errCode) const
246 {
247 if (sqliteStorageEngine_ == nullptr) {
248 errCode = -E_INVALID_DB;
249 return nullptr;
250 }
251
252 return static_cast<SQLiteSingleVerRelationalStorageExecutor *>(sqliteStorageEngine_->FindExecutor(isWrite,
253 OperatePerm::NORMAL_PERM, errCode));
254 }
ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor * & handle) const255 void SQLiteRelationalStore::ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor *&handle) const
256 {
257 if (handle == nullptr) {
258 return;
259 }
260
261 if (sqliteStorageEngine_ != nullptr) {
262 StorageExecutor *databaseHandle = handle;
263 sqliteStorageEngine_->Recycle(databaseHandle);
264 handle = nullptr;
265 }
266 }
267
Sync(const ISyncer::SyncParma & syncParam)268 int SQLiteRelationalStore::Sync(const ISyncer::SyncParma &syncParam)
269 {
270 return syncAbleEngine_->Sync(syncParam);
271 }
272
273 // Called when a connection released.
DecreaseConnectionCounter()274 void SQLiteRelationalStore::DecreaseConnectionCounter()
275 {
276 int count = connectionCount_.fetch_sub(1, std::memory_order_seq_cst);
277 if (count <= 0) {
278 LOGF("Decrease db connection counter failed, count <= 0.");
279 return;
280 }
281 if (count != 1) {
282 return;
283 }
284
285 LockObj();
286 auto notifiers = std::move(closeNotifiers_);
287 UnlockObj();
288
289 for (auto ¬ifier : notifiers) {
290 if (notifier) {
291 notifier();
292 }
293 }
294
295 // Sync Close
296 syncAbleEngine_->Close();
297
298 if (sqliteStorageEngine_ != nullptr) {
299 delete sqliteStorageEngine_;
300 sqliteStorageEngine_ = nullptr;
301 }
302 // close will dec sync ref of storageEngine_
303 DecObjRef(storageEngine_);
304 }
305
ReleaseDBConnection(RelationalStoreConnection * connection)306 void SQLiteRelationalStore::ReleaseDBConnection(RelationalStoreConnection *connection)
307 {
308 if (connectionCount_.load() == 1) {
309 sqliteStorageEngine_->SetConnectionFlag(false);
310 }
311
312 connectMutex_.lock();
313 if (connection != nullptr) {
314 KillAndDecObjRef(connection);
315 DecreaseConnectionCounter();
316 connectMutex_.unlock();
317 KillAndDecObjRef(this);
318 } else {
319 connectMutex_.unlock();
320 }
321 }
322
WakeUpSyncer()323 void SQLiteRelationalStore::WakeUpSyncer()
324 {
325 syncAbleEngine_->WakeUpSyncer();
326 }
327
CreateDistributedTable(const std::string & tableName)328 int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName)
329 {
330 bool schemaChanged = false;
331 int errCode = sqliteStorageEngine_->CreateDistributedTable(tableName, schemaChanged);
332 if (errCode != E_OK) {
333 LOGE("Create distributed table failed. %d", errCode);
334 }
335 if (schemaChanged) {
336 LOGD("Notify schema changed.");
337 storageEngine_->NotifySchemaChanged();
338 }
339 return errCode;
340 }
341
RemoveDeviceData(const std::string & device,const std::string & tableName)342 int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std::string &tableName)
343 {
344 std::map<std::string, TableInfo> tables = sqliteStorageEngine_->GetSchemaRef().GetTables();
345 if (!tableName.empty() && tables.find(tableName) == tables.end()) {
346 LOGW("Remove device data with table name which is not a distributed table or not exist.");
347 return E_OK;
348 }
349
350 int errCode = E_OK;
351 auto *handle = GetHandle(true, errCode);
352 if (handle == nullptr) {
353 return errCode;
354 }
355
356 errCode = handle->StartTransaction(TransactType::IMMEDIATE);
357 if (errCode != E_OK) {
358 ReleaseHandle(handle);
359 return errCode;
360 }
361
362 errCode = handle->DeleteDistributedDeviceTable(device, tableName);
363 if (errCode != E_OK) {
364 LOGE("delete device data failed. %d", errCode);
365 (void)handle->Rollback();
366 ReleaseHandle(handle);
367 return errCode;
368 }
369 errCode = handle->Commit();
370 storageEngine_->NotifySchemaChanged();
371 ReleaseHandle(handle);
372 return (errCode != E_OK) ? errCode : syncAbleEngine_->EraseDeviceWaterMark(device, true, tableName);
373 }
374
RegisterObserverAction(const RelationalObserverAction & action)375 void SQLiteRelationalStore::RegisterObserverAction(const RelationalObserverAction &action)
376 {
377 storageEngine_->RegisterObserverAction(action);
378 }
379
StopLifeCycleTimer()380 int SQLiteRelationalStore::StopLifeCycleTimer()
381 {
382 auto runtimeCxt = RuntimeContext::GetInstance();
383 if (runtimeCxt == nullptr) {
384 return -E_INVALID_ARGS;
385 }
386 if (lifeTimerId_ != 0) {
387 TimerId timerId = lifeTimerId_;
388 lifeTimerId_ = 0;
389 runtimeCxt->RemoveTimer(timerId, false);
390 }
391 return E_OK;
392 }
393
StartLifeCycleTimer(const DatabaseLifeCycleNotifier & notifier)394 int SQLiteRelationalStore::StartLifeCycleTimer(const DatabaseLifeCycleNotifier ¬ifier)
395 {
396 auto runtimeCxt = RuntimeContext::GetInstance();
397 if (runtimeCxt == nullptr) {
398 return -E_INVALID_ARGS;
399 }
400 RefObject::IncObjRef(this);
401 TimerId timerId = 0;
402 int errCode = runtimeCxt->SetTimer(DBConstant::DEF_LIFE_CYCLE_TIME,
403 [this](TimerId id) -> int {
404 std::lock_guard<std::mutex> lock(lifeCycleMutex_);
405 if (lifeCycleNotifier_) {
406 // normal identifier mode
407 auto identifier = properties_.GetStringProp(DBProperties::IDENTIFIER_DATA, "");
408 auto userId = properties_.GetStringProp(DBProperties::USER_ID, "");
409 lifeCycleNotifier_(identifier, userId);
410 }
411 return 0;
412 },
413 [this]() {
414 int ret = RuntimeContext::GetInstance()->ScheduleTask([this]() {
415 RefObject::DecObjRef(this);
416 });
417 if (ret != E_OK) {
418 LOGE("SQLiteSingleVerNaturalStore timer finalizer ScheduleTask, errCode %d", ret);
419 }
420 },
421 timerId);
422 if (errCode != E_OK) {
423 lifeTimerId_ = 0;
424 LOGE("SetTimer failed:%d", errCode);
425 RefObject::DecObjRef(this);
426 return errCode;
427 }
428
429 lifeCycleNotifier_ = notifier;
430 lifeTimerId_ = timerId;
431 return E_OK;
432 }
433
RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier & notifier)434 int SQLiteRelationalStore::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier)
435 {
436 int errCode;
437 {
438 std::lock_guard<std::mutex> lock(lifeCycleMutex_);
439 if (lifeTimerId_ != 0) {
440 errCode = StopLifeCycleTimer();
441 if (errCode != E_OK) {
442 LOGE("Stop the life cycle timer failed:%d", errCode);
443 return errCode;
444 }
445 }
446
447 if (!notifier) {
448 return E_OK;
449 }
450 errCode = StartLifeCycleTimer(notifier);
451 if (errCode != E_OK) {
452 LOGE("Register life cycle timer failed:%d", errCode);
453 return errCode;
454 }
455 }
456 auto listener = std::bind(&SQLiteRelationalStore::HeartBeat, this);
457 storageEngine_->RegisterHeartBeatListener(listener);
458 return errCode;
459 }
460
HeartBeat()461 void SQLiteRelationalStore::HeartBeat()
462 {
463 std::lock_guard<std::mutex> lock(lifeCycleMutex_);
464 int errCode = ResetLifeCycleTimer();
465 if (errCode != E_OK) {
466 LOGE("Heart beat for life cycle failed:%d", errCode);
467 }
468 }
469
ResetLifeCycleTimer()470 int SQLiteRelationalStore::ResetLifeCycleTimer()
471 {
472 if (lifeTimerId_ == 0) {
473 return E_OK;
474 }
475 auto lifeNotifier = lifeCycleNotifier_;
476 lifeCycleNotifier_ = nullptr;
477 int errCode = StopLifeCycleTimer();
478 if (errCode != E_OK) {
479 LOGE("[Reset timer]Stop the life cycle timer failed:%d", errCode);
480 }
481 return StartLifeCycleTimer(lifeNotifier);
482 }
483
GetStorePath() const484 std::string SQLiteRelationalStore::GetStorePath() const
485 {
486 return properties_.GetStringProp(DBProperties::DATA_DIR, "");
487 }
488
GetProperties() const489 RelationalDBProperties SQLiteRelationalStore::GetProperties() const
490 {
491 return properties_;
492 }
493 }
494 #endif