1 /*
2 * Copyright (c) 2024 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
16 #define LOG_TAG "DBStoreManager"
17
18 #include "db_store_manager.h"
19
20 #include <dirent.h>
21 #include <securec.h>
22 #include <sys/stat.h>
23
24 #include "db_common.h"
25 #include "log_print.h"
26 #include "rd_utils.h"
27 #include "cloud_db_proxy.h"
28
29 namespace OHOS::CollaborationEdit {
30 GRD_ThreadPoolT DBStoreManager::threadPool_ = {reinterpret_cast<GRD_ScheduleFunc>(DBStoreManager::Schedule)};
31 std::shared_ptr<ExecutorPool> DBStoreManager::executorPool_ = nullptr;
32 std::shared_ptr<DBStoreMgrThreadPool> DBStoreManager::executors_ = nullptr;
33 constexpr size_t MAX_THREADS_SIZE = 12;
34 constexpr size_t MIN_THREADS_SIZE = 5;
35
GetInstance()36 DBStoreManager &DBStoreManager::GetInstance()
37 {
38 static DBStoreManager manager;
39 return manager;
40 }
41
DBStoreManager()42 DBStoreManager::DBStoreManager()
43 {}
44
~DBStoreManager()45 DBStoreManager::~DBStoreManager()
46 {}
47
GetDBStore(const DBStoreConfig & config)48 std::shared_ptr<DBStore> DBStoreManager::GetDBStore(const DBStoreConfig &config)
49 {
50 std::lock_guard<std::mutex> lock(mutex_);
51 auto it = storeCache_.find(config.GetName());
52 if (it != storeCache_.end()) {
53 return it->second;
54 }
55 std::shared_ptr<DBStore> dbStore = OpenDBStore(config);
56 if (dbStore != nullptr) {
57 storeCache_[config.GetName()] = dbStore;
58 }
59 return dbStore;
60 }
61
OpenDBStore(const DBStoreConfig & dbConfig)62 std::shared_ptr<DBStore> DBStoreManager::OpenDBStore(const DBStoreConfig &dbConfig)
63 {
64 std::string dbFilePath = dbConfig.GetPath();
65 std::string name = dbConfig.GetName();
66 LOG_DEBUG("[OpenDBStore] start");
67 // create database and oplog directory if not exists
68 if (access(dbFilePath.c_str(), F_OK) != 0) {
69 int ret = DBCommon::CreateDirectory(dbFilePath);
70 if (ret != 0) {
71 LOG_ERROR("[OpenDBStore] Create base dir go wrong, ret = %{public}d", ret);
72 return nullptr;
73 }
74 // creating oplog dir here is to provide group permission for other processes access
75 std::string opLogDir = dbFilePath + "/" + name + OP_LOG_DIR;
76 ret = DBCommon::CreateDirectory(opLogDir);
77 if (ret != 0) {
78 LOG_ERROR("[OpenDBStore] Create oplog dir go wrong, ret = %{public}d", ret);
79 return nullptr;
80 }
81 }
82
83 GRD_DB *db = nullptr;
84 std::string dbFile = dbFilePath + "/" + name;
85 std::string config = R"({"sharedModeEnable":1,"redoFlushByTrx":1})";
86 int32_t errCode = RdUtils::RdDbOpen(dbFile.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db);
87 if (errCode != GRD_OK || db == nullptr) {
88 LOG_ERROR("[OpenDBStore] open db go wrong, err = %{public}d", errCode);
89 return nullptr;
90 }
91 LOG_INFO("[OpenDBStore] open db successfully");
92 std::shared_ptr<DBStore> dbStore = std::make_shared<DBStore>(db, name);
93 return dbStore;
94 }
95
DeleteDBStore(const DBStoreConfig & config)96 int DBStoreManager::DeleteDBStore(const DBStoreConfig &config)
97 {
98 std::lock_guard<std::mutex> lock(mutex_);
99 std::string dbPath = config.GetPath();
100 if (dbPath.empty()) {
101 LOG_ERROR("[DeleteDBStore] empty path");
102 return -1;
103 }
104 auto it = storeCache_.find(config.GetName());
105 if (it != storeCache_.end()) {
106 std::shared_ptr<DBStore> dbStorePtr = it->second;
107 int32_t errCode = RdUtils::RdDbClose(dbStorePtr->GetDB(), GRD_DB_CLOSE);
108 if (errCode != GRD_OK) {
109 LOG_ERROR("[DeleteDBStore] db close go wrong, err = %{public}d", errCode);
110 return -1;
111 }
112 dbStorePtr->FreeCloudDB();
113 }
114 int ret = RemoveDir(dbPath.c_str());
115 if (ret != 0) {
116 LOG_ERROR("[DeleteDBStore] remove dir go wrong");
117 return ret;
118 }
119 LOG_INFO("[DeleteDBStore] delete db successfully");
120 storeCache_.erase(config.GetName());
121 return 0;
122 }
123
RemoveDir(const char * dir)124 int DBStoreManager::RemoveDir(const char *dir)
125 {
126 if (access(dir, F_OK) != 0) {
127 return 0;
128 }
129
130 struct stat dirStat;
131 if (stat(dir, &dirStat) < 0) {
132 LOG_ERROR("[RemoveDir] get dir stat go wrong");
133 return -1;
134 }
135
136 char dirName[PATH_MAX];
137 DIR *dirPtr = nullptr;
138 struct dirent *dr = nullptr;
139 if (S_ISREG(dirStat.st_mode)) { // normal file
140 remove(dir);
141 } else if (S_ISDIR(dirStat.st_mode)) {
142 dirPtr = opendir(dir);
143 while ((dr = readdir(dirPtr)) != nullptr) {
144 // ignore . and ..
145 if ((strcmp(".", dr->d_name) == 0) || (strcmp("..", dr->d_name) == 0)) {
146 continue;
147 }
148 if (sprintf_s(dirName, PATH_MAX, "%s/%s", dir, dr->d_name) <= 0) {
149 LOG_ERROR("[RemoveDir] dirName too long.");
150 closedir(dirPtr);
151 return -1;
152 }
153 RemoveDir(dirName);
154 }
155 closedir(dirPtr);
156 rmdir(dir); // remove empty dir
157 } else {
158 LOG_ERROR("[RemoveDir] unknown file type, st mode %{public}d", dirStat.st_mode);
159 }
160 return 0;
161 }
162
SetCloudDb(std::shared_ptr<DBStore> dbStore,NapiCloudDb * napiCloudDb)163 int DBStoreManager::SetCloudDb(std::shared_ptr<DBStore> dbStore, NapiCloudDb *napiCloudDb)
164 {
165 AssetLoaderT *assetLoader = (AssetLoaderT *)malloc(sizeof(AssetLoaderT));
166 if (assetLoader == nullptr) {
167 LOG_ERROR("[SetCloudDb] malloc AssetLoaderT go wrong");
168 return -1;
169 }
170 assetLoader->downloadAsset = CloudDbProxy::DownloadAsset;
171 assetLoader->uploadAsset = CloudDbProxy::UploadAsset;
172 assetLoader->deleteAsset = CloudDbProxy::DeleteAsset;
173 assetLoader->deleteLocalAsset = CloudDbProxy::DeleteLocalAsset;
174
175 CloudDbProxy *cloudDbProxy = new (std::nothrow) CloudDbProxy();
176 if (cloudDbProxy == nullptr) {
177 LOG_ERROR("[SetCloudDb] create cloudDbProxy go wrong");
178 free(assetLoader);
179 return -1;
180 }
181 cloudDbProxy->SetNapiCloudDb(napiCloudDb);
182
183 GRD_ICloudDBT *cloudDB = (GRD_ICloudDBT *)malloc(sizeof(GRD_ICloudDBT));
184 if (cloudDB == nullptr) {
185 LOG_ERROR("[SetCloudDb] malloc ICloudDBT go wrong");
186 free(assetLoader);
187 delete cloudDbProxy;
188 return -1;
189 }
190 cloudDB->assetLoader = assetLoader;
191 cloudDB->cloudDB = reinterpret_cast<void *>(cloudDbProxy);
192 cloudDB->batchInsert = CloudDbProxy::BatchInsert;
193 cloudDB->query = CloudDbProxy::Query;
194 cloudDB->sendAwarenessData = CloudDbProxy::SendAwarenessData;
195 cloudDB->heartBeat = CloudDbProxy::HeartBeat;
196 cloudDB->lock = CloudDbProxy::Lock;
197 cloudDB->unLock = CloudDbProxy::UnLock;
198 cloudDB->close = CloudDbProxy::Close;
199
200 int32_t errCode = RdUtils::RdSetCloudDb(dbStore->GetDB(), cloudDB);
201 if (errCode != GRD_OK) {
202 LOG_ERROR("[SetCloudDb] RdSetCloudDb go wrong, errCode = %{public}d", errCode);
203 free(assetLoader);
204 free(cloudDB);
205 delete cloudDbProxy;
206 return -1;
207 }
208 dbStore->SetCloudDbProxy(cloudDbProxy, cloudDB);
209 return 0;
210 }
211
Schedule(void * func,void * param)212 void DBStoreManager::Schedule(void *func, void *param)
213 {
214 if (executors_ == nullptr) {
215 LOG_ERROR("executors_ is nullptr.");
216 return;
217 }
218 executors_->Execute([func, param]() {
219 void (*funcPtr)(void *) = reinterpret_cast<void (*)(void *)>(func);
220 funcPtr(param);
221 });
222 }
223
InitThreadPool()224 void DBStoreManager::InitThreadPool()
225 {
226 std::lock_guard<std::mutex> lock(threadPoolMutex_);
227 if (executorPool_ == nullptr) {
228 executorPool_ = std::make_shared<ExecutorPool>(MAX_THREADS_SIZE, MIN_THREADS_SIZE);
229 }
230 if (executors_ == nullptr) {
231 executors_ = std::make_shared<DbThreadPool>(DBStoreManager::executorPool_);
232 LOG_INFO("init thread pool success");
233 }
234 }
235 } // namespace OHOS::CollaborationEdit
236