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 "relational_store_manager.h"
17
18 #include <thread>
19
20 #include "auto_launch.h"
21 #include "relational_store_instance.h"
22 #include "db_common.h"
23 #include "db_dfx_adapter.h"
24 #include "param_check_utils.h"
25 #include "log_print.h"
26 #include "db_errno.h"
27 #include "kv_store_errno.h"
28 #include "relational_store_changed_data_impl.h"
29 #include "relational_store_delegate_impl.h"
30 #include "runtime_context.h"
31 #include "platform_specific.h"
32
33 namespace DistributedDB {
34 namespace {
35 const int GET_CONNECT_RETRY = 3;
36 const int RETRY_GET_CONN_INTER = 30;
37 }
38
RelationalStoreManager(const std::string & appId,const std::string & userId,int32_t instanceId)39 RelationalStoreManager::RelationalStoreManager(const std::string &appId, const std::string &userId, int32_t instanceId)
40 : appId_(appId),
41 userId_(userId),
42 instanceId_(instanceId)
43 {}
44
GetOneConnectionWithRetry(const RelationalDBProperties & properties,int & errCode)45 static RelationalStoreConnection *GetOneConnectionWithRetry(const RelationalDBProperties &properties, int &errCode)
46 {
47 for (int i = 0; i < GET_CONNECT_RETRY; i++) {
48 auto conn = RelationalStoreInstance::GetDatabaseConnection(properties, errCode);
49 if (conn != nullptr) {
50 return conn;
51 }
52 if (errCode == -E_STALE) {
53 std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_GET_CONN_INTER));
54 } else {
55 return nullptr;
56 }
57 }
58 return nullptr;
59 }
60
OpenStore(const std::string & path,const std::string & storeId,const RelationalStoreDelegate::Option & option,RelationalStoreDelegate * & delegate)61 DB_API DBStatus RelationalStoreManager::OpenStore(const std::string &path, const std::string &storeId,
62 const RelationalStoreDelegate::Option &option, RelationalStoreDelegate *&delegate)
63 {
64 if (delegate != nullptr) {
65 LOGE("[RelationalStoreMgr] Invalid delegate!");
66 return INVALID_ARGS;
67 }
68
69 std::string canonicalDir;
70 if (!ParamCheckUtils::CheckDataDir(path, canonicalDir)) {
71 return INVALID_ARGS;
72 }
73
74 if (!ParamCheckUtils::CheckStoreParameter(storeId, appId_, userId_) || path.empty()) {
75 return INVALID_ARGS;
76 }
77
78 RelationalDBProperties properties;
79 properties.SetStringProp(RelationalDBProperties::DATA_DIR, canonicalDir);
80 properties.SetIdentifier(userId_, appId_, storeId, instanceId_);
81 properties.SetBoolProp(RelationalDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode);
82 if (option.isEncryptedDb) {
83 if (!ParamCheckUtils::CheckEncryptedParameter(option.cipher, option.passwd) || option.iterateTimes == 0) {
84 return INVALID_ARGS;
85 }
86 properties.SetCipherArgs(option.cipher, option.passwd, option.iterateTimes);
87 }
88
89 int errCode = E_OK;
90 auto *conn = GetOneConnectionWithRetry(properties, errCode);
91 if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) {
92 DBDfxAdapter::ReportFault( { DBDfxAdapter::EVENT_OPEN_DATABASE_FAILED, userId_, appId_, storeId, errCode } );
93 }
94 if (conn == nullptr) {
95 return TransferDBErrno(errCode);
96 }
97
98 delegate = new (std::nothrow) RelationalStoreDelegateImpl(conn, path);
99 if (delegate == nullptr) {
100 conn->Close();
101 return DB_ERROR;
102 }
103 conn->RegisterObserverAction([option, storeId, this](const std::string &changedDevice) {
104 RelationalStoreChangedDataImpl data(changedDevice);
105 data.SetStoreProperty({userId_, appId_, storeId});
106 if (option.observer) {
107 LOGD("begin to observer on changed, changedDevice=%s", STR_MASK(changedDevice));
108 option.observer->OnChange(data);
109 }
110 });
111 return OK;
112 }
113
CloseStore(RelationalStoreDelegate * store)114 DBStatus RelationalStoreManager::CloseStore(RelationalStoreDelegate *store)
115 {
116 if (store == nullptr) {
117 return INVALID_ARGS;
118 }
119
120 auto storeImpl = static_cast<RelationalStoreDelegateImpl *>(store);
121 DBStatus status = storeImpl->Close();
122 if (status == BUSY) {
123 LOGD("NbDelegateImpl is busy now.");
124 return BUSY;
125 }
126 storeImpl->SetReleaseFlag(true);
127 delete store;
128 store = nullptr;
129 return OK;
130 }
131
GetDistributedTableName(const std::string & device,const std::string & tableName)132 std::string RelationalStoreManager::GetDistributedTableName(const std::string &device, const std::string &tableName)
133 {
134 if ((!RuntimeContext::GetInstance()->ExistTranslateDevIdCallback() && device.empty()) || tableName.empty()) {
135 return {};
136 }
137 return DBCommon::GetDistributedTableName(device, tableName);
138 }
139
SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback & callback)140 void RelationalStoreManager::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback)
141 {
142 RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback, DBType::DB_RELATION);
143 }
144
GetRelationalStoreIdentifier(const std::string & userId,const std::string & appId,const std::string & storeId,bool syncDualTupleMode)145 std::string RelationalStoreManager::GetRelationalStoreIdentifier(const std::string &userId, const std::string &appId,
146 const std::string &storeId, bool syncDualTupleMode)
147 {
148 if (!ParamCheckUtils::CheckStoreParameter(storeId, appId, userId, syncDualTupleMode)) {
149 return "";
150 }
151 if (syncDualTupleMode) {
152 return DBCommon::TransferHashString(appId + "-" + storeId);
153 }
154 return DBCommon::TransferHashString(DBCommon::GenerateIdentifierId(storeId, appId, userId));
155 }
156 } // namespace DistributedDB
157 #endif