• 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_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)> &notifier)
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 &notifier : 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 &notifier)
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 &notifier)
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