From 21da64cca7ef3fe7784769dda08ac7006617af85 Mon Sep 17 00:00:00 2001 From: asfernandes Date: Sat, 5 Apr 2008 19:28:52 +0000 Subject: [PATCH] Link blobs of autonomous transaction with the outer transaction - to fix invalid BLOB ID errors. --- src/jrd/blb.cpp | 38 +++++++++++++-------------- src/jrd/exe.cpp | 15 ++++++----- src/jrd/tra.cpp | 62 +++++++++++++++++++++++++-------------------- src/jrd/tra.h | 27 +++++++++++++++----- src/jrd/tra_proto.h | 4 +-- 5 files changed, 86 insertions(+), 60 deletions(-) diff --git a/src/jrd/blb.cpp b/src/jrd/blb.cpp index 4c4ed980a9..b038bc3d82 100644 --- a/src/jrd/blb.cpp +++ b/src/jrd/blb.cpp @@ -1106,8 +1106,8 @@ void BLB_move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, jrd_nod* field) materialized_blob = true; } else { - if (transaction->tra_blobs.locate(source->bid_temp_id())) { - blobIndex = &transaction->tra_blobs.current(); + if (transaction->tra_blobs->locate(source->bid_temp_id())) { + blobIndex = &transaction->tra_blobs->current(); if (blobIndex->bli_materialized) { 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, bpb.getCount(), bpb.begin(), relPages->rel_pg_space_id); - transaction->tra_blobs.locate(newBlob->blb_temp_id); - BlobIndex* newBlobIndex = &transaction->tra_blobs.current(); + transaction->tra_blobs->locate(newBlob->blb_temp_id); + BlobIndex* newBlobIndex = &transaction->tra_blobs->current(); - transaction->tra_blobs.locate(oldTempID); - blobIndex = &transaction->tra_blobs.current(); + transaction->tra_blobs->locate(oldTempID); + blobIndex = &transaction->tra_blobs->current(); newBlobIndex->bli_blob_object = blob; 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); blob = newBlob; - transaction->tra_blobs.locate(blob->blb_temp_id); - blobIndex = &transaction->tra_blobs.current(); + transaction->tra_blobs->locate(blob->blb_temp_id); + 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) { // hvlad: we have possible thread switch in DPM_store_blob above and somebody // 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 // means memory structures are inconsistent and crash is appropriate BUGCHECK(305); // msg 305 Blobs accounting is inconsistent } - blobIndex = &transaction->tra_blobs.current(); + blobIndex = &transaction->tra_blobs->current(); blobIndex->bli_materialized = true; blobIndex->bli_blob_id = *destination; @@ -1287,8 +1287,8 @@ blb* BLB_open2(thread_db* tdbb, /* Search the index of transaction blobs for a match */ const blb* new_blob = NULL; - if (transaction->tra_blobs.locate(blob_id->bid_temp_id())) { - current = &transaction->tra_blobs.current(); + if (transaction->tra_blobs->locate(blob_id->bid_temp_id())) { + current = &transaction->tra_blobs->current(); if (!current->bli_materialized) new_blob = current->bli_blob_object; else @@ -1918,7 +1918,7 @@ static blb* allocate_blob(thread_db* tdbb, jrd_tra* transaction) // Do not generate null blob ID if (!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; 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 jrd_tra* transaction = tdbb->getRequest()->req_transaction; - if (transaction->tra_blobs.locate(blob_temp_id)) { - BlobIndex* current = &transaction->tra_blobs.current(); + if (transaction->tra_blobs->locate(blob_temp_id)) { + BlobIndex* current = &transaction->tra_blobs->current(); if (current->bli_materialized) { // Delete BLOB from request owned blob list 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 - transaction->tra_blobs.fastRemove(); + transaction->tra_blobs->fastRemove(); } else { // 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 (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) { @@ -2624,7 +2624,7 @@ static void release_blob(blb* blob, const bool purge_flag) } } - transaction->tra_blobs.fastRemove(); + transaction->tra_blobs->fastRemove(); } else { diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp index fd3235255d..1130c8faa9 100644 --- a/src/jrd/exe.cpp +++ b/src/jrd/exe.cpp @@ -779,9 +779,9 @@ void EXE_receive(thread_db* tdbb, const bid* id = (bid*) ((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 && 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_transaction = TRA_start(tdbb, 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); if (!(tdbb->getAttachment()->att_flags & ATT_no_db_triggers)) @@ -3215,13 +3216,14 @@ static void release_blobs(thread_db* tdbb, jrd_req* request) /* Release blobs bound to this request */ - if (request->req_blobs.getFirst()) + if (request->req_blobs.getFirst()) + { while (true) { 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) { request->req_blobs.fastRemove(); @@ -3248,6 +3250,7 @@ static void release_blobs(thread_db* tdbb, jrd_req* request) if (!request->req_blobs.getNext()) break; } + } request->req_blobs.clear(); diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index 6777d7f54e..e623db83a0 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -737,7 +737,7 @@ void TRA_init(thread_db* tdbb) Database* dbb = tdbb->getDatabase(); 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; 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); 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_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(); Attachment* attachment = tdbb->getAttachment(); - if (transaction->tra_blobs.getFirst()) - while (true) + if (!transaction->tra_outer) + { + if (transaction->tra_blobs->getFirst()) { - BlobIndex *current = &transaction->tra_blobs.current(); - if (current->bli_materialized) { - if (!transaction->tra_blobs.getNext()) - break; - } - else { - ULONG temp_id = current->bli_temp_id; - BLB_cancel(tdbb, current->bli_blob_object); - if (!transaction->tra_blobs.locate(Firebird::locGreat, temp_id)) - break; + while (true) + { + BlobIndex *current = &transaction->tra_blobs->current(); + if (current->bli_materialized) { + if (!transaction->tra_blobs->getNext()) + break; + } + else { + ULONG temp_id = current->bli_temp_id; + BLB_cancel(tdbb, current->bli_blob_object); + if (!transaction->tra_blobs->locate(Firebird::locGreat, temp_id)) + break; + } } } - while (transaction->tra_arrays) - BLB_release_array(transaction->tra_arrays); + while (transaction->tra_arrays) + BLB_release_array(transaction->tra_arrays); + } if (transaction->tra_pool) { // Iterate the doubly linked list of requests for transaction and null out the transaction references @@ -1180,9 +1185,10 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction) // Release the transaction pool - MemoryPool* tra_pool = transaction->tra_pool; + MemoryPool* tra_pool = transaction->tra_outer ? NULL : transaction->tra_pool; delete transaction; - dbb->deletePool(tra_pool); + if (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 // transaction block first, seize relation locks, then go ahead and // make up the real transaction block. - Jrd::ContextPoolHolder context(tdbb, dbb->createPool()); - jrd_tra* temp = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool()); + Jrd::ContextPoolHolder context(tdbb, (outer ? outer->tra_pool : dbb->createPool())); + jrd_tra* temp = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool(), outer); temp->tra_flags = flags; 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 // transaction block first, seize relation locks, then go ahead and // make up the real transaction block. - Jrd::ContextPoolHolder context(tdbb, dbb->createPool()); - jrd_tra* temp = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool()); + Jrd::ContextPoolHolder context(tdbb, (outer ? outer->tra_pool : dbb->createPool())); + jrd_tra* temp = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool(), outer); 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; if (temp->tra_flags & TRA_read_committed) - trans = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool()); - else { - trans = FB_NEW_RPT(*tdbb->getDefaultPool(), (number - base + TRA_MASK) / 4) jrd_tra(tdbb->getDefaultPool()); + trans = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) jrd_tra(tdbb->getDefaultPool(), temp->tra_outer); + else + { + 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); diff --git a/src/jrd/tra.h b/src/jrd/tra.h index 7e0c9f736e..a070631bd4 100644 --- a/src/jrd/tra.h +++ b/src/jrd/tra.h @@ -94,19 +94,29 @@ public: tra_wait }; - explicit jrd_tra(MemoryPool* p) : + explicit jrd_tra(MemoryPool* p, jrd_tra* outer) : tra_pool(p), - tra_blobs(p), + tra_blobs_tree(p), + tra_blobs(&tra_blobs_tree), tra_resources(*p), tra_context_vars(*p), tra_lock_timeout(DEFAULT_LOCK_TIMEOUT), 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() { - delete tra_temp_space; + if (!tra_outer) + delete tra_temp_space; } Attachment* tra_attachment; /* database attachment */ @@ -118,7 +128,8 @@ public: jrd_tra* tra_next; /* next transaction in database */ jrd_tra* tra_sibling; /* next transaction in group */ 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 */ Lock* tra_lock; /* lock for transaction */ 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) RuntimeStatistics tra_stats; Firebird::Array tra_open_cursors; + jrd_tra* tra_outer; // outer transaction of an autonomous transaction private: TempSpace* tra_temp_space; // temp space storage @@ -156,6 +168,9 @@ public: TempSpace* getTempSpace() { + if (tra_outer) + return tra_outer->getTempSpace(); + if (!tra_temp_space) tra_temp_space = FB_NEW(*tra_pool) TempSpace(*tra_pool, TRA_TEMP_SPACE); diff --git a/src/jrd/tra_proto.h b/src/jrd/tra_proto.h index 2a799f4171..943415f912 100644 --- a/src/jrd/tra_proto.h +++ b/src/jrd/tra_proto.h @@ -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_shutdown_attachment(Jrd::thread_db*, Jrd::Attachment*); 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*, int, const UCHAR*); +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* outer = NULL); int TRA_state(const UCHAR*, ULONG, ULONG); bool TRA_sweep(Jrd::thread_db*, Jrd::jrd_tra*); int TRA_wait(Jrd::thread_db*, Jrd::jrd_tra*, SLONG, Jrd::jrd_tra::wait_t);