ExtDS.cpp (Firebird-3.0.2.32703-0.tar.bz2) | : | ExtDS.cpp (Firebird-3.0.4.33054-0.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 63 | skipping to change at line 63 | |||
Provider* Manager::m_providers = NULL; | Provider* Manager::m_providers = NULL; | |||
volatile bool Manager::m_initialized = false; | volatile bool Manager::m_initialized = false; | |||
Manager::Manager(MemoryPool& pool) : | Manager::Manager(MemoryPool& pool) : | |||
PermanentStorage(pool) | PermanentStorage(pool) | |||
{ | { | |||
} | } | |||
Manager::~Manager() | Manager::~Manager() | |||
{ | { | |||
ThreadContextHolder tdbb; | ||||
while (m_providers) | while (m_providers) | |||
{ | { | |||
Provider* to_delete = m_providers; | Provider* to_delete = m_providers; | |||
m_providers = m_providers->m_next; | m_providers = m_providers->m_next; | |||
to_delete->clearConnections(tdbb); | ||||
delete to_delete; | delete to_delete; | |||
} | } | |||
} | } | |||
void Manager::addProvider(Provider* provider) | void Manager::addProvider(Provider* provider) | |||
{ | { | |||
for (const Provider* prv = m_providers; prv; prv = prv->m_next) | for (const Provider* prv = m_providers; prv; prv = prv->m_next) | |||
{ | { | |||
if (prv->m_name == provider->m_name) { | if (prv->m_name == provider->m_name) { | |||
return; | return; | |||
skipping to change at line 273 | skipping to change at line 276 | |||
} | } | |||
void Provider::cancelConnections() | void Provider::cancelConnections() | |||
{ | { | |||
MutexLockGuard guard(m_mutex, FB_FUNCTION); | MutexLockGuard guard(m_mutex, FB_FUNCTION); | |||
Connection** ptr = m_connections.begin(); | Connection** ptr = m_connections.begin(); | |||
Connection** end = m_connections.end(); | Connection** end = m_connections.end(); | |||
for (; ptr < end; ptr++) { | for (; ptr < end; ptr++) { | |||
(*ptr)->cancelExecution(); | (*ptr)->cancelExecution(true); | |||
} | } | |||
} | } | |||
// Connection | // Connection | |||
Connection::Connection(Provider& prov) : | Connection::Connection(Provider& prov) : | |||
PermanentStorage(prov.getPool()), | PermanentStorage(prov.getPool()), | |||
m_provider(prov), | m_provider(prov), | |||
m_dbName(getPool()), | m_dbName(getPool()), | |||
m_dpb(getPool(), ClumpletReader::dpbList, MAX_DPB_SIZE), | m_dpb(getPool(), ClumpletReader::dpbList, MAX_DPB_SIZE), | |||
skipping to change at line 364 | skipping to change at line 367 | |||
return m_dpb.simpleCompare(dpb); | return m_dpb.simpleCompare(dpb); | |||
} | } | |||
Transaction* Connection::createTransaction() | Transaction* Connection::createTransaction() | |||
{ | { | |||
Transaction* tran = doCreateTransaction(); | Transaction* tran = doCreateTransaction(); | |||
m_transactions.add(tran); | m_transactions.add(tran); | |||
return tran; | return tran; | |||
} | } | |||
void Connection::deleteTransaction(Transaction* tran) | void Connection::deleteTransaction(thread_db* tdbb, Transaction* tran) | |||
{ | { | |||
// Close all active statements in tran context avoiding commit of already | ||||
// deleted transaction | ||||
Statement** stmt_ptr = m_statements.begin(); | ||||
while (stmt_ptr < m_statements.end()) | ||||
{ | ||||
Statement* stmt = *stmt_ptr; | ||||
if (stmt->getTransaction() == tran) | ||||
{ | ||||
if (stmt->isActive()) | ||||
stmt->close(tdbb, true); | ||||
} | ||||
// close() above could destroy statement and remove it from m_sta | ||||
tements | ||||
if (stmt_ptr < m_statements.end() && *stmt_ptr == stmt) | ||||
stmt_ptr++; | ||||
} | ||||
FB_SIZE_T pos; | FB_SIZE_T pos; | |||
if (m_transactions.find(tran, pos)) | if (m_transactions.find(tran, pos)) | |||
{ | { | |||
m_transactions.remove(pos); | m_transactions.remove(pos); | |||
delete tran; | delete tran; | |||
} | } | |||
else { | else { | |||
fb_assert(false); | fb_assert(false); | |||
} | } | |||
if (!m_used_stmts && m_transactions.getCount() == 0 && !m_deleting) | if (!m_used_stmts && m_transactions.getCount() == 0 && !m_deleting) | |||
m_provider.releaseConnection(JRD_get_thread_data(), *this); | m_provider.releaseConnection(tdbb, *this); | |||
} | } | |||
Statement* Connection::createStatement(const string& sql) | Statement* Connection::createStatement(const string& sql) | |||
{ | { | |||
m_used_stmts++; | m_used_stmts++; | |||
for (Statement** stmt_ptr = &m_freeStatements; *stmt_ptr; stmt_ptr = &(*s tmt_ptr)->m_nextFree) | for (Statement** stmt_ptr = &m_freeStatements; *stmt_ptr; stmt_ptr = &(*s tmt_ptr)->m_nextFree) | |||
{ | { | |||
Statement* stmt = *stmt_ptr; | Statement* stmt = *stmt_ptr; | |||
if (stmt->getSql() == sql) | if (stmt->getSql() == sql) | |||
skipping to change at line 444 | skipping to change at line 463 | |||
if (!m_used_stmts && m_transactions.getCount() == 0 && !m_deleting) | if (!m_used_stmts && m_transactions.getCount() == 0 && !m_deleting) | |||
m_provider.releaseConnection(tdbb, *this); | m_provider.releaseConnection(tdbb, *this); | |||
} | } | |||
void Connection::clearTransactions(Jrd::thread_db* tdbb) | void Connection::clearTransactions(Jrd::thread_db* tdbb) | |||
{ | { | |||
while (m_transactions.getCount()) | while (m_transactions.getCount()) | |||
{ | { | |||
Transaction* tran = m_transactions[0]; | Transaction* tran = m_transactions[0]; | |||
tran->rollback(tdbb, false); | try | |||
{ | ||||
tran->rollback(tdbb, false); | ||||
} | ||||
catch (const Exception&) | ||||
{ | ||||
if (!m_deleting) | ||||
throw; | ||||
} | ||||
} | } | |||
} | } | |||
void Connection::clearStatements(thread_db* tdbb) | void Connection::clearStatements(thread_db* tdbb) | |||
{ | { | |||
Statement** stmt_ptr = m_statements.begin(); | Statement** stmt_ptr = m_statements.begin(); | |||
Statement** end = m_statements.end(); | while (stmt_ptr < m_statements.end()) | |||
for (; stmt_ptr < end; stmt_ptr++) | ||||
{ | { | |||
Statement* stmt = *stmt_ptr; | Statement* stmt = *stmt_ptr; | |||
if (stmt->isActive()) | if (stmt->isActive()) | |||
stmt->close(tdbb); | stmt->close(tdbb); | |||
Statement::deleteStatement(tdbb, stmt); | ||||
// close() above could destroy statement and remove it from m_sta | ||||
tements | ||||
if (stmt_ptr < m_statements.end() && *stmt_ptr == stmt) | ||||
{ | ||||
Statement::deleteStatement(tdbb, stmt); | ||||
stmt_ptr++; | ||||
} | ||||
} | } | |||
m_statements.clear(); | m_statements.clear(); | |||
m_freeStatements = NULL; | m_freeStatements = NULL; | |||
m_free_stmts = m_used_stmts = 0; | m_free_stmts = m_used_stmts = 0; | |||
} | } | |||
void Connection::detach(thread_db* tdbb) | void Connection::detach(thread_db* tdbb) | |||
{ | { | |||
skipping to change at line 654 | skipping to change at line 685 | |||
FbLocalStatus status; | FbLocalStatus status; | |||
doCommit(&status, tdbb, retain); | doCommit(&status, tdbb, retain); | |||
if (status->getState() & IStatus::STATE_ERRORS) { | if (status->getState() & IStatus::STATE_ERRORS) { | |||
m_connection.raise(&status, tdbb, "transaction commit"); | m_connection.raise(&status, tdbb, "transaction commit"); | |||
} | } | |||
if (!retain) | if (!retain) | |||
{ | { | |||
detachFromJrdTran(); | detachFromJrdTran(); | |||
m_connection.deleteTransaction(this); | m_connection.deleteTransaction(tdbb, this); | |||
} | } | |||
} | } | |||
void Transaction::rollback(thread_db* tdbb, bool retain) | void Transaction::rollback(thread_db* tdbb, bool retain) | |||
{ | { | |||
FbLocalStatus status; | FbLocalStatus status; | |||
doRollback(&status, tdbb, retain); | doRollback(&status, tdbb, retain); | |||
Connection& conn = m_connection; | Connection& conn = m_connection; | |||
if (!retain) | if (!retain) | |||
{ | { | |||
detachFromJrdTran(); | detachFromJrdTran(); | |||
m_connection.deleteTransaction(this); | m_connection.deleteTransaction(tdbb, this); | |||
} | } | |||
if (status->getState() & IStatus::STATE_ERRORS) { | if (status->getState() & IStatus::STATE_ERRORS) { | |||
conn.raise(&status, tdbb, "transaction rollback"); | conn.raise(&status, tdbb, "transaction rollback"); | |||
} | } | |||
} | } | |||
Transaction* Transaction::getTransaction(thread_db* tdbb, Connection* conn, TraS cope tra_scope) | Transaction* Transaction::getTransaction(thread_db* tdbb, Connection* conn, TraS cope tra_scope) | |||
{ | { | |||
jrd_tra* tran = tdbb->getTransaction(); | jrd_tra* tran = tdbb->getTransaction(); | |||
skipping to change at line 707 | skipping to change at line 738 | |||
ext_tran->start(tdbb, | ext_tran->start(tdbb, | |||
tra_scope, | tra_scope, | |||
traMode, | traMode, | |||
tran->tra_flags & TRA_readonly, | tran->tra_flags & TRA_readonly, | |||
tran->getLockWait() != 0, | tran->getLockWait() != 0, | |||
-tran->getLockWait() | -tran->getLockWait() | |||
); | ); | |||
} | } | |||
catch (const Exception&) | catch (const Exception&) | |||
{ | { | |||
conn->deleteTransaction(ext_tran); | conn->deleteTransaction(tdbb, ext_tran); | |||
throw; | throw; | |||
} | } | |||
} | } | |||
return ext_tran; | return ext_tran; | |||
} | } | |||
void Transaction::detachFromJrdTran() | void Transaction::detachFromJrdTran() | |||
{ | { | |||
if (m_scope != traCommon) | if (m_scope != traCommon) | |||
return; | return; | |||
fb_assert(m_jrdTran); | fb_assert(m_jrdTran || m_connection.isBroken()); | |||
if (!m_jrdTran) | if (!m_jrdTran) | |||
return; | return; | |||
Transaction** tran_ptr = &m_jrdTran->tra_ext_common; | Transaction** tran_ptr = &m_jrdTran->tra_ext_common; | |||
m_jrdTran = NULL; | ||||
for (; *tran_ptr; tran_ptr = &(*tran_ptr)->m_nextTran) | for (; *tran_ptr; tran_ptr = &(*tran_ptr)->m_nextTran) | |||
{ | { | |||
if (*tran_ptr == this) | if (*tran_ptr == this) | |||
{ | { | |||
*tran_ptr = this->m_nextTran; | *tran_ptr = this->m_nextTran; | |||
this->m_nextTran = NULL; | this->m_nextTran = NULL; | |||
return; | return; | |||
} | } | |||
} | } | |||
skipping to change at line 804 | skipping to change at line 836 | |||
{ | { | |||
} | } | |||
Statement::~Statement() | Statement::~Statement() | |||
{ | { | |||
clearNames(); | clearNames(); | |||
} | } | |||
void Statement::deleteStatement(Jrd::thread_db* tdbb, Statement* stmt) | void Statement::deleteStatement(Jrd::thread_db* tdbb, Statement* stmt) | |||
{ | { | |||
if (stmt->m_boundReq) | ||||
stmt->unBindFromRequest(); | ||||
stmt->deallocate(tdbb); | stmt->deallocate(tdbb); | |||
delete stmt; | delete stmt; | |||
} | } | |||
void Statement::prepare(thread_db* tdbb, Transaction* tran, const string& sql, b ool named) | void Statement::prepare(thread_db* tdbb, Transaction* tran, const string& sql, b ool named) | |||
{ | { | |||
fb_assert(!m_active); | fb_assert(!m_active); | |||
// already prepared the same non-empty statement | // already prepared the same non-empty statement | |||
if (isAllocated() && (m_sql == sql) && (m_sql != "") && | if (isAllocated() && (m_sql == sql) && (m_sql != "") && | |||
skipping to change at line 905 | skipping to change at line 939 | |||
FbLocalStatus status; | FbLocalStatus status; | |||
Arg::Gds(isc_sing_select_err).copyTo(&status); | Arg::Gds(isc_sing_select_err).copyTo(&status); | |||
raise(&status, tdbb, "isc_dsql_fetch"); | raise(&status, tdbb, "isc_dsql_fetch"); | |||
} | } | |||
return false; | return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
void Statement::close(thread_db* tdbb) | void Statement::close(thread_db* tdbb, bool invalidTran) | |||
{ | { | |||
// we must stuff exception if and only if this is the first time it occur s | // we must stuff exception if and only if this is the first time it occur s | |||
// once we stuff exception we must punt | // once we stuff exception we must punt | |||
const bool wasError = m_error; | const bool wasError = m_error; | |||
bool doPunt = false; | bool doPunt = false; | |||
if (isAllocated() && m_active) | if (isAllocated() && m_active) | |||
{ | { | |||
fb_assert(isAllocated() && m_stmt_selectable); | fb_assert(isAllocated() && m_stmt_selectable); | |||
skipping to change at line 934 | skipping to change at line 968 | |||
ex.stuffException(tdbb->tdbb_status_vector); | ex.stuffException(tdbb->tdbb_status_vector); | |||
} | } | |||
} | } | |||
m_active = false; | m_active = false; | |||
} | } | |||
if (m_boundReq) { | if (m_boundReq) { | |||
unBindFromRequest(); | unBindFromRequest(); | |||
} | } | |||
if (invalidTran) | ||||
m_transaction = NULL; | ||||
if (m_transaction && m_transaction->getScope() == traAutonomous) | if (m_transaction && m_transaction->getScope() == traAutonomous) | |||
{ | { | |||
bool commitFailed = false; | bool commitFailed = false; | |||
if (!m_error) | if (!m_error) | |||
{ | { | |||
try { | try { | |||
m_transaction->commit(tdbb, false); | m_transaction->commit(tdbb, false); | |||
} | } | |||
catch (const Exception& ex) | catch (const Exception& ex) | |||
{ | { | |||
skipping to change at line 1044 | skipping to change at line 1081 | |||
} | } | |||
} | } | |||
else { | else { | |||
ret = ttOther; | ret = ttOther; | |||
} | } | |||
break; | break; | |||
case '-': | case '-': | |||
if (p < end && *p == '-') | if (p < end && *p == '-') | |||
{ | { | |||
while (p < end) | while (++p < end) | |||
{ | { | |||
if (*p++ == '\n') | if (*p == '\r') | |||
{ | { | |||
p--; | p++; | |||
ret = ttComment; | if (p < end && *p == '\n') | |||
p++; | ||||
break; | break; | |||
} | } | |||
else if (*p == '\n') | ||||
break; | ||||
} | } | |||
ret = ttComment; | ||||
} | } | |||
else { | else { | |||
ret = ttOther; | ret = ttOther; | |||
} | } | |||
break; | break; | |||
default: | default: | |||
if (classes(c) & CHR_DIGIT) | if (classes(c) & CHR_DIGIT) | |||
{ | { | |||
while (p < end && (classes(*p) & CHR_DIGIT)) | while (p < end && (classes(*p) & CHR_DIGIT)) | |||
skipping to change at line 1573 | skipping to change at line 1614 | |||
m_ReqImpure = NULL; | m_ReqImpure = NULL; | |||
m_boundReq = NULL; | m_boundReq = NULL; | |||
m_prevInReq = m_nextInReq = NULL; | m_prevInReq = m_nextInReq = NULL; | |||
} | } | |||
// EngineCallbackGuard | // EngineCallbackGuard | |||
void EngineCallbackGuard::init(thread_db* tdbb, Connection& conn, const char* fr om) | void EngineCallbackGuard::init(thread_db* tdbb, Connection& conn, const char* fr om) | |||
{ | { | |||
m_tdbb = tdbb; | m_tdbb = tdbb; | |||
m_mutex = conn.isConnected() ? &conn.m_mutex : &conn.m_provider.m_mutex; | m_mutex = &conn.m_mutex; | |||
m_saveConnection = NULL; | m_saveConnection = NULL; | |||
if (m_tdbb) | if (m_tdbb) | |||
{ | { | |||
jrd_tra* transaction = m_tdbb->getTransaction(); | jrd_tra* transaction = m_tdbb->getTransaction(); | |||
if (transaction) | if (transaction) | |||
{ | { | |||
if (transaction->tra_callback_count >= MAX_CALLBACKS) | if (transaction->tra_callback_count >= MAX_CALLBACKS) | |||
ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded) ); | ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded) ); | |||
transaction->tra_callback_count++; | transaction->tra_callback_count++; | |||
} | } | |||
Jrd::Attachment* attachment = m_tdbb->getAttachment(); | Jrd::Attachment* attachment = m_tdbb->getAttachment(); | |||
if (attachment) | if (attachment) | |||
{ | { | |||
m_saveConnection = attachment->att_ext_connection; | m_saveConnection = attachment->att_ext_connection; | |||
attachment->att_ext_connection = &conn; | m_stable = attachment->getStable(); | |||
attachment->getStable()->getMutex()->leave(); | m_stable->getMutex()->leave(); | |||
MutexLockGuard guardAsync(*m_stable->getMutex(true, true) | ||||
, FB_FUNCTION); | ||||
MutexLockGuard guardMain(*m_stable->getMutex(), FB_FUNCTI | ||||
ON); | ||||
if (m_stable->getHandle() == attachment) | ||||
attachment->att_ext_connection = &conn; | ||||
} | } | |||
} | } | |||
if (m_mutex) { | if (m_mutex) { | |||
m_mutex->enter(from); | m_mutex->enter(from); | |||
} | } | |||
} | } | |||
EngineCallbackGuard::~EngineCallbackGuard() | EngineCallbackGuard::~EngineCallbackGuard() | |||
{ | { | |||
if (m_mutex) { | if (m_mutex) { | |||
m_mutex->leave(); | m_mutex->leave(); | |||
} | } | |||
if (m_tdbb) | if (m_tdbb) | |||
{ | { | |||
Jrd::Attachment* attachment = m_tdbb->getAttachment(); | Jrd::Attachment* attachment = m_tdbb->getAttachment(); | |||
if (attachment && m_stable.hasData()) | ||||
if (attachment) | ||||
{ | { | |||
attachment->getStable()->getMutex()->enter(FB_FUNCTION); | MutexLockGuard guardAsync(*m_stable->getMutex(true, true) | |||
attachment->att_ext_connection = m_saveConnection; | , FB_FUNCTION); | |||
m_stable->getMutex()->enter(FB_FUNCTION); | ||||
if (m_stable->getHandle() == attachment) | ||||
attachment->att_ext_connection = m_saveConnection | ||||
; | ||||
else | ||||
m_stable->getMutex()->leave(); | ||||
} | } | |||
jrd_tra* transaction = m_tdbb->getTransaction(); | jrd_tra* transaction = m_tdbb->getTransaction(); | |||
if (transaction) | if (transaction) | |||
transaction->tra_callback_count--; | transaction->tra_callback_count--; | |||
} | } | |||
} | } | |||
} // namespace EDS | } // namespace EDS | |||
End of changes. 26 change blocks. | ||||
24 lines changed or deleted | 80 lines changed or added |