File indexing completed on 2024-11-10 07:17:56
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003-2017 Jarosław Staniek <staniek@kde.org> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this program; see the file COPYING. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "KDbTransaction.h" 0021 #include "KDbConnection.h" 0022 #include "KDbTransactionData.h" 0023 #include "KDbTransactionGuard.h" 0024 #include "kdb_debug.h" 0025 0026 #ifdef KDB_TRANSACTIONS_DEBUG 0027 //helper for debugging 0028 int KDbTransaction_globalcount = 0; 0029 0030 KDB_EXPORT int KDbTransaction::globalCount() 0031 { 0032 return KDbTransaction_globalcount; 0033 } 0034 0035 int KDbTransactionData_globalcount = 0; 0036 0037 KDB_EXPORT int KDbTransactionData::globalCount() 0038 { 0039 return KDbTransactionData_globalcount; 0040 } 0041 #endif 0042 0043 class Q_DECL_HIDDEN KDbTransactionData::Private 0044 { 0045 public: 0046 Private(KDbConnection *c) : connection(c) 0047 { 0048 Q_ASSERT(connection); 0049 } 0050 KDbConnection *connection; 0051 bool active = true; 0052 int refcount = 1; 0053 }; 0054 0055 KDbTransactionData::KDbTransactionData(KDbConnection *connection) 0056 : d(new Private(connection)) 0057 { 0058 #ifdef KDB_TRANSACTIONS_DEBUG 0059 KDbTransaction_globalcount++; // because of refcount is initialized to 1 0060 KDbTransactionData_globalcount++; 0061 transactionsDebug() << "-- globalcount ==" << KDbTransactionData_globalcount; 0062 #endif 0063 } 0064 0065 KDbTransactionData::~KDbTransactionData() 0066 { 0067 #ifdef KDB_TRANSACTIONS_DEBUG 0068 KDbTransactionData_globalcount--; 0069 transactionsDebug() << "-- globalcount ==" << KDbTransactionData_globalcount; 0070 #endif 0071 delete d; 0072 } 0073 0074 void KDbTransactionData::ref() 0075 { 0076 d->refcount++; 0077 } 0078 0079 void KDbTransactionData::deref() 0080 { 0081 d->refcount--; 0082 } 0083 0084 int KDbTransactionData::refcount() const 0085 { 0086 return d->refcount; 0087 } 0088 0089 bool KDbTransactionData::isActive() const 0090 { 0091 return d->active; 0092 } 0093 0094 void KDbTransactionData::setActive(bool set) 0095 { 0096 d->active = set; 0097 } 0098 0099 KDbConnection *KDbTransactionData::connection() 0100 { 0101 return d->connection; 0102 } 0103 0104 const KDbConnection *KDbTransactionData::connection() const 0105 { 0106 return d->connection; 0107 } 0108 0109 //--------------------------------------------------- 0110 0111 KDbTransaction::KDbTransaction() 0112 : m_data(nullptr) 0113 { 0114 } 0115 0116 KDbTransaction::KDbTransaction(const KDbTransaction& trans) 0117 : m_data(trans.m_data) 0118 { 0119 if (m_data) { 0120 m_data->ref(); 0121 #ifdef KDB_TRANSACTIONS_DEBUG 0122 KDbTransaction_globalcount++; 0123 #endif 0124 } 0125 } 0126 0127 KDbTransaction::~KDbTransaction() 0128 { 0129 if (m_data) { 0130 m_data->deref(); 0131 #ifdef KDB_TRANSACTIONS_DEBUG 0132 KDbTransaction_globalcount--; 0133 #endif 0134 transactionsDebug() << "m_data->refcount==" << m_data->refcount(); 0135 if (m_data->refcount() == 0) 0136 delete m_data; 0137 } else { 0138 transactionsDebug() << "null"; 0139 } 0140 #ifdef KDB_TRANSACTIONS_DEBUG 0141 transactionsDebug() << "-- globalcount == " << KDbTransaction_globalcount; 0142 #endif 0143 } 0144 0145 KDbTransaction& KDbTransaction::operator=(const KDbTransaction & trans) 0146 { 0147 if (this != &trans) { 0148 if (m_data) { 0149 m_data->deref(); 0150 #ifdef KDB_TRANSACTIONS_DEBUG 0151 KDbTransaction_globalcount--; 0152 #endif 0153 transactionsDebug() << "m_data->refcount==" << m_data->refcount(); 0154 if (m_data->refcount() == 0) 0155 delete m_data; 0156 } 0157 m_data = trans.m_data; 0158 if (m_data) { 0159 m_data->ref(); 0160 #ifdef KDB_TRANSACTIONS_DEBUG 0161 KDbTransaction_globalcount++; 0162 #endif 0163 } 0164 } 0165 return *this; 0166 } 0167 0168 bool KDbTransaction::operator==(const KDbTransaction& other) const 0169 { 0170 return m_data == other.m_data; 0171 } 0172 0173 KDbConnection* KDbTransaction::connection() 0174 { 0175 return m_data ? m_data->connection() : nullptr; 0176 } 0177 0178 const KDbConnection* KDbTransaction::connection() const 0179 { 0180 return const_cast<KDbTransaction*>(this)->connection(); 0181 } 0182 0183 bool KDbTransaction::isActive() const 0184 { 0185 return m_data && m_data->isActive(); 0186 } 0187 0188 bool KDbTransaction::isNull() const 0189 { 0190 return m_data == nullptr; 0191 } 0192 0193 //--------------------------------------------------- 0194 0195 class Q_DECL_HIDDEN KDbTransactionGuard::Private 0196 { 0197 public: 0198 Private() {} 0199 KDbTransaction transaction; 0200 bool doNothing = false; 0201 }; 0202 0203 KDbTransactionGuard::KDbTransactionGuard(KDbConnection *connection) 0204 : KDbTransactionGuard() 0205 { 0206 if (connection) { 0207 d->transaction = connection->beginTransaction(); 0208 } 0209 } 0210 0211 KDbTransactionGuard::KDbTransactionGuard(const KDbTransaction &transaction) 0212 : KDbTransactionGuard() 0213 { 0214 d->transaction = transaction; 0215 } 0216 0217 KDbTransactionGuard::KDbTransactionGuard() 0218 : d(new Private) 0219 { 0220 } 0221 0222 KDbTransactionGuard::~KDbTransactionGuard() 0223 { 0224 if (!d->doNothing && d->transaction.isActive()) { 0225 const bool result = rollback(); 0226 #ifdef KDB_TRANSACTIONS_DEBUG 0227 transactionsDebug() << "~KDbTransactionGuard is rolling back transaction:" << result; 0228 #else 0229 Q_UNUSED(result) 0230 #endif 0231 } 0232 delete d; 0233 } 0234 0235 void KDbTransactionGuard::setTransaction(const KDbTransaction& transaction) 0236 { 0237 d->transaction = transaction; 0238 } 0239 0240 bool KDbTransactionGuard::commit(KDbTransaction::CommitOptions options) 0241 { 0242 if (d->transaction.connection()) { 0243 return d->transaction.connection()->commitTransaction(d->transaction, options); 0244 } 0245 return false; 0246 } 0247 0248 bool KDbTransactionGuard::rollback(KDbTransaction::CommitOptions options) 0249 { 0250 if (d->transaction.connection()) { 0251 return d->transaction.connection()->rollbackTransaction(d->transaction, options); 0252 } 0253 return false; 0254 } 0255 0256 void KDbTransactionGuard::doNothing() 0257 { 0258 d->doNothing = true; 0259 } 0260 0261 const KDbTransaction KDbTransactionGuard::transaction() const 0262 { 0263 return d->transaction; 0264 }