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 #define LOG_TAG "RdConnection"
16 #include "rd_connection.h"
17 
18 #include "logger.h"
19 #include "rd_statement.h"
20 #include "rdb_errno.h"
21 #include "sqlite_global_config.h"
22 namespace OHOS {
23 namespace NativeRdb {
24 using namespace OHOS::Rdb;
25 __attribute__((used))
26 const int32_t RdConnection::regCreator_ = Connection::RegisterCreator(DB_VECTOR, RdConnection::Create);
27 __attribute__((used))
28 const int32_t RdConnection::regRepairer_ = Connection::RegisterRepairer(DB_VECTOR, RdConnection::Repair);
29 __attribute__((used))
30 const int32_t RdConnection::regDeleter_ = Connection::RegisterDeleter(DB_VECTOR, RdConnection::Delete);
31 
Create(const RdbStoreConfig & config,bool isWrite)32 std::pair<int32_t, std::shared_ptr<Connection>> RdConnection::Create(const RdbStoreConfig& config, bool isWrite)
33 {
34     std::pair<int32_t, std::shared_ptr<Connection>> result;
35     auto& [errCode, conn] = result;
36     for (size_t i = 0; i < ITERS_COUNT; i++) {
37         std::shared_ptr<RdConnection> connection = std::make_shared<RdConnection>(config, isWrite);
38         if (connection == nullptr) {
39             LOG_ERROR("SqliteConnection::Open new failed, connection is nullptr.");
40             return result;
41         }
42         errCode = connection->InnerOpen(config);
43         if (errCode == E_OK) {
44             conn = connection;
45             break;
46         }
47     }
48     return result;
49 }
50 
Repair(const RdbStoreConfig & config)51 int32_t RdConnection::Repair(const RdbStoreConfig& config)
52 {
53     std::string dbPath = "";
54     auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
55     if (errCode != E_OK) {
56         LOG_ERROR("Can not get db path.");
57         return errCode;
58     }
59     errCode = RdUtils::RdDbRepair(dbPath.c_str(), GRD_OPEN_CONFIG_STR);
60     if (errCode != E_OK) {
61         LOG_ERROR("Fail to repair db.");
62     }
63     return errCode;
64 }
65 
66 static constexpr const char *RD_POST_FIXES[] = {
67     "",
68     ".redo",
69     ".undo",
70     ".ctrl",
71     ".ctrl.dwr",
72     ".safe",
73     ".map",
74     ".corruptedflg",
75 };
76 
Delete(const RdbStoreConfig & config)77 int32_t RdConnection::Delete(const RdbStoreConfig &config)
78 {
79     auto path = config.GetPath();
80     for (auto postFix : RD_POST_FIXES) {
81         std::string shmFilePath = path + postFix;
82         if (access(shmFilePath.c_str(), F_OK) == 0) {
83             remove(shmFilePath.c_str());
84         }
85     }
86     return E_OK;
87 }
88 
RdConnection(const RdbStoreConfig & config,bool isWriter)89 RdConnection::RdConnection(const RdbStoreConfig &config, bool isWriter) : isWriter_(isWriter), config_(config)
90 {
91 }
92 
~RdConnection()93 RdConnection::~RdConnection()
94 {
95     if (dbHandle_ != nullptr) {
96         int errCode = RdUtils::RdDbClose(dbHandle_, 0);
97         if (errCode != E_OK) {
98             LOG_ERROR("~RdConnection ~RdConnection: could not close database err = %{public}d", errCode);
99         }
100         dbHandle_ = nullptr;
101     }
102 }
103 
InnerOpen(const RdbStoreConfig & config)104 int RdConnection::InnerOpen(const RdbStoreConfig &config)
105 {
106     std::string dbPath = "";
107     auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
108     if (errCode != E_OK) {
109         LOG_ERROR("Can not get db path.");
110         return errCode;
111     }
112     errCode = RdUtils::RdDbOpen(dbPath.c_str(), configStr_.c_str(), GRD_DB_OPEN_CREATE, &dbHandle_);
113     if (errCode != E_OK) {
114         LOG_ERROR("Can not open rd db.");
115         return errCode;
116     }
117     return errCode;
118 }
119 
OnInitialize()120 int32_t RdConnection::OnInitialize()
121 {
122     return E_NOT_SUPPORT;
123 }
124 
CreateStatement(const std::string & sql,Connection::SConn conn)125 std::pair<int32_t, RdConnection::Stmt> RdConnection::CreateStatement(const std::string& sql, Connection::SConn conn)
126 {
127     auto stmt = std::make_shared<RdStatement>();
128     stmt->conn_ = conn;
129     stmt->config_ = &config_;
130     stmt->setPragmas_["user_version"] = ([this](const int &value) -> int32_t {
131         return RdUtils::RdDbSetVersion(dbHandle_, GRD_CONFIG_USER_VERSION, value);
132     });
133     stmt->getPragmas_["user_version"] = ([this](int &version) -> int32_t {
134         return RdUtils::RdDbGetVersion(dbHandle_, GRD_CONFIG_USER_VERSION, version);
135     });
136     int32_t ret = stmt->Prepare(dbHandle_, sql);
137     if (ret != E_OK) {
138         return { ret, nullptr };
139     }
140     return { ret, stmt };
141 }
142 
GetDBType() const143 int32_t RdConnection::GetDBType() const
144 {
145     return DB_VECTOR;
146 }
147 
IsWriter() const148 bool RdConnection::IsWriter() const
149 {
150     return isWriter_;
151 }
152 
ReSetKey(const RdbStoreConfig & config)153 int32_t RdConnection::ReSetKey(const RdbStoreConfig& config)
154 {
155     return E_NOT_SUPPORT;
156 }
157 
TryCheckPoint(bool timeout)158 int32_t RdConnection::TryCheckPoint(bool timeout)
159 {
160     return E_NOT_SUPPORT;
161 }
162 
LimitWalSize()163 int32_t RdConnection::LimitWalSize()
164 {
165     return E_NOT_SUPPORT;
166 }
167 
ConfigLocale(const std::string & localeStr)168 int32_t RdConnection::ConfigLocale(const std::string& localeStr)
169 {
170     return E_NOT_SUPPORT;
171 }
172 
CleanDirtyData(const std::string & table,uint64_t cursor)173 int32_t RdConnection::CleanDirtyData(const std::string& table, uint64_t cursor)
174 {
175     return E_NOT_SUPPORT;
176 }
177 
SubscribeTableChanges(const Connection::Notifier & notifier)178 int32_t RdConnection::SubscribeTableChanges(const Connection::Notifier& notifier)
179 {
180     return E_NOT_SUPPORT;
181 }
182 
GetMaxVariable() const183 int32_t RdConnection::GetMaxVariable() const
184 {
185     return MAX_VARIABLE_NUM;
186 }
187 
GetJournalMode()188 int32_t RdConnection::GetJournalMode()
189 {
190     return E_NOT_SUPPORT;
191 }
192 
ClearCache()193 int32_t RdConnection::ClearCache()
194 {
195     return E_NOT_SUPPORT;
196 }
197 
Subscribe(const std::string & event,const std::shared_ptr<DistributedRdb::RdbStoreObserver> & observer)198 int32_t RdConnection::Subscribe(const std::string& event,
199     const std::shared_ptr<DistributedRdb::RdbStoreObserver>& observer)
200 {
201     return E_NOT_SUPPORT;
202 }
203 
Unsubscribe(const std::string & event,const std::shared_ptr<DistributedRdb::RdbStoreObserver> & observer)204 int32_t RdConnection::Unsubscribe(const std::string& event,
205     const std::shared_ptr<DistributedRdb::RdbStoreObserver>& observer)
206 {
207     return E_NOT_SUPPORT;
208 }
209 
Backup(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,bool isAsync,SlaveStatus & slaveStatus)210 int32_t RdConnection::Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
211     bool isAsync, SlaveStatus &slaveStatus)
212 {
213     uint32_t size = destEncryptKey.size();
214     if (size != 0) {
215         return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), const_cast<uint8_t*>(&destEncryptKey[0]), size);
216     }
217     return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), nullptr, 0);
218 }
219 
Restore(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,SlaveStatus & slaveStatus)220 int32_t RdConnection::Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
221     SlaveStatus &slaveStatus)
222 {
223     uint32_t size = destEncryptKey.size();
224     if (size != 0) {
225         return RdUtils::RdDbRestore(dbHandle_, databasePath.c_str(), const_cast<uint8_t*>(&destEncryptKey[0]), size);
226     }
227     return RdUtils::RdDbRestore(dbHandle_, databasePath.c_str(), nullptr, 0);
228 }
229 
GenerateExchangeStrategy(const SlaveStatus & status)230 ExchangeStrategy RdConnection::GenerateExchangeStrategy(const SlaveStatus &status)
231 {
232     return ExchangeStrategy::NOT_HANDLE;
233 }
234 } // namespace NativeRdb
235 } // namespace OHOS