1 /*
2 * Copyright (c) 2025 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 "GdbTrans"
16 #include "transaction_impl.h"
17
18 #include <utility>
19
20 #include "gdb_errors.h"
21 #include "db_trace.h"
22 #include "logger.h"
23 #include "trans_db.h"
24
25 namespace OHOS::DistributedDataAip {
26
27 constexpr const char *START_GQL = "START TRANSACTION;";
28 constexpr const char *COMMIT_GQL = "COMMIT;";
29 constexpr const char *ROLLBACK_GQL = "ROLLBACK;";
30
31 __attribute__((used))
32 const int32_t TransactionImpl::regCreator_ = Transaction::RegisterCreator(TransactionImpl::Create);
33
TransactionImpl(std::shared_ptr<Connection> connection)34 TransactionImpl::TransactionImpl(std::shared_ptr<Connection> connection)
35 : connection_(std::move(connection))
36 {
37 }
38
~TransactionImpl()39 TransactionImpl::~TransactionImpl()
40 {
41 CloseInner();
42 }
43
Create(std::shared_ptr<Connection> conn)44 std::pair<int32_t, std::shared_ptr<Transaction>> TransactionImpl::Create(std::shared_ptr<Connection> conn)
45 {
46 if (conn == nullptr) {
47 LOG_ERROR("conn is nullptr");
48 return { E_ERROR, nullptr };
49 }
50 auto trans = std::make_shared<TransactionImpl>(std::move(conn));
51 if (trans == nullptr) {
52 LOG_ERROR("trans is nullptr");
53 return { E_ERROR, nullptr };
54 }
55 auto errorCode = trans->Start();
56 if (errorCode != E_OK) {
57 LOG_ERROR("transaction start failed, errorCode=%{public}d", errorCode);
58 return { errorCode, nullptr };
59 }
60 return { E_OK, trans };
61 }
62
Start()63 int32_t TransactionImpl::Start()
64 {
65 std::lock_guard lock(mutex_);
66 store_ = std::make_shared<TransDB>(connection_);
67 if (store_ == nullptr) {
68 LOG_ERROR("create trans db failed");
69 return E_ERROR;
70 }
71
72 if (connection_ == nullptr) {
73 LOG_ERROR("connection already closed");
74 return E_GRD_DB_INSTANCE_ABNORMAL;
75 }
76
77 auto [errorCode, statement] = connection_->CreateStatement(START_GQL, connection_);
78 if (errorCode != E_OK || statement == nullptr) {
79 LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
80 CloseInner();
81 return errorCode;
82 }
83 errorCode = statement->Step();
84 if (errorCode != E_OK) {
85 LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
86 CloseInner();
87 return errorCode;
88 }
89 return E_OK;
90 }
91
Commit()92 int32_t TransactionImpl::Commit()
93 {
94 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
95 std::lock_guard lock(mutex_);
96 if (connection_ == nullptr) {
97 LOG_ERROR("connection already closed");
98 return E_GRD_DB_INSTANCE_ABNORMAL;
99 }
100
101 auto [errorCode, statement] = connection_->CreateStatement(COMMIT_GQL, connection_);
102 if (errorCode != E_OK || statement == nullptr) {
103 LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
104 CloseInner();
105 return errorCode;
106 }
107
108 errorCode = statement->Step();
109 CloseInner();
110 if (errorCode != E_OK) {
111 LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
112 return errorCode;
113 }
114 return E_OK;
115 }
116
Rollback()117 int32_t TransactionImpl::Rollback()
118 {
119 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
120 std::lock_guard lock(mutex_);
121 if (connection_ == nullptr) {
122 LOG_ERROR("connection already closed");
123 return E_GRD_DB_INSTANCE_ABNORMAL;
124 }
125
126 auto [errorCode, statement] = connection_->CreateStatement(ROLLBACK_GQL, connection_);
127 if (errorCode != E_OK || statement == nullptr) {
128 LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
129 CloseInner();
130 return errorCode;
131 }
132
133 errorCode = statement->Step();
134 CloseInner();
135 if (errorCode != E_OK) {
136 LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
137 return errorCode;
138 }
139 return E_OK;
140 }
141
CloseInner()142 int32_t TransactionImpl::CloseInner()
143 {
144 std::lock_guard lock(mutex_);
145 store_ = nullptr;
146 connection_ = nullptr;
147 return E_OK;
148 }
149
Close()150 int32_t TransactionImpl::Close()
151 {
152 return Rollback();
153 }
154
GetStore()155 std::shared_ptr<DBStore> TransactionImpl::GetStore()
156 {
157 std::lock_guard lock(mutex_);
158 return store_;
159 }
160
Query(const std::string & gql)161 std::pair<int32_t, std::shared_ptr<Result>> TransactionImpl::Query(const std::string &gql)
162 {
163 auto store = GetStore();
164 if (store == nullptr) {
165 LOG_ERROR("transaction already close");
166 return { E_GRD_DB_INSTANCE_ABNORMAL, std::make_shared<FullResult>() };
167 }
168 return store->QueryGql(gql);
169 }
170
Execute(const std::string & gql)171 std::pair<int32_t, std::shared_ptr<Result>> TransactionImpl::Execute(const std::string &gql)
172 {
173 auto store = GetStore();
174 if (store == nullptr) {
175 LOG_ERROR("transaction already close");
176 return { E_GRD_DB_INSTANCE_ABNORMAL, std::make_shared<FullResult>() };
177 }
178 return store->ExecuteGql(gql);
179 }
180 } // namespace OHOS::DistributedDataAip
181