8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 23:23:04 +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;
}
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
{

View File

@ -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();

View File

@ -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);

View File

@ -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<dsql_req*> 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);

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_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);