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 #define LOG_TAG "Config"
16 #include "sqlite_global_config.h"
17
18 #include <sys/stat.h>
19 #include <sys/types.h>
20
21 #include <cerrno>
22 #include <chrono>
23 #include <cinttypes>
24 #include <cstring>
25 #include <mutex>
26 #include <regex>
27
28 #include "logger.h"
29 #include "rdb_errno.h"
30 #include "sqlite3sym.h"
31 #include "sqlite_utils.h"
32 #include "rdb_fault_hiview_reporter.h"
33
34 namespace OHOS {
35 namespace NativeRdb {
36 using namespace OHOS::Rdb;
37 using namespace std::chrono;
38
39 static std::string g_lastCorruptionMsg;
40 static std::mutex g_corruptionMutex;
41
InitSqliteGlobalConfig()42 void SqliteGlobalConfig::InitSqliteGlobalConfig()
43 {
44 static SqliteGlobalConfig globalConfig;
45 }
46
SqliteGlobalConfig()47 SqliteGlobalConfig::SqliteGlobalConfig()
48 {
49 umask(GlobalExpr::APP_DEFAULT_UMASK);
50
51 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
52
53 sqlite3_config(SQLITE_CONFIG_LOG, &Log, GlobalExpr::CALLBACK_LOG_SWITCH ? reinterpret_cast<void *>(1) : NULL);
54
55 sqlite3_config(SQLITE_CONFIG_CORRUPTION, &Corruption, nullptr);
56
57 sqlite3_soft_heap_limit(GlobalExpr::SOFT_HEAP_LIMIT);
58
59 sqlite3_initialize();
60
61 sqlite3_register_cksumvfs(0);
62 }
63
~SqliteGlobalConfig()64 SqliteGlobalConfig::~SqliteGlobalConfig()
65 {
66 sqlite3_unregister_cksumvfs();
67 sqlite3_config(SQLITE_CONFIG_CORRUPTION, nullptr, nullptr);
68 sqlite3_config(SQLITE_CONFIG_LOG, nullptr, nullptr);
69 LOG_INFO("Destruct.");
70 }
71
Corruption(void * arg,const void * msg)72 void SqliteGlobalConfig::Corruption(void *arg, const void *msg)
73 {
74 std::lock_guard<std::mutex> lockGuard(g_corruptionMutex);
75 g_lastCorruptionMsg = (const char *)msg;
76 }
77
Log(const void * data,int err,const char * msg)78 void SqliteGlobalConfig::Log(const void *data, int err, const char *msg)
79 {
80 bool verboseLog = (data != nullptr);
81 auto errType = static_cast<unsigned int>(err);
82 errType &= 0xFF;
83 if (errType == SQLITE_ERROR && strstr(msg, "\"?\": syntax error in \"PRAGMA user_ve") != nullptr) {
84 return;
85 }
86 if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA || errType == SQLITE_NOTICE ||
87 err == SQLITE_WARNING_AUTOINDEX) {
88 if (verboseLog) {
89 LOG_INFO("Error(%{public}d) %{public}s ", err, SqliteUtils::SqlAnonymous(msg).c_str());
90 }
91 } else if (errType == SQLITE_WARNING) {
92 LOG_WARN("WARNING(%{public}d) %{public}s ", err, SqliteUtils::SqlAnonymous(msg).c_str());
93 } else {
94 LOG_ERROR("Error(%{public}d) errno is:%{public}d %{public}s.", err, errno,
95 SqliteUtils::SqlAnonymous(msg).c_str());
96 SqliteErrReport(err, msg);
97 }
98 }
99
SqliteErrReport(int err,const char * msg)100 void SqliteGlobalConfig::SqliteErrReport(int err, const char *msg)
101 {
102 auto lowErr = static_cast<uint32_t>(err) & 0xFF;
103 if (lowErr == SQLITE_NOMEM || lowErr == SQLITE_INTERRUPT || lowErr == SQLITE_FULL || lowErr == SQLITE_SCHEMA ||
104 lowErr == SQLITE_NOLFS || lowErr == SQLITE_AUTH || lowErr == SQLITE_BUSY || lowErr == SQLITE_LOCKED ||
105 lowErr == SQLITE_IOERR || lowErr == SQLITE_CANTOPEN) {
106 std::string log(msg == nullptr ? "" : SqliteUtils::Anonymous(msg).c_str());
107 log.append(",errcode=").append(std::to_string(err)).append(",errno=").append(std::to_string(errno));
108 RdbFaultHiViewReporter::ReportFault(RdbFaultEvent(FT_SQLITE, E_DFX_SQLITE_LOG, BUNDLE_NAME_COMMON, log));
109 }
110 }
111
GetMemoryDbPath()112 std::string SqliteGlobalConfig::GetMemoryDbPath()
113 {
114 return GlobalExpr::MEMORY_DB_PATH;
115 }
116
GetSharedMemoryDbPath(const std::string & name)117 std::string SqliteGlobalConfig::GetSharedMemoryDbPath(const std::string &name)
118 {
119 static const std::regex pattern(R"(^[\w\-\.]+$)");
120 if (!name.empty() && !std::regex_match(name, pattern)) {
121 return "";
122 }
123 return GlobalExpr::SHARED_MEMORY_DB_PATH_PREFIX + name + GlobalExpr::SHARED_MEMORY_DB_PATH_SUFFIX;
124 }
125
GetPageSize()126 int SqliteGlobalConfig::GetPageSize()
127 {
128 return GlobalExpr::DB_PAGE_SIZE;
129 }
130
GetSyncMode()131 std::string SqliteGlobalConfig::GetSyncMode()
132 {
133 return GlobalExpr::DEFAULE_SYNC_MODE;
134 }
135
GetJournalFileSize()136 int SqliteGlobalConfig::GetJournalFileSize()
137 {
138 return GlobalExpr::DB_JOURNAL_SIZE;
139 }
140
GetWalAutoCheckpoint()141 int SqliteGlobalConfig::GetWalAutoCheckpoint()
142 {
143 return GlobalExpr::WAL_AUTO_CHECKPOINT;
144 }
145
GetDefaultJournalMode()146 std::string SqliteGlobalConfig::GetDefaultJournalMode()
147 {
148 return GlobalExpr::JOURNAL_MODE_WAL;
149 }
150
GetDbPath(const RdbStoreConfig & config,std::string & dbPath)151 int SqliteGlobalConfig::GetDbPath(const RdbStoreConfig &config, std::string &dbPath)
152 {
153 if (config.GetStorageMode() == StorageMode::MODE_MEMORY) {
154 if (config.GetRoleType() != OWNER) {
155 LOG_ERROR("not support MODE_MEMORY, storeName:%{public}s, role:%{public}d",
156 SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetRoleType());
157 return E_NOT_SUPPORT;
158 }
159 dbPath = SqliteGlobalConfig::GetSharedMemoryDbPath(config.GetName());
160 return dbPath.empty() ? E_INVALID_FILE_PATH : E_OK;
161 }
162 std::string path;
163 if (config.GetRoleType() == OWNER) {
164 path = config.GetPath();
165 } else if (config.GetRoleType() == VISITOR || config.GetRoleType() == VISITOR_WRITE) {
166 path = config.GetVisitorDir();
167 } else {
168 LOG_ERROR("not support Role, storeName:%{public}s, role:%{public}d",
169 SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetRoleType());
170 return E_NOT_SUPPORT;
171 }
172 if (path.empty() || path.front() != '/') {
173 LOG_ERROR("invalid path, bundleName:%{public}s, role:%{public}d, %{public}s",
174 config.GetBundleName().c_str(), config.GetRoleType(), SqliteUtils::Anonymous(path).c_str());
175 return E_INVALID_FILE_PATH;
176 }
177 dbPath = std::move(path);
178 return E_OK;
179 }
180
GetLastCorruptionMsg()181 std::string SqliteGlobalConfig::GetLastCorruptionMsg()
182 {
183 std::lock_guard<std::mutex> lockGuard(g_corruptionMutex);
184 std::string msg = g_lastCorruptionMsg;
185 g_lastCorruptionMsg = "";
186 return msg;
187 }
188 } // namespace NativeRdb
189 } // namespace OHOS
190