mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 06:43:04 +01:00
Fixed bug CORE-2183 : Error in ExtDS when server shutdown started with opened Execute Statement
This commit is contained in:
parent
7ce8528fc2
commit
62ca23fa58
@ -369,6 +369,18 @@ void Connection::releaseStatement(Jrd::thread_db *tdbb, Statement *stmt)
|
||||
m_provider.releaseConnection(JRD_get_thread_data(), *this);
|
||||
}
|
||||
|
||||
void Connection::clearTransactions(Jrd::thread_db *tdbb)
|
||||
{
|
||||
Transaction **tran_ptr = m_transactions.begin();
|
||||
Transaction **end = m_transactions.end();
|
||||
|
||||
while (m_transactions.getCount())
|
||||
{
|
||||
Transaction *tran = m_transactions[0];
|
||||
tran->rollback(tdbb, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::clearStatements(thread_db *tdbb)
|
||||
{
|
||||
Statement **stmt_ptr = m_statements.begin();
|
||||
@ -389,6 +401,19 @@ void Connection::clearStatements(thread_db *tdbb)
|
||||
m_free_stmts = m_used_stmts = 0;
|
||||
}
|
||||
|
||||
void Connection::detach(thread_db *tdbb)
|
||||
{
|
||||
const bool was_deleting = m_deleting;
|
||||
m_deleting = true;
|
||||
|
||||
clearStatements(tdbb);
|
||||
clearTransactions(tdbb);
|
||||
|
||||
m_deleting = was_deleting;
|
||||
|
||||
doDetach(tdbb);
|
||||
}
|
||||
|
||||
Transaction* Connection::findTransaction(thread_db *tdbb, TraScope traScope) const
|
||||
{
|
||||
jrd_tra *tran = tdbb->getTransaction();
|
||||
@ -494,11 +519,13 @@ void Transaction::start(thread_db *tdbb, TraScope traScope, TraModes traMode,
|
||||
{
|
||||
case traCommon :
|
||||
this->m_nextTran = tran->tra_ext_common;
|
||||
this->m_jrdTran = tran;
|
||||
tran->tra_ext_common = this;
|
||||
break;
|
||||
|
||||
case traTwoPhase :
|
||||
// join transaction
|
||||
// this->m_jrdTran = tran;
|
||||
// tran->tra_ext_two_phase = ext_tran;
|
||||
break;
|
||||
}
|
||||
@ -523,7 +550,9 @@ void Transaction::commit(thread_db *tdbb, bool retain)
|
||||
m_connection.raise(status, tdbb, "transaction commit");
|
||||
}
|
||||
|
||||
if (!retain) {
|
||||
if (!retain)
|
||||
{
|
||||
detachFromJrdTran();
|
||||
m_connection.deleteTransaction(this);
|
||||
}
|
||||
}
|
||||
@ -533,7 +562,9 @@ void Transaction::rollback(thread_db *tdbb, bool retain)
|
||||
ISC_STATUS_ARRAY status = {0};
|
||||
doRollback(status, tdbb, retain);
|
||||
|
||||
if (!retain) {
|
||||
if (!retain)
|
||||
{
|
||||
detachFromJrdTran();
|
||||
m_connection.deleteTransaction(this);
|
||||
}
|
||||
|
||||
@ -581,15 +612,35 @@ Transaction* Transaction::getTransaction(thread_db *tdbb, Connection *conn, TraS
|
||||
return ext_tran;
|
||||
}
|
||||
|
||||
void Transaction::detachFromJrdTran()
|
||||
{
|
||||
if (m_scope != traCommon)
|
||||
return;
|
||||
|
||||
fb_assert(m_jrdTran);
|
||||
if (!m_jrdTran)
|
||||
return;
|
||||
|
||||
Transaction **tran_ptr = &m_jrdTran->tra_ext_common;
|
||||
for (; *tran_ptr; tran_ptr = &(*tran_ptr)->m_nextTran)
|
||||
{
|
||||
if (*tran_ptr == this)
|
||||
{
|
||||
*tran_ptr = this->m_nextTran;
|
||||
this->m_nextTran = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
void Transaction::jrdTransactionEnd(thread_db *tdbb, jrd_tra* transaction,
|
||||
bool commit, bool retain, bool force)
|
||||
{
|
||||
Transaction** ext_tran = &transaction->tra_ext_common;
|
||||
Transaction* tran = *ext_tran;
|
||||
|
||||
while (tran)
|
||||
while (transaction->tra_ext_common)
|
||||
{
|
||||
Transaction* next = tran->m_nextTran;
|
||||
Transaction* tran = transaction->tra_ext_common;
|
||||
try
|
||||
{
|
||||
if (commit)
|
||||
@ -604,11 +655,7 @@ void Transaction::jrdTransactionEnd(thread_db *tdbb, jrd_tra* transaction,
|
||||
|
||||
// ignore rollback error
|
||||
fb_utils::init_status(tdbb->tdbb_status_vector);
|
||||
}
|
||||
|
||||
tran = next;
|
||||
if (!retain) {
|
||||
*ext_tran = tran;
|
||||
tran->detachFromJrdTran();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ public:
|
||||
|
||||
virtual void attach(Jrd::thread_db *tdbb, const Firebird::string &dbName,
|
||||
const Firebird::string &user, const Firebird::string &pwd) = 0;
|
||||
virtual void detach(Jrd::thread_db *tdbb) = 0;
|
||||
virtual void detach(Jrd::thread_db *tdbb);
|
||||
|
||||
int getSqlDialect() const { return m_sqlDialect; }
|
||||
|
||||
@ -198,8 +198,12 @@ protected:
|
||||
|
||||
virtual Transaction* doCreateTransaction() = 0;
|
||||
virtual Statement* doCreateStatement() = 0;
|
||||
|
||||
void clearTransactions(Jrd::thread_db *tdbb);
|
||||
void clearStatements(Jrd::thread_db *tdbb);
|
||||
|
||||
virtual void doDetach(Jrd::thread_db *tdbb) = 0;
|
||||
|
||||
// Protection against simultaneous ISC API calls for the same connection
|
||||
Firebird::Mutex m_mutex;
|
||||
|
||||
@ -253,6 +257,7 @@ public:
|
||||
protected:
|
||||
virtual void generateTPB(Jrd::thread_db *tdbb, Firebird::ClumpletWriter &tpb,
|
||||
TraModes traMode, bool readOnly, bool wait, int lockTimeout) const;
|
||||
void detachFromJrdTran();
|
||||
|
||||
virtual void doStart(ISC_STATUS* status, Jrd::thread_db *tdbb, Firebird::ClumpletWriter &tpb) = 0;
|
||||
virtual void doPrepare(ISC_STATUS* status, Jrd::thread_db *tdbb, int info_len, const char* info) = 0;
|
||||
@ -263,6 +268,7 @@ protected:
|
||||
Connection &m_connection;
|
||||
TraScope m_scope;
|
||||
Transaction *m_nextTran; // next common transaction
|
||||
Jrd::jrd_tra *m_jrdTran; // parent JRD transaction
|
||||
};
|
||||
|
||||
|
||||
|
@ -146,11 +146,10 @@ void InternalConnection::attach(thread_db *tdbb, const Firebird::string &dbName,
|
||||
SQL_DIALECT_V6 : SQL_DIALECT_V5;
|
||||
}
|
||||
|
||||
void InternalConnection::detach(thread_db *tdbb)
|
||||
void InternalConnection::doDetach(thread_db *tdbb)
|
||||
{
|
||||
clearStatements(tdbb);
|
||||
|
||||
fb_assert(m_attachment);
|
||||
|
||||
if (m_isCurrent)
|
||||
{
|
||||
m_attachment = 0;
|
||||
@ -170,9 +169,10 @@ void InternalConnection::detach(thread_db *tdbb)
|
||||
}
|
||||
|
||||
if (status[1]) {
|
||||
raise(status, tdbb, "dettach");
|
||||
raise(status, tdbb, "detach");
|
||||
}
|
||||
}
|
||||
|
||||
fb_assert(!m_attachment)
|
||||
}
|
||||
|
||||
|
@ -66,8 +66,6 @@ public:
|
||||
virtual void attach(Jrd::thread_db *tdbb, const Firebird::string &dbName,
|
||||
const Firebird::string &user, const Firebird::string &pwd);
|
||||
|
||||
virtual void detach(Jrd::thread_db *tdbb);
|
||||
|
||||
virtual bool isAvailable(Jrd::thread_db *tdbb, TraScope traScope) const;
|
||||
|
||||
virtual bool isConnected() const { return (m_attachment != 0); }
|
||||
@ -84,6 +82,7 @@ public:
|
||||
protected:
|
||||
virtual Transaction* doCreateTransaction();
|
||||
virtual Statement* doCreateStatement();
|
||||
virtual void doDetach(Jrd::thread_db *tdbb);
|
||||
|
||||
Jrd::Attachment* m_attachment;
|
||||
bool m_isCurrent;
|
||||
|
@ -154,10 +154,8 @@ void IscConnection::attach(thread_db *tdbb, const string &dbName, const string &
|
||||
}
|
||||
}
|
||||
|
||||
void IscConnection::detach(thread_db *tdbb)
|
||||
void IscConnection::doDetach(thread_db *tdbb)
|
||||
{
|
||||
clearStatements(tdbb);
|
||||
|
||||
ISC_STATUS_ARRAY status = {0};
|
||||
if (m_handle)
|
||||
{
|
||||
|
@ -508,7 +508,6 @@ public:
|
||||
|
||||
virtual void attach(Jrd::thread_db *tdbb, const Firebird::string &dbName,
|
||||
const Firebird::string &user, const Firebird::string &pwd);
|
||||
virtual void detach(Jrd::thread_db *tdbb);
|
||||
|
||||
virtual bool isAvailable(Jrd::thread_db *tdbb, TraScope traScope) const;
|
||||
|
||||
@ -519,6 +518,7 @@ public:
|
||||
protected:
|
||||
virtual Transaction* doCreateTransaction();
|
||||
virtual Statement* doCreateStatement();
|
||||
virtual void doDetach(Jrd::thread_db *tdbb);
|
||||
|
||||
IscProvider& m_iscProvider;
|
||||
FB_API_HANDLE m_handle;
|
||||
|
@ -5580,9 +5580,13 @@ static void purge_attachment(thread_db* tdbb,
|
||||
}
|
||||
}
|
||||
|
||||
const bool wasShuttingDown = engineShuttingDown;
|
||||
try
|
||||
{
|
||||
// allow to free resources used by dynamic statements
|
||||
engineShuttingDown = false;
|
||||
EDS::Manager::jrdAttachmentEnd(tdbb, attachment);
|
||||
engineShuttingDown = wasShuttingDown;
|
||||
|
||||
const ULONG att_flags = attachment->att_flags;
|
||||
attachment->att_flags |= ATT_shutdown;
|
||||
@ -5601,6 +5605,7 @@ static void purge_attachment(thread_db* tdbb,
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
engineShuttingDown = wasShuttingDown;
|
||||
attachment->att_flags |= (ATT_shutdown | ATT_purge_error);
|
||||
throw;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user