1 /*
2  * Copyright (c) 2023 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 #include "rd_single_ver_storage_engine.h"
16 
17 #include "db_constant.h"
18 #include "grd_error.h"
19 #include "grd_type_export.h"
20 #include "rd_single_ver_storage_executor.h"
21 #include "rd_utils.h"
22 #include "single_ver_utils.h"
23 #include "sqlite_single_ver_storage_executor_sql.h"
24 
25 namespace DistributedDB {
RdSingleVerStorageEngine()26 RdSingleVerStorageEngine::RdSingleVerStorageEngine()
27 {
28     LOGD("[RdSingleVerStorageEngine] RdSingleVerStorageEngine Created");
29 }
30 
~RdSingleVerStorageEngine()31 RdSingleVerStorageEngine::~RdSingleVerStorageEngine()
32 {
33 }
34 
GetTableMode(bool isHash)35 inline std::string GetTableMode(bool isHash)
36 {
37     return isHash ? DBConstant::RD_KV_HASH_COLLECTION_MODE : DBConstant::RD_KV_COLLECTION_MODE;
38 }
39 
CreateNewExecutor(bool isWrite,StorageExecutor * & handle)40 int RdSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle)
41 {
42     int ret = PreCreateExecutor(isWrite);
43     if (ret != E_OK) {
44         LOGE("[RdSingleVerStorageEngine][CreateNewExecutor] PreCreateExecutor unscuccess");
45         return ret;
46     }
47     GRD_DB *db = nullptr;
48     ret = TryToOpenMainDatabase(isWrite, db);
49     if (ret != E_OK) {
50         LOGE("[RdSingleVerStorageEngine] GRD_DBOPEN FAILED:%d", ret);
51         return ret;
52     }
53     if (!option_.readOnly) {
54         std::string tableMode = GetTableMode(option_.isHashTable);
55         ret = RdCreateCollection(db, SYNC_COLLECTION_NAME, tableMode.c_str(), 0);
56         if (ret != E_OK) {
57             LOGE("[RdSingleVerStorageEngine] GRD_CreateCollection SYNC_COLLECTION_NAME FAILED %d", ret);
58             (void)RdDBClose(db, GRD_DB_CLOSE_IGNORE_ERROR);
59             return ret;
60         }
61     }
62     ret = IndexPreLoad(db, SYNC_COLLECTION_NAME);
63     if (ret != E_OK) {
64         LOGE("[RdSingleVerStorageEngine] GRD_IndexPreload FAILED %d", ret);
65         (void)RdDBClose(db, GRD_DB_CLOSE_IGNORE_ERROR);
66         return ret;
67     }
68     handle = new (std::nothrow) RdSingleVerStorageExecutor(db, isWrite);
69     if (handle == nullptr) {
70         (void)RdDBClose(db, GRD_DB_CLOSE_IGNORE_ERROR);
71         return -E_OUT_OF_MEMORY;
72     }
73     if (OS::CheckPathExistence(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) &&
74         OS::RemoveFile(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) {
75         LOGE("Finish to create the complete database, but delete token fail! errCode = [E_SYSTEM_API_FAIL]");
76         delete handle;
77         handle = nullptr;
78         return -E_SYSTEM_API_FAIL;
79     }
80     return E_OK;
81 }
82 
InitRdStorageEngine(const StorageEngineAttr & poolSize,const OpenDbProperties & option,const std::string & identifier)83 int RdSingleVerStorageEngine::InitRdStorageEngine(const StorageEngineAttr &poolSize, const OpenDbProperties &option,
84     const std::string &identifier)
85 {
86     if (StorageEngine::CheckEngineAttr(poolSize)) {
87         LOGE("Invalid storage engine attributes!");
88         return -E_INVALID_ARGS;
89     }
90     engineAttr_ = poolSize;
91     option_ = option;
92     identifier_ = identifier;
93     hashIdentifier_ = DBCommon::TransferStringToHex(identifier_);
94     int errCode = Init();
95     if (errCode != E_OK) {
96         LOGI("Storage engine init fail! errCode = [%d]", errCode);
97     }
98     return errCode;
99 }
100 
GetExistedSecOption(SecurityOption & secOption) const101 int RdSingleVerStorageEngine::GetExistedSecOption(SecurityOption &secOption) const
102 {
103     LOGD("[RdSingleVerStorageEngine] Try to get existed sec option");
104     return GetExistedSecOpt(option_, secOption);
105 }
106 
CheckDatabaseSecOpt(const SecurityOption & secOption) const107 int RdSingleVerStorageEngine::CheckDatabaseSecOpt(const SecurityOption &secOption) const
108 {
109     if (!(secOption == option_.securityOpt) && (secOption.securityLabel > option_.securityOpt.securityLabel) &&
110         secOption.securityLabel != SecurityLabel::NOT_SET &&
111         option_.securityOpt.securityLabel != SecurityLabel::NOT_SET) {
112         LOGE("[RdSingleVerStorageEngine] SecurityOption mismatch, existed:[%d-%d] vs input:[%d-%d]",
113             secOption.securityLabel, secOption.securityFlag, option_.securityOpt.securityLabel,
114             option_.securityOpt.securityFlag);
115         return -E_SECURITY_OPTION_CHECK_ERROR;
116     }
117     return E_OK;
118 }
119 
CreateNewDirsAndSetSecOpt() const120 int RdSingleVerStorageEngine::CreateNewDirsAndSetSecOpt() const
121 {
122     LOGD("[RdSingleVerStorageEngine] Begin to create new dirs and set security option");
123     return CreateNewDirsAndSetSecOption(option_);
124 }
125 
TryToOpenMainDatabase(bool isWrite,GRD_DB * & db)126 int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db)
127 {
128     // Only could get the main database handle in the uninitialized and the main status.
129     if (GetEngineState() != EngineState::INVALID && GetEngineState() != EngineState::MAINDB) {
130         LOGE("[RdSinStoreEng][GetMainHandle] Can only create new handle for state[%d]", GetEngineState());
131         return -E_EKEYREVOKED;
132     }
133 
134     option_.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE +
135         DBConstant::DB_EXTENSION;
136 
137     OpenDbProperties optionTemp = option_;
138     if (!isWrite) {
139         optionTemp.createIfNecessary = false;
140     }
141     int errCode = OpenGrdDb(optionTemp, db);
142     if (errCode != E_OK) {
143         LOGE("Failed to open the main database [%d], uri: %s", errCode, (option_.uri).c_str());
144         return errCode;
145     }
146 
147     // Set the engine state to main status for that the main database is valid.
148     SetEngineState(EngineState::MAINDB);
149     return errCode;
150 }
151 
GetDbHandle(bool isWrite,const SecurityOption & secOpt,GRD_DB * & dbHandle)152 int RdSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption &secOpt, GRD_DB *&dbHandle)
153 {
154     int errCode = TryToOpenMainDatabase(isWrite, dbHandle);
155     LOGD("Finish to open the main database, write[%d], label[%d], flag[%d], id[%.6s], errCode[%d]",  isWrite,
156         secOpt.securityLabel, secOpt.securityFlag, hashIdentifier_.c_str(), errCode);
157     if (!(ParamCheckUtils::IsS3SECEOpt(secOpt) && errCode == -E_EKEYREVOKED)) {
158         return errCode;
159     }
160     return -E_NOT_SUPPORT;
161 }
162 
PreCreateExecutor(bool isWrite)163 int RdSingleVerStorageEngine::PreCreateExecutor(bool isWrite)
164 {
165     if (!isWrite) {
166         return E_OK;
167     }
168     // Get the existed database secure option.
169     SecurityOption existedSecOpt;
170     int ret = GetExistedSecOption(existedSecOpt);
171     if (ret != E_OK) {
172         LOGD("[RdSingleVerStorageEngine][PreCreateExecutor]Something unexpected happened");
173         return ret;
174     }
175     ret = CheckDatabaseSecOpt(existedSecOpt);
176     if (ret != E_OK) {
177         LOGD("[RdSingleVerStorageEngine][CheckDatabaseSecOpt]Something unexpected happened");
178         return ret;
179     }
180     ret = CreateNewDirsAndSetSecOpt();
181     if (ret != E_OK) {
182         LOGD("[RdSingleVerStorageEngine][CreateNewDirsAndSetSecOpt]Something unexpected happened");
183     }
184     return ret;
185 }
186 
OpenGrdDb(const OpenDbProperties & option,GRD_DB * & db)187 int RdSingleVerStorageEngine::OpenGrdDb(const OpenDbProperties &option, GRD_DB *&db)
188 {
189     uint32_t flag = GRD_DB_OPEN_ONLY;
190     if (option.createIfNecessary && !option.readOnly) {
191         flag |= GRD_DB_OPEN_CREATE;
192     }
193     if (option.readOnly) {
194         flag |= GRD_DB_OPEN_SHARED_READ_ONLY;
195     }
196     int errCode = RdDbOpen(option.uri.c_str(), option.rdConfig.c_str(), flag, db);
197     if (errCode == -E_REBUILD_DATABASE) {
198         if (option.isNeedRmCorruptedDb) {
199             LOGD("[RdSingleVerStorageEngine] rebuild database successfully");
200             return E_OK;
201         } else {
202             LOGE("[RdSingleVerStorageEngine] database is corrupted");
203             return -E_INVALID_PASSWD_OR_CORRUPTED_DB;
204         }
205     }
206     return errCode;
207 }
208 
IndexPreLoad(GRD_DB * & db,const char * collectionName)209 int RdSingleVerStorageEngine::IndexPreLoad(GRD_DB *&db, const char *collectionName)
210 {
211     int ret = E_OK;
212     if (isFirstTimeOpenDb_) {
213         ret = RdIndexPreload(db, collectionName);
214         if (ret != E_OK) {
215             LOGE("Unable to RdIndexPreload %d", ret);
216             return ret;
217         }
218         isFirstTimeOpenDb_ = false;
219     }
220     return E_OK;
221 }
222 } // namespace DistributedDB