• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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