8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 02:03:03 +01:00

Link blobs of autonomous transaction with the outer transaction - to fix invalid BLOB ID errors.

This commit is contained in:
asfernandes 2008-04-05 19:28:52 +00:00
parent dd994c20bc
commit 21da64cca7
5 changed files with 86 additions and 60 deletions

View File

@ -1106,8 +1106,8 @@ void BLB_move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, jrd_nod* field)
materialized_blob = true; materialized_blob = true;
} }
else { else {
if (transaction->tra_blobs.locate(source->bid_temp_id())) { if (transaction->tra_blobs->locate(source->bid_temp_id())) {
blobIndex = &transaction->tra_blobs.current(); blobIndex = &transaction->tra_blobs->current();
if (blobIndex->bli_materialized) if (blobIndex->bli_materialized)
{ {
if (blobIndex->bli_request) { if (blobIndex->bli_request) {
@ -1143,11 +1143,11 @@ void BLB_move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, jrd_nod* field)
blb* newBlob = copy_blob(tdbb, source, destination, blb* newBlob = copy_blob(tdbb, source, destination,
bpb.getCount(), bpb.begin(), relPages->rel_pg_space_id); bpb.getCount(), bpb.begin(), relPages->rel_pg_space_id);
transaction->tra_blobs.locate(newBlob->blb_temp_id); transaction->tra_blobs->locate(newBlob->blb_temp_id);
BlobIndex* newBlobIndex = &transaction->tra_blobs.current(); BlobIndex* newBlobIndex = &transaction->tra_blobs->current();
transaction->tra_blobs.locate(oldTempID); transaction->tra_blobs->locate(oldTempID);
blobIndex = &transaction->tra_blobs.current(); blobIndex = &transaction->tra_blobs->current();
newBlobIndex->bli_blob_object = blob; newBlobIndex->bli_blob_object = blob;
blobIndex->bli_blob_object = newBlob; blobIndex->bli_blob_object = newBlob;
@ -1158,8 +1158,8 @@ void BLB_move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, jrd_nod* field)
BLB_cancel(tdbb, blob); BLB_cancel(tdbb, blob);
blob = newBlob; blob = newBlob;
transaction->tra_blobs.locate(blob->blb_temp_id); transaction->tra_blobs->locate(blob->blb_temp_id);
blobIndex = &transaction->tra_blobs.current(); blobIndex = &transaction->tra_blobs->current();
} }
} }
} }
@ -1181,12 +1181,12 @@ void BLB_move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, jrd_nod* field)
if (materialized_blob) { if (materialized_blob) {
// hvlad: we have possible thread switch in DPM_store_blob above and somebody // hvlad: we have possible thread switch in DPM_store_blob above and somebody
// can modify transaction->tra_blobs therefore we must update our blobIndex // can modify transaction->tra_blobs therefore we must update our blobIndex
if (!transaction->tra_blobs.locate(blob->blb_temp_id)) { if (!transaction->tra_blobs->locate(blob->blb_temp_id)) {
// If we didn't find materialized blob in transaction blob index it // If we didn't find materialized blob in transaction blob index it
// means memory structures are inconsistent and crash is appropriate // means memory structures are inconsistent and crash is appropriate
BUGCHECK(305); // msg 305 Blobs accounting is inconsistent BUGCHECK(305); // msg 305 Blobs accounting is inconsistent
} }
blobIndex = &transaction->tra_blobs.current(); blobIndex = &transaction->tra_blobs->current();
blobIndex->bli_materialized = true; blobIndex->bli_materialized = true;
blobIndex->bli_blob_id = *destination; blobIndex->bli_blob_id = *destination;
@ -1287,8 +1287,8 @@ blb* BLB_open2(thread_db* tdbb,
/* Search the index of transaction blobs for a match */ /* Search the index of transaction blobs for a match */
const blb* new_blob = NULL; const blb* new_blob = NULL;
if (transaction->tra_blobs.locate(blob_id->bid_temp_id())) { if (transaction->tra_blobs->locate(blob_id->bid_temp_id())) {
current = &transaction->tra_blobs.current(); current = &transaction->tra_blobs->current();
if (!current->bli_materialized) if (!current->bli_materialized)
new_blob = current->bli_blob_object; new_blob = current->bli_blob_object;
else else
@ -1918,7 +1918,7 @@ static blb* allocate_blob(thread_db* tdbb, jrd_tra* transaction)
// Do not generate null blob ID // Do not generate null blob ID
if (!transaction->tra_next_blob_id) if (!transaction->tra_next_blob_id)
transaction->tra_next_blob_id++; transaction->tra_next_blob_id++;
} while (!transaction->tra_blobs.add(BlobIndex(transaction->tra_next_blob_id, blob))); } while (!transaction->tra_blobs->add(BlobIndex(transaction->tra_next_blob_id, blob)));
blob->blb_temp_id = transaction->tra_next_blob_id; blob->blb_temp_id = transaction->tra_next_blob_id;
return blob; return blob;
@ -2503,8 +2503,8 @@ static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc
// variables. - 2007-03-24 // variables. - 2007-03-24
jrd_tra* transaction = tdbb->getRequest()->req_transaction; jrd_tra* transaction = tdbb->getRequest()->req_transaction;
if (transaction->tra_blobs.locate(blob_temp_id)) { if (transaction->tra_blobs->locate(blob_temp_id)) {
BlobIndex* current = &transaction->tra_blobs.current(); BlobIndex* current = &transaction->tra_blobs->current();
if (current->bli_materialized) { if (current->bli_materialized) {
// Delete BLOB from request owned blob list // Delete BLOB from request owned blob list
jrd_req* blob_request = current->bli_request; jrd_req* blob_request = current->bli_request;
@ -2520,7 +2520,7 @@ static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc
} }
// Free materialized blob handle // Free materialized blob handle
transaction->tra_blobs.fastRemove(); transaction->tra_blobs->fastRemove();
} }
else { else {
// But even in bad case when we cannot free blob immediately // But even in bad case when we cannot free blob immediately
@ -2608,9 +2608,9 @@ static void release_blob(blb* blob, const bool purge_flag)
if (purge_flag) if (purge_flag)
{ {
if (transaction->tra_blobs.locate(blob->blb_temp_id)) if (transaction->tra_blobs->locate(blob->blb_temp_id))
{ {
jrd_req* blob_request = transaction->tra_blobs.current().bli_request; jrd_req* blob_request = transaction->tra_blobs->current().bli_request;
if (blob_request) if (blob_request)
{ {
@ -2624,7 +2624,7 @@ static void release_blob(blb* blob, const bool purge_flag)
} }
} }
transaction->tra_blobs.fastRemove(); transaction->tra_blobs->fastRemove();
} }
else else
{ {

View File

@ -779,9 +779,9 @@ void EXE_receive(thread_db* tdbb,
const bid* id = (bid*) const bid* id = (bid*)
((UCHAR*)request + message->nod_impure + (ULONG)(IPTR)desc->dsc_address); ((UCHAR*)request + message->nod_impure + (ULONG)(IPTR)desc->dsc_address);
if (transaction->tra_blobs.locate(id->bid_temp_id())) if (transaction->tra_blobs->locate(id->bid_temp_id()))
{ {
BlobIndex* current = &transaction->tra_blobs.current(); BlobIndex* current = &transaction->tra_blobs->current();
if (current->bli_request && if (current->bli_request &&
current->bli_request->req_blobs.locate(id->bid_temp_id())) current->bli_request->req_blobs.locate(id->bid_temp_id()))
@ -2712,7 +2712,8 @@ static jrd_nod* looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node)
request->req_auto_trans.push(request->req_transaction); request->req_auto_trans.push(request->req_transaction);
request->req_transaction = TRA_start(tdbb, request->req_transaction = TRA_start(tdbb,
request->req_transaction->tra_flags, request->req_transaction->tra_flags,
request->req_transaction->tra_lock_timeout); request->req_transaction->tra_lock_timeout,
request->req_transaction);
tdbb->setTransaction(request->req_transaction); tdbb->setTransaction(request->req_transaction);
if (!(tdbb->getAttachment()->att_flags & ATT_no_db_triggers)) if (!(tdbb->getAttachment()->att_flags & ATT_no_db_triggers))
@ -3216,12 +3217,13 @@ static void release_blobs(thread_db* tdbb, jrd_req* request)
/* Release blobs bound to this request */ /* Release blobs bound to this request */
if (request->req_blobs.getFirst()) if (request->req_blobs.getFirst())
{
while (true) while (true)
{ {
const ULONG blob_temp_id = request->req_blobs.current(); const ULONG blob_temp_id = request->req_blobs.current();
if (transaction->tra_blobs.locate(blob_temp_id)) if (transaction->tra_blobs->locate(blob_temp_id))
{ {
BlobIndex *current = &transaction->tra_blobs.current(); BlobIndex *current = &transaction->tra_blobs->current();
if (current->bli_materialized) if (current->bli_materialized)
{ {
request->req_blobs.fastRemove(); request->req_blobs.fastRemove();
@ -3248,6 +3250,7 @@ static void release_blobs(thread_db* tdbb, jrd_req* request)
if (!request->req_blobs.getNext()) if (!request->req_blobs.getNext())
break; break;
} }
}
request->req_blobs.clear(); request->req_blobs.clear();

View File

@ -737,7 +737,7 @@ void TRA_init(thread_db* tdbb)
Database* dbb = tdbb->getDatabase(); Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb); CHECK_DBB(dbb);
jrd_tra* trans = FB_NEW_RPT(*dbb->dbb_permanent, 0) jrd_tra(dbb->dbb_permanent); jrd_tra* trans = FB_NEW_RPT(*dbb->dbb_permanent, 0) jrd_tra(dbb->dbb_permanent, NULL);
dbb->dbb_sys_trans = trans; dbb->dbb_sys_trans = trans;
trans->tra_flags |= TRA_system | TRA_ignore_limbo; trans->tra_flags |= TRA_system | TRA_ignore_limbo;
} }
@ -1008,7 +1008,7 @@ jrd_tra* TRA_reconnect(thread_db* tdbb, const UCHAR* id, USHORT length)
ERR_post(isc_read_only_database, 0); ERR_post(isc_read_only_database, 0);
Jrd::ContextPoolHolder context(tdbb, dbb->createPool()); Jrd::ContextPoolHolder context(tdbb, dbb->createPool());
jrd_tra* trans = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool()); jrd_tra* trans = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool(), NULL);
trans->tra_number = gds__vax_integer(id, length); trans->tra_number = gds__vax_integer(id, length);
trans->tra_flags |= TRA_prepared | TRA_reconnected | TRA_write; trans->tra_flags |= TRA_prepared | TRA_reconnected | TRA_write;
@ -1070,24 +1070,29 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction)
Database* dbb = tdbb->getDatabase(); Database* dbb = tdbb->getDatabase();
Attachment* attachment = tdbb->getAttachment(); Attachment* attachment = tdbb->getAttachment();
if (transaction->tra_blobs.getFirst()) if (!transaction->tra_outer)
{
if (transaction->tra_blobs->getFirst())
{
while (true) while (true)
{ {
BlobIndex *current = &transaction->tra_blobs.current(); BlobIndex *current = &transaction->tra_blobs->current();
if (current->bli_materialized) { if (current->bli_materialized) {
if (!transaction->tra_blobs.getNext()) if (!transaction->tra_blobs->getNext())
break; break;
} }
else { else {
ULONG temp_id = current->bli_temp_id; ULONG temp_id = current->bli_temp_id;
BLB_cancel(tdbb, current->bli_blob_object); BLB_cancel(tdbb, current->bli_blob_object);
if (!transaction->tra_blobs.locate(Firebird::locGreat, temp_id)) if (!transaction->tra_blobs->locate(Firebird::locGreat, temp_id))
break; break;
} }
} }
}
while (transaction->tra_arrays) while (transaction->tra_arrays)
BLB_release_array(transaction->tra_arrays); BLB_release_array(transaction->tra_arrays);
}
if (transaction->tra_pool) { if (transaction->tra_pool) {
// Iterate the doubly linked list of requests for transaction and null out the transaction references // Iterate the doubly linked list of requests for transaction and null out the transaction references
@ -1180,8 +1185,9 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction)
// Release the transaction pool // Release the transaction pool
MemoryPool* tra_pool = transaction->tra_pool; MemoryPool* tra_pool = transaction->tra_outer ? NULL : transaction->tra_pool;
delete transaction; delete transaction;
if (tra_pool)
dbb->deletePool(tra_pool); dbb->deletePool(tra_pool);
} }
@ -1519,7 +1525,7 @@ int TRA_snapshot_state(thread_db* tdbb, const jrd_tra* trans, SLONG number)
} }
jrd_tra* TRA_start(thread_db* tdbb, ULONG flags, SSHORT lock_timeout) jrd_tra* TRA_start(thread_db* tdbb, ULONG flags, SSHORT lock_timeout, Jrd::jrd_tra* outer)
{ {
/************************************** /**************************************
* *
@ -1545,8 +1551,8 @@ jrd_tra* TRA_start(thread_db* tdbb, ULONG flags, SSHORT lock_timeout)
// To handle the problems of relation locks, allocate a temporary // To handle the problems of relation locks, allocate a temporary
// transaction block first, seize relation locks, then go ahead and // transaction block first, seize relation locks, then go ahead and
// make up the real transaction block. // make up the real transaction block.
Jrd::ContextPoolHolder context(tdbb, dbb->createPool()); Jrd::ContextPoolHolder context(tdbb, (outer ? outer->tra_pool : dbb->createPool()));
jrd_tra* temp = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool()); jrd_tra* temp = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool(), outer);
temp->tra_flags = flags; temp->tra_flags = flags;
temp->tra_lock_timeout = lock_timeout; temp->tra_lock_timeout = lock_timeout;
@ -1555,7 +1561,7 @@ jrd_tra* TRA_start(thread_db* tdbb, ULONG flags, SSHORT lock_timeout)
} }
jrd_tra* TRA_start(thread_db* tdbb, int tpb_length, const UCHAR* tpb) jrd_tra* TRA_start(thread_db* tdbb, int tpb_length, const UCHAR* tpb, Jrd::jrd_tra* outer)
{ {
/************************************** /**************************************
* *
@ -1581,8 +1587,8 @@ jrd_tra* TRA_start(thread_db* tdbb, int tpb_length, const UCHAR* tpb)
// To handle the problems of relation locks, allocate a temporary // To handle the problems of relation locks, allocate a temporary
// transaction block first, seize relation locks, then go ahead and // transaction block first, seize relation locks, then go ahead and
// make up the real transaction block. // make up the real transaction block.
Jrd::ContextPoolHolder context(tdbb, dbb->createPool()); Jrd::ContextPoolHolder context(tdbb, (outer ? outer->tra_pool : dbb->createPool()));
jrd_tra* temp = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool()); jrd_tra* temp = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool(), outer);
transaction_options(tdbb, temp, tpb, tpb_length); transaction_options(tdbb, temp, tpb, tpb_length);
@ -3194,9 +3200,11 @@ static jrd_tra* transaction_start(thread_db* tdbb, jrd_tra* temp)
jrd_tra* trans; jrd_tra* trans;
if (temp->tra_flags & TRA_read_committed) if (temp->tra_flags & TRA_read_committed)
trans = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool()); trans = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool(), temp->tra_outer);
else { else
trans = FB_NEW_RPT(*tdbb->getDefaultPool(), (number - base + TRA_MASK) / 4) jrd_tra(tdbb->getDefaultPool()); {
trans = FB_NEW_RPT(*tdbb->getDefaultPool(), (number - base + TRA_MASK) / 4)
jrd_tra(tdbb->getDefaultPool(), temp->tra_outer);
} }
fb_assert(trans->tra_pool == temp->tra_pool); fb_assert(trans->tra_pool == temp->tra_pool);

View File

@ -94,18 +94,28 @@ public:
tra_wait tra_wait
}; };
explicit jrd_tra(MemoryPool* p) : explicit jrd_tra(MemoryPool* p, jrd_tra* outer) :
tra_pool(p), tra_pool(p),
tra_blobs(p), tra_blobs_tree(p),
tra_blobs(&tra_blobs_tree),
tra_resources(*p), tra_resources(*p),
tra_context_vars(*p), tra_context_vars(*p),
tra_lock_timeout(DEFAULT_LOCK_TIMEOUT), tra_lock_timeout(DEFAULT_LOCK_TIMEOUT),
tra_timestamp(Firebird::TimeStamp::getCurrentTimeStamp()), tra_timestamp(Firebird::TimeStamp::getCurrentTimeStamp()),
tra_open_cursors(*p) tra_open_cursors(*p),
{} tra_outer(outer)
{
if (outer)
{
fb_assert(p == outer->tra_pool);
tra_arrays = outer->tra_arrays;
tra_blobs = outer->tra_blobs;
}
}
~jrd_tra() ~jrd_tra()
{ {
if (!tra_outer)
delete tra_temp_space; delete tra_temp_space;
} }
@ -118,7 +128,8 @@ public:
jrd_tra* tra_next; /* next transaction in database */ jrd_tra* tra_next; /* next transaction in database */
jrd_tra* tra_sibling; /* next transaction in group */ jrd_tra* tra_sibling; /* next transaction in group */
MemoryPool* tra_pool; /* pool for transaction */ MemoryPool* tra_pool; /* pool for transaction */
BlobIndexTree tra_blobs; /* list of active blobs */ BlobIndexTree tra_blobs_tree; // list of active blobs
BlobIndexTree* tra_blobs; // pointer to actual list of active blobs
ArrayField* tra_arrays; /* Linked list of active arrays */ ArrayField* tra_arrays; /* Linked list of active arrays */
Lock* tra_lock; /* lock for transaction */ Lock* tra_lock; /* lock for transaction */
Lock* tra_cancel_lock; /* lock to cancel the active request */ Lock* tra_cancel_lock; /* lock to cancel the active request */
@ -141,6 +152,7 @@ public:
DatabaseSnapshot* tra_db_snapshot; // Database state snapshot (for monitoring purposes) DatabaseSnapshot* tra_db_snapshot; // Database state snapshot (for monitoring purposes)
RuntimeStatistics tra_stats; RuntimeStatistics tra_stats;
Firebird::Array<dsql_req*> tra_open_cursors; Firebird::Array<dsql_req*> tra_open_cursors;
jrd_tra* tra_outer; // outer transaction of an autonomous transaction
private: private:
TempSpace* tra_temp_space; // temp space storage TempSpace* tra_temp_space; // temp space storage
@ -156,6 +168,9 @@ public:
TempSpace* getTempSpace() TempSpace* getTempSpace()
{ {
if (tra_outer)
return tra_outer->getTempSpace();
if (!tra_temp_space) if (!tra_temp_space)
tra_temp_space = FB_NEW(*tra_pool) TempSpace(*tra_pool, TRA_TEMP_SPACE); tra_temp_space = FB_NEW(*tra_pool) TempSpace(*tra_pool, TRA_TEMP_SPACE);

View File

@ -55,8 +55,8 @@ void TRA_rollback(Jrd::thread_db*, Jrd::jrd_tra*, const bool, const bool);
void TRA_set_state(Jrd::thread_db*, Jrd::jrd_tra*, SLONG, SSHORT); void TRA_set_state(Jrd::thread_db*, Jrd::jrd_tra*, SLONG, SSHORT);
void TRA_shutdown_attachment(Jrd::thread_db*, Jrd::Attachment*); void TRA_shutdown_attachment(Jrd::thread_db*, Jrd::Attachment*);
int TRA_snapshot_state(Jrd::thread_db*, const Jrd::jrd_tra*, SLONG); int TRA_snapshot_state(Jrd::thread_db*, const Jrd::jrd_tra*, SLONG);
Jrd::jrd_tra* TRA_start(Jrd::thread_db*, ULONG flags, SSHORT lock_timeout); Jrd::jrd_tra* TRA_start(Jrd::thread_db*, ULONG flags, SSHORT lock_timeout, Jrd::jrd_tra* outer = NULL);
Jrd::jrd_tra* TRA_start(Jrd::thread_db*, int, const UCHAR*); Jrd::jrd_tra* TRA_start(Jrd::thread_db*, int, const UCHAR*, Jrd::jrd_tra* outer = NULL);
int TRA_state(const UCHAR*, ULONG, ULONG); int TRA_state(const UCHAR*, ULONG, ULONG);
bool TRA_sweep(Jrd::thread_db*, Jrd::jrd_tra*); bool TRA_sweep(Jrd::thread_db*, Jrd::jrd_tra*);
int TRA_wait(Jrd::thread_db*, Jrd::jrd_tra*, SLONG, Jrd::jrd_tra::wait_t); int TRA_wait(Jrd::thread_db*, Jrd::jrd_tra*, SLONG, Jrd::jrd_tra::wait_t);