• 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 "db_common.h"
22 #include "db_dfx_adapter.h"
23 #include "db_errno.h"
24 #include "cloud/cloud_db_constant.h"
25 #include "cloud/cloud_storage_utils.h"
26 #include "kv_store_errno.h"
27 #include "log_print.h"
28 #include "param_check_utils.h"
29 #include "platform_specific.h"
30 #include "query_sync_object.h"
31 #include "relational_store_changed_data_impl.h"
32 #include "relational_store_delegate_impl.h"
33 #include "relational_store_instance.h"
34 #include "runtime_config.h"
35 #include "runtime_context.h"
36 
37 namespace DistributedDB {
38 namespace {
39 const int GET_CONNECT_RETRY = 3;
40 const int RETRY_GET_CONN_INTER = 30;
41 }
42 
RelationalStoreManager(const std::string & appId,const std::string & userId,int32_t instanceId)43 RelationalStoreManager::RelationalStoreManager(const std::string &appId, const std::string &userId, int32_t instanceId)
44     : appId_(appId),
45       userId_(userId),
46       instanceId_(instanceId)
47 {}
48 
RelationalStoreManager(const std::string & appId,const std::string & userId,const std::string & subUser,int32_t instanceId)49 RelationalStoreManager::RelationalStoreManager(const std::string &appId, const std::string &userId,
50     const std::string &subUser, int32_t instanceId)
51     : appId_(appId),
52       userId_(userId),
53       subUser_(subUser),
54       instanceId_(instanceId)
55 {}
56 
GetOneConnectionWithRetry(const RelationalDBProperties & properties,int & errCode)57 static RelationalStoreConnection *GetOneConnectionWithRetry(const RelationalDBProperties &properties, int &errCode)
58 {
59     for (int i = 0; i < GET_CONNECT_RETRY; i++) {
60         auto conn = RelationalStoreInstance::GetDatabaseConnection(properties, errCode);
61         if (conn != nullptr) {
62             return conn;
63         }
64         if (errCode == -E_STALE) {
65             std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_GET_CONN_INTER));
66         } else {
67             return nullptr;
68         }
69     }
70     return nullptr;
71 }
72 
PreCheckOpenStore(const std::string & path,const std::string & storeId,RelationalStoreDelegate * & delegate,std::string & canonicalDir)73 bool RelationalStoreManager::PreCheckOpenStore(const std::string &path, const std::string &storeId,
74     RelationalStoreDelegate *&delegate, std::string &canonicalDir)
75 {
76     if (delegate != nullptr) {
77         LOGE("[RelationalStoreMgr] Invalid delegate!");
78         return false;
79     }
80 
81     if (!ParamCheckUtils::CheckDataDir(path, canonicalDir)) {
82         return false;
83     }
84 
85     if (!ParamCheckUtils::CheckStoreParameter({userId_, appId_, storeId}, false, subUser_, true) || path.empty()) {
86         return false;
87     }
88 
89     return true;
90 }
91 
OpenStore(const std::string & path,const std::string & storeId,const RelationalStoreDelegate::Option & option,RelationalStoreDelegate * & delegate)92 DB_API DBStatus RelationalStoreManager::OpenStore(const std::string &path, const std::string &storeId,
93     const RelationalStoreDelegate::Option &option, RelationalStoreDelegate *&delegate)
94 {
95     std::string canonicalDir;
96     if (!PreCheckOpenStore(path, storeId, delegate, canonicalDir)) {
97         return INVALID_ARGS;
98     }
99 
100     RelationalDBProperties properties;
101     properties.SetStringProp(RelationalDBProperties::DATA_DIR, canonicalDir);
102     properties.SetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast<int>(option.tableMode));
103     properties.SetIdentifier(userId_, appId_, storeId, subUser_, instanceId_);
104     properties.SetBoolProp(RelationalDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode);
105     if (option.isEncryptedDb) {
106         if (!ParamCheckUtils::CheckEncryptedParameter(option.cipher, option.passwd) || option.iterateTimes == 0) {
107             return INVALID_ARGS;
108         }
109         properties.SetCipherArgs(option.cipher, option.passwd, option.iterateTimes);
110     }
111 
112     int errCode = E_OK;
113     auto *conn = GetOneConnectionWithRetry(properties, errCode);
114     if (conn == nullptr) {
115         return TransferDBErrno(errCode);
116     }
117 
118     delegate = new (std::nothrow) RelationalStoreDelegateImpl(conn, path);
119     if (delegate == nullptr) {
120         conn->Close();
121         return DB_ERROR;
122     }
123 
124     if (option.observer == nullptr) {
125         return OK;
126     }
127     DBStatus status = delegate->RegisterObserver(option.observer);
128     if (status != OK) {
129         LOGE("register observer failed when open store: %d", status);
130         conn->Close();
131     }
132     return status;
133 }
134 
CloseStore(RelationalStoreDelegate * store)135 DBStatus RelationalStoreManager::CloseStore(RelationalStoreDelegate *store)
136 {
137     if (store == nullptr) {
138         return INVALID_ARGS;
139     }
140 
141     auto storeImpl = static_cast<RelationalStoreDelegateImpl *>(store);
142     DBStatus status = storeImpl->Close();
143     if (status == BUSY) {
144         LOGD("NbDelegateImpl is busy now.");
145         return BUSY;
146     }
147     storeImpl->SetReleaseFlag(true);
148     delete store;
149     store = nullptr;
150     return OK;
151 }
152 
GetDistributedTableName(const std::string & device,const std::string & tableName)153 std::string RelationalStoreManager::GetDistributedTableName(const std::string &device, const std::string &tableName)
154 {
155     if ((!RuntimeContext::GetInstance()->ExistTranslateDevIdCallback() && device.empty()) || tableName.empty()) {
156         return {};
157     }
158     return DBCommon::GetDistributedTableName(device, tableName);
159 }
160 
GetDistributedLogTableName(const std::string & tableName)161 DB_API std::string RelationalStoreManager::GetDistributedLogTableName(const std::string &tableName)
162 {
163     return DBCommon::GetLogTableName(tableName);
164 }
165 
GetCollateTypeByName(const std::map<std::string,CollateType> & collateTypeMap,const std::string & name,CollateType & collateType)166 static int GetCollateTypeByName(const std::map<std::string, CollateType> &collateTypeMap,
167     const std::string &name, CollateType &collateType)
168 {
169     auto it = collateTypeMap.find(name);
170     if (it == collateTypeMap.end()) {
171         LOGW("collate map doesn't contain primary key we need");
172         collateType = CollateType::COLLATE_NONE;
173         return E_OK;
174     }
175     if (static_cast<uint32_t>(it->second) >= static_cast<uint32_t>(CollateType::COLLATE_BUTT)) {
176         LOGE("collate type is invalid");
177         return -E_INVALID_ARGS;
178     }
179     collateType = it->second;
180     return E_OK;
181 }
182 
CalcPrimaryKeyHash(const std::map<std::string,Type> & primaryKey,const std::map<std::string,CollateType> & collateTypeMap)183 DB_API std::vector<uint8_t> RelationalStoreManager::CalcPrimaryKeyHash(const std::map<std::string, Type> &primaryKey,
184     const std::map<std::string, CollateType> &collateTypeMap)
185 {
186     std::vector<uint8_t> result;
187     if (primaryKey.empty()) {
188         LOGW("primaryKey is empty");
189         return result;
190     }
191     int errCode = E_OK;
192     CollateType collateType = CollateType::COLLATE_NONE;
193     if (primaryKey.size() == 1) {
194         auto iter = primaryKey.begin();
195         Field field = {iter->first, static_cast<int32_t>(iter->second.index()), true, false};
196         if (GetCollateTypeByName(collateTypeMap, iter->first, collateType) != E_OK) {
197             return result;
198         }
199         errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, result);
200         if (errCode != E_OK) {
201             // never happen
202             LOGE("calc hash fail when there is one primary key errCode = %d", errCode);
203         }
204     } else {
205         std::vector<uint8_t> tempRes;
206         std::map<std::string, Type> pkOrderByUpperName;
207         for (const auto &item : primaryKey) { // we sort by upper case name in log table when calculate hash
208             pkOrderByUpperName[DBCommon::ToUpperCase(item.first)] = item.second;
209         }
210 
211         for (const auto &item : pkOrderByUpperName) {
212             std::vector<uint8_t> temp;
213             Field field = {DBCommon::ToLowerCase(item.first), static_cast<int32_t>(item.second.index()), true, false};
214             if (GetCollateTypeByName(collateTypeMap, DBCommon::ToLowerCase(item.first), collateType) != E_OK) {
215                 return result;
216             }
217             errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, temp);
218             if (errCode != E_OK) {
219                 // never happen
220                 LOGE("calc hash fail when there is more than one primary key errCode = %d", errCode);
221                 return result;
222             }
223             tempRes.insert(tempRes.end(), temp.begin(), temp.end());
224         }
225         errCode = DBCommon::CalcValueHash(tempRes, result);
226         if (errCode != E_OK) {
227             LOGE("calc hash fail when calc the composite primary key errCode = %d", errCode);
228         }
229     }
230     return result;
231 }
232 
SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback & callback)233 void RelationalStoreManager::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback)
234 {
235     RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback, DBTypeInner::DB_RELATION);
236 }
237 
GetRelationalStoreIdentifier(const std::string & userId,const std::string & appId,const std::string & storeId,bool syncDualTupleMode)238 std::string RelationalStoreManager::GetRelationalStoreIdentifier(const std::string &userId, const std::string &appId,
239     const std::string &storeId, bool syncDualTupleMode)
240 {
241     return RelationalStoreManager::GetRelationalStoreIdentifier(userId, "", appId, storeId, syncDualTupleMode);
242 }
243 
GetRelationalStoreIdentifier(const std::string & userId,const std::string & subUserId,const std::string & appId,const std::string & storeId,bool syncDualTupleMode)244 std::string RelationalStoreManager::GetRelationalStoreIdentifier(const std::string &userId,
245     const std::string &subUserId, const std::string &appId, const std::string &storeId, bool syncDualTupleMode)
246 {
247     StoreInfo info;
248     info.storeId = storeId;
249     info.appId = appId;
250     info.userId = userId;
251     return DBCommon::GetStoreIdentifier(info, subUserId, syncDualTupleMode, true);
252 }
253 
ParserQueryNodes(const Bytes & queryBytes,DBStatus & status)254 std::vector<QueryNode> RelationalStoreManager::ParserQueryNodes(const Bytes &queryBytes,
255     DBStatus &status)
256 {
257     std::vector<QueryNode> res;
258     status = TransferDBErrno(QuerySyncObject::ParserQueryNodes(queryBytes, res));
259     return res;
260 }
261 } // namespace DistributedDB
262 #endif
263