• 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 "relational_store_manager.h"
17 
18 #include <thread>
19 
20 #include "auto_launch.h"
21 #include "cloud/cloud_db_constant.h"
22 #include "cloud/cloud_storage_utils.h"
23 #include "relational_store_instance.h"
24 #include "db_common.h"
25 #include "db_dfx_adapter.h"
26 #include "db_errno.h"
27 #include "kv_store_errno.h"
28 #include "log_print.h"
29 #include "param_check_utils.h"
30 #include "platform_specific.h"
31 #include "relational_store_changed_data_impl.h"
32 #include "relational_store_delegate_impl.h"
33 #include "runtime_config.h"
34 #include "runtime_context.h"
35 
36 namespace DistributedDB {
37 namespace {
38 const int GET_CONNECT_RETRY = 3;
39 const int RETRY_GET_CONN_INTER = 30;
40 }
41 
RelationalStoreManager(const std::string & appId,const std::string & userId,int32_t instanceId)42 RelationalStoreManager::RelationalStoreManager(const std::string &appId, const std::string &userId, int32_t instanceId)
43     : appId_(appId),
44       userId_(userId),
45       instanceId_(instanceId)
46 {}
47 
GetOneConnectionWithRetry(const RelationalDBProperties & properties,int & errCode)48 static RelationalStoreConnection *GetOneConnectionWithRetry(const RelationalDBProperties &properties, int &errCode)
49 {
50     for (int i = 0; i < GET_CONNECT_RETRY; i++) {
51         auto conn = RelationalStoreInstance::GetDatabaseConnection(properties, errCode);
52         if (conn != nullptr) {
53             return conn;
54         }
55         if (errCode == -E_STALE) {
56             std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_GET_CONN_INTER));
57         } else {
58             return nullptr;
59         }
60     }
61     return nullptr;
62 }
63 
PreCheckOpenStore(const std::string & path,const std::string & storeId,RelationalStoreDelegate * & delegate,std::string & canonicalDir)64 bool RelationalStoreManager::PreCheckOpenStore(const std::string &path, const std::string &storeId,
65     RelationalStoreDelegate *&delegate, std::string &canonicalDir)
66 {
67     if (delegate != nullptr) {
68         LOGE("[RelationalStoreMgr] Invalid delegate!");
69         return false;
70     }
71 
72     if (!ParamCheckUtils::CheckDataDir(path, canonicalDir)) {
73         return false;
74     }
75 
76     if (!ParamCheckUtils::CheckStoreParameter(storeId, appId_, userId_) || path.empty()) {
77         return false;
78     }
79 
80     return true;
81 }
82 
OpenStore(const std::string & path,const std::string & storeId,const RelationalStoreDelegate::Option & option,RelationalStoreDelegate * & delegate)83 DB_API DBStatus RelationalStoreManager::OpenStore(const std::string &path, const std::string &storeId,
84     const RelationalStoreDelegate::Option &option, RelationalStoreDelegate *&delegate)
85 {
86     std::string canonicalDir;
87     if (!PreCheckOpenStore(path, storeId, delegate, canonicalDir)) {
88         return INVALID_ARGS;
89     }
90 
91     RelationalDBProperties properties;
92     properties.SetStringProp(RelationalDBProperties::DATA_DIR, canonicalDir);
93     properties.SetIdentifier(userId_, appId_, storeId, instanceId_);
94     properties.SetBoolProp(RelationalDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode);
95     if (option.isEncryptedDb) {
96         if (!ParamCheckUtils::CheckEncryptedParameter(option.cipher, option.passwd) || option.iterateTimes == 0) {
97             return INVALID_ARGS;
98         }
99         properties.SetCipherArgs(option.cipher, option.passwd, option.iterateTimes);
100     }
101 
102     int errCode = E_OK;
103     auto *conn = GetOneConnectionWithRetry(properties, errCode);
104     if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) {
105         DBDfxAdapter::ReportFault( { DBDfxAdapter::EVENT_OPEN_DATABASE_FAILED, userId_, appId_, storeId, errCode } );
106     }
107     if (conn == nullptr) {
108         return TransferDBErrno(errCode);
109     }
110 
111     delegate = new (std::nothrow) RelationalStoreDelegateImpl(conn, path);
112     if (delegate == nullptr) {
113         conn->Close();
114         return DB_ERROR;
115     }
116     return option.observer != nullptr ? delegate->RegisterObserver(option.observer) : OK;
117 }
118 
CloseStore(RelationalStoreDelegate * store)119 DBStatus RelationalStoreManager::CloseStore(RelationalStoreDelegate *store)
120 {
121     if (store == nullptr) {
122         return INVALID_ARGS;
123     }
124 
125     auto storeImpl = static_cast<RelationalStoreDelegateImpl *>(store);
126     DBStatus status = storeImpl->Close();
127     if (status == BUSY) {
128         LOGD("NbDelegateImpl is busy now.");
129         return BUSY;
130     }
131     storeImpl->SetReleaseFlag(true);
132     delete store;
133     store = nullptr;
134     return OK;
135 }
136 
GetDistributedTableName(const std::string & device,const std::string & tableName)137 std::string RelationalStoreManager::GetDistributedTableName(const std::string &device, const std::string &tableName)
138 {
139     if ((!RuntimeContext::GetInstance()->ExistTranslateDevIdCallback() && device.empty()) || tableName.empty()) {
140         return {};
141     }
142     return DBCommon::GetDistributedTableName(device, tableName);
143 }
144 
GetDistributedLogTableName(const std::string & tableName)145 DB_API std::string RelationalStoreManager::GetDistributedLogTableName(const std::string &tableName)
146 {
147     return DBCommon::GetLogTableName(tableName);
148 }
149 
CalcPrimaryKeyHash(const std::map<std::string,Type> primaryKey)150 DB_API std::vector<uint8_t> RelationalStoreManager::CalcPrimaryKeyHash(const std::map<std::string, Type> primaryKey)
151 {
152     std::vector<uint8_t> result;
153     if (primaryKey.empty()) {
154         LOGW("primaryKey is empty");
155         return result;
156     }
157     int errCode = E_OK;
158     if (primaryKey.size() == 1) {
159         auto iter = primaryKey.begin();
160         Field field = {iter->first, static_cast<int32_t>(iter->second.index()), true, false};
161         errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, result);
162         if (errCode != E_OK) {
163             // never happen
164             LOGE("calc hash fail when there is one primary key errCode = %d", errCode);
165         }
166     } else {
167         std::vector<uint8_t> tempRes;
168         for (const auto &item : primaryKey) {
169             std::vector<uint8_t> temp;
170             Field field = {item.first, static_cast<int32_t>(item.second.index()), true, false};
171             errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, temp);
172             if (errCode != E_OK) {
173                 // never happen
174                 LOGE("calc hash fail when there is more than one primary key errCode = %d", errCode);
175                 return result;
176             }
177             tempRes.insert(tempRes.end(), temp.begin(), temp.end());
178         }
179         errCode = DBCommon::CalcValueHash(tempRes, result);
180         if (errCode != E_OK) {
181             LOGE("calc hash fail when calc the composite primary key errCode = %d", errCode);
182         }
183     }
184     return result;
185 }
186 
SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback & callback)187 void RelationalStoreManager::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback)
188 {
189     RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback, DBTypeInner::DB_RELATION);
190 }
191 
GetRelationalStoreIdentifier(const std::string & userId,const std::string & appId,const std::string & storeId,bool syncDualTupleMode)192 std::string RelationalStoreManager::GetRelationalStoreIdentifier(const std::string &userId, const std::string &appId,
193     const std::string &storeId, bool syncDualTupleMode)
194 {
195     return RuntimeConfig::GetStoreIdentifier(userId, appId, storeId, syncDualTupleMode);
196 }
197 } // namespace DistributedDB
198 #endif